Przerwania generowane programowo w AVRach

To forum jest dla wszystkich pasjonatów mikrokontrolerów AVR Atmela. Wymiana doświadczeń i pomoc dla początkujących w pisaniu programów zarówno w C, Asemblerze jak i BASCOM. Zapraszam znawców tematu, aby pomogli wszystkim początkującym!
Awatar użytkownika
kayron
Użytkownik
Posty: 2088
Rejestracja: 21 wrz 2008, 12:53
Lokalizacja: Poland
Kontakt:

Post autor: kayron » 22 lip 2011, 16:41

Ostatecznie na 8-bitowcach to do pisania systemu operacyjnego bardzo wdzięczna jest stara dobra 8051, bo można sobie odpalać soft z RAMu, a nowsze odmiany dysponują szybszymi rdzeniami. Na takim DS89C430 wszczepionym do AVT2250 mogło by to nieźle śmigać, tylko trzeba by zrobić nową PCB do wyświetlacza graficznego i klawiatury, zamiast oryginalnej z wyświetlaczem LED.
W sumie ciekawy pomysł, gdyby tylko AVT2250 nie kosztowało tyle można by się pokusić, no chyba że avt sklep na specjalną prośbę byłby w stanie sprzedać tylko PCB płyty głównej, wtedy sam bym się zainteresował, bo akurat parę 51 mi leży, i to z udoskonalonymi rdzeniami tak od MAXIMA jak i ATmela.

slawek55
Użytkownik
Posty: 475
Rejestracja: 16 sie 2005, 11:47
Lokalizacja: Szczecin

Post autor: slawek55 » 22 lip 2011, 18:20

Odpowiadam po co mi to.
Mam (na razie chęć) podłączyć do wejścia INT0 (lub 1) wejście z czujnika krańcowego. Jak nastąpi warunek (dokładnie jest to dojście mechanizmu do końca lub początku) układ ma natychmiast to wyłączyć i oprócz tego wykonać kilka innych poleceń. Jest to jakby taka procedura stopu.
Dlatego chciałem móc ją wywołać jeszcze z innego miejsca niż przerwanie INTx np po odebraniu znaku z UART.
Mam na to pewne rozwiązanie, ale nie jest wg mnie to eleganckie. Myślałem aby całość umieścić w jakiejś funkcji i w przerwaniu ją tylko wywołać. Ale.... się pojawia.
Jeśli nastąpi faktyczne przerwanie to funkcja jakby zostanie wywołana podwójnie, tzn. może być wykonywana np z związku z poleceniem z portu szeregowego a w tym czasie może zdarzyć się przerwanie. Nie może tak być i by nie było jakby przerwanie mogło być wywoływane właśnie jako przerwanie.
Z tym że teraz to zrobiła się już raczej też kwestia zaspokojenie ciekawości czy w ogóle jest taka możliwość w AVRach.

Awatar użytkownika
kayron
Użytkownik
Posty: 2088
Rejestracja: 21 wrz 2008, 12:53
Lokalizacja: Poland
Kontakt:

Post autor: kayron » 22 lip 2011, 19:16

Akurat nie wiem czy użycie wejścia INTx jest dobrym pomysłem do podłączenia krańcówki.
Po pierwsze drgania zestyków i zakłócenia indukujące sie w przewodzie, mogą ci dawać fałszywe impulsy, które ci wyzwolą układ. No i napięcie na krancówce, jeżeli to maszyna, to pewnie jest tam 24V, więc musiałbyś izolować takie wejście, np. TAK:
Obrazek
Lepsze AVRy np. ATMega 164 mają praktycznie możliwość zgłaszania przerwań no dowolnym pinie CPU, bo mają sygnały PCINTx, na każdym porcie.
Twój pomysł, nie jest tak do końca dobry, bo przerwanie zawsze beędzie miało wyższy priorytet wykonania niż wywołana programowo funkcja, nawet jeżeli będzie to ta sama, chyba że wyłączysz przerwania, na czas wywołania programowego. Ale ogólnie jest to ryzykowne podejście, bo program może wpaść w reakcje łańcuchowej obsługi tak przerwań sprzętowych jak i wywoływanych programowo, przepełnić stos i się zwiesić, lub po prostu coś przeoczyć.
Ale lepiej zrobić to strikte programowo, czyli w przerwaniach od timera sprawdzać sobie krańcówkę np. 200x/ sek. i jak jest sygnał to np, za 10-20ms (jeżeli ten czas oczywiście nie jest krytyczny), znowu sobie sprawdzić czy nadal jest, aby odkłucić taki styk.

