PICmicro Cult – Gestione di una connessione RS232 1/2

Gestione di una connessione RS232

Analizzando in questa lezione come sia possibile dotare il PIC16F84A di una interfaccia RS232 per collegarlo alla porta seriale del nostro PC.

L'applicazione d'esempio che andremo a realizzare utilizza il circuito per la gestione di un display LCD presentato nella lezione 8 a cui aggiungeremo la sezione RS232 per realizzare una sorta di miniterminale RS232.
In pratica con il nostro circuito d'esempio potremo visualizzare su display LCD i caratteri ASCII trasmessi dal nostro PC su una qualsiasi porta seriale tramite un normale emulatore di terminale tipo Hyperterminal (su Windows 95/98/ME/2000/XP), Telix (su MS/DOS) o Minicom (su Linux).

Vediamo subito lo schema elettrico riportato nella figura seguente:

Come potete vedere la base del circuito che andremo a realizzare è identica a quella del passo precedente con la sola aggiunta del circuito integrato U3, del connettore a vaschetta DB9 per il collegamento alla porta seriale del PC ed una manciata di componenti accessori.

L'integrato U3, un MAX232 prodotto dalla Maxim, si occupa di convertire i segnali RS232 dai +/-12 volt necessari per trasmettere e ricevere dati sulla porta seriale ai 0/5 volt TTL gestibili direttamente dalle porte del PIC.
Ma vediamo in dettaglio come funziona la comunicazione seriale in RS232.

Cos'è e a cosa serve l'RS232

Lo standard RS232 definisce una serie di specifiche per la trasmissione seriale di dati tra due dispositivi denominati DTE (Data Terminal Equipment) e DCE (Data Communication Equipment). Come si può vagamente intuire dal nome, il Data Communication Equipment è un dispositivo che si occupa di gestire una comunicazione dati mentre il Data Terminal Equipment è un dispositivo che si occupa di generare o ricevere dati.
In pratica l'RS232 è stata creata per connettere tra loro un terminale dati (nel nostro caso un computer) con un modem per la trasmissione a distanza dei dati generati.
Per avere una connessione tra due computer è quindi necessario disporre di quattro dispositivi come visibile in figura: un computer (DTE) collegato al suo modem (DCE) ed un altro modem (DCE) collegato al suo computer (DTE). In questo modo qualsiasi dato generato dal primo computer e trasmesso tramite RS232 al relativo modem verrà trasmesso da questo al modem remoto che a sua volta provvederà ad inviarlo al suo computer tramite RS232. Lo stesso vale per il percorso a ritroso.

Per usare la RS232 per collegare tra loro due computer vicini senza interporre tra loro alcun modem dobbiamo simulare in qualche modo le connessioni intermedie realizzando un cavo NULL MODEM o cavo invertente, ovvero un cavo in grado di far scambiare direttamente tra loro i segnali dai due DTE come se tra loro ci fossero effettivamente i DCE.
Per connettere il PC al nostro circuito simuleremo invece direttamente un DCE facendo credere al PC di essere collegato ad un modem. Prima di fare questo diamo uno sguardo in dettaglio al principio di funzionamento di una comunicazione seriale.

La comunicazione seriale asincrona

Per consentire la trasmissione di dati tra il PC ed il modem, lo standard RS232 definisce una serie di specifiche elettriche e meccaniche. Una di queste riguarda il tipo di comunicazione seriale che si vuole implementare che può essere sincrona o asincrona.
Nel nostro caso analizzeremo solo la comunicazione seriale asincrona ignorando completamente quella sincrona in quanto più complessa e non disponibile sui normali PC.
Una comunicazione seriale consiste in genere nella trasmissione e ricezione di dati da un punto ad un altro usando una sola linea elettrica. In pratica se desideriamo trasmettere un intero byte dobbiamo prendere ogni singolo bit in esso contenuto ed inviarlo in sequenza sulla stessa linea elettrica, un po come avviene per la trasmissione in codice morse. La differenza sostanziale sta nel fatto che a generare e ricevere dati non c'è il telegrafista ma un computer per cui le velocità di trasmissione raggiungibili sono molto superiori.

Facciamo subito un esempio pratico e vediamo come fa un PC a trasmettere, ad esempio, il carattere A usando la RS232.

