W artykule opiszę podstawy sterowania pinami w mikrokontrolerach 32-bitowych firmy Microchip . W szczególności skupię się na PC32MM0256GPM048 czyli moim ulubionym obecnie mikrokontrolerem 32-bitowym. Opisywałem już te zagadnienia przy okazji zabaw z PIC24 , wiele rzeczy będzie wspólnych. Migracja z 8 czy 16 bitów na 32-bity w produktach Microchipa jest bardzo płynna i to jest ogromna zaleta ekosystemu PIC. Stanowi to bardzo duże ułatwienie w szczególności dla hobbystów. Mikrokontrolery PIC32 są znacznie prostsze w poznaniu niż np. ARM-y.
Najważniejsze rejestry służące do konfiguracji portów wejścia/wyjścia w mikrokontrolerach PIC32 to:
- TRISx - ustawia port jako wejście lub wyjście
- PORTx - odczyt/zapis faktycznej wartości portu
- LATx - rejestr zatrzaskowy portu (zapis ostatniej wartości portu lub odczyt zapisanej wartości)
- ODCx - ustawia piny wyjściowe jako zwykłe piny lub z otwartym drenem
- ANSELx - umożliwia odłączenie niektórych pinów od sekcji analogowej, tam gdzie jest to wymagane. A to czy jest to wymagane na konkretnym pinie czy nie dowiemy się z tego rejestru :)
Konfiguracja portów jako wejścia lub wyjścia
Każdy
port (port to zbiór pojedynczych pinów), posiada swój rejestr
TRISx, który odpowiada za ustawienie czy określone piny są
wejściem czy wyjściem. Jeżeli do bitu powiązanego z określonym
pinem jest zapisane "1" pin jest wejściem, natomiast
jeżeli zapiszemy "0", wybrany pin staje się wyjściem.
To jest dokładnie odwrotnie niż w AVR-ach.
Port
TRISx może być również oczywiście odczytany, dostaniemy
wtedy ostatnio zapisaną tam wartość.
Po włączeniu zasilania,
wszystkie piny są skonfigurowane jako wejścia.!!
Zapis/odczyt wartości portu
Jeśli chodzi o zapis i
odczyt portów wejścia/wyjścia mamy do dyspozycji dwa rejestry
PORTx oraz LATx. Odczytując rejestr PORTx,
odczytujemy bezpośrednio wartość logiczną panującą na pinach
portów danej chwili, zapisując do tego rejestru zmieniamy bezpośrednio wartości
pinów portu.
Zapis do rejestru PORTx powoduje również
zapis do odpowiadającego mu rejestru LATx.
Rejestr LATx,
można odczytywać jakby był to zwykły rejestr, w którym jest
duplikat ostatnio zapisanej wartości do portu, zapis do LATx
powoduje zmianę stanów na pinach portu, tak samo jak zapis do
rejestru PORTx, ale odczyt z tego rejestru jest odporny na
zakłócenia na liniach portu, bo nie jest fizycznie podczas tej
operacji czytany port, tylko jego rejestr, to znaczy, że nie możemy
odczytać napięcia panującego faktycznie na pinie, jedynie wartość
jaką ostatnio zapisaliśmy.
Podsumowując:
- Zapis do portu możemy dokonywać przez zapis do PORTx lub LATx
- Odczyt wartości z końcówek portu dokonujemy przez odczyt PORTx
- Odczyt ostatnio zapisanej wartości do portu, dokonujemy
przez odczyt rejestru LATx
- jeśli chcemy uzyskać podwyższoną odporność na zakłócenia zapis i odczyt realizujmy za pomocą rejestru LATx .
Konfiguracja portów jako cyfrowe lub analogowe
Wszystkie
porty które mogą być wejściami analogowymi domyślnie nimi są,
ponieważ rejestr ANSELx, który odpowiada za to
ustawienie, domyślnie ma zapisaną wartość 0xFFFF.
Jeżeli chcemy używać portów analogowych np. z cyfrowymi peryferiami,
takimi jak Timery czy UART, musimy ustawić je jako cyfrowe przez wyzerowanie określonych bitów rejestru ANSELx,
dodatkowo kiedy porty są ustawione jako analogowe wejścia, próba
odczytania ich wartości przez rejestr PORTx skończy się
pobraniem samych zer, tak jakby na pinach panował logiczny stan 0.
W przypadku mikrokontrolera PIC32MM0256GPM048 piny analogowe , które wymagają odłączenia od sekcji analogowej jeśli chcemy je używać jako np wyjścia cyfrowe są oznaczone w datasheet jako ANx :
Z pliku nagłówkowego dla PIC32MM0256GPM048, p32mm0256gpm048.h wynika, że piny podpięte do sekcji analogowej to :
Na porcie A : RA0,RA1,RA2,RA3
Na porcie B :RB0,RB1,RB2,RB3,RB4
Na porcie C :RC0,RC1,RC5,RC8
i tu UWAGA !!! jest jak sądze błąd/niedopatrzenie Microchipa ponieważ w pliku nagłówkowym nie uwzględniono np pinów RA6,RB13,RB14 i RB15
A poniżej podaję adekwatne nazwy bitów w rejestrze ANSELx uwzględnione w pliku nagłówkowym (bez RA6,RB13,RB14 i RB15) , potem w przykładzie pokażę jak tego używać.
RA0 --> ANSA0
RA1 --> ANSA1
RA2 --> ANSA2
RA3 --> ANSA3
RB0 --> ANSB0
RB1 --> ANSB1
RB2 --> ANSB2
RB3 --> ANSB3
RB4 --> ANSB4
RC0 --> ANSC0
RC1 --> ANSC1
RC5 --> ANSC5
RC8 --> ANSC8
Do rejestrów możemy zapisywać całe wartości portów, lub
odwoływać się do indywidualnych pinów. Do dyspozycji mamy wygodne
makra i struktury zdefiniowane w pliku nagłówkowym naszego
mikrokontrolera . Plik znajduje się w katalogu kompilatora XC32. W
przypadku Linuxa jest dostępny pod ścieżką :
/opt/microchip/xc32/v2.05/pic32mx/include/proc/p32mm0256gpm048.h
W programie nie musimy jednak pamietać nazwy pliku nagłówkowego , includujemy magiczny skrót xc.h i już mamy dostęp do naszego pliku.
Przykłady :
Ustawiamy kierunek czyli wejście lub wyjście za pomocą rejestru TRISx :
TRISA = 0x001F ;// ustawiamy 5 pierwszych bitów rejestru na 1 czyli pięć pierwszych pinów portu A będzie wejściami
TRISA = 0x0000;// ustawiamy wszystkie bity rejestru na 0 czyli wszystkie piny portu A są wyjściami
za pomocą zdefiniowanych struktur :
TRISAbits.TRISA1 = 1 ; // ustaw drugi bit rejestru na 1 czyli na pinie RA1 mamy wejście
TRISAbits.TRISA1 = 0 ; // ustaw drugi bit rejestru na 0 czyli na pinie RA1 mamy wyjście.
Ustawiamy stan na wyjściach za pomocą rejestru PORTx :
PORTA = 0x001F ; // ustawiamy 5 pierwszych bitów rejestru na 1 czyli na pięciu pierwszych pinach portu A mamy stan wysoki
PORTA
= 0x0000 ; //
ustawiamy bity
rejestru na 0
czyli na wszystkich
pinach
portu A mamy stan
niski
za pomocą zdefiniowanych struktur :
PORTAbits.RA1 = 1 ; // ustaw drugi bit rejestru na 1 czyli na pinie RA1 mamy stan wysoki
PORTAbits.RA1
= 0 ; // ustaw drugi bit rejestru na 0 czyli na
pinie RA1 mamy
stan niski.
Możemy również zastosować zapis analogicznie jak w AVR-ach :
PORTA | = (1<<_PORTA_RA1_POSITION) ; // ustaw drugi bit rejestru na 1 czyli na pinie RA1 mamy stan wysoki
PORTA
& = ~
(1<<_PORTA_RA1_POSITION)
; // ustaw
drugi bit rejestru na 0 czyli na pinie RA1
mamy stan
niski.
Wartość jaką wpiszemy w rejestr zatrzaskowy LATx jest przepisywana automatycznie do rejestru PORTx.
LATA = 0x001F ; // ustawiamy 5 pierwszych bitów rejestru na 1 czyli na pięciu pierwszych pinach portu A mamy stan wysoki
LATA
= 0x0000 ; //
ustawiamy bity
rejestru na 0
czyli na wszystkich
pinach
portu A mamy stan
niski
za pomocą zdefiniowanych struktur :
LATAbits.LATA1 = 1 ; // ustaw drugi bit rejestru na 1 czyli na pinie RA1 mamy stan wysoki
LATAbits.LATA1
= 0 ; // ustaw drugi bit rejestru na 0 czyli na
pinie RA1 mamy
stan niski.
Odczyt wartości za pomocą rejestru PORTx :
Odczyt wartości za pomocą rejestru PORTx :
int
val
;
val
= PORTA
; //
zapisz
wszystkie wartości pinów portu A do zmiennej valval = PORTAbits.RA1 ; // zapisz tylko wartość pinu RA1 do zmiennej val
Odczyt
wartości za pomocą rejestru LATx :
int
val
;
val
= LATA
; //
zapisz
wszystkie wartości rejestru
do zmiennej val
val
= LATAbits.LATA1
; // zapisz
tylko wartość wybranego
bitu z rejestru do zmiennej val
Rejestr ANSELx - odłączenie sekcji analogowej od pinu który chcemy używać jako np.wyjście cyfrowe :
W przypadku niektórych pinów wymienionych wyżej dla PIC32MM0256GPM048 (dla 64 nóżek będzie ciut inaczej ale to doczytamy sobie jednym spojrzeniem na rejestr ANSELx w datasheet), wymagane jest odłączenie sekcji analogowej !! . Jeśli tego nie zrobimy a ustawimy np. za pomocą rejestru TRISx pin jako wyjście i chcemy je mieć jako cyfrowe to wyjście nam nie zadziała. Poniżej przykład sterowania bitami w rejestrze ANSELx :
ANSELAbits.ANSA1
= 1 ; // pin RA1 podłączony do sekcji analogowej (nie możemy działać cyfrowo)
ANSELBbits.ANSB2
= 0 ; // pin RB2 odłączony od sekcji analogowej (możemy działać cyfrowo)
Na koniec ważna uwaga dotycząca pinu RA3, jest to pin wewnętrznie podłączony do oscylatora RC. Jeśli chcemy ten pin wykorzystywać jako normalny pin I/O musimy odłączyć go od oscylatora.
A zrobimy to tak :
najbardziej prosta i bezstresowa metoda za pomocą MCC
w panelu MCC opcja Clock Output Pin Configuration powinna być na OSCO pin operates as a normal I/O i już po bólu.
Reasumując dostęp do rejestrów I/O i operowanie na nich w PIC32 jest bardzo proste i sympatyczne. Szybko można się z tym zapoznać i polubić. Przyczynia się do tego ładne opisanie rejestrów definicjami i strukturami zawarte tylko w jednym pliku nagłówkowym do którego dostęp z poziomu programu jest automatyczny za pomocą includowania xc.h.
Prezentowana w artykule specyfika rejestrów jest typowa dla wszystkich PIC32.
Na koniec artykułu zapodam przykładowy program w postaci migania diodą LED w którym pokażę dokładnie jakie należy podjąć kroki aby zasterować wybranym pinem. W programie rozważymy "najtrudniejszy" przypadek czyli pin RA3. Działania swoje oprę na mojej ulubionej obecnie płytce developerskiej PIC32MM.
Pozdrawiam
picmajster.blog@gmail.com
picmajster.blog@gmail.com
Linki:
PIC32MM - Family
PIC32 - I/O ports
GitHub:
Projekt do MPLABX IDE
Nie wygląda groźnie :)
OdpowiedzUsuńNie jest groźne a nawet całkiem sympatyczne. Ja sam nie wiem kiedy się obejrzałem i znalazłem się z 8 na 32-bitach :)
OdpowiedzUsuńczekam na omówienie modułów SCCP i MCCP
OdpowiedzUsuńCiekawy procek to i ciekawe moduły :)
OdpowiedzUsuńPozdrawiam
PICmajster
Witam mam pytanie a jak jest tak naprawdę z tym darmowym środowiskiem MPLABX IDE ? Mam ochotę poznać mikrokontrolery Pic32 . Wcześniej trochę bawiłem się pic16 jednak cały czas myślę w jakim stopniu MPLABX w wersji free spowalnia mój program i czy ma to tez takie znaczenie przy picach32
OdpowiedzUsuńA małe sprostowanie nie tyle z środowiskiem co z kompilatorem np XC8 czy XC32
OdpowiedzUsuńMPLABX -IDE to środowisko i ono Tobie nic nie spowolni jest całkowicie free bez żadnych ograniczeń. Do środowiska instalujesz kompilator XC32 w wersji free (domyślnej). Wynikowy kod będzie zajmował Tobie ciut więcej pamięci Flasha, niż wersja płatna PRO. Z punktu widzenia zasobów MCU nie ma to większego znaczenia bo PIC32 mają dużą pamięć flash i nie odczujesz tego w żaden sposób. Jeśli chcesz podoktoryzować się w porównaniach szybkości wykonywania kodu między wersją kompilatora XC32 free a PRO to masz możliwość bezpłatnej 60 dniowej hulanki na wersji PRO ale w/g mnie jest to niepotrzebna strata czasu. Nie jest mi potrzebna do szczęścia wersja PRO, wersja free robi swoje. Przestań myśleć nad takimi aspektami bo cię głowa rozboli :) zacznij działać. MCU PIC32 są cool :) ale żeby wyrobić sobie zdanie trzeba je poznać :) Proponuję Tobie zainteresować się na początek serią PIC32MM w wydaniu GPM (Part Number: DM320107 - PIC32MM USB Curiosity Development Board),potem odpytaj mocniejszą serię MX (Part Number: DM320103 - Curiosity PIC32MX470 Development Board). Na płytkach developerskich masz PICkit3, nie musisz więc oddzielnie kupować programatora.Płytki kosztują ok 100 zł są dostępne również u nas. Płytki które Tobie podałem są bardzo fajne mają złącza do modułów Mikroelektroniki a to już daje nieograniczone możliwości :) Jeśli masz jakieś problemy pomogę, przetarłem trochę szlak :)
OdpowiedzUsuńOk dzięki za odpowiedź. A więc zaczynam przygodę z PIC32 i czekam na kolejne artykuły na ich temat .
OdpowiedzUsuńObecnie czekam na dostawę moich poprawionych płytek developerskich do PIC32MM,polutuję sobie kilka i będziemy jechać z koksem dalej, rozpoznamy interfejsy etc.
OdpowiedzUsuńZ tego co widzę Microchip obecnie zmienia oprawę i technologię w zakresie swojej strony www, ciekawe czy za tymi zmianami pójdą inne ciekawsze rzeczy :)
Pozdrawiam
PICmajster
Super wpis. Bardzo pomocne informacje
OdpowiedzUsuń