środa, 22 lutego 2017

UART - pierwsze starcie.


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 .

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 :

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.

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