Non è necessario ovviamente realizzare gli esempi riportati di seguito in quanto presuppongono l'uso di una coppia di PC ed un oscilloscopio non sempre disponibili nei nostri mini-laboratori da hobbysta. Per comprendere il funzionamento di quanto esposto e' sufficiente fare riferimento alle figure a corredo.
Se prendiamo una coppia di fili e colleghiamo tra loro le porte seriali di due PC (che denomineremo PC trasmittente e PC ricevente) secondo lo schema riportato in figura:

otterremo la più semplice delle connessioni in RS232.

La linea Transmit Data (TXD) presente sul pin 3 del connettore DB9 maschio di cui il vostro PC è dotato è connessa alla linea Receive Data (RXD) presente sul pin 2 del secondo PC. Le masse (GND) presenti sul pin 5 di entrambe i PC sono connesse tra loro.
Per osservare i segnali generati dal PC trasmittente durante la trasmissione seriale colleghiamo tra la linea TXD e la linea GND un oscilloscopio e lanciamo in esecuzione su entrambe i PC un programma di emulazione terminale (tipo Hyperterminal o simili).
Configuriamo le porte seriali di entrambe i PC a 9600 baud, 8 data bit, 1 stop bit, no parity e disabilitiamo il controllo di flusso (handshake) sia hardware che xon/xoff. In questo stato qualsiasi cosa digiteremo sul PC trasmittente verrà inviata immediatamente sulla porta seriale. Assicuriamoci inoltre che il programma di emulazione terminale scelto sia opportunamente configurato per usare la porta seriale su cui siamo connessi (COM1 o COM2).

Proviamo a digitare la lettera A maiuscola e verifichiamo se è stata correttamente ricevuta sul PC ricevente. Fatto questo controllo andiamo a vedere sull'oscilloscopio che tipo di segnali sono stati generati per effettuare la trasmissione.
Quando non c'è nessuna trasmissione in corso la tensione sulla linea TXD è di -12 volt corrispondente alla condizione logica 1. Per indicare al PC ricevente che la trasmissione ha inizio, il PC trasmittente porta a +12 volt la linea TXD per un tempo pari all'inverso della frequenza di trasmissione ovvero al tempo di trasmissione di un singolo bit.

Nel nostro caso, avendo scelto di trasmettere a 9600 bit per secondo, la tensione di alimentazione rimarrà a +12 volt per: 1/9600=0.104 mS.
Questo segnale viene denominato START BIT ed e' sempre presente all'inizio di trasmissione di ogni singolo byte. Dopo lo start bit vengono trasmessi in sequenza gli otto bit componenti il codice ASCII del carattere trasmesso partendo dal bit meno significativo. Nel nostro caso la lettera A maiuscola corrisponde al valore binario 01000001 per cui la sequenza di trasmissione sarà la seguente:

Una volta trasmesso l'ottavo bit (bit 7), il PC aggiunge automaticamente un ultimo bit a 1 denominato STOP BIT ad indicare l'avvenuta trasmissione dell'intero byte. La stessa sequenza viene ripetuta per ogni byte trasmesso sulla linea.
Aggiungendo al nostro cavo seriale una connessione tra il pin TXD (pin 3) del PC ricevente con il pin RXD (pin 2) del PC trasmittente, potremo effettuare una trasmissione RS232 bidirezionale. Il cavo che abbiamo ottenuto è il più semplice cavo NULL MODEM in grado di mettere in collegamento tra loro due DTE.

Come collegare il nostro circuito d'esempio

Come accennato prima il nostro circuito d'esempio simula un dispositivo DCE. Questo significa che il cavo che dovremo realizzare non dovrà essere di tipo NULL MODEM o INVERTENTE ma DRITTO ovvero con i pin numerati allo stesso modo connessi tra loro. Questo tipo di cavo è identico a quelli che vengono usati per connettere al PC un modem esterno.
Dato che i dispositivi DTE sono sempre dotati di connettore DB9 maschio, il nostro circuito, essendo un DCE, avrà un connettore DB9 femmina la cui piedinature è riportata nella seguente tabella:

In alcuni casi i PC sono dotati di vecchi connettori DB25 anziché DB9 per cui occorre far riferimento alla seguente tabella per ricavare le corrette equivalenze:

