Časovač pro ATMega32 - spouštění funkce každých 5 minut

Ahoj všem, mám problém s časovačem na ATMega32. Potřeboval bych něco spustit jednou za pět minut, taktuji MCU interně na 8 000 000 Hz. Používám Céčko (winavr). Můžete mne někdo nakopnout, jak to udělat? Chtěl bych na to použít 16ti bitový časovač a obsluhu v přerušení, bloková idea je tato:

  • Při inicializaci nastavit časovač a spustit jej
  • Inkrementovat při každém přetečení časovače proměnnou
  • Nejsem si jist, zda v obsluze přerušení dát na začátku cli() a na konci sei()
  • V hlavní smyčce kontrolovat, zda hodnota proměnné nedosáhla požadovano hodnoty. Pokud ano, cli(), provést obsluhu, vynulovat proměnnou a cli()
    Je tato myšlenka správná? Měl by někdo nějaký kód? Právě pro ATM32… Děkuji předem.

:arrow_right: administrator: přejmenováno z "časovač pro ATMega32"

Postup je správný, jen ta cli a sei v přerušení jsou zbytečná. Ostatní přerušení se blokují při vstupu do jiného automaticky.
Pokud bude obsluha v mainu trvat dlouho a budeš chtít počítat 5min až od jejího ukončení (tedy né mít pevný interval 5 min), tak tam cli a sei být mohou. Jesli chceš ovšem interval 5mit bez ohledu na délku obsluhy, tak ani v mainu cli a sei neoužívej (mimo první aktivaci přerušení).

Jakou potřebuješ přesnost? Dá se to naprogramovat přesně (pak bude záležet na přesnosti hodi), nebo jednodušeji ale jen přibližně. Rozdíl je pouze v nastavení timeru a potřebné velikosti počítací proměnné.

Pro jistotu je tam i blikátko (každých přibližně 8s změní stav diody na PD7.

[code]#include <avr/io.h>
#include <avr/interrupt.h>

#define F_CPU 8000000UL

#define FALSE 0
#define TRUE 1

volatile unsigned char timeElapsed = FALSE;

void obsluha5min(void)
{
// funkce vykonaná každých 5 min

}

void timer1Init(void)
{
//
TCCR1B = 1<<CS12 | 1<<CS10; // start timer, clkI/O/1024 (From prescaler)
TIMSK |= 1<<TOIE1; // Timer/Counter1, Overflow Interrupt Enable
}

void main(void)
{
DDRD |= 1<<PD7; // pro blikátko

sei();

for(;;)
{
	//
	if(timeElapsed)
	{
		timeElapsed = FALSE;
		obsluha5min();
	}
} 

}

ISR(TIMER1_OVF_vect)
{
// 5min = 300sec
// ovf = 8e6/1024/65536 = 0.1192/sec
// ovfCount = 300 * 0.1192 = 35,7 ~ 36

// T = 36 / (8e6/1024/65536) = 301,99s = 5min 2sec

static unsigned int cnt = 0;

PORTD ^= 1<<PD7;

if(++cnt > 35)
{
	cnt = 0;
	timeElapsed = TRUE;
}

}[/code]

děkuji moc, přesnost je více méně plus mínus pár sekund nevadí. děkuji.

skvele, diky moc, funguje to přesně podle představ.

Bacha, měl jsem tam chybu (nedostatek).
U řádku “volatile unsigned char timeElapsed = FALSE;” mi chybělo “volatile”. Tak si ho do programu doplň.

díky, upravil jsem.

Na začátku ještě chybělo “#include <avr/interrupt.h>”

Nechápu, jak mi to mohlo původně projít překladem :open_mouth:. Tobě to šlo přeložit bez varování?
Pak ještě ve “void timer1Init(void)” chybělo “void”, ale to už je jen detail.

Taky nebyl úplný vnitřek podmínky v nekonečný smyčce (jakmile jednou uplnul čas, funkce se volala stále dokola bez dalšího čekání na 5 min interval.

Přišel jsem na to teď, když jsem si v tom programu zkoušel něco jinýho a tentokrát to přeložit nešlo. Nechápu :unamused: .

jasne, to jsou drobnosti, ktere jsem mel pokryte (include) nebo pokryl jako jasnou upravo drobneho nedostatku. slo mi hlavne o ten postup a ukazku,. jak to udelat. doladeni uz bylo snadne (za to nakopnuti fakt velky dik, moc jsi mi obecne zde na foru pomohl)