läsa inport atmega8

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
sualo
Inlägg: 9
Blev medlem: 22 februari 2008, 14:56:34
Ort: Malmö

läsa inport atmega8

Inlägg av sualo »

Hejsan
Jag har precis börjat roa mig med avr programmering. Har skrivit mina första program idag på en atmega8. Har gjort rinnande ljus och en tärning som fungerade bra. Tärningen är i en evig loop och slumpar fram nya värden var tredje sekund. Jag skulle vilja koppla en brytare som kastar tärningen istället. Jag tänkte vänta någon dag med att lära mig avbrott så jag tänkte läsa av porten som brytaren sitter kopplad till kontinuerligt. Jag lyckas tyvärr inte läsa från inporten så tärningen startar inte. Har surfat runt på nätet i nån timme men har inte lyckats hitta ngt svar. Koden jag skrivit ser ut enl följande:

Kod: Markera allt

#include<avr/io.h>
#include <util/delay.h>
#include <stdlib.h>

void dice();

int main()
{
	DDRD=0x7f; //D0-D6-utportar
	PORTD=0x80;//etta till D7(pullup på?)
	while(1)
	{
		int p =PIND;//läs pin ?
		p=p&0x80;//maska ut bit 7

		if(p=0x80)
		{
			dice(); //kasta tärning
			_delay_ms(3000);
		//	PORTD=0;
		}
	}
	return 0;
}
void dice()
{
	char d[7]={0x08,0x22,0x49,0x63,0x6B,0x77};//kodning för ögonen på tärningen
	int rnd=rand()%6;
	PORTD=d[rnd];
}

Tärningen består av 7 LED PortD0-D6. Till PortD7 är en strömbrytare kopplad till vad som är tänkt att vara en ingång. Men det fungerar inte!
Är osäker på flera saker:
Om man skriver en etta till inporten, skall brytaren då kopplas mellan porten och jord? Och om en nolla är skriven skall brytaren då kopplas till logisk etta?
Hur ser syntaxen ut för att läsa ett värde från inporten? int n = PIND eller int n = PIND7 verkar inte funka. I Databladet för atmega8 finns ett exempel som jag inte förstår, de sätter bitarna med hjälp av |(1<<xxx). Jag förstår att en etta skiftas in på rätt position men det borde ju vara enklare att bara göra som jag gör ovan och slriva ett värde direkt till porten. (Det fungerade i alla fall för att skriva till porten)

Nåja detta blev ju ett långt första inlägg på forumet. Hoppas någon sitter på kunskap och ork för att hjälpa en stackars nybörjare.

MVH Jonas
Användarvisningsbild
Stinrew
Inlägg: 954
Blev medlem: 20 augusti 2006, 03:14:41
Ort: Motala
Kontakt:

Re: läsa inport atmega8

Inlägg av Stinrew »

Vad jag kan se har du varit medlem i över ett år, så jag skippar att välkomna dig till forumet. Jag gratulerar dig istället till ditt första inlägg :bravo:

Det stora felet du gjort i din kod är att du skrivit fel i villkoret till din if-sats. När man efterfrågar en likhet måste man använda dubbla likhetstecken if(p==0x80). Samtidigt måste du fundera på hur din koppling är gjord, då du har pull-up aktiverad. Sänker knapptryckning signalen? I så fall ska din if-sats villkor vara inte likamed if(p!=0x80).

Fick du inga varningar av din kompilator? Varningar ska betraktas som fel (dom ska åtgärdas innan man kan känna sig färdig).

Lycka till! :)
Användarvisningsbild
cykze
EF Sponsor
Inlägg: 1539
Blev medlem: 8 april 2004, 10:40:28
Ort: Uppsala

Re: läsa inport atmega8

Inlägg av cykze »

Tja och välkommen till forumet! :)

1. Använd inte "int". "int" brukar betyda en 16-bitars-variabel. I det här fallet räcker det gott och väl med 8-bitars-variabler. Jag föredrar att använda typen "uint8_t" för att beskriva en teckenlös (unsigned) byte (=8 bitar). Kolla i "stdint.h" så ser du.