Il cavo di collegamento tra il PC ed il nostro circuito dovrà essere intestato a sua volta con un connettore femmina da un lato per poter essere inserito nella seriale del PC ed un connettore maschio dall'altro per poter essere inserito nel connettore del nostro circuito di prova. I collegamenti interni al cavo da usare sono riportati nella seguente figura.

Funzionamento del MAX232

Come accennato prima, nel nostro circuito d'esempio useremo un driver RS232, ovvero un integrato in grado di convertire i segnali a +/- 12 volt tipici della RS232 in segnali a 0/5 volt gestibili dalle porte del PIC.
Seguendo lo schema elettrico del nostro circuito d'esempio vediamo che il segnale di trasmissione proveniente dal PC entra dal pin 3 del connettore DB9 femmina sul pin 13 di U3. Sul pin 12 di U3 sarà presente un segnale a 0 volt quando sul pin 13 ci saranno +12 volt e 5 volt quando sul pin 13 ci saranno -12 volt. Il segnale presente sul pin 12 di U3 viene quindi inviato alla linea RA1 della porta A del PIC che in questo caso farà da linea di ricezione.
Sul pin 18 del PIC (RA1) avremo quindi la seguente corrispondenza di segnali con la linea TXD del PC.

Viceversa sul pin 17 (RA0) il PIC genera i segnali da inviare al PC a livello TTL che vengono convertiti in segnali RS232 da U3 tramine i pin 11 (ingresso TTL) e 14 (uscita RS232) e quindi inviati al PC tramite il pin 2 del connettore J2.

Applicazione d'esempio

Mettiamo finalmente mano al source della nostra applicazione d'esempio e vediamo come ricevere e trasmettere dati dal nostro PIC.
Nel file LCDTERM.ASM troverete il source completo del nostro terminale d'esempio.

Una volta montato il nostro circuito d'esempio e programmato correttamente il PIC16F84 possiamo collegare al nostro PC il circuito e fornire alimentazione. Sul display apparirà il cursore lampeggiante in alto a sinistra.
A questo punto lanciamo in esecuzione un programma qualsiasi di emulazione terminale e configuriamolo per usare la porta seriale a cui è collegato il circuito a 9600 baud, 8 data bit, 1 stop bit e no parity. Assicuriamoci inoltre che non sia abilitato alcun controllo di flusso dei dati sulla seriale sia esso hardware che xon/xoff.
Proviamo ora a premere qualche tasto sulla tastiera del PC ed osserviamo come i caratteri digitati vengano visualizzati anche sul display LCD del nostro circuito. Premendo i tasti CTRL-L potremo pulire lo schermo dell'LCD e visualizzare nuove scritte.

Analizziamo il sorgente

Andiamo ad analizzare ora il sorgente LCDTERM.ASM del firmware della nostra applicazione d'esempio.
Partiamo dalla linea 24 dove troviamo le seguenti direttive:

TX equ 0 ;Tx data
RX equ 1 ;Rx data

in cui vengono assegnate alle costanti TX e RX rispettivamente le linee di trasmissione (TX) e ricezione (RX) del PIC. In questa applicazione in realtà non viene ancora usata la linea di trasmissione in quanto il nostro miniterminale è in grado per ora solo di ricevere caratteri.
Queste due costanti vengono utilizzate rispettivamente dalle subroutine di trasmissione e ricezione di caratteri via RS232: TxChar (vedi linea 421) ed RxChar (vedi linea 483). Queste due subroutine consentono in pratica di trasmette e ricevere byte in modalità seriale asincrona a 9600 bps, 8 bit dati, 1 stop bit e nessuna parità.
Per trasmettere un carattere sulla linea TX basta inserire nel registro W il valore da trasmettere ed effettuare una chiamata alla subroutine TxChar. Ipotizzando di voler trasmettere il carattere 'A' al PC dovremo inserire il seguente codice:

movlw  'A'
call   TxChar

Per ricevere caratteri l'operazione è leggermente più complessa. Prendiamo in esame il nostro esempio a partire dalla linea 129:

MainLoop
        btfsc PORTA,RX
        goto MainLoop

        call RxChar

