INT0 někdy nezareaguje

Dotazy na technické problémy, vlastní řešení technických problémů

Moderátor: Moderátoři

Zpráva
Autor
Uživatelský avatar
TommyNET
Příspěvky: 13
Registrován: 10 říj 2012, 00:00

INT0 někdy nezareaguje

#1 Příspěvek od TommyNET »

Zdravím,
mám problél s ATMEGA88 která běží na 20MHz s napětím 5V. Stavím řízení předstihu zapalování na motorku a na pinu INT0 zachytávám imlulzy od kliky. Vyskytl se mi problém v tom že občas INT0 nezareaguje, nespustí interrupt a to tak jednou za cca 20 pulzů.

Hodil jsem jí tedy na bastlící destičku a zapojil tak že na INT0 mám tlačítko a pullup rezistor 4k7. + mám připojenou na PC3 diodu aby bylo jasně vidět jak se to chová. Interrupt je nastaven tak aby reagoval jak na náběžnou tak sestupnou hranu.

Kód: Vybrat vše

ISR (INT0_vect)
{
   PORTC=!PORTC;
}
int MAIN (void)
{
   while(1)
   {
      ;
   }
}


Stimhle kódem by to mělo teoreticky při stisku tlačítka rozsvítit a při puštění zhasnout. Problém je v tom, že mačkám a funguje, jenomže jednou za pár stisknutí to na jednu hranu nezareaguje, interupt se nespustí a celé se to otočí. Při zmáčknutí dioda zhasne, při puštění se rozsvítí. A zase furt do kola... Prostě jednou za čas to na nějakou hranu nezareaguje. Setkal už se s tím někdo?

Díky za jakoukoli radu.
Uživatelský avatar
ZdenekHQ
Významný člen
Příspěvky: 25519
Registrován: 21 črc 2006, 00:00
Bydliště: skoro Brno
Kontaktovat uživatele:

#2 Příspěvek od ZdenekHQ »

Zákmity kratší než délka běhu přerušení.
Pro moje oslovení klidně použijte jméno Zdeněk
Správně navržené zapojení je jako recept na dobré jídlo.
Můžete vynechat půlku ingrediencí, nebo přidat jiné,
ale jste si jistí, že vám to bude chutnat[?
]
Uživatelský avatar
TommyNET
Příspěvky: 13
Registrován: 10 říj 2012, 00:00

#3 Příspěvek od TommyNET »

včéra jsem to měl na generátoru, pouštěl jsem do toho obedníkovej signál a vstup i výstup snímal na osciloskopu. Ten samý problém.

Ty zákmity by nevyřešilo třeba smazat flagy těsně před opuštěním přerušení?
Uživatelský avatar
Crifodo
Příspěvky: 14779
Registrován: 11 říj 2005, 00:00

#4 Příspěvek od Crifodo »

a zakážeš přerušení hned po jeho vyvolání a povolíš po návratu z obslužného podprogramu?
Informace o poloze kliky snímáš nejspíš opticky, takže problém zákmitů se tím eliminuje dřív než by vznikl?
Uživatelský avatar
TommyNET
Příspěvky: 13
Registrován: 10 říj 2012, 00:00

#5 Příspěvek od TommyNET »

to: Crifodo
takle nejak si to myslel?

Kód: Vybrat vše

ISR (INT0_vect)
{
   EIMSK=0x00;        //maskovani externiho preruseni
   PORTC=!PORTC;   //LED ON/OFF
}
int MAIN (void)
{
   while(1)
   {
      if(EIMSK==0x00)
      {
         EIFR=0x01;      //smaze flag preruseni
         EIMSK=0x01;   //odmaskovani preruseni
      }
   }
}

furt to samé...
Uživatelský avatar
ZdenekHQ
Významný člen
Příspěvky: 25519
Registrován: 21 črc 2006, 00:00
Bydliště: skoro Brno
Kontaktovat uživatele:

#6 Příspěvek od ZdenekHQ »

Dej do toho testu dvě či tři podmínky na stálost stavu na vstupu vzdálený od sebe "vhodnou dobu" - to musíš posoudit sám. Pokud kontrola neprojde, nereaguj a vrať se z přerušení.
Pro moje oslovení klidně použijte jméno Zdeněk
Správně navržené zapojení je jako recept na dobré jídlo.
Můžete vynechat půlku ingrediencí, nebo přidat jiné,
ale jste si jistí, že vám to bude chutnat[?
]
Uživatelský avatar
frpr666
Příspěvky: 1051
Registrován: 28 pro 2009, 00:00

#7 Příspěvek od frpr666 »

RE: Setkal už se s tím někdo?

Přesně tak, zákmity na tlačítku. Google images: contact bouncing
Při 20MHz je na jednu instrukci 0.05us, takže CPU je strašně rychlé a zachytí i jehlové impulsy.
Řešení
1/ po INT0 přerušení od INT0 zakaž např. na 1ms a pak zase povol. Tím potlačíš "falešné" spínání.
2/ na vstup přidej RC filtr, který špičky "odfiltruje"

edit1: neodzkoušeno

Kód: Vybrat vše

ISR (INT0_vect)
{
   EIMSK=0x00;        //maskovani externiho preruseni
   PORTC=!PORTC;   //LED ON/OFF
 
  // start timer, prescaler 1024, clear TOV flag
  TCNT0 = 0;
  TCCR0B = _BV(CS02)|_BV(CS00);
  TIFR0 = _BV(TOV0);
}
int MAIN (void)
{
   while(1)
   {
      if(bit_is_set(TIFR0,TOV0))
      {
         EIFR=0x01;      //smaze flag preruseni
         EIMSK=0x01;   //odmaskovani preruseni

        TCCR0B = 0x00;  // stop timer
        TIFR0 = _BV(TOV0); // clear flag
      }
   }
}
Uživatelský avatar
TommyNET
Příspěvky: 13
Registrován: 10 říj 2012, 00:00

