AVR Assembler Övningsexempel 4 (3 / 9 steg)
Steg 3: Timer/Counter 0
Nu tänker jag inte gå in i detalj om delarna av koden som du förstår redan från tidigare delar av dessa tutorials. Också, om du ser några instruktioner för att leta nya eller du inte minns vad de gör, du vet redan vad jag ska göra. Du kan vända sig till instruktionsuppsättningen Sammanfattning i databladet och Påminn dig själv så, eller kan du gå till den fullständiga instruktionsuppsättning manuell: www.atmel.com/images/doc0856.pdf som har en mer detaljerad förklaring av varje instruktion och även exempelkod för hur den används. Jag tror du hittar en användbar handbok om du tänker fortsätta kodning i assembler. Vad vi gör hädanefter, i stället för rad-för-rad analys, är att diskutera de nya begrepp som vi inför att du inte har sett förut i dessa tutorials.
Så, innan vi kommer till subrutiner, kan börja med att ta en titt på vår klocka timer. Ni minns den sista läraren visade vi hur du använder avbrott och timer/counter TCNT0 för att skapa en metod för att har förseningar i vårt program där vi behöver dem. Du kommer att märka att denna gång, vi har ändrat den något. Här är koden jag talar om:
Reset:
LDI temp, 0b00000011
ut TCCR0B, temp; TCNT0 i FCPU/64-läge 250000 cnts/SEK
LDI temp, 249
ut OCR0A, temp; toppen av disk på 250 räknas/spill
; så Buffertspill inträffar varje 1/1000 SEK
; Detta innebär ett dataspill varje 1ms
LDI temp, 0b00000010
ut TCCR0A, temp; återställa TCNT0 längst upp på OCR0A
STS TIMSK0, temp; Aktivera timern Overflow avbryter
SEI; Aktivera global avbryter
Som ni kan se, i stället för FCPU/1024 som man förra gången, denna gång vi använder FCPU/64. Detta innebär att våra timer kommer att kryssa i en takt på
TCNT0 ränta = 16000000/64 = 250000 fästingar per sekund.
Nu introducerar vi något nytt. OCR0A utgång jämför registrera en (se sidan 108 i databladet). Vi satt ett värde av 249 i detta register (se tabell 15-1 sida 94). Sedan vi satt Wave Generation läge klämma fast WGM01 i TCCR0A och vi ser av tabell 15-8 på sidan 106 som detta innebär timern kommer att rensa och återställa när det når det värde vi har placerat i OCR0A. Med andra ord återställs till 0 när timern når 249. Detta innebär att det kommer att flöda över en gång varje 250 räknas. Eftersom det räknas uppgå till 250000 fästingar per sekund, tar det 1/1000 sekund att svämma över. Därav TCNT0 nu svämmar över varje millisekund.
Vi aktiverar sedan timer overflow avbrott och även global avbryter som vi förklarat i handledning 3.
Jag tror du håller med om att timer/räknare är komplicerade saker. Det finns tre olika räknare i mikrokontroller och du kan använda dem till tid och avbrott i olika kombinationer om du vill att tid olika saker eller du vill jämföra den tid det tar för att göra en sak i stället för en annan. Användningsområdena är oändliga och viktigt. För nu kommer vi endast att använda TCNT0 eftersom jag tror att få används för att det är tillräckligt komplicerat.
Ett bra sätt att visa alla dessa särskilda register som TCCR0A, TCCR0A, TIMSK0 och liknande är som en panel med vippströmbrytare på den. Som i en NASA kontrollera rum eller en skinka radiooperatören inrättas. Du kan växla mellan på och av olika växlar och detta kommer att kontrollera hur enheten fungerar. I detta fall timer TCNT0. Jag har tagit en bild från min doktorand dagar i partikelfysik stående i kontrollrummet ett accelerator laboratorium. Ibland kodning dessa marker kan kännas som att.
Anledningen till att vi har satt upp att svämma över varje ms är så att vi kan skapa en "delay" subrutin som fördröjer i millisekunder (precis som funktionen Arduino "delay()").
I vår kod kan du se att vi har genomfört detta med en subrutin som räknar antalet översvämningar och jämför detta värde med antalet millisekunder som vi vill fördröja.