atmega16 timer1 generujacy irq co 1s

Tak na szybko - jak te wszystkie rejestry poustawiac? Zegar 4MHz. Wykombinowalem tak: Prescaler 256, wiec zliczenia nastepuja co 0,000064s, czyli do zliczenia

1s potrzebuje zliczyc 15625 impulsow. Wiec timer1 16bit zlicza w gore od 0 ... OCRA ustawiony na 15625 Clear Timer on Compare Match (CTC) Mode WGM13:0 = 4 i wywoluje procedurke moja (ktora np zlicza sekundy, jak sekundy >60 to minuty++ itd) czy wywolanie procedurki bedzie w postaci ?: SIGNAL(TIMER1_COMPA_vect) { costam; } I jak do tego poustawiac TCCR1A,TCCR1B i co jeszcze zeby wlaczyc przerwanie (tylko) od tego przeladowania?
Reply to
BartekK
Loading thread data ...

murmi napisał(a):

Dzieki Oczywiscie na dokladnosc nie licze, po prostu chce przerobic stare programy z basica na c, i przy okazji powyrzucac "wait 15" zamieniajac na dekrementacje licznika w przerwaniu, cos mniejwiecej zamiast: if cos then wlacz costam wait 15 wylacz costam zamienie na: volatine uint8_t timer_jakis if (cos) timer_jakis=15; if (timer_jakis>0) {wlacz costam;} else {wylacz costam;} endif a w przerwaniu co 1s od timer1 bedzie if (timer_jakis>0) timer_jakis--;

Dzieki temu program sie zrobi troche bardziej "wielozadaniowy" ;)

Reply to
BartekK

ale gdy licznik doliczy do tej wartosci wpisanej do rejestrow OCR1Ax pojdzie dalej od wartosci 15625 do 65535, przejdzie przez 0 i wywola przerwanie znow gdy osiagnie 15625. Dlatego ustaw dodatkowo licznik w tryb pracy "Clear Timer on Compare Match (Auto Reload)", a wartosc poczatkowa ustaw na 0. Tak mi sie wydaje, wiec doczytaj szczegoly w pdf-ie procesora

Mariusz

Reply to
MariuszC

MariuszC napisał(a):

czyli jak? (jaka zawartosc i ktorych rejestow jeszcze trzeba zmienic?) bo juz mi oczy od patrzenia w pdf wypadaja

Reply to
BartekK

Wlasciwie zdublowalem info podane wczesniej przez BartkaK. On w przykladowym kodzie powyzej zrobil to o czym ja mowilem, a ze nie uzywalem do tej pory timerow w AVRze wiec podalem ogolnie jak ma dzialac timer aby osiagnac to o co Ci chodzi. CTC to wlasnie tryb "Clear Timer on Compare Match (Auto Reload)".

Uzywasz trybu CTC gdzie wartosc TOP jest brana z rejestru OCR1A, wtedy bit WGM12 musi byc ustawiony a reszta (WGM10, WGM11, WGM13) wyzerowana. Zatem kod podany przez BartkaK jest OK, jedynie wyczytalem w opisie rejestru Timer/Counter Interrupt Flag Register - TIFR że bit TOV1 jest ustawiany w trybie normalnym i CTC(!) timera, więc wektor przerwania to ma byc SIG_OVERFLOW1, a nie SIG_OUTPUT_COMPARE1A (jak to podal BartekK):

Zatem przykladowy kod:

// Handler obslugi przerwania SIGNAL( SIG_OVERFLOW1 ) { // funkcja wolana co 1 sekunde! }

// funkcja main inicjuje timer i globalne przerwania procesora void main( void ) { TCCR1B |= _BV(WGM12) //CTC - zakladam, ze reszta bitow poprawna OCR1AH = 0x3D; OCR1AL = 0x09;

TCCR1B |= _BV(CS12); // CLK/256 (from prescaller)

TIMSK |= _BV(TOIE1); // Enable Timer1 Overflow Interrupt Enable SREG |= _BV(I); // Enable Interrupts (instrukcja sei procesora)

for ( ; ; ); // nieskonczona petla }

_BV( x ) to makro wykonujace operacje ( 1 << x ) gdy uzywasz srodowiska WinAVR.

Jakby cos Ci nie dzialalo to daj znac, moze znajde chwile aby poprobowac na jakiejs mojej plytce prototypowej. Oczywiscie skoro uzywasz kwarca zewnetrzego, ustawiles odpowiednie fuse bity aby nie byl wykorzystany oscylator wewnetrzny ~1MHz.

Pozdrawiam Mariusz

Reply to
MariuszC

Wlasciwie zdublowalem info podane wczesniej przez Murmiego. On w przykladowym kodzie powyzej zrobil to o czym ja mowilem, a ze nie uzywalem do tej pory timerow w AVRze wiec podalem ogolnie jak ma dzialac timer aby osiagnac to o co Ci chodzi. CTC to wlasnie tryb "Clear Timer on Compare Match (Auto Reload)".