Awatar użytkownika
Aro
Użytkownik
Posty: 677
Rejestracja: 30 paź 2006, 18:49
Lokalizacja: Świerczyniec | Wrocław
Kontakt:

Post autor: Aro » 22 lip 2011, 20:08

Myślę, że dodatkowa funkcja wywoływana w przerwaniu jest najbardziej eleganckim rozwiązaniem. Zaraz po wejściu do funkcji trzeba tylko zablokować przerwania tak jak pisze kayron. A jeszcze lepiej zaraz przed wejściem do funkcji. Wtedy nie będzie problemu z podwójnym wywołaniem.
Natomiast jeżeli koniecznie chcesz to mieć w przerwaniu to spróbuj skoczyć pod adres przerwania jak do normalnej funkcji poleceniem call. Oczywiście skok należy wykonać pod adres wektora przerwań. Jedyna różnica jest tak, że przy wyjściu z funkcji używa się instrukcji ret, natomiast z przerwania reti. Trzeba więc będzie dopisać krótki warunek, który sprawdzi czy zaszło przerwanie czy zwykłe wywołanie. Nie wiem czy da się to bezpośrednio sprawdzić, jeśli nie, to można wykorzystać np. flagę T do takiej sygnalizacji.
Ciekawe czy kompilator strawi coś takiego:)

slawek55
Użytkownik
Posty: 475
Rejestracja: 16 sie 2005, 11:47
Lokalizacja: Szczecin

Post autor: slawek55 » 23 lip 2011, 9:38

Pewnie się Wam przyda więc rozwiązanie jest takie (oczywiście w WinAvr).

Zakładam że mamy taki przerwanie:

Kod: Zaznacz cały

ISR(TIMER0_OVF_vect)
{
PORTB=cykl++;
/*coś tam jeszcze....*/
}
A teraz w gdzieś w programie potrzebujemy to wywołać niezależnie od sprzętowego przerwania, w tym przypadku od przepełnienia licznika.

Piszemy tak jak wywołanie zwykłej funkcji, czyli

Kod: Zaznacz cały

TIMER0_OVF_vect();

Jeśli nie chcemy, aby to co wywołamy nałożyło się na "normalne" przerwanie należy zablokować przerwania poleceniem cli(); (odblokować nie trzeba bo zakończenie samo spowoduje odblokowanie przerwań).


P.S. Może to nie odkrycie ameryki, ale satysfakcja wiedzy jak to zrobić.

rezasurmar
Użytkownik
Posty: 626
Rejestracja: 19 kwie 2009, 15:59
Lokalizacja: Tychy
Kontakt:

Post autor: rezasurmar » 23 lip 2011, 14:12

No i super :D. Gratuluję zawzięcia :D.
Sam ostatnio jestem zajęty projektem w podobnym stylu jak tu http://www.eevblog.com/2011/05/31/eevbl ... ect-sagan/

Przez co nie zawsze mam czas, siły i chęci na coś innego ;).

Awatar użytkownika
Aro
Użytkownik
Posty: 677
Rejestracja: 30 paź 2006, 18:49
Lokalizacja: Świerczyniec | Wrocław
Kontakt:

Post autor: Aro » 23 lip 2011, 14:31

slawek55 pisze:

Kod: Zaznacz cały

TIMER0_OVF_vect();
Heh, najciemniej pod latarnią :grin:

ODPOWIEDZ