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.
Przerwania generowane programowo w AVRach
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.
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.
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:
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.
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:
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.
- Aro
- Użytkownik
- Posty: 677
- Rejestracja: 30 paź 2006, 18:49
- Lokalizacja: Świerczyniec | Wrocław
- Kontakt:
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:)
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:)
Pewnie się Wam przyda więc rozwiązanie jest takie (oczywiście w WinAvr).
Zakładam że mamy taki przerwanie:
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
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ć.
Zakładam że mamy taki przerwanie:
Kod: Zaznacz cały
ISR(TIMER0_OVF_vect)
{
PORTB=cykl++;
/*coś tam jeszcze....*/
}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:
No i super
. Gratuluję zawzięcia
.
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
.
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
- Aro
- Użytkownik
- Posty: 677
- Rejestracja: 30 paź 2006, 18:49
- Lokalizacja: Świerczyniec | Wrocław
- Kontakt:
Heh, najciemniej pod latarniąslawek55 pisze:Kod: Zaznacz cały
TIMER0_OVF_vect();