2. För att kolla om en bit är 1 så är det väl enklast att se om villkoret "PIND & _BV(PD7)" är sant eller "!(PIND & _BV(PD7))" om du vill kolla om biten är 0. Där _BV(x) är definerad som "(1<<x)". Jag föredrar att använda _BV(x) för att undvika slarvfel.

3. För det mesta tycker jag att det blir tydligast om man använder sig av (1<<x) (eller _BV(x)) istället för att använda talen direkt.

4. I if-satsen gör du ju en tilldelning (=) av 0x80 till variabeln p, inte en jämförelse (==). Kompilatorn borde varna för sånt. Slå på "-Wall"-flaggan om du inte redan har gjort det. Eftersom p=0x80 alltid blir skiljt för noll så borde villkoret alltid uppfyllas och tärningen kastas varje varv i loopen. Gör den inte det?

5. Arrayen i dice() är 6 element stor. Alltså ska det stå en 6:a istället för 7:an. Eller så skriver du ingenting alls så räknar kompilatorn ut det. :)

6. Får du inte samma tärningsutfall varje gång du kör AVR:en, efter omstart? :)

7.
>Om man skriver en etta till inporten, skall brytaren då kopplas mellan porten och jord?

Vad menar du med att du "skriver en etta till inporten"?
sualo
Inlägg: 9
Blev medlem: 22 februari 2008, 14:56:34
Ort: Malmö

Re: läsa inport atmega8

Inlägg av sualo »

Tack för svaren!

Självklart skall det stå p==0x80 jag vet inte hur det blev p=0x80 men jag har väl lyckats klanta till det vid någon ändring men det fungerar inte med == heller. Tyvärr kan jag inte testa något mer nu efterssom det verkar som om jag haft sönder min atmega8, jag hadde bara en. men jag får väl köpa ett gäng och experimnetera vidare.

På vilket sätt är det tydligare att skriva (1<<xx) istället för att bara ange talet? Kanske är en vanesak. Men det skall väl fungera att skriva talet om man nu tycker det är lättare? Vad betyder skrivsättet _BV(PD7)

Jag har inte testat om jag får samma serie men det är väl troligt när man tänker på hur rand() är uppbyggt.

Med att skriva en etta till inporten menar jag PORTD=0x80 Jag är dock lite osäker på vad detta betyder. Om man skriver en bit till porten betyder det att pullup är aktiverad? betyder det att porten är hög och att brytaren då skall kopplas till jord? om så vad är då värdet på inporten när brytaren är nedtryckt 1 eller 0 ( borde var 0). Det är den här biten jag inte riktigt förstår.

Mycket frågor så här i början!
Nu blir det till att köpa en ny microcontroller och experimentera vidare.
eqlazer
Inlägg: 923
Blev medlem: 22 september 2007, 13:53:45
Ort: Göteborg

Re: läsa inport atmega8

Inlägg av eqlazer »

- På vilket sätt är det tydligare att skriva (1<<xx) istället för att bara ange talet? Kanske är en vanesak. Men det skall väl fungera att skriva talet om man nu tycker det är lättare? Vad betyder skrivsättet _BV(PD7)

I dina exempel så går det ju lika bra med talet direkt, men när det börjar röra sig om mer än bara 8 bitar så blir det snabbt ganska rörigt och (1<<23) blir bra mycket mer överskådligare än 0x800000. Men det är ju givetvis beroende på vad man ska använda det till. Kan också vara smidigt att bygga maskar med sättet (1<<7)|(1<<3)|(1<<0), vilket om det gäller port D skulle kunna betyda (1<<PD7)|(1<<PD4)|(1<<PD0). Där ser man direkt vilka pinnar du petar på, det gör man inte lika enkelt med 0x91.

Vad var oklart med _BV(PD7)? _BV(x) förklarade ju cykze och PD7 är bara en define för numret för pinne 7 på port D. _BV(PD7) är alltså precis samma sak som (1<<8).