#8 Příspěvek od TommyNET »

Děkuju moc všem za pomoct.
Udělal jsem to nakonec tak že když přijde přerušení tak ho maskou zakážu a povolím až dál v programu. Příští týden to zajdu přeměřit do laboratoře.

Jen se chci informovat jak to je když maskou zakážu a pak povolím přerušení. Smaže se flag nebo ne? Jde o to aby mi nezustal vyset flag a až přerušení povolím tak aby se hned nevyvolalo přerušení. Já totiž pořádně nevím jak ho smazat a to jak sem to dělal asi moc nefunguje.
Uživatelský avatar
ZdenekHQ
Významný člen
Příspěvky: 25519
Registrován: 21 črc 2006, 00:00
Bydliště: skoro Brno
Kontaktovat uživatele:

#9 Příspěvek od ZdenekHQ »

Nesmaže, ale nemůžu to říct univerzálně. Najdi si registr s příznaky přerušení. Smaže se jen po vyvolání přerušení.
Pro moje oslovení klidně použijte jméno Zdeněk
Správně navržené zapojení je jako recept na dobré jídlo.
Můžete vynechat půlku ingrediencí, nebo přidat jiné,
ale jste si jistí, že vám to bude chutnat[?
]
Uživatelský avatar
TommyNET
Příspěvky: 13
Registrován: 10 říj 2012, 00:00

#10 Příspěvek od TommyNET »

"Alternatively, the flag can be cleared by writing a logical one to it."

Takže podle tohodle co jsem našel v datasheetu tak flag se smaže pokud na příslušný bit uložím jedničku.
EIFR=0x01
Uživatelský avatar
Celeron
Příspěvky: 20508
Registrován: 02 dub 2011, 00:00
Bydliště: Nový Bydžov

#11 Příspěvek od Celeron »

Nematla se Ti tam do toho naky dalsi preruseni od neceho jinyho a nebo nemas tam nejaky zretezeni preruseni? At Megu skoro neznam, ale u regulaci s 8051 jsem si s tim uzil svy, hlave kdyz se pouzivalo preruseni od vice zarizeni (casovac, seriova lajna, prevodnik...)
Jirka
Uživatelský avatar
ZdenekHQ
Významný člen
Příspěvky: 25519
Registrován: 21 črc 2006, 00:00
Bydliště: skoro Brno
Kontaktovat uživatele:

#12 Příspěvek od ZdenekHQ »

TommyNET píše:Takže podle tohodle co jsem našel v datasheetu tak flag se smaže pokud na příslušný bit uložím jedničku.
EIFR=0x01


Jasně, že to jde smazat "ručně", stejně jako nastavit. Taky to někdy preventivně používám, aby se mě přerušení nezavolalo znovu hned po návratu. Jen si nejsem jistý tou jedničkou, ale je to u megy klidně možný.
Pro moje oslovení klidně použijte jméno Zdeněk
Správně navržené zapojení je jako recept na dobré jídlo.
Můžete vynechat půlku ingrediencí, nebo přidat jiné,
ale jste si jistí, že vám to bude chutnat[?
]
Uživatelský avatar
TommyNET
Příspěvky: 13
Registrován: 10 říj 2012, 00:00

#13 Příspěvek od TommyNET »

Celeron píše:Nematla se Ti tam do toho naky dalsi preruseni od neceho jinyho a nebo nemas tam nejaky zretezeni preruseni? At Megu skoro neznam, ale u regulaci s 8051 jsem si s tim uzil svy, hlave kdyz se pouzivalo preruseni od vice zarizeni (casovac, seriova lajna, prevodnik...)
Jirka


Samozřejsmě že v celém programu mám ještě jedno přerušení a to od čítače když přeteče, ale mám nastaveno nepřerušitelné přerušení takže si musí počkat až to běžící se dokončí a pak může začít teprve to další v pořadí. I tak jsou obě přerušení směšně krátká vzhedem k tomu jak často se spouštějí. Takže nehrozí nějaký kolaps.

Problém bude asi opravdu nějaký ten zákmit na INT0. Po odskoku do přerušení ho teda zakážu po chvilce smažu flag a povolím. Teď už to musím jen otestovat.
Uživatelský avatar
piitr
Příspěvky: 1003
Registrován: 19 říj 2007, 00:00
Kontaktovat uživatele:

#14 Příspěvek od piitr »

Kdybych to řešil já, tak v obslužné rutině udělám:
1) Smažu příznak přerušení, takže jakákoliv změna na vstupu od tohoto momentu mi po ukončení tohoto přerušení vyvolá hned nové a dozvím se o ní.
2) Načtu hodnotu na sledovaném vstupu. To musím udělat až po smazání příznaku v bodě 1. Kdybych to udělal obráceně, tak mi některé změny mohou utéct.
3) Zpracuji načtenou hodnotu. Typicky ji porovnám s poslední schovanou od minule, a pokud se liší (tj. je změna), něco udělám.
4) Povolím přerušení a ukončím obslužnou rutinu. Typicky jednou instrukcí, aby se mi přerušovací rutiny nevnořovaly do sebe. Bývá na to instrukce "iret", "retfie", "rti", atd. Nevím, co máš ty.
Uživatelský avatar
Atlan
Příspěvky: 4514
Registrován: 10 kvě 2004, 00:00
Bydliště: Košice

#15 Příspěvek od Atlan »

No rad by som videl aj schemu lebo stavba zapalovania nieje len o softe ale aj o schmeme a prevedeni dps.
Odpovědět

Zpět na „Poradna“