This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
en:avr:timers [2010/02/28 14:34] – mikk.leini | en:avr:timers [2020/07/20 09:00] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== Counters/ | ====== Counters/ | ||
- | Loendurid (inglise keeles // | + | Counters, which in some sense can be called timers, are one of the most important sub-functions of a microcontroller. These enable to precisely time processes, generate signals and count events. A counter converts the number of input cycles to a binary value using an array of triggers. The maximum number of counted cycles depends on the length of this array, and this is marked by the length of the binary code. AVR has 8- and 16-bit counters. If a timer has reached its maximum value (255 in 8-bit and 65535 in 16-bit counters), the next cycle will generate an overflow |
- | ===== Loenduri normaalrežiim | + | ===== Counter' |
- | Normaalrežiimis ei täida loendur muud funktsiooni kui pidevat järestikulist arvude loendamist. Loenduri väärtust saab igal hetkel programmis muidugi ka lugeda ja muuta. Ainuke lisavõimalus normaalrežiimis | + | In the default mode, a counter does nothing more than continually count sequential numbers. Its value can, of course, be read and changed from the program at any time. The only additional function in the default mode is to cause an interrupt |
- | <box 100% round #EEEEEE|Näide> | + | <box 100% round #EEEEEE|Example> |
- | Vaja on 8 MHz taktsagedusel töötav | + | Task: Make an 8 MHz ATmega128 |
<code c> | <code c> | ||
Line 16: | Line 16: | ||
ISR(TIMER0_OVF_vect) | ISR(TIMER0_OVF_vect) | ||
{ | { | ||
- | // Loendurile sellise väärtuse omistamine, | + | // Give the counter such a value |
- | // et järgmine ületäitumine tekiks | + | // that the next overflow occurs in 10 ms. |
- | // Valem: 256 - 8 MHz / 1024 / 100 Hz = 177,785 = ~178 | + | // Formula: 256 - 8 MHz / 1024 / 100 Hz = 177,785 = ~178 |
TCNT0 = 178; | TCNT0 = 178; | ||
} | } | ||
Line 24: | Line 24: | ||
int main() | int main() | ||
{ | { | ||
- | // Et esimene ületäitumise katkestus tekiks | + | // To make the first overflow interrupt fire in 10 ms as well, |
- | // tuleb ka siinkohal loendur algväärtustada. | + | // the counter needs to be initialized here. |
TCNT0 = 178; | TCNT0 = 178; | ||
- | // Sagedusjaguri teguriks | + | // Prescaler value 1024 |
TCCR0 = 0x07; | TCCR0 = 0x07; | ||
- | // Loenduri täitumise katkestuse lubamine | + | // Allow overflow interrupts |
TIMSK |= (1 << TOIE0); | TIMSK |= (1 << TOIE0); | ||
- | // Globaalne katkestuste lubamine | + | // Allow interrupts globally |
sei(); | sei(); | ||
- | // Lõputu programmitsükkel | + | // Endless loop |
while (1) continue; | while (1) continue; | ||
} | } | ||
</ | </ | ||
- | Näites toodud loendurile omistatava väärtusega siiski täpselt | + | The counter in this example will not generate the interrupt in exactly |
</ | </ | ||
- | ==== Välise taktiga loendur | + | ==== External Clock Counter |
- | Loenduri taktsignaalina saab kasutada ka mikrokontrollerivälist signaali (inglise keeles //external clock source//). Selleks on AVR mikrokontrolleril | + | It is also possible to use an external clock source |
- | ==== Sündmuste mõõtmine | + | ==== Timing Events |
- | Kuna loendurid võimaldavad mõõta aega, on keerukamatel | + | Since the counters allow timing operations, more complex |
- | <box 100% round #EEEEEE|Näide> | + | <box 100% round #EEEEEE|Example> |
- | Vaja on 8 MHz taktsagedusel töötava ATmega128-ga mõõta välise | + | Task: Measure the frequency of an external |
<code c> | <code c> | ||
Line 63: | Line 63: | ||
unsigned long frequency; | unsigned long frequency; | ||
- | // Sündmuse toimumise katkestus | + | // Interrupt for the event |
ISR(TIMER1_CAPT_vect) | ISR(TIMER1_CAPT_vect) | ||
{ | { | ||
- | // Loenduri nullimine | + | // Counter to 0 |
TCNT1 = 0; | TCNT1 = 0; | ||
- | // Tulemus on ainult siis arvestatav, kui | + | // The result is valid only if the counter |
- | // loendur pole vahepeal üle täitunud | + | // has not overflowed yet |
if (!(TIFR & (1 << TOV1))) | if (!(TIFR & (1 << TOV1))) | ||
{ | { | ||
- | // Sageduse arvutamine perioodi pöördväärtusest. | + | // Calculating the frequency from the period |
frequency = (unsigned long)8000000 / | frequency = (unsigned long)8000000 / | ||
(unsigned long)ICR1; | (unsigned long)ICR1; | ||
Line 79: | Line 79: | ||
else | else | ||
{ | { | ||
- | // Sagedus on vähem kui 122 Hz | + | // Frequency is less than 122 Hz |
frequency = 0; | frequency = 0; | ||
- | // Loenduri ületäitumise lipukese nullimine | + | // Set the counter' |
TIFR &= ~(1 << TOV1); | TIFR &= ~(1 << TOV1); | ||
} | } | ||
Line 89: | Line 89: | ||
int main() | int main() | ||
{ | { | ||
- | // Tõusva frondi registreerimine, sagedusjaguri tegur 1 | + | // Register a rising front, prescaler value 1 |
TCCR1B = (1 << ICES1) | (1 << CS10); | TCCR1B = (1 << ICES1) | (1 << CS10); | ||
- | // Sündmuse toimumise katkestuse lubamine | + | // Allow event interrupts |
TIMSK = (1 << TICIE1); | TIMSK = (1 << TICIE1); | ||
- | // Globaalne katkestuste lubamine | + | // Allow interrupts globally |
sei(); | sei(); | ||
- | // Lõputu programmitsükkel | + | // Endless loop |
while (1) continue; | while (1) continue; | ||
} | } | ||
</ | </ | ||
- | Programmis tekib välise signaali tõusva frondi ajal sündmuse katkestus. Katkestuse jooksul kontrollitakse, ega loenduri ületäitumine pole toimunud | + | The program fires an interrupt each time a rising front occurs in the external signal. During the interrupt, the counter is checked for overflows |
</ | </ | ||
- | Sündmuste püüdmist ning nende aja registreerimist saab teha ka tarkvaraliselt. Saab kasutada väliseid või muid katkestusi ja nende tekkimise ajal lugeda loenduri väärtus. Riistvaraline sündmuste püüdmine on siiski mõeldud eeskätt programmist sõltumatuks töötamiseks ja suhteliselt lühiajaliste | + | Catching events and registering the time it took for them to occur can also be resolved at the software level. It is possible to use external or other interrupts and read the value of the counter during these events. The hardware-level event catching is meant to run independently from the main program and time relatively short (or frequent) events. |
- | ===== Signaali genereerimine | + | ===== Signal Generating |
- | Keerukamate loenduritega saab peale signaali pikkuse mõõtmise ka signaali tekitada. Selleks on loenduril väärtuse võrdlemise üksus (inglise keeles //output compare unit//) ja võrdlustulemuse väljastusüksus (inglise keeles //compare match output unit//). Võrdlusüksusesse kuuluvad registrid sama bitilaiusega kui loendur ise ja nende registrite väärtusi võrreldakse loenduri väärtusega selle töö ajal. Hetkel, mil loenduri väärtus saab võrdseks võrdlusüksuse registri väärtusega, | + | More complex counters can generate a signal, in addition to timing the length of one. For this purpose the counter has an output compare unit and a compare match output unit. The output compare unit has registers with the same bit-width as the counter and the values of these registers are compared to the value of the counter while it is running. An interrupt can be generated and special pins' values can be changed each time the counter' |
- | Mõnedel signaali genereerimise režiimidel on määratav ka loenduri suurim väärtus - loenduri füüsiline suurus jääb küll samaks, kuid mängus on võrdlusregister, mille väärtust ületades loendur nullitakse. Seda võimalust kasutades saab eespool toodud ülesandeid täpse ajalise katkestuse tekitamise kohta lahendada, kuid mõeldud on see pigem signaali perioodi muutmiseks. Lisaks sellele on võimalik loendurit seadistada režiimi, kus see toimib nii juurde- kui mahalugemisel. | + | In some signal generating modes, the counter' |
- | Loendurid ja nende abil genereeritavate signaalide režiimid on ühed keerulisemad perifeeriamoodulid | + | The counters and the signal generating modes using them are one of the most complex peripheral modules in an AVR. Writing about all of them here is beyond the scope of this text, and typically there is no need to know all aspects in order to use them. The following describes one of the most common |
- | ==== Pulsilaius-modulatsioon | + | ==== Pulse Width Modulation |
- | Pulsilaius-modulatsioon (inglise keeles // | + | Pulse width modulation |
- | <box 100% round #EEEEEE|Näide> | + | <box 100% round #EEEEEE|Example> |
- | Vaja on 8 MHz taktsagedusel töötava | + | Task: Using an 8MHz ATmega128, generate two speed regulating servo motor signals. Use pin PB5 (OC1A) |
<code c> | <code c> | ||
Line 130: | Line 130: | ||
int main() | int main() | ||
{ | { | ||
- | // Viigud väljundiks | + | // Set pins as outputs |
DDRB |= (1 << PIN5) | (1 << PIN6); | DDRB |= (1 << PIN5) | (1 << PIN6); | ||
- | // Väljundid | + | // Set outputs |
- | // "Fast PWM" | + | // "Fast PWM" |
TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11); | TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11); | ||
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11); | TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11); | ||
- | // Suurim loenduri väärtus. Valem: | + | // Maximum value of the counter. Formula: |
// TOP = 8 MHz / 8 / 50 Hz | // TOP = 8 MHz / 8 / 50 Hz | ||
ICR1 = 20000; | ICR1 = 20000; | ||
- | // Esimese mootori poolperiood | + | // Half-period of the first motor is 1 ms, and second |
OCR1A = 1000; | OCR1A = 1000; | ||
OCR1B = 2000; | OCR1B = 2000; | ||
- | // Lõputu programmitsükkel | + | // Endless loop |
while (1) continue; | while (1) continue; | ||
} | } |