Zdravím,
Chtěl jsem si vyzkoušet výrobu a programování a vrhnul jsem se do výroby palubního počítače do auta (na internetu jsem našel již pár řešení, ale chtěl jsem si to zkusit sám). Bohužel se mi nedaří dodělat poslední část programu, část pracující s přerušením. Chápu jak na to teoreticky, ale nedaří se mi přijít na to, jak to napsat ideálně.
Proto jsem se chtěl zeptat, zda by mi někdo nemohl poradit s touto částí programu,aby byla efektivní.
Teď se pokusím nastínit, o co jsem se marně snažil.
Používám procesor Atmega32 a programuji v AVRku v Cčku.
Můj problém se týká dvou signálů, které přivádím na porty procesoru:
Na port INT0 přijde signál (hardwarově je jedno, jestli 1 nebo nula, takže co se hodí do programu) a po dobu, co je přiveden signál, počítá Timer1 (tím změřím délku pulsu které se rovná spotřebě paliva za určitou dobu) a po konci pulsu přičte svůj obsah k proměnné PAL1.
Jestliže je přiveden signál na INT1 je přičtena jednička (inkrementováno) do VZD1.
S tímto jediným si tak nějak asi tuším rady, že by to mohlo vypadat:
Nastavím vektor přerušení aby reagoval na signál na tento port a když dojde k přerušení, přičtu do registru a je hotovo.
Bohužel nevím, jak to v praxi napsat.
Pak jsem chtěl použít ještě jeden timer (Timer2), který počítá a odpočítává čas, třeba vteřinu, a vždy, když dopočítá vteřinu, tak dojde k zapsání proměnných VZD1 a PAL1 do proměnných VZDALENOST a PALIVO a vymazání proměnných VZD1 a PAL1.
Za pomoc bych byl moc vděčný, už 14 dní s tím nemůžu hnout a v mém okolí není nikdo, na koho se obrátil. Jsem na tohle nějaký zabedněný.
Fórum › Mikrokontroléry
AVR přerušení program
to pocitani delky timerem se da zmaknout pomoci externiho povoleni citace... proste si ho nainicializujes na nulu a pak kdyz prijde log1 tak bude automaticky pocitat takty ... po skonceni pulsu se vygeneruje preruseni ... trochu prostuduj mody citace...
druhe je taky snadne... nastavis automaticky restart citace po urcitem poctu taktu... nejlepe treba po 1s idealni je na to 16b citac s dobre nastavenou preddelickou...
nastavis mu pak treba se ma vyresetovat po napocitani dejme tomu 25000 a pri tom vyvola preruseni... (zalezi na frekvenci krystalu, nastaveni preddelicky a tak)
To KIIV :
Dobrý den,
Používám atmega8 a chci se zeptat jsetli by to takhle bylo možný - meření doby vtřiku - připojené na INT0
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <avr/interrupt.h>
// externí přerušení INT0
ISR (INT0_vect)
{
TCCR1B=0x00; //zastavení čítače/časovače 1 = zastavení času
pal1 = TCNT1L;
pal1 |= (TCNT1H<<8);
palivo += pal1;
TCNT1H = 0;
TCNT1H = 1; //nulování čítače/časovače 1
}
unsigned char palivo = 0, pal1=0;
int main(void)
{
GICR|=0x40; // nastaveni přerušeni od INT0
MCUCR=0x02; // přerušení na INT0 - sestupnou hranou impulzu
GIFR=0x40; // nastaveni příznaku INT0 - přesně nevim k čemu se použivají příznaky?
TIMSK=0x20; // povolení přerušení pro čítač/časovač1
DDRD = (1<<PD2);
PORTD = 0;
sei(); // globalní povolení přeručení
while(1){
if((PORTD & 0x02)==1)
TCCR1B=0x05; //spouštění čítače/časovače 1, nastavení na 7 813 Hz, předdělička 1024
//zde už jenom vypis "palivo" na lcd
}
}
Doufám, že by to takhle nějak mohlo fungovat jen si vubec nevim rady jak to udělat aby se proměnná "palivo" každou vteřinu smazala. Děkuju
chce to napriklad vyvolat kazdou vterinu preruseni.. pouziva se rezim citace, kdy je napojenej na hodiny krystalu a ma nastavenou hodnotu, pri ktere se vynuluje a zaroven vyvola preruseni.. kdyz nastavis spravnou hodnotu na reset citace, tak to bude prave po jedne vterine
To KIIV :
nejmenuje se to? "Watchdog Timer" nebo mám použít klasickej čítač a při na čitaní určité hodnoty se vyvola přerušení - ale k dispozici bych měl už jenom 8bit čitač např. pomocí vektoru ISR(TIMER2_COMP_vect
To ADAM : muzes nastavit i mensi hodnotu a pripocitavat si k promenne .. a pokud dosahnes urcite hodnoty tak vynulovat + vynulovat i tu promennou
watchdog se neda pouzit na presne casovani ..
zalezi uz na tobe jak presne to potrebujes..
dejme tomu 8MHz na 10kHz .. to je perioda 125ns a 10kHz je perioda 0,1ms to je delici pomer 800
takze dejme tomu das preddelicku na :8 a opakovani po 100 cyklech citace... ( nebo 50 a :16 nebo 25 a deleni 32)
V tvojom SW je nevhodne nastaveny GIFR. Po tomto zapise a vykonani funkcie sei() je ihned vyvolane prerusenie.Tento register sa nenastavuje a sluzi len HW procesora,ktory si takto "pamätá" požiadavku na prerušenie.
V prerušení máš zastavený Timer a nasledne pravdepodobne mal byť znulovaný,len neviem,prečo potom TCNT1H=1?Následne ho potom nemáš nikde spustený.
Watchdog slúži najčastejšie k tomu,aby "zablúdený" program zresetoval MCU.Niekedy sa dá využiť aj inak,ale to je trošku o inom.
je tam nutný psát sei(); globální přerušení, když ho tam dám tak mi to spousti program pořád od začátku
sei() je jistě nutné, pokud chceš používat nějaké přerušení.
Program ti spouští stále od začátku proto, že máš povolené přerušení od zachycení u timer1
TIMSK = 0x20;
a nemáš pro ně napsanou obsluhu.
Jinak, při všem respektu, tvůj program je jeden velký zmatek, který tak jak je ani nejde zkompilovat,
protože ukazuje 5 chyb.
Chtělo by to nastudovat přerušení a čítače.
To Adam : Da sa povedat, ze AB ma pravdu.pokial chces pouzivat prerusenia,musis si riadne nastudovat,ako to cele funguje.pokial ten tvoj vypis je cely program,tak to nebude fungovat z dovodu, ktore ti napisal AB,ja som to neskusal skompilovat.
Pre kazde prerusenie,ktore povolis MUSI byt napisana prerusovacia rutina,inak ti program zhavaruje.Vyznam flagov som ti uz popisal,ale nastuduj si, ako funguju prerusenia v globale.
ked chces pouzit casovac,musis ho nastavit a spustit.Ked ma vyvolat prerusenie,tak musi mat rutinu prerusenia.V programe pracujes s Timer1,ale nikde nie je nastaveny. Citace/Casovace mozu fungovat v niekolkych rezimoch.
To Adam: Myslím, že jednoduchšie je to urobiť bez prerušenia.
Asi takto:
int main(void)
{
TCCR1B=0x05; //spouštění čítače/časovače 1, nastavení na 7 813 Hz, předdělička 1024
while(1){
while((PIND & (1<<PD2))==0); //ak PIND2 je 0, čakaj
TCNT1=0; //nulování čítače/časovače 1
while((PIND & (1<<PD2))==1); //ak PIND2 je 1, čakaj
pal1=TCNT1; //uloženie 16-bitovej hodnoty čítača do pal1
palivo += pal1;
//zde už jenom vypis "palivo" na lcd
}
}
Ahoj, chtěl bych se podělit o svůj výtvor s ATmega32 a Nokia displejem:
http://jedla.kx.cz/auto/palubni_pocitac/palubak.php
Ještě mimo to, vteřina (přesná) je docela těžká na vygenerování (pokud se nepoužije delay(1000) :-D). ;) OT: Dá se udělat finta, dle počítání počtu přerušení.
Přidej příspěvek
Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku
×Vložení zdrojáku
×Vložení obrázku
×Vložení videa
Uživatelé prohlížející si toto vlákno
Podobná vlákna
AVR Ledky program — založil Alfonz
Program pro AVR — založil Ravien
AVR Toolchain 3.3.0 + AVR studio + ATTiny26 - mala rada — založil xhans69
Přerušení u MCP23S17 — založil Tonda
Raspberry Pi a hw preruseni — založil svoby1
Moderátoři diskuze