In pratica il nostro programma esegue un loop infinito finché non rileva uno stato logico 0 sulla linea RX. Quando questo avviene significa che molto probabilmente e' arrivato lo START BIT dal PC e che, secondo quanto detto sopra, arriveranno in sequenza i bit apparteneti al dato trasmesso dal PC.
In questo caso viene chiamata la RxChar che si occuperà di leggere ogni singolo bit ricevuto, compattarli in un unico byte e restituire il valore del byte cosi' ricevuto nel registro ShiftReg.
Una volta lanciata la RxChar azzera il registro ShiftReg in cui verranno memorizzati i bit man mano che vengono ricevuti

RxChar
        clrf ShiftReg

quindi mette a 8 il registro BitCount usato per il conteggio del numero di bit in arrivo

        movlw 8
        movwf BitCount

a questo punto attende un periodo pari a circa 1 bit e mezzo in modo da far scorrere il tempo necessario alla trasmissione dello start bit e campionare il valore del BIT 0 circa a meta' del tempo di durata.

        
DELAY BIT_DELAY+BIT_DELAY/2 ;Wait 1.5 bit

a questo punto legge lo stato della linea RX ed inserisce il valore letto nel flag di CARRY (C) del registro STATUS e quindi effettua una istruzione di ROTATE RIGHT F TROUGHT CARRY (RRF) con il registro ShiftReg in modo da spostare verso destra tutti i bit del registro ShiftReg ed inserire nel bit più'significativo il valore appena letto dalla linea RX come riportato nella seguente figura:

questa lettura avviene per otto volte ad intervalli di tempo pari alla durata di un bit in modo da campionare il valore della linea RX sempre al centro del bit in ricezione.

wDB
        btfss PORTA,RX
        goto RxBitL
RxBitH
        nop

        bsf STATUS,C
        goto RxShift
RxBitL
        bcf STATUS,C
        goto RxShift
RxShift
        nop
        rrf ShiftReg,F

attende per un periodo di tempo pari ad 1 bit

            DELAY BIT_DELAY

continua a campionare se non ha ancora letto tutti ed otto i bit

            decfsz BitCount,F
            goto wDB

esce da RxChar dopo aver letto l'ultimo bit

        return

a questo punto nel registri ShiftReg dovrebbe esserci il byte trasmesso dal PC
Una volta letto il byte proveniente dal PC il nostro programma d'esempio controlla se il byte ricevuto e' un carattere di controllo oppure un normale carattere da visualizzare su LCD.
L'unico carattere di controllo implementato dal nostro miniterminale è il Form Feed (FF) corrispondente al codice ASCII decimale 12. La trasmissione di questo carattere verso una stampante determina l'avanzamento di un foglio di carta. Nel nostro caso pulisce il contenuto dell'LCD. Il form feed può essere trasmesso dal nostro simulatore di terminale su PC premendo il tasto CTRL seguito dalla lettera L.
Questa è la parte di codice che gestisce la ricezione di un Form Feed:

CheckFormFeed

        movlw 12
        xorwf ShiftReg,W
        btfss STATUS,Z
        goto _CheckFormFeed

        clrf xCurPos
        clrf yCurPos
        call LcdClear
        goto MainLoop

_CheckFormFeed

in pratica viene controllato se il valore ricevuto dalla subroutine RxChar è pari a 12. In caso affermativo vengono azzerati i registri xCurPos e yCurPos che mantengono il valore X,Y del cursore carattere su display. Quindi viene chiamata la subroutine LcdClear che si occupa di inviare i comandi corretti al display LCD per azzerarne il contenuto.
Nel caso non sia stato trasmetto un FF dal PC, il carattere ricevuto viene inviato nudo e crudo al display con il seguente codice:

movf ShiftReg,W
call putchar

e quindi si ritorna ad attendere lo START BIT del prossimo carattere con la seguente istruzione:

goto MainLoop

La subroutine putchar in pratica invia il valore contenuto nel registro W al display LCD nella posizione in cui si trova il cursore carattere (xCurPos e yCurPos), quindi si occupa di mandare a capo il cursore se si è raggiunto il fine riga o di riportarlo alla prima riga se si è raggiunto il fine display, In tutti i casi i registri xCurPos ed yCurPos vengono aggiornati alla prossima posizione in cui poter scrivere il successivo carattere ricevuto dal PC.

Scarica subito una copia gratis
Tags:

Una risposta

  1. Avatar photo testato 9 Dicembre 2011

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend