Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

Ricerca personalizzata
14
voti

Impariamo con il Pierin - La USART

Indice

Premesse

In questo articolo verrà spiegato cos’è e come configurare correttamente la periferica USART presente sul PIC della scheda PIERIN PIC18. L’obiettivo di questo articolo è quello di stabilire una comunicazione seriale tra la scheda e un PC, inviando e ricevendo dati.

Cos’è l’USART?

L’USART (Universal Syncronous Asynchronous Receiver/Transmitter) è una periferica di trasmissioni dati seriale che utilizza solo due cavi per la comunicazione. E’ una delle primissime interfaccedi comunicazione anche se ultimamente è stata declassata da altri tipi di comunicazioni seriali (USB). Esistono essenzialmente due modalità di trasmissione:

-Modalità asincrona (full-duplex)

-Modalità sincrona (half-duplex)

La prima modalità (l’unica trattata in questo articolo), è una comunicazione asincrona, ovvero il trasmettitore e il ricevente non sono sincronizzati e posso inviare e ricevere dati in contemporanea(full-duplex). La velocità di trasmissione deve essere la medesima in entrambi i dispositivi ed è detta Baud Rate, espressa in bit al secondo. Per la comunicazione sono necessari due pin: uno trasmittente (TX) e uno ricevente (RX),

Nella modalità sincrona la trasmissione e la ricezione sono sincronizzate da un clock di sistema fornito da un master e uno o più slave che ricevono e inviano dati alla frequenza stabilita dal master. Dato che la linea dati è unica sia in ricezione che in trasmissione, la comunicazione è di tipo half-duplex: trasmissione e ricezione tra dispositivi non può avvenire contemporaneamente. Sono necessari due pin: uno per i dati (DT) e uno per il clock (CK).

La prima modalità è meno efficiente della prima, perché oltre ad inviare dati, deve inviare anche un bit di start e uno di stop. Ne deriva quindi che l’80% dei bit inviati rappresenta un’informazione utile al ricevente, al contrario di quella sincrona in cui ogni bit rappresenta un’informazione utile. Nonostante ciò, la modalità asincrona è quella che maggiormente si è diffusa.


Protocollo di trasmissione

Trasmissione

Trasmissione


I dati transitano da e per la periferica USART utilizzando il seguente schema: un bit di start, 8 bit dati (1 byte) e uno o due bit di stop. Se si devono inviare più byte, la procedura si ripete (nuovo bit di start e così via). Solitamente viene inviato prima il bit meno significativo e lo stato di riposo (ovvero ciò che si trova tra due trasmissioni separate) si trova allo stato logico alto. Tutto ciò è comunque impostabile mediante i registri del PIC.


I registi di configurazione

Per la configurazione della periferica USART sono presenti 3 registri: TXSTAx , RCSTAx e BAUDCONx.


TXSTAx

TXSTAx


Bit Funzione
CSRCNella modalità asincrona non regola nulla mentre nella modalità sincrona regola se il dispositivo è master o slave
TX9Permette di stabilire una trasmissione a 9 bit
TXENAbilita il trasmettitore
SYNCScelta tra modalità sincrono o asincrona
SENDBSe settato invia un sync break che serve per il “risveglio” dalla modalità sleep.
BRGHScelta tra alta o bassa velocità
TRMTBit di sola lettura che indica se il registro TSR(quello di trasmissione) è pieno o meno
TX9DE’ il nono bit nella trasmissione a 9 bit
RCSTAx

RCSTAx


Bit Funzione
SPENSetta i pin RC6 e RC7 come porte seriali
RX9Attiva la ricezione a 9bit
SRENHa utilità solo nella modalità sincrona master.
CRENAttiva il modulo ricevente
ADDENNella modalità a 9bit, serve per scegliere se quello ricevuto è un indirizzo o un byte con bit di parità
FERRBit di sola lettura che segnala un errore nella struttura del pacchetto ricevuto
OERRBit di sola lettura che segnala che un byte è arrivato e il registro RCxSTA non è ancora stato letto
RX9D E’ il nono bit nella trasmissione a 9 bit


BAUDCONx

BAUDCONx


Bit Funzione
ABDOVFAttiva la modalità di auto rilevazione del baud rate.
RCIDLBit di sola lettura che indica se la linea dati RXè occupata o meno
RXDTPInverte lo stato logico della comunicazione(attivo-alto o attivo-basso)
TXCKOScelta tra stato logico alto o basso per lo stato di riposo
BRG16Scelta tra baud rate generator a 8 o 16 bit
WUEAttiva il “risveglio” del micro nel caso in cui ci sia un passaggio logico da alto a basso sulla linea RX
ABDENAttiva la rilevazione del baud rate dal prossimo dato


