This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| et:examples:timer:hardware_delay [2010/02/08 14:11] – Links to et:software:library:pin changed to et:software:homelab:library:pin mikk.leini | et:examples:timer:hardware_delay [2020/07/20 12:00] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | < | ||
| + | ====== Riistvaraline viide ====== | ||
| + | |||
| + | //Vajalikud teadmised: [HW] [[et: | ||
| + | |||
| + | ===== Teooria ===== | ||
| + | |||
| + | Tarkvaraline viide pole ainus meetod pausi tekitamiseks. Sama asja saab teha ka taimeriga. Taimer on riistvaraline kindla sagedusega suurenev või vähenev loendur. Loenduri taktsignaali saab enamasti tekitada mikrokontrolleri töötaktist või mingist välisest taktist. Taktsignaali sagedust saab üldjuhul ka mingi teguriga jagada väiksem taktsageduse saavutamiseks - seda tehakse taktijaguriga, | ||
| + | |||
| + | [{{ : | ||
| + | |||
| + | AVR loendurit saab panna teavitama loenduri ületäitumisest (inglise keeles // | ||
| + | |||
| + | Selleks, et taimeriga viide tekitada, piisabki vaid loenduri seadistamisest ja olekubiti kõrgeks minemise ootamisest. Erinevalt tarkvaralisest viitest ei sõltu taimerite töö kompilaatorist, | ||
| + | |||
| + | ===== Praktika ===== | ||
| + | |||
| + | Allpool olev programmikood on taimeril põhinev viitefunktsioon, | ||
| + | |||
| + | Tsüklis toimub loenduri algväärtustamine ja ületäitumise lipukese nullimine (sellesse 1 kirjutades). Seejärel oodatakse, kuni loendur loendab algväärtusest 256-ni, ehk ületäitumiseni. Ületäitumise hetkel läheb ületäitumise lipuke kõrgeks ja 1 ms viide ongi toimunud. Funktsiooni lõpus taimer peatatakse. | ||
| + | |||
| + | <code c> | ||
| + | // | ||
| + | // Riistvaraline viide millisekundites Atmega kontrolleril | ||
| + | // | ||
| + | void hw_delay_ms(unsigned short count) | ||
| + | { | ||
| + | // Taimeri algväärtuse arvutamine | ||
| + | register unsigned char timer_start = 256 - F_CPU / 1000 / 64; | ||
| + | |||
| + | // Taimeri käivitamine | ||
| + | timer0_init_normal(TIMER0_PRESCALE_64); | ||
| + | |||
| + | // Viite muutuja nullini loendamine | ||
| + | while (count-- > 0) | ||
| + | { | ||
| + | // Taimeri algväärtustamine | ||
| + | timer0_set_value(timer_start); | ||
| + | |||
| + | // Ületäitumise lipukese nullimine | ||
| + | timer0_overflow_flag_clear(); | ||
| + | |||
| + | // Ületäitumise ootamine | ||
| + | while (!timer0_overflow_flag_is_set()) | ||
| + | { | ||
| + | asm volatile (" | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // Ületäitumise lipukese nullimine | ||
| + | timer0_overflow_flag_clear(); | ||
| + | |||
| + | // Taimeri peatamine | ||
| + | timer0_stop(); | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | |||
| + | Esitatud viite funktsioon kasutab aga taimerite teeki, mille lähtekood Atmega kontrollerile näeb välja järgmine: | ||
| + | |||
| + | <code c> | ||
| + | // | ||
| + | // Taimer 0 taktijaguri valiku tüüp | ||
| + | // | ||
| + | typedef enum | ||
| + | { | ||
| + | TIMER0_NO_PRESCALE | ||
| + | TIMER0_PRESCALE_8 | ||
| + | TIMER0_PRESCALE_32 | ||
| + | TIMER0_PRESCALE_64 | ||
| + | TIMER0_PRESCALE_128 | ||
| + | TIMER0_PRESCALE_256 | ||
| + | TIMER0_PRESCALE_1024 | ||
| + | } | ||
| + | timer0_prescale; | ||
| + | |||
| + | // | ||
| + | // Taimer 0 normaalrežiimi seadistamine | ||
| + | // | ||
| + | inline void timer0_init_normal(timer0_prescale prescale) | ||
| + | { | ||
| + | TCCR0 = prescale & 0x07; | ||
| + | } | ||
| + | |||
| + | // | ||
| + | // Taimer 0 peatamine | ||
| + | // | ||
| + | inline void timer0_stop() | ||
| + | { | ||
| + | TCCR0 = 0x00; | ||
| + | } | ||
| + | |||
| + | // | ||
| + | // Taimer 0 loenduri väärtuse määramine | ||
| + | // | ||
| + | inline void timer0_set_value(unsigned char value) | ||
| + | { | ||
| + | TCNT0 = value; | ||
| + | } | ||
| + | |||
| + | // | ||
| + | // Taimer 0 ületäitumise lipukese nullimine | ||
| + | // | ||
| + | inline void timer0_overflow_flag_clear(void) | ||
| + | { | ||
| + | bit_set(TIFR, | ||
| + | } | ||
| + | |||
| + | // | ||
| + | // Taimer 0 ületäitumise lipukese oleku lugemine | ||
| + | // | ||
| + | inline bool timer0_overflow_flag_is_set(void) | ||
| + | { | ||
| + | return (bit_is_set(TIFR, | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | |||
| + | Järgnevalt on toodud samasugune programm nagu tarkvaralise viite näiteski. Lühemal 100 ms poolperioodil LED süüdatakse, | ||
| + | |||
| + | <code c> | ||
| + | // | ||
| + | // Kodulabori riistvaralise viite demonstratsioonprogramm. | ||
| + | // Programm vilgutab ~1 sekundi järel hetkeks LED-i. | ||
| + | // | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | // | ||
| + | // Test LED viigu määramine | ||
| + | // | ||
| + | pin debug_led = PIN(B, 7); | ||
| + | |||
| + | // | ||
| + | // Põhiprogramm | ||
| + | // | ||
| + | int main(void) | ||
| + | { | ||
| + | // LED-i viigu väljundiks seadmine | ||
| + | pin_setup_output(debug_led); | ||
| + | |||
| + | // Lõputu tsükkel | ||
| + | while (true) | ||
| + | { | ||
| + | // LED-i põlema panek | ||
| + | pin_clear(debug_led); | ||
| + | |||
| + | // Riistvaraline paus 100 millisekundit | ||
| + | hw_delay_ms(100); | ||
| + | |||
| + | // LED-i kustutamine | ||
| + | pin_set(debug_led); | ||
| + | |||
| + | // Riistvaraline paus 900 millisekundit | ||
| + | hw_delay_ms(900); | ||
| + | } | ||
| + | } | ||
| + | </ | ||