Přerušení každou 1ms [Atmega32]

Dobrý večer,

chtěl bych se naučit programovat AVRka, bohužel zatím jsem v začátcích a narazil jsem na problém u přerušení čítače. Zaboha jsi nejsem schopný nastavit přerušení co 1ms. Zatím jsem nenašel žádný hezký článek jak si takové přerušení spočítat. Mohl by mě někdo nakopnout ? Popřípadě i tenhle triviální kód naprogramovat ? Děkuji

Pokud nepohrdnes anglictinou velice pekne vysvetleni zde avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=50106.
Dokonce i kdyz neumis anglicky tak to z toho pochopis…
Pokud ovsem nepouzijes externi oscilator, nepocitej, ze ta 1ms bude nejak presna.
Nebo pokud budes vedet, ze budes mit konstantni teplotu, muzes interni oscilator zkalibrovat aby ti vysla 1ms.

Kdyby ti nestačil návod odkazovaný Dragonem, budem potřebovat znát frekvenci procesoru a přesnost(max/±T) odpočítávané doby vzhledem k teoreticky ideálně přesným hodinám - 10% toleranci interního RC oscilátoru bych teď neřešil.

Rychlost CPU je 8MHz. Návod je fajn. A kdyby k tomu byl i kus kódu od vás bylo by to ještě fajnovější. Tolerance ±0,5ms. Moc na tom nezáleží. Spíš mi jde o to jak to vypočítat.

Prostudoval jsem lehce ten tutorial. Anglicky moc neumím. No sesmolil jsem něco takového. Akorát nevím jestli je to opravdu zhruba ta 1ms.

TCCR1B |= (1 << WGM12);
TIMSK |= (1 << OCIE1A);
TCCR1B |= (1 << CS11);
OCR1A = 1001;
sei();

ISR(TIMER1_COMPA_vect)
{
}

To by mělo fungovat, jen TOP bude 999.
Osobně mám radši FastPWM módy s nastavitelným TOPem (mode 14 a 15) a přerušení overflow, ale je to vcelku jedno.

příklad pro Timer0:

#include <avr/io.h>
#define F_CPU 8000000UL
#include <avr/interrupt.h>


int main(void)
{
	DDRC = 0b00000001;	//jen pro test

//nastavení přerušení pro Timer0 po 1ms

// 1/8MHz = 125ns;1ms / 125ns = 8000
// 8000/64 = 125
//čítač čítá od 0 do 255(při přetečení dojde k přerušení), takže je potřeba aby načetl 125,tj. 256 - 125 = 131

	TCNT0 = 131;					
	TCCR0 = (1<<CS00)|(1<<CS01);	//1:64
	TIMSK = (1<<TOIE0);

	sei();				//povolení přerušení

	while(1)
	{

	}

}


ISR (TIMER0_OVF_vect)
{
	TCNT0 = 131;
	PORTC = ~PINC;		//jen pro test		
}

Interrupt_1ms.GIF

Je nutno podotknou, že toto poloprogramové řešení funguje přesně pouze tehdy, pokud je dělička vyšší, než doba reakce na přerušení a zpracování zápisu do registru, tedy vyšší než asi 16 (4 takty reakce, dobré 4 dvoutaktové pushe). Jinak by se perioda prodloužila právě o to zpracování.

Plně hw řešení (CTC/PWM režim) těmito problémy netrpí.

No kód který jsem napsal já nefunguje tak jak bych si představoval. Měl jsem asi mylné představy o tom jak přerušení funguje.
Potřebuju vyvolat co jednu nebo 2 milisekundy přerušení. V přerušení si zavolám podprogram který netrvá déle než 0,5ms když to přeženu. Nicméně takto to nefunguje. Podprogram se mi přetíná a nedokončuje výpočty které jsem tam naprogramoval. Nebo je krpa někde jinde.

Potřebuji aby to fungovalo takto.
vyvolá se přerušení příkaz se zpracovává klidně do doby než přijde znovu přerušení poté jede příkaz odznova. Takže aby ten program v přerušení měl dobu na zpracování necelou 1ms. Momentálně se mi pravděpodobně přerušeuje mnohem dřív.

Dej sem celej program.
Přerušení nemůže být přerušeno, dokud to ručně nepřikážeš.
Každopádně obsluha přerušení má být co nejkratší. Nejlépe tedy si pouze označit požadavek/uložit data a zpracovat později až bude čas. To sice není vždy možné, ale často ano.

Pro vyzkoušení samotného přerušení tam dej jen blikátko (po 500 přerušeních změní stav ledky).

Tak to za podivných okolností začalo fungovat. Nechápu ovšem proč to předtím nešlo, v kódu jsem neudělal ani řádek jinak.

Mam otazku ak zakazem prerusenie, timer bezi dalej? je mozne ze sa nastavi priznak prerusenia a po povoleni prerusenia od timera mi to hned skoci do prerusenia aj ked casovac nepretiekol ?

Ano, presne tak.

Chod timera nijako nesuvisi s aktivaciou prerusenia od neho.
Kazda udalost, ktora moze nastavit priznak prerusenia. Prerusenie sarealizuje, az ked sa povoli prerusenie od periferie. Ak chces udalosti nastavujuce priznak prerusenie pred povolenim prerusenia ignorovat, musis ich pred samotnym prerusenim rucne vynulovat. Pozor, niektore priznaky sa nuluju tak, ze do nich zapises log.1. Je to presne popisane pri tom ktorom bite, treba nastudovat datasheet.

Ok je to tak, dik za potvrdenie a radu.