Pinologia mikrokontrolera PIC24HJ128GP502 :
Na wstępie przypominam za pomocą pisma obrazkowego pinologię rozważanego mikrokontrolera.
W mikrokontrolerze tym mamy do dyspozycji dwa UART-y. Tajemnicą poliszynela jest jednak na których pinach schowały się te UART-y ?. Jak widać na powyższym zdjęciu brak w opisach przyporządkowania pinów pod UART-a.
O ile w Atmegach mamy na sztywno zdefiniowane piny pod UART-a to tutaj mały zong. Rozjaśnia nam się jednak sprawa po zapoznaniu się z datsheet-em rozdział 11.6 "Perypherial Pin Select". Dowiadujemy się tam m.in o tym , że nasz mikrokontroler jest wyposażony w mechanizm remappingu pinów. I wielki szacun dla Microchipa za taką super elastyczną możliwość.Czyli w dużym skrócie mamy możliwość przyporządkować sobie wybrane peryferia do prawie dowolnych pinów, prawie oznacza , że jest wytypowany zakres takich pinów i jeśli się nie pomyliłem w zliczaniu to prawie ma wymiar 16 sztuk. Piny oznaczone RPx (gdzie x od 0 do15) podlegają dowolnemu remappingowi .
O ile w Atmegach mamy na sztywno zdefiniowane piny pod UART-a to tutaj mały zong. Rozjaśnia nam się jednak sprawa po zapoznaniu się z datsheet-em rozdział 11.6 "Perypherial Pin Select". Dowiadujemy się tam m.in o tym , że nasz mikrokontroler jest wyposażony w mechanizm remappingu pinów. I wielki szacun dla Microchipa za taką super elastyczną możliwość.Czyli w dużym skrócie mamy możliwość przyporządkować sobie wybrane peryferia do prawie dowolnych pinów, prawie oznacza , że jest wytypowany zakres takich pinów i jeśli się nie pomyliłem w zliczaniu to prawie ma wymiar 16 sztuk. Piny oznaczone RPx (gdzie x od 0 do15) podlegają dowolnemu remappingowi .
Podepnijmy zatem do wybranych pinów naszego UART-a.
Życzę sobie aby na pinie nr 14 znalazło się TX a na pinie nr 11 RX. Domyślnie działamy na UART1, pamiętając , że jest jeszcze dostępny UART2. A do czego można wykorzystać drugi UART ? taki na szybko pomysł to na jednym zapewniamy komunikację z modułem wi-fi komunikując się ze stroną www na hostingu , drugim UART-em spinamy sieć wewnętrzną po RS-485. Więcej niż jeden UART może naprawdę się przydać.
Dla podpięcia pinu 14 (RP5) do TX korzystamy z Table 11-2 na stronie 139 (datasheet) i rejestru RPOR2 (Peripheral Pin Select Output Register 2). Z tabelki odczytujemy wartość jaką trzeba wpisać do rejestru .Dla funkcji U1TX odczytujemy z tabelki wartość bitową 00011 (dziesiętnie 3) i to musimy wpisać na 5-ciu bitach do rejestru RPOR2 dokładnie na bicie od 8 do 12 (przyporządkowanie do pinu 14 oznaczonego RP5). Zapis do rejestru umożliwia nam wygodna struktura oferowana przez plik nagłówkowy naszego mikrokontrolera i wygląda to tak :
RPOR2bits.RP5R = 3;Przy okazji trzeba nadmienić, że opisanie rejestrów w pliku nagłówkowym mikrokontrolera za pomocą struktur to po prostu bajka i jest to bardzo duży plus dla Microchipa. :).
Rozważmy teraz przyporządkowanie do pinu nr 11 (RP4) RX-a Uartowego .
W tym celu korzystamy z Table 11-1 na stronie 138 (datasheet) i rejestru RPINR18 (Peripheral Pin Select Input Register 18). Na pięciu pierwszych bitach w/w rejestru wpisujemy numer RPx (w naszym przypadku pin nr 11 ma oznaczenie RP4) czyli 4 (dziesiętnie) i tyle trzeba wpisać w rejstr RPINR18.
Wygląda to tak :RPINR18bits.U1RXR = 4;.
Można odnieść wrażenie, że ten remapping w ustawieniach jest upierdliwy no i trochę jest bo można się łatwo walnąć, ale trud konfiguracji rekompensuje całkowicie luksus samej idei remappingu. W przypadku mikrokontrolerów serii PIC24FJ i dsPIC33 mamy do dyspozycji wtyczkę MPLAB Code Configurator , i tutaj remapping robimy za pomocą klikania i pykania w obrazki, taka opcja dla leniwców. Można i tak .
Ale ja sobie obecnie nawet chwalę , że w PIC24HJ nie mam tej możliwości bo w ten sposób lepiej poznaje mikrokontroler od strony bebechów.
Aby skomunikować mikrokontroler z PC-etem potrzebujemy jednego gadżetu czyli konwertera UART - USB.
Ja dysponuję konwerterem z serii CP210x (Silicon Labs) , który chodzi mi bez problemu zarówno w Linuxie jak i Windzie. Konwerter daje nam m.in zasilanie +3.3 V , którym możemy zasilić układ mikrokontrolera na czas testów. Pamiętajmy o prawidłowym podłączeniu czyli :
Ja dysponuję konwerterem z serii CP210x (Silicon Labs) , który chodzi mi bez problemu zarówno w Linuxie jak i Windzie. Konwerter daje nam m.in zasilanie +3.3 V , którym możemy zasilić układ mikrokontrolera na czas testów. Pamiętajmy o prawidłowym podłączeniu czyli :
TX konwertera ---> RX mikrokontrolera (nóżka 11)
RX konwertera ---> TX mikrokontrolera (nóżka 14)
Do komunikacji z PC-etem używam najbardziej przyjaznego programu jaki znalazłem w sieci. Jest prosty jak budowa cepa i user friendly . Pobieramy go tutaj : https://sites.google.com/site/terminalbpp/
Mikrokontroler konfigurujemy na zegar wewnętrzny ok 40 MHz. Poniżej kod do konfiguracji zegara i innych niezbędnych do odpalenia gadżetów. W pliku main.c wysyłamy jeden raz znak i stringa a w pętli głównej oczekujemy na jeden odebrany znak i wysyłamy go z powrotem torem nadawczym. Przy nadawaniu i odbiorze nie korzystamy z przerwań.
1 /* 2 * File: ustaw_zegar.h 3 */ 4 5 #ifndef USTAW_ZEGAR_H 6 #define USTAW_ZEGAR_H 7 8 void ustaw_zegar(void) ; 9 10 #endif /* USTAW_ZEGAR_H */ 11 12
1 /* 2 * File: ustaw_zegar.c 3 */ 4 /*Ustawiamy zegar wewnetrzny na ok 40 MHz (dokladnie na 39.61375 MHz*/ 5 #include "xc.h" /* wykrywa rodzaj procka i includuje odpowiedni plik 6 naglówkowy "p24HJ128GP502.h"*/ 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <stdint.h> /*dyrektywy do uint8_t itp*/ 10 11 /*deklaracja funkcji*/ 12 void ustaw_zegar(void) ; 13 14 /*definicja funkcji*/ 15 void ustaw_zegar(void) { 16 /* 17 * to co mozemy ustawic za pomoca '#pragma' jest dostepne w pliku 18 * xc16/docs/config_index.html 19 */ 20 #pragma config JTAGEN = OFF 21 // Watchdog timer enable/disable by user software 22 #pragma config FWDTEN = OFF 23 24 //********************Start Ustawien Zegara************************ 25 /* 26 * Fcy - zegar instrukcji , Fosc - zegar rdzenia (jest zawsze dwa razy wiekszy 27 * od zegara instrukcji)) Ustawiamy zegar instrukcji na 40 Mhz z wewnetrznego 28 * oscylatora Fin=7.37 MHz w/g wzoru Fcy=Fosc/2 gdzie Fosc=Fin x (M/(N1+N2)) 29 * gdzie M=43, N2=2, N1=2 ustawiane w rejestrach PLLFBD/PLLPOST/PLLPRE 30 */ 31 //Select Internal FRC (Fast RC Oscillator) 32 #pragma config FNOSC = FRC // FOSCSEL-->FNOSC=0b000 (Fast RC Oscillator (FRC)) 33 //Enable Clock Switching and Configure 34 #pragma config FCKSM = CSECMD //FOSC-->FCKSM=0b01 - wlacz zegar 35 #pragma config OSCIOFNC = OFF //FOSC-->OSCIOFNC=1 - Fcy b?dzie na pinie OSCO 36 37 /*Config PLL prescaler, PLL postscaler, PLL divisor*/ 38 PLLFBD = 41 ; //M=43 (0 bit to 2 st?d 41 = 43 patrz w rejestrze), tutaj 3.685 x 43 = 158.455MHz 39 CLKDIVbits.PLLPRE=0 ; //N1=2, tutaj 7.37 MHz / 2 = 3.685 MHz 40 CLKDIVbits.PLLPOST=0 ; //N2=2, tutaj 158.455 MHz / 2 = 79.2275 MHz (Fosc) 41 /* 42 * UWAGA przerwania musza byc wylaczone podczas wywolywania ponizszych 43 * dwóch funkcji __builtin_write_...brak definicji w pliku naglówkowym 44 * to wewnetrzne funkcje kompilatora patrz help M-LAB IDE 45 * i datasheet str 140(11.6.3.1 Control Register Lock) 46 */ 47 /*Initiate Clock Switch to Internal FRC with PLL (OSCCON-->NOSC = 0b001)*/ 48 __builtin_write_OSCCONH(0x01); //tutaj argumentem jest wartosc z NOSC 49 /*Start clock switching*/ 50 __builtin_write_OSCCONL(0x01); 51 52 /*Wait for Clock switch to occur*/ 53 while(OSCCONbits.COSC !=0b001); 54 55 /*Wait for PLL to lock*/ 56 while(OSCCONbits.LOCK !=1) {}; 57 58 }
1 /* 2 * File: main.c 3 * PIC24HJ128GP502 4 */ 5 #include "xc.h" 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <stdint.h> /*dyrektywy uint8_t itp*/ 9 10 #define FCY 40000000 /* podajemy wartosc ustawionego zegara (40 MHz), wazne 11 aby przed includowaniem <libpic30.h>, potrzebne to jest do wyliczania delay-i*/ 12 #include <libpic30.h> // biblioteka dajaca dostep do delay-i. 13 #include "ustaw_zegar.h" /*ustawienie zegara systemowego*/ 14 15 #define BAUDRATE 9600 /*definujemy szybkosc UART-a*/ 16 #define BRGVAL ((FCY/BAUDRATE)/16)-1 17 /*deklaracje funkcji*/ 18 void UartSend(char data); 19 void UartSendString(char *data); 20 21 int main(void) { 22 /*konfiguracja zegara i inne potrzebne do startu mikrokontrolera*/ 23 ustaw_zegar(); 24 25 /*remapping pinow pod UART1*/ 26 /*TX ustawiamy na pinie 14 (RP5)--> U1TX wartosc 00011, wpisac na bitach od 8 do 12 do rejestru RPOR2*/ 27 RPOR2bits.RP5R = 3; 28 /*RX ustawiamy na pinie 11 (RP4)--> U1RX wartosc 00100, wpisac na bitach od 0 do 5 do rejestru RPINR18*/ 29 RPINR18bits.U1RXR = 4 ; 30 31 /*konfiguracja UARTA1*/ 32 33 U1BRG = BRGVAL; /* Baud Rate setting */ 34 35 /*nie korzystamy z przerwania, dezaktywujemy ten fragment kodu */ 36 //IEC0bits.U1TXIE = 1; /*odblokowujemy przerwanie TX*/ 37 //IEC0bits.U1RXIE = 1; /*odblokowujemy przerwanie RX*/ 38 39 U1MODEbits.UARTEN = 1; /*Enable UART*/ 40 U1STAbits.UTXEN = 1; /*Enable UART TX*/ 41 /* Wait at least 105 microseconds (1/9600) before sending first char */ 42 __delay_us(105); 43 /*Uff..koniec konfiguracji UART1*/ 44 45 /*wysylamy znak i stringa*/ 46 UartSend('a') ; 47 UartSendString("\r\n"); 48 UartSendString("Ala ma kota") ; 49 UartSendString("\r\n"); 50 char ReceivedChar; 51 while(1) 52 { 53 /* Get the data */ 54 if(U1STAbits.URXDA == 1)/*flaga URXDA sygnalizuje jak cos pojawi się w rejestrze odbiorczym U1RXREG*/ 55 { 56 ReceivedChar = U1RXREG; /*przepisz odebrany znak z rejestru odbiorczego do zmiennej*/ 57 UartSend(ReceivedChar); /*wyslij odebrany znak, bawimy sie w echo*/ 58 } 59 } 60 return 0; 61 } 62 63 64 /*definicja funkcji do nadawania znaku*/ 65 void UartSend(char data) { 66 U1TXREG = data ; /*pakujemy znak do sprzetowego bufora nadawczego */ 67 /*petla oczekujaca az oprozni sie Transmit Shift Register, jesli 1 to oprozniony*/ 68 while(U1STAbits.TRMT !=1) {} 69 } 70 71 /*definicja funkcji do nadawania stringa*/ 72 void UartSendString(char *data) { 73 while((*data !='\0')) 74 { 75 U1TXREG = *data ; 76 /*petla oczekujaca az oprozni sie Transmit Shift Register, jesli 1 to oprozniony*/ 77 while(U1STAbits.TRMT !=1) {} 78 data++ ; 79 } 80 } 81
Konfiguracja i komunikacja po UART w PIC nie nastręczyła mi żadnych problemów, wszystko zatrybiło od przysłowiowego pierwszego razu. Pewnym zaskoczeniem było działanie sekwencji odbierająco/wysyłającej w pętli głównej. Spodziewałem się odbioru i retransmisji tylko jednego znaku, w rzeczywistości sekwencja potrafi odebrać i wysłać cały długi string w jednym wierszu. Mamy co prawda sprzętowy bufor nadawczy i odbiorczy FIFO w mikrokontrolerze ale ma on wymiar 4 bajty nie tłumaczy to chyba takiego działania. Na razie nie wiem ,wymaga to chwili zastanowienia i podrapania się w głowę jak to możliwe a możliwe jest bo widziałem to na własne oczy :)W przyszłości zajmiemy się wykorzystaniem UART w komunikacji dwustronnej ze stroną www na hostingu. W tym celu do nadawania wykorzystamy DMA a do odbioru danych bufor cykliczny.
Pozdrawiam
picmajster.blog@gmail.com
Linki :
Drivery do konwertera CP210x :
http://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers
Datasheet PIC24HJ128GP502 :
http://ww1.microchip.com/downloads/en/DeviceDoc/70293G.pdf
UART materiał rozszerzony :
http://ww1.microchip.com/downloads/en/DeviceDoc/70000582e.pdf
Remapping i inne
http://ww1.microchip.com/downloads/en/DeviceDoc/70234B.pdf
Brak komentarzy:
Prześlij komentarz