Atmel AVR: wywolywanie funkcji co pewien czas

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.

Reply to
Trix
Loading thread data ...

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

Reply to
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

Reply to
Maksymilian Dutka

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

Reply to
Sebasto

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

Reply to
Maksymilian Dutka

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

Reply to
tomkut

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 :)

Reply to
Tomasz Pyra

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

Trix.

Reply to
Trix

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

Reply to
Tomasz Pyra

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.

Reply to
Trix

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.