Atmel AVR: wywolywanie funkcji co pewien czas

Feb 09, 2004 9 Replies

Na wstepie pragne podziekowac za wczesniejsze odpowiedzi.



Przypominam co chce uzyskac. Chodzi mi o napisanie programu dla AVR AT90S8535, w ktorym pewna funkcja (obslugi przerwania) bylaby wywolywana co pewien czas -- potrzebuje uzyskac wywolywanie mojej funkcji co 0.1 sekundy albo 1 sekunde, moze okaze sie niezbedne wywolywanie funkcji co 0.01 sek.



Mam .pdf "AVR130: Setup and Use the AVR Timers". Na stronie 8 mamy: "Example - Timer0 Overflow Interrupt". Oto kod: void init_Ex1(void) { TCCR0 = (1<<CS02) | (1<<CS00); // Timer clock = system clock / 1024 TIFR = 1<<TOV0; // Clear TOV0 / clear pending interrupts TIMSK = 1<<TOIE0; // Enable Timer 0, Overflow Interrupt DDRB = 0xFF; // Set Port B as output }



void interrupt [TIMER0_0VF0_vect] ISR_TOV0 (void) { PORTB = ~PORTB; }



Do portu B podlaczamy diody LED. Przy 8-bitowym timerze 0 (MaxVal=256). CK=3.69Mhz. PVal = 1024, stad czestotliwosc migania diod fLED=CK/(2*Pval*MaxVal) = okolo 7Hz.


Inny przyklad z tego .pdf ze strony 12 wykorzystuje 8-bitowy timer2 i kwarc. W tym przykladzie, mozna migac diodami z czestotliwoscia np. 1Hz. Czy da sie sterowac diodami (chodzi o wywolywanie funkcji obslugi przerwania z okreslona czestotliwoscia) z czestotliwoscia 1Hz wykorzystujac timer0? Jesli nie, to z czego to wynika? Czy chodzi o to, ze wartosc CK=3.69Mhz, MaxVal=256 i dostepne wartosci Pval sprawiaja, ze podstawiajac do wzoru CK/(2*Pval*MaxVal) nie da sie uzyskac wartosci rzedu 0.1Hz, 1Hz ? Sterowanie z timera0 (tak jak w przytoczonym kodzie) byloby dla mnie o tyle dogodniejsze, ze nie wymagany bylby kwarc. Chcialbym tez zrozumiec czy z timera0 (bez kwarcu) mozna uzyskac czestotliwosc 1Hz, tak jak z timera2 z kwarcem. Z tego wzgledu, bylbym niezmiernie wdzieczny za uswiadomienie.



Z gory dziekuje za odpowiedzi, Trix.


A jak bys chcial migac dioda raz na tydzien to tez bys wywolywal przerwanie z ta czestotliwoscia ??? Ustaw sobie czestostliowsc Timera0 np na 100Hz i w jego procedurze obslugi zwiekszaj wartosc jakiejsc zmiennej sluzacej za licznik. W glownym programie sprawdzaj jedynie wartosc tego licznika i gdy bedzie rowny 100 zapal diode(albo zgas) i wyzeruj licznik ( dostaniesz 1Hz ). W ten sposob niezalenie mozesz obslugiwac wieksza liczbe licznikow i uzyskiwac czestotliowsci bedace wielokrotnoscia czestotliwosci przerwania Timer0 Staraj sie rowniez by kod obslugi przerwania byl jak najkrotszy( tylko inkrementacja licznikow), a cala reszte pakuj do glownego programu.

Sebasto

Dlaczego, przeciez o ile sie nie myle to licznik dalej liczy w trakcie obslugi przerwania, czyli dluga obsluga przerwania nie ma znaczenia (oczywiscie jezeli zakonczy sie szybciej niz kolejne wywolania przerwania).

Max

przerwania).

Chodzilo mi wlasnie o ogolna zasade by skracac czas obslugi przerwan, ktora przyda sie w przyszlosci gdy jego programy beda korzystaly z wielu przerwan. Jestem zwolennikiem wyrabiania zdrowych nawykow :))

Sebasto

I chwala Ci za to, ale trzeba wytlumaczyc dla czego.

Czy da sie sterowac diodami (chodzi o wywolywanie funkcji obslugi przerwania z

Da sie to zrobic, ale nie bez dodatkowym operacji jak zliczanie liczby przerwan. To masz opisane w drugim poscie od kogos innego wiec nie bede opisywal. Najwolniejszy odstep czasu miedzy przerwaniamia od timre0 przy 3.96Mhz mozna wyliczyc

1/((3.96MHz/1024)/256) = ok. 67ms Czy nie mozesz uzyc Timer1 ktory jest 16bitowym licznikiem? Zeby generowane bylo przerwanie co 1s wystarczy jako wartosc poczatkowa wstawic: 65536 - (3,96Mhz/64) = 3661 = 0x0E4D Jako sygnal zegarowy CK/64 i powinno hulac:)

Pozdrawiam Tomek

Wystarczy zrobic to tak: void interrupt [TIMER0_0VF0_vect] ISR_TOV0 (void) { static unsigned char cnt; if ( (cnt++)==7 ) { cnt=0; PORTB = ~PORTB; } }

I juz z 7Hz robi sie 1Hz.

Jak poprzednicy napisali lepiej nawet puscic przerwanie czeciej, a za to sterowac nim wieloma rzeczami - na przyklad podlaczasz 8 diod i kazda migasz z inna czestotliwoscia :)

Tylko problem polega na tym, ze ja nie mam 7 Hz, ale okolo 7Hz.

Trix.

To moze lepiej (latwiej) uzyskac dokladnie 1000Hz? I licznikiem liczyc do 1000?

W programie, ktory wczesniej podalem (dla timera0) funkcja obslugi przerwania wywolywana jest przy przepelnieniu licznika. Jest wzor na czestotliwosc: Czestotliwosc = Ck/(2*Pval*MaxVal) czyli Czestotliwosc = 3,69MHz/(2*1024*256) Zatem Czestotliwosc = 7,038116455078125. Jedyne co mozemy tu zmienic to Pval z 1024 na inna wartosc prescalera. Ale nawet gdybysmy manipulowali MaxVal i prescalerem, nie uzyskamy liczb calkowitych.

Inaczej jest dla timera2 z kwarcem i uzyciem compare interrupt: Czestotliwosc=Cz_kwarcu/(PVal*Val) Gdy mamy timer taktowany kwarcem 32768, to mamy ladne czestotliwosci typu: 32, 16, 8, 4, 2, 1.6, 1.28, 1. Natomiast, gdy mamy timer taktowany kwarcem 8000000 i damy prescaler 64, to dal Val=125 mamy 1000Hz.

Zatem wynika mi z tego, ze nie mozna uzyskac "ladnych" czestotliwosci na timerze0. Pozostaje mi uzycie mojego procka i kwarcu, albo uzycie ATMega z kwarcem na pokladzie.

Trix.

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required