PCINT Bascom AVR, jak je pogodzić?

PCINT Bascom AVR, jak je pogodzić?
5 (100%) 1 vote

Od pewnego czasu pojawiają się ulepszone wersje µC. Nowa bryza przyniosła też nowe funkcjonalności. Jedną z nich są asynchroniczne przerwania zewnętrzne pod nazwą PCINT. Fajna sprawa gdy µC nie posiada wielu wyprowadzeń z funkcjonalnością INT, ale …

Funkcjonalność PCINT posiada jedynie cechy asynchronicznego przerwania INT, znaczy to – działa tylko przy zmianie stanu z wysokiego na niski i odwrotnie. Zasadniczo w wielu przypadkach będzie to wystarczające a wręcz możliwość zastosowania takiej akcji zbawienna. I fajnie, ale … jak środowisko Bascom AVR wspiera nową funkcjonalność? Doszły jakieś nowe dyrektywy? coś się zmieniło w składni?

Otóż niespecjalnie.

Trochę ględzenia.

Środowisko Bascom AVR samo w sobie umożliwia dokonanie konfiguracji peryferiów µC samodzielnie. Jeśli ktoś posiada stosowną wiedzę i chęć wcale nie musi używać funkcji wbudowanych temu służących.
W temacie tym po trosze jest podobnie. A to dlatego, że sama konfiguracja nowych przerwań µC nie wymaga specjalnych zabiegów. Postępujemy znaną drogą. uczynniamy przerwania globalne (modyfikacja SREG – Status Register), uczynniamy wybrane przerwanie PCINT (modyfikacja GIMSK – General Interrupt Mask Register), i w tym momencie trafiamy na coś nowego 😛
Jeżeli chcemy by przerwanie wyzwalane było jedynie przez zmianę stanu logicznego na wybranym pinie, potrzebny jest dodatkowy zabieg. W przeciwnym razie zmiana stanu dowolnego pinu, przyporządkowanemu wybranemu przerwaniu nie spowoduje dokładnie NIC 😉 . I tak, selekcja aktywnych pinów dla przerwania, polega na ustawieniu odpowiednich wartości w rejestrze PCMSK. Inaczej mówiąc – założeniu maski na wybrane piny. Tym samym przerwanie może być wzbudzane przez większą ilość pinów niż jeden, jeżeli tego oczekujemy. Super funkcjonalność  :mrgreen:

Suche fakty.

Funkcjonalność ciekawa i nie skomplikowana w używaniu. Ale by się nią cieszyć trzeba się trochę napocić. Sytuacja taka występuje ponieważ dane potrzebne do uczynnienia są potraktowane trochę po macoszemu przez producenta, i pochowane w notkach katalogowych. Najczęściej najbardziej wymowny jest rysunek z opisem pinów, jeśli naniesiono przy nim jawnie przyporządkowane znaczniki PCINTx. W przeciwnym wypadku pomocna może być tabela I/O Multiplexing z noty katalogowej wybranego µC.

Skąd taka rozbieżność w podawaniu informacji … licho wie. Powyżej wycinek z nowszej wersji notki katalogowej, a nad nim ze starszej, dla różnych µC. W dodatku ten nowszy wzór wydaje się być niepełny – zawierać niekompletne informacje – brak opisu dla INT1.  😯

Dla nas istotne są informacje:

• µC może posiadać do 3 przerwań PCINTx dla wybranych portów IO, przy czym numerowane są one rosnąco dla kolejnych liter przyporządkowanych portom. Np Port B zasadniczo wyzwala przerwanie PCINT0. W mikrokontrolerach z dużą liczbą wyprowadzeń warto dobrze pozaglądać w czym rzecz by nie popełnić błędu, gdyż kolejne porty nie muszą posiadać omawianej funkcjonalności, w MCU ATmega640/1280/1281/2560/2561 są to porty PB, PJ, PK,
• piny przyporządkowane do danego portu, występować mogą w różnej ilości, zależnie od typu µC, tym samym ilość znaczników w rejestrze PCMSK nie zawsze musi być równa 8,
• znaczniki PCINTy numerowane są globalnie bez względu na przynależność do portu, oczywiście z zachowaniem chronologii. To znaczy, startujemy od liczby zero i od portu oznaczonego literą najbliższą początkowi alfabetu, następnie zwiększamy licznik w miarę zliczania kolejnych pinów portu, przechodząc do kolejnego portu kontynuujemy liczenie dalej itd … W przypadku pinu nie wyprowadzonego fizycznie w porcie, licznik zwiększamy licząc nie występującą pozycję.

Ufff chyba nie zawikłałem. Sytuacja może wydawać się zagmatwana z tytułu identycznego nazewnictwa dla przerwań i znaczników, np przerwanie PCINT0, PCINT1, PCINT2, znacznik PCINT0, PCINT1, PCINT2, PCINT3PCINT22, PCINT23. A wszystko przez Atmel-a  😉

Jeśli będziemy o pamiętać o tych kilku rzeczach, będzie łatwiej i być może unikniemy błędu.
.

PCINT Bascom w praktyce.

