Hej, har en övning här som jag har hållit på med jättelänge och inte kommer vidare med därför att jag har fastnat och är inte helt på det klara med hur jag ska beräkna det här "compare value".
Uppgiften lyder så här:
1. Initilisera några register så att du får en interrupt per 1 ms. på en "compare match" (registererna: OCR1A TCNT1).
Använd CTC-läge så nollställs räknaren varenda gång, det blir en matchning. (se tabell s.148 i datablad).
2. Beräkna compare value, så kriteriet på 1 ms. är uppfyllt, CTC–mode-formeln finns på s.150 i databladet och ska användas där FoCA ska sättas till 0.5*1000 svarande till en periodtid på 2 ms.
[Det vill säga den är formeln:]
Studera timing diagram s.149.
Prescalling värde för fosc ska du också sätta, se tabell 17-6 s.161 i databladet, det är viktigt att uppnå ett heltal till compare value registret OCR1A!
Så håll ett av värdena och finn ett annat. Tabell 17-2 s.148 i databladet beskriver bit för CTC-läge.
Och så här har jag försökt beräkna och sätta koden men jag är ju inte alls säker på att det är rätt när det gäller CS1n-bitsen, alltså jag kommer liksom inte längre här?
Förutsatt att jag använder en 16-bit timer (TIMER1) och har en CPU Clock Frequency på 16 MHz
Då vet jag att MAX är 2^16 = 65535 (MAX)
En klockperiod är då:
För 16MHz: T = 1 / frekvens ---> T = 1 / 16MHz = 1 / 16 000 000
= 0,0000000625ms
Så samtiga prescalers faller inom maxgränsen 65535 men då jag ska ha ett heltalsvärde för prescalern så kan jag inte använda 256 eller 1024, då de har decimaler.
Alltså kan jag bara välja mellan prescalern 8 eller 64, och i det fallet är det nog lämpligast att välja 8:an då det ger bättre "resolution".
Med 16-bit timer skulle jag inte använt prescaler alls för att få hög upplösning. Med 8-bit timer är det å andra sidan nödvändigt. Och då blir också valen av lämplig prescaler mer begränsade.
Nu krävde ju uppgiften att du skulle använda prescaler, så du har gjort rätt.
Nästan tror jag.
Någon som vet varför min kod ändå inte funkar nu? Jag får min lysdiod att blinka till snabbt men sen fortsätter den bara att lysa och jag får inte de beräknade blinkningarna på 2 sekunder.
Har först listat kraven och sedan min kod (databladsbilderna finns ju i första inlägget ovan).
1. Initilisera några register så att du får en interrupt per 1 ms. på en "compare match" (registererna: OCR1A TCNT1).
Använd CTC-läge så nollställs räknaren varenda gång, det blir en matchning. (se tabell s.148 i datablad).
2. Beräkna compare value, så kriteriet på 1 ms. är uppfyllt, CTC–mode-formeln finns på s.150 i databladet och ska användas där FoCA ska sättas till 0.5*1000 svarande till en periodtid på 2 ms.
Studera timing diagram s.149.
Prescalling värde för fosc ska du också sätta, se tabell 17-6 s.161 i databladet, det är viktigt att uppnå ett heltal till compare value registret OCR1A!
Så håll ett av värdena och finn ett annat. Tabell 17-2 s.148 i databladet beskriver bit för CTC-läge.
3. Sätt värden in i compare value-registeret: OCR1A = ”compare value hittat i tidigare fråga”
4. Initilalisera bit i TIMSK1A-registeret och enable global interrupt.
5. Skriv interrupt service routinen ISR(vektornamn – c-compilermanual för namn på vektoren) I service routinen räknas en global variabel upp för varje gång det är interrupt.
6. I main funktionen testas – med ett if statement – ifall räknaren har nått 999, om den är 999 nollställs räkne-variablen och så tänds LED på PB7 varannan gång och släcks varannan gång (toogle). Kontrollera med en klocka att det passar med ett blink på 2 sek. – när det är klart så är koden i main klar till att integreras ihop med uppgiften från förra veckan.
Och här är min kod, varför fungerar det inte?
16 MHz
Prescale: 8 (vilket jag i databladet kom fram till att vara "(1 << CS11)").
Operationsläge: CTC (vilket jag i databladet kom fram till att vara "(1 << WGM12)").
Compare value: 1999 (beräkning finns i mitt tidigare inlägg, är fortfarande lite osäker på ifall det är rätt dock)
Du har missförstått uppgift 5 och 6. TCNT1 är själva hårdvarutimern. Den räknar mellan 0 och 1999 väldigt fort. Varje gång den når 1999 (och nollställs) körs interruptrutinen (varje millisekund i ditt program). Enligt uppgift 5 ska du, i interruptet, räkna upp en global variabel (som du definierat själv). Den variabeln ska sedan jämföras med 999 i mainloopen, för att växla lysdiodens läge en gång per sekund.
Det är inte lämpligt att läsa och skriva TCNT1 i mainloopen. Låt hårdvarutimern räkna på automatiskt. Eftersom att TCNT1 nollställs i mainloopen när den är större än 999, kommer TCNT1 aldrig att nå 1999, d.v.s det blir inte något interrupt.
Det ser rimligt ut. counter bör initieras i början av programmet, annars tänds dioden slumpmässigt med ca 64/65-dels sannolikhet vid programstart. (Från spänningslöst tillstånd. Vid enbart reset behåller variabeln sannolikt värdet den hade innan reset.) Alternativt deklarera static volatile eftersom att static initieras till 0. Om enbart volatile gör det minns jag inte, men tror inte det.
Eftersom att du inte har några avrundningar i beräkningarna borde lysdioden blinka i 0,5Hz med lika stor noggrannhet som kristallen. Kristaller brukar ha 50ppm.
In the absence of explicit initialization, external and static variables are guaranteed to be initialized to zero; automatic and register variables have undefined (i.e., garbage) initial values.
(Trots sidans namn handlar artikeln om C och inte java.)
In these languages, the term "static variable" has two meanings which are easy to confuse:
1.A variable with the same lifetime as the program, as described above (language-independent); or
2.(C-family-specific) A variable declared with storage class static.
Den länkade artikeln talar om "static variables", dvs definition 1.
"volatile uint16_t counter;" ger en "static variable" som lever under hela programmets livslängd. Den ÄR initierad när programmet går igång. Att kasta på nyckelordet "static" och tala om initiering är nonsens. Att dra in "volatile" i initieringsdiskussionen likaså.
Lagringsklassen static i C (definition 2) styr synlighet och åtkomst, plus att inuti en funktion ger det funktionsmässigt en variabel enligt typdefinition 1, men med åtkomst enbart inuti funktionen.
Javisst. Men enda gången static gör nån skillnad är inuti funktioner. Där kommer static-deklarationen att påverka livslängd, lagring och initiering. Det är inte detta beteende vi diskuterar, inte jag åtminstone. Dessutom torde det vara onödigt meckigt att få en static-deklarerad lokal variabel att lira ihop med en interruptrutin, men visst går det om man är envis.
I globalt scope så är "static int foo;" exakt samma sak som "int foo;" och initieras till noll. Med eller utan static. Alla variabler i globalt scope har statisk lagring/livslängd. Static tillför där ingenting funktionellt, bara en inkapslingsförstärkning av symbolen, så att den bara blir synlig i den fil den står definerad i. Att hävda att static där påverkar initieringen är trams.