- Med att skriva en etta till inporten menar jag PORTD=0x80 Jag är dock lite osäker på vad detta betyder. Om man skriver en bit till porten betyder det att pullup är aktiverad? betyder det att porten är hög och att brytaren då skall kopplas till jord? om så vad är då värdet på inporten när brytaren är nedtryckt 1 eller 0 ( borde var 0).

Vet du vad pullup är och varför man utnyttjar det? Först och främst gäller det att veta vad DDRD, PIND och PORTD (port D i detta fallet) gör, du verkar ju fattat en del iaf. Står beskrivet bra i databladet vad pinnarna får för egenskaper beroende på hur registerna är konfigurerade.

Om pullupen är aktiverad så kommer ingången ligga hög (1) då den är opåverkad, kopplar du in en brytare som sänker till jord så kommer den bli låg (0) när du aktiverar brytaren. Skulle inte pullup finnas i en sån koppling så vet vi inte vad ingången får för värde då brytaren inte är aktiverad.
Självklart kan man koppla tvärt om också, med en pulldown och brytaren till Vcc, men fördelen med varianten med pullup är att vi kan använda AVRns interna pullup annars måste man koppla en extra resistor externt. Enklare att hantera få komponenter.

Med reservation för ev räknefel :) Men hoppas iaf att nått av detta gör dig lite klokare.
eqlazer
Inlägg: 923
Blev medlem: 22 september 2007, 13:53:45
Ort: Göteborg

Re: läsa inport atmega8

Inlägg av eqlazer »

Och ta du och skaffa dig en mega88 istället för en gammal 8:a. Ofta är också 88 billigare. 88:an är pinkompatibel och ersättare för 8:an och har fler funktioner. Registernamn kan skilja sig lite åt men det är inget avancerat, och du verkar inte ha kommit in på några avancerade funktioner än så det är inget du behöver lära om.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: läsa inport atmega8

Inlägg av sodjan »

> mer nu efterssom det verkar som om jag haft sönder min atmega8,

Varför tror du det ?
Generellt sätt är det inte lätt att ha "sönder" dessa kretsar...
Användarvisningsbild
BEEP
EF Sponsor
Inlägg: 1593
Blev medlem: 21 januari 2006, 16:57:56
Ort: Mölndal

Re: läsa inport atmega8

Inlägg av BEEP »

Rättar man till felet i if satsen och om tärningen ska ha 7 siffror :) så fungerar det för annars så har du kopplat fel. Som cykze påpekade så får man samma tärningsutfall varje gång man startar µC.

Du har en varning kvar att fixa. "F_CPU not defined for <util/delay.h>"
sualo
Inlägg: 9
Blev medlem: 22 februari 2008, 14:56:34
Ort: Malmö

Re: läsa inport atmega8

Inlägg av sualo »

Tackar!
Nu tror jag att jag börjar greppa det här!!

Varför jag tror att jag har haft sönder kretsen är för att jag inte längre kan programmera den. Jag får ett felmeddelande som jag tyvärr inte kan ange just nu efterssom jag inte är hemma, men det slutade fungera efter det att jag experimenterade med att lägga ett och jord ganska vårdslöst på olika pinnar så jag antog att jag hade haft sönder något? Men det är kanske inte så lätt gjort?

Jepp atmega88 får det bli de var slut när jag var på elfa och handlade min programmerare så därför köpte jag en 8:a istälet.

Tack för alla svar, jag tror jag börjar förstå nu återkommer när jag har provat.
MVH
Jonas

BEEP hann visst emellan: Jepp jag får ta och definiera F_CPU brydde mig inte om det efterssom timingen inte var så viktigt, slarvigt av mig. :tumner:
Hur gör man för att få olika resultat när man kör tärningen, hur kan man så olika "frö" till srand()?
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: läsa inport atmega8

Inlägg av sodjan »

> Hur gör man för att få olika resultat när man kör tärningen, hur kan man så olika "frö" till srand()?

