// demonstrace použítí časovače TCB pro periodické přerušení // + využití jako "milis" // Program spustí MCU s interním clockem 1MHz // Spustí časovač TCB0 s periodickým přerušením každou 1ms // V rutině přerušení inkrementuje milis_cnt (počítadlo milisekund) // Voláním funkce "milis()" lze přečíst aktuální "čas" // Funkce a proměnné související s milis nejsou k chodu časovače nutné // Příklad lze využít i bez milis, případně milis lze implementovat i na jiném časovači #include #include #include // kvůli funkci "milis" volatile uint16_t milis_cnt=0; // počet milisekund od startu časovače/programu uint16_t milis(void); // funkce pro čtení hodnoty milis_cnt int main(void) { _PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, CLKCTRL_FRQSEL_1M_gc); // clock 1MHz PORTA.DIRSET = PIN7_bm; // jen pro demonstrační účely, PA7 jako výstup TCB0.CTRLB = TCB_CNTMODE_INT_gc; // TCB0 do režimu "Periodic interrupt" TCB0.CTRLA = TCB_CLKSEL_DIV1_gc | TCB_ENABLE_bm; // TCB0 spustit s clockem F_CPU/1 TCB0.INTCTRL = TCB_CAPT_bm; // povolit v TCB0 přerušení od "capture" události TCB0.CCMP = 999; // strop TCB0 (počítá od 0), perioda F_CPU/1000=1ms sei(); // globální povolení přerušení while (1) { // nějaká užitečná činnost } } // rutina přerušení od TCB0 ISR(TCB0_INT_vect){ TCB0.INTFLAGS = TCB_CAPT_bm; // vymazat vlajku přerušení milis_cnt++; // inkrementovat počet milisekund (jen pro účely milis) } // funkce pro čtení hodnoty milis_cnt // (čtení 16bit hodnoty s 8bit instrukcemi je potřeba udělat "atomicky") uint16_t milis(void){ uint16_t tmp; // dočasná pomocná proměnná ATOMIC_BLOCK(ATOMIC_FORCEON){ // atomické operace (blokuje přerušení) tmp = milis_cnt; // zkopírovat milis_cnt } // konec atomické operace return tmp; // vrátit kopii milis_cnt }