Uzywasz trybu CTC gdzie wartosc TOP jest brana z rejestru OCR1A, wtedy bit WGM12 musi byc ustawiony a reszta (WGM10, WGM11, WGM13) wyzerowana. Zatem kod podany przez Murmiego jest OK, jedynie wyczytalem w opisie rejestru Timer/Counter Interrupt Flag Register - TIFR że bit TOV1 jest ustawiany w trybie normalnym i CTC(!) timera, więc wektor przerwania to ma byc SIG_OVERFLOW1, a nie SIG_OUTPUT_COMPARE1A (jak to podal Murmie):

Zatem przykladowy kod:

// Handler obslugi przerwania SIGNAL( SIG_OVERFLOW1 ) { // funkcja wolana co 1 sekunde! }

// funkcja main inicjuje timer i globalne przerwania procesora void main( void ) { TCCR1B |= _BV(WGM12) //CTC - zakladam, ze reszta bitow poprawna OCR1AH = 0x3D; OCR1AL = 0x09;

TCCR1B |= _BV(CS12); // CLK/256 (from prescaller)

TIMSK |= _BV(TOIE1); // Enable Timer1 Overflow Interrupt Enable SREG |= _BV(I); // Enable Interrupts (instrukcja sei procesora)

for ( ; ; ); // nieskonczona petla }

_BV( x ) to makro wykonujace operacje ( 1 << x ) gdy uzywasz srodowiska WinAVR.

Jakby cos Ci nie dzialalo to daj znac, moze znajde chwile aby poprobowac na jakiejs mojej plytce prototypowej. Oczywiscie skoro uzywasz kwarca zewnetrzego, ustawiles odpowiednie fuse bity aby nie byl wykorzystany oscylator wewnetrzny ~1MHz.

Pozdrawiam Mariusz

Reply to
MariuszC

Odpowiadam sam sobie, ale juz z ciekawosci chcialem przecwiczyc ten timer w trybie CTC (kto wie moze w przyszlosci mi sie to przyda) i napisalem kod na swoja uklad testowy. Okazuje sie ze kod ktory przytoczylem powyzej jest zly, bo nie sa generowane przerwania. Wkurzylem sie i poczytalem dokladnie wszystko o Timerach, w opisie trybu CTC Timera0 jest "An interrupt can be generated each time the counter value reaches the TOP value by using the OCF0 Flag." (a nie ma podobnej informacji w opisie trybu CTC Timera1 dotyczacego bitu OCIE1A), zaś w opisie rejestru TIFR Timera1: "In Normal and CTC modes, the TOV1 Flag is set when the timer overflows.". Ta druga informacja mnie zmyliła. Zatem kolega Murmie podal faktycznie uzywany wektor przerwania w swoim kodzie przykladowym. Ponizej podaje sprawdzony, dzialajacy kod:

#include <avr/io.h>

#include <avr/interrupt.h>

int main( void ) { DDRA = 0xFF; // PORTA bedzie przelaczany miedzy 0x00 a 0xFF

OCR1AH = 0x3D; OCR1AL = 0x09; TCCR1B |= _BV( WGM12 ) | _BV( CS12 ); // Tryb CTC, CLK/256 TIMSK |= _BV( OCIE1A ); // Enable Timer1 Overflow Interrupt Enable

sei(); // Enable Interrupts

for ( ; ; ); // nieskonczona petla

return 0; // tylko aby uniknac warning kompilatora }

SIGNAL( SIG_OUTPUT_COMPARE1A ) { // funkcja wolana co 1 sekunde! PORTA = ~PORTA; // Neguj zawartosc bitow PORTA }

Teraz na porcieA co sekunde jego bity beda negowane.

Uwaga: na symulatorze AVRStudio widac, ze rejestry Timera nie sa automatycznie zerowane w momencie dojscia do wartosci takiej jak zapisana w OCR1 (16bit), tylko troszke pozniej -> tak samo jest na sprzecie, w funkcji obslugi przerwania jak odczytywalem wartosc TCNT1L i wpisywalem ja do portuA mial wartosc 0x00, ale max wartosc odczytywana w tej nieskonczonej petli jaka TCNT1L uzyskal byla rowna OCR1AL (przy czym OCR1AH byl ustawiony na 0x00).

Mariusz

Reply to
MariuszC

Jest to zresztą zgodne z dokumentacją. Dlatego też dla 1 sekundy musi być: OCR1AH = 0x3D; OCR1AL = 0x08;

Tomek

Reply to
TomekM

Faktycznie, jest to w punkcie "Output Compare Units": "If TCNT equals OCRnx the comparator signals a match. A match will set the Output Compare Flag (OCFnx) at the next timer clock cycle."

Człowiek nie doczyta dwóch zdań a potem spędzi tydzien dociekając z jakiej przyczyny dostaje event nie co 1sekundę, ale co 999,936 milisekund!!!

Mariusz

Reply to
MariuszC

Faktycznie, jest to w punkcie "Output Compare Units": "If TCNT equals OCRnx the comparator signals a match. A match will set the Output Compare Flag (OCFnx) at the next timer clock cycle."

Człowiek nie doczyta dwóch zdań a potem spędzi tydzien dociekając z jakiej przyczyny dostaje event nie co 1sekundę, ale co 1000,064 milisekund!!!

Mariusz

Reply to
MariuszC

Witam przeczytaj proszę mój następny post (pod tym na który dałeś odpowiedź, tam jest wyjaśnione że coś jest nie tak z dokumentacją procesora

Mariusz

Reply to
MariuszC

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.