Ofta får man förlita sig på någon okänt utanför kretsen, t.ex att någon trycker
på en knapp. Allt du gör i koden kommer ju att vara rellativt deterministiskt, d.v.s
att det kommer alltid at köras på samma sätt varje gång. Ibland går det att köra
två prylar i processorn (som t.ex en watchdog timer och en vanlig timer) mot varandra
och på det sättet få ett ganska slumpmässigt värde som bl.a kommer att variera
med temperaturen.
Användarvisningsbild
vfr
EF Sponsor
Inlägg: 3515
Blev medlem: 31 mars 2005, 17:55:45
Ort: Kungsbacka

Re: läsa inport atmega8

Inlägg av vfr »

Bara en synpunkt

lägga ett och jord ganska vårdslöst på olika pinnar

Man lägger inte ett på en pinne utan en spänning (eller kanske rättare en potential), t.ex "jord" som du också angett. Nu blev det lite sammanblandat med en spänning och ett bitvärde i samma mening. :)
Användarvisningsbild
cykze
EF Sponsor
Inlägg: 1539
Blev medlem: 8 april 2004, 10:40:28
Ort: Uppsala

Re: läsa inport atmega8

Inlägg av cykze »

> På vilket sätt är det tydligare att skriva (1<<xx) istället för att bara ange talet?

PORTD = 0x80; // sätter PD7 till 1
PORTD = _BV(PD7); // behöver inte ens kommenteras ;)

Tycker jag i alla fall. :)

När du sen vill börja använda inbyggda funktioner i AVR:en så styr du ju dom genom att skriva och läsa bitar till olika register. Då finns det (oftast) ingen som helst anledning att inte köra med (1<<bitnamn) eller _BV(bitnamn).

Istället för att använda rand() så skulle du ju kunna använda värdet från en timer istället. TCNTn-registrena är helt enkelt tal som räknar upp automatiskt i bakgrunden. Ett bra tillfälle att lära sig lite om timers kanske? Kolla i databladet.
Användarvisningsbild
MicaelKarlsson
Inlägg: 4669
Blev medlem: 18 juni 2004, 09:16:07
Ort: Aneby
Kontakt:

Re: läsa inport atmega8

Inlägg av MicaelKarlsson »

Fungerar din delay?

Kod: Markera allt

_delay_ms(3000);
Om man tittar i delay.h står det så här:
Perform a delay of \c __ms milliseconds, using _delay_loop_2().

The macro F_CPU is supposed to be defined to a
constant defining the CPU clock frequency (in Hertz).

The maximal possible delay is 262.14 ms / F_CPU in MHz.

When the user request delay which exceed the maximum possible one,
_delay_ms() provides a decreased resolution functionality. In this
mode _delay_ms() will work with a resolution of 1/10 ms, providing
delays up to 6.5535 seconds (independent from CPU frequency). The
user will not be informed about decreased resolution.
sualo
Inlägg: 9
Blev medlem: 22 februari 2008, 14:56:34
Ort: Malmö

Re: läsa inport atmega8

Inlägg av sualo »

Nähä det var visst inte fel på komponenten för jag får samma felmeddelande med en annan (atmega88 den här gången!). Kanske någon här kan hjälpa mig med att tolka vad som är fel eller jag bör kanske hellre starta en ny tråd om det?
iaf felmeddelandet jag får är följande:

Kod: Markera allt

sudo avrdude -c dragon_isp -p m88 -P usb -U flash:w:main.hex
avrdude: jtagmkII_setparm(): bad response to set parameter command: RSP_FAILED
avrdude: jtagmkII_getsync(): ISP activation failed, trying debugWire
avrdude: jtagmkII_setparm(): bad response to set parameter command: RSP_DEBUGWIRE_SYNC_FAILED
avrdude: failed to sync with the JTAG ICE mkII in ISP mode

Som programmerare använder jag en AVR Dragon och programmerar via ISP med avrdude i linux
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: läsa inport atmega8

Inlägg av sodjan »

Är inte JTAG och ISP och Debugwire olika metoder ?
Jag har inte en aning igentligen, men tycker att det är lite
märkligt att alltihopa nämns i samma sammanhang...
Skriv svar