Poi ci sono i registri TXREGx, RCREGx, SPBRGx e SPBRGHx. Ilprimo serve per inviare un byte via seriale, il secondo invece serve per leggere un byte appena ricevuto. Gli ultimi due servono per stabilire il baud rate che viene calcolato secondo queste formule in base ai settaggi precedenti.


Tabella baud rate

Tabella baud rate

Stabiliamo la comunicazione

Iniziamo preparando l’ambiente di lavoro in MPLABX. Se avete problemi potete consultare questo articolo. Ad ogni modo, il mio programma è strutturato in 4 file: main.c, funzioni.c, header.h econfiguration_bits.c. Il primo contiene il main e le funzioni delle interrupt; funzioni.c contiene tutte le altre funzioni mentre l’header.h contiene tutte le definizioni e costanti del programma, le variabili globali e i prototipi di funzione. Comunque ognuno è libero di organizzare il proprio lavoro come è più comodo.


Per prima cosa dobbiamo configurare la periferica:


    //Pin TX e RX del modulo UART
    TRISC6=0;
    TRISC7=1;

    //Configurazione modulo UART
    //Trasmissione asincrona a 8bit, alta velocità e generatore del baud-rate a 8bit
    //Invio ericezione dati non invertita e idle state ad alto livello
    TXSTA1=0b00100100;
    RCSTA1=0b10010000;
    BAUDCON1=0;
    SPBRG1=155;         //Baud=19200(Fout=Fosc/(16*(SPBRG1+1))

Se avete letto con attenzione la spiegazione dei vari registri non avrete problemi a capire queste poche righe.

N.B: la maggior parte delle volte è impossibile trovare un valore per il registro del baud rate tale che la frequenza di trasmissione venga perfettamente il valore prefissato. Nel caso corrente, per esempio, ne risulta un baud rate di 19230, quindi l’errore è del 0,15%. (per il calcolo dell’errore si veda pag. 350 del datasheet). E’ consigliato mantenere l’errore inferiore al 6% per evitare errori.


//Invia questo testo al PC solo all'inizio
    stampaTesto("Ciao Programmatore!!! ");
    stampaTesto("Invia un carattere e il pierin te lo rimandera'! \n");
    stampaTesto("\n");
    //Ciclo infinito
    while(1)
    {            
        while(!RC1IF);
        RD6=1;              //Segnalo con il led LD1 che il PIC ha ricevuto un dato
        dato=RCREG1;        //Salvo il carattere nella variabile dato
        stampaTesto("Il Pierin ha ricevuto: ");     //Invio al PC una stringa
        while(!TX1IF);      //Controllo e attendo che il PIC abbia finito di trasmettere
        TXREG1=dato;        //e invio il carattere appena ricevuto
        stampaTesto("\n");  //Vado a capo
        RD6=0;              //Spengo il led
    }


Questo codice contenuto nel main, si occupa di ricevere ed inviare i byte al computer. Le prime istruzioni inviano una stringa di testo utilizzando una funzione che vedremo in seguito. Dentro al ciclo while, il micro attende che un byte venga inviato. Infatti come è possibile vedere nell'immagine qua sotto, quando un byte viene ricevuto, il bit RC1IF del registro PIR1 viene settato. Per resettare il bit basta leggere il registro RCREG1, cosa che nel listato avviene e il valore che contiene viene salvato in una variabile.


Ricezione

Ricezione


Trasmissione

Trasmissione


Poi controlla se il registro di trasmissione è pieno o meno,e se è vuoto procede con l’invio del byte via seriale. Tutto questo procedimento viene segnalato da il led LD1 che si accende al momento della ricezione del byte e si spegne a ritrasmissione compiuta.

//Dato in ingresso una stringa, invia un carattere per volta alla seriale.
void stampaTesto(char *t)
{
    while (*t)
    {
        while(!TX1IF);
        TXREG1=*t;
        t++;
    }
}


Questa funzione non fa altro che inviare un carattere per volta fino a che arriva alla fine della stringa.


Collegamenti

Per simulare una porta seriale che i computer moderni non hanno più, si deve usare un qualche altro dispositivo esterno. Io ho usato ilPickit 2 che ha anche la funzione di porta seriale. Ecco lo schema di collegamento:



Schema collegamento

Schema collegamento


Per stabilire la comunicazione, dovete avviare il pickit2,nel menù Tool selezionare UART tool. In seguito settate il baud rate a 19200 es puntate la casella VDD. Premete su connect e collegate al PIERIN PIC18 il cavoUSB per dargli alimentazione. Vi dovrebbe comparire una scritta iniziale e poi ad ogni carattere che gli inviate, la scheda dovrebbe rispondervi come in figura:


Uart tool

Uart tool


Migliorie al codice