Dla zobrazowania, gdy zaglądniemy do pliku definicji dowolnego µC ze środowiska Bascom AVR, zobaczymy w czym rzecz. Ja wybrałem sobie ATtiny13A i dla porównania ATmega328.

powyżej wycinki dla ATtiny13A, plik ATtiny13A.DAT

powyżej wycinki z pliku definicji µC ATmega328, plik M328DEF.DAT.

Podsumowując. Przerwanie PCINT0 może być wzbudzane pinem ze znacznikiem PCINT0…7, obsługuje je rejestr PCMSK0,
Przerwanie PCINT1 może być wzbudzane pinem ze znacznikiem PCINT8…15, obsługuje je wektor PCMSK1,
Przerwanie PCINT2 może być wzbudzane pinem ze znacznikiem PCINT16…23, obsługuje je wektor PCMSK2.
A który to pin i znacznik jest przyporządkowany w którym porcie, to już trzeba sobie sprawdzić indywidualnie, bo w każdym MCU może to być wykonane odmiennie.

W załączonych wycinkach widać, że przerwania zewnętrzne mają najwyższy priorytet  😉 z pośród pozostałych.

Z omówionej funkcjonalności – PCINT Bascom AVR, można korzystać np w poniższy sposób:

powyżej przykładowy sposób deklaracji.

i sposób obsługi przerwania.


Na zakończenie przypomnę – obsługą przerwań PCINT bezpośrednio związane są rejestry:
•  SREG – Status Register,
GIMSK – General Interrupt Mask Register,
GIFR – General Interrupt Flag Register,
PCMSK – Pin Change Mask Register.

Z perspektywy czasu dodać można. iż starsze typy µC mogą nie posiadać rejestru PCMSK. A maskowanie linii IO może występować automatycznie z tytułu uruchomienia innego bloku funkcjonalnego. W związku z czym nie jest dostępne użytkownikowi. Dlatego wykrywanie zmiany stanu na wybranym pinie należy wykonać indywidualnie.


Opis zacząłem tworzyć we wrześniu 2014 (2014-09-10) i stąd taki początek.  :mrgreen: Wycinki kodu pochodzą z forum MCS.

Share Button
Tagi , , , , .Dodaj do zakładek Link.

7 odpowiedzi na „PCINT Bascom AVR, jak je pogodzić?

  1. Nowicjusz mówi:

    Co można zrobić jeżeli przez wykorzystanie pcint0 i podpięcie switcha do masy i wejścia pb0 do Vcc, układ z fragmentem kodu jak poniżej po każdorazowym pobudzeniu switcha dolicza dodatkowe wartości (więcej jak jedna dla każdej zmiany stanu switcha) do zmiennej „liczba”? Dodam, że próbowałem dodać bezskutecznie kondensator przeciwzakłóceniowy do wejścia pb0. Dodatkowo w układzie wykorzystuję PWM i ADC (wszystko na płytce testowej i pajęczynce).

    On Pcint0 Przeplyw
    Enable Pcint0

    Enable Interrupts
    Pcmsk0 = &B00000001

    Przeplyw:
    Liczba = Liczba + 1
    Return

    • kaktus mówi:

      Kondensatorek blokujący daj, niech pracuje. Atmel zaleca dodatkowy rezystor szeregowy ograniczający prąd przy zwarciu switcha. Nie rozwiąże on problemu ale zrobi dobrze µC.
      Problem może być ze zbyt częstym wywołaniem przerwania, a niżeli byś się spodziewał. Piszesz „po każdorazowym pobudzeniu switcha dolicza dodatkowe wartości (więcej jak jedna dla każdej zmiany stanu switcha) do zmiennej „liczba””, więc zapytam kiedy wystąpi wyzwolenie przerwania? ;-D
      W opisie jasno to przedstawiłem :-p

  2. Nowicjusz mówi:

    No właśnie, nawet jeżeli tylko raz przyciśnie się switcha i puści, to powinien naliczyć dwa, a nalicza różnie nawet do kilkudziesięciu.

  3. Nowicjusz mówi:

    Już jest ok. Nie było dostatecznie dobrze eliminowane drganie styków. W celu sprawdzenia dopisałem fragment kodu który cyklicznie zmieniał stan wyjścia uC i ten sygnał podałem przez opór do interesującego mnie PCINTa. Dzięki temu wyeliminowałem drganie styków i tak oto mogę się cieszyć kolejnymi zewnętrznymi przerwaniami w procku. Szkoda tylko że PCINT reaguje na zmianę stanu.

    Pozdrawiam i dzięki za naprowadzenie.

    • kaktus mówi:

      Jak to się mówi experience rośnie ;-D
      Dla mnie zaletą jest, że mogę dowolnie oprogramować czy program ma reagować na wystąpienie stanu niskiego czy też wysokiego.

  4. Nowicjusz mówi:

    Od biedy można zrobić reakcję na zbocze opadające lub narastające. Z tym że trzeba kilka linijek dopisać. Ale dzięki za podpowiedź.

    W celu reakcji na stan dołożyłem warunek w przerwaniu:

    if pin.x=0/1 then
    ….

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

one × 4 =