In un programma reale, è improbabile che il PIC svolga solo il compito di gestire i dati della seriale. Probabilmente dovrà gestire qualcos'altro,tipo un lcd, un motore un altro dispositivo seriale ecc. Utilizzando il codice precedente, si “paralizza” in un certo senso il micro, dato che rimane inattesa di un dato in arrivo, e se nel frattempo si deve svolgere qualcos'altro(che non sia gestito via interrupt) si deve aspettare. E’ quindi una buona cosa gestire il flusso dati della UART mediante gli interrupt.

Il modulo USART del micro è in grado di scatenare un interrupt quando un dato è stato ricevuto. Per attivarlo si deve agire sul bit RC1iE del registro PIE1 e settare la priorità con il bit RC1IP del registro IPR1.

Le nuove configurazioni della periferica diventano:

//Pin TX e RX del modulo UART
    TRISC6=0;
    TRISC7=1;
    
    //Configurazione modulo UART
    //Trasmissione asincrona a 8bit, alta velocità e generatore del baud-rate a 8bit
    //Invio e ricezione dati non invertita e idle state ad alto livello
    TXSTA1=0b00100100;
    RCSTA1=0b10010000;
    BAUDCON1=0;
    SPBRG1=155;         //Baud=19200 (Fout=Fosc/(16*(SPBRG1+1))
    
    //Interrupt UART
    RC1IE=1;            //Attivo l'interrupt in ricezione
    RC1IP=1;            //Alta priorità

    //Abilitazione interrupt generale
    GIE=1;
    PEIE=1;


Così facendo, ogni volta che viene ricevuto un dato, si scatena un interrupt che pone al livello logico 1 il bit RC1IF. La gestione dell’interrupt sarà quindi la seguente:

//Alta Priorità
void interrupt high_isr(void)
{
    //Se il registro RCREG1 è pieno, si scatena un interrupt
    if (RC1IF)
    {
        RD6=1;              //Segnalo con il led LD1 che il PIC ha ricevuto un dato
        dato=RCREG1;        //Salvo il carattere nella variabile dato
        stampaTesto("Il Pierin ha ricevuto: ");     //Invio al PC una stringa
        while(!TX1IF);      //Controllo e attendo che il PIC abbia finito di trasmettere
        TXREG1=dato;        //e invio il carattere appena ricevuto
        stampaTesto("\n");  //Vado a capo
        RD6=0;              //Spengo il led
    }
}


Molto simile al codice precedente, solo che ora non è presente il while che imponeva l’attesa di un dato in ingresso. Ora il micro può svolgere qualsiasi altra cosa e se arriva un byte dalla seriale, interrompe tutto e lo legge, per poi riprendere da dove si era interrotto.


Conclusioni

Qui potete scaricare il primo programma.

Qui potete scaricare il secondo.


Se avete domande o ho commesso qualche errore, non esitate a commentare l’articolo. Buona sperimentazione!

6

Commenti e note

Inserisci un commento

di ,

Ciao Galaxi93, in pratica sto cercando di costruire un dispositivo in grado di comunicare con macchine a cnc abbastanza datate, quindi munite di porta seriale RS232. Il dispositivo deve poter ricevere o trasmettere programmi o parametri. IL tutto viene gestito da un pic18 e una Sram da un mega che mi immagazzina i dati. In commercio esistono prodotti simili ma costano uno sproporito: http://pcecad.com/indexc00a.html

Rispondi

di ,

Di che dispositivo si tratta? Così a botta, ti direi che basta configurare il pic a 8 bit e l'ultimo bit che invii lo metti sempre a 1 in modo che il tuo dispositivo interpreti come bit di stop. Grazie a tutti per i complimenti!!

Rispondi

di ,

Complimenti per il lavoro ben fatto. Anch'io sono uno dei fortunati possessori del Pierin e mi hai anticipato nella stesura dell'articolo. Volevo farti una domanda, dovrei collegare un dispositivo al Pierin tramite usart ma questo può trasmettere solo 7bit e non 8 o 9 come tutti i pic. Hai qualche suggerimento! Grazie Marcello.

Rispondi

di ,

Ottimo articolo, utile per tutti e spiegato bene!

Rispondi

di ,

Ottimo lavoro!
Stavo proprio in procinto di fare una cosa del genere, mi hai fatto risparmiare un bel po' di tempo, grazie!

Rispondi

di ,

Complimenti per l'articolo...in molti saranno contenti di leggere uno dei primissimi articoli sul Pierin! Una piccola osservazione: circa all'inizio c'é un piccolo errore di battitura "La prima modalità è meno efficiente della prima, perché oltre ad inviare dati..."

Rispondi

Inserisci un commento

Per inserire commenti è necessario iscriversi ad ElectroYou. Se sei già iscritto, effettua il login.