Comunicazione su CAN-BUS con dsPIC30F

Can bus dspic

Una panoramica sul protocollo di comunicazione CAN (Controller Area Network) ed un approfondimento sull'utilizzazione del canbus con il dsPIC30F. Inoltre un interessante studio sugli interrupt e sulla gestione errori del modulo CAN del dsPIC30F.

Il sistema di comunicazione CAN risale alla fine degli anni ’80 ma solo verso la metà degli anni ’90 prende piede nel settore automotive. Vista la sua robustezza ed immunità al rumore, la sua applicazione si è allargata fino a coinvolgere il settore elettromedicale e dell’automazione industriale e oggi è considerato uno dei protocolli di trasmissione più utilizzati in campo industriale. Le specifiche del protocollo sono state standardizzate e sono descritte nella specifica ISO-11898.

IL PROTOCOLLO CAN

Messaggi

Una rete CAN è basata sull’interconnessione dei dispositivi mediante una linea di comunicazione seriale differenziale a due fili come mostrato in figura 1.

Figura 1. La struttura di una rete CAN

Figura 1. La struttura di una rete CAN

Ogni dispositivo connesso è un nodo ed ogni nodo può inviare o ricevere dati sulla rete. Chiaramente tutti  i nodi della stessa rete devono operare utilizzando il medesimo baud rate scelto in fase di progettazione tra diversi standard in base ai requisiti di latenza imposti. Tipiche velocità di trasmissione sono 1MHz, 500KHz e 125KHz. Diversi nodi sulla stessa rete potrebbero trovarsi ad inviare messaggi sul bus nello stesso momento, ma poiché il bus può essere occupato da una sola trasmissione per volta, è dunque necessario un arbitraggio per la determinazione delle priorità di accesso al bus. I dati vengono trasmessi sottoforma di messaggio e ciascun messaggio è composto da un identificatore (ID) e da un eventuale campo dati. Il messaggio inviato da un nodo viene ricevuto da tutti i nodi della rete (compreso il nodo trasmettitore) i quali, come prima cosa, verificano che quanto ricevuto sia privo di errori, quindi inviano una notifica di avvenuta ricezione (ACK). La figura 2 mostra un tipico messaggio dati.

Figura 2. Messaggio dati CAN

Figura 2. Messaggio dati CAN

Il primo bit è lo Start Of Frame che indica l’inizio di una nuova trasmissione sul bus. Successivamente viene inviato il campo ID (l’identificatore  del messaggio) che permette di determinare a quale dei nodi della rete quel particolare messaggio è destinato. Sono previsti due formati per il campo ID: Standard ID (SID) e Extended ID (EID). Il primo prevede un identificatore ad 11 bit, mentre il secondo, oltre all’identificatore di 11 bit prevede una estensione di ulteriori  18  bit.  All’identificatore  segue il campo dati preceduto da un campo che ne specifica la lunghezza in byte (da 0 fino a 8byte). Segue quindi un campo di 15 bit destinato ad un controllo di ridondanza ciclico (CRC) che permette al nodo ricevente di individuare eventuali errori nella trasmissione. La coda del messaggio è infine costituita da un campo ACK quindi il campo EOF (End Of Frame) che notifica la chiusura della trasmissione e rende il bus libero per un nuovo scambio dati. L’effetto di una trasmissione dati sul bus è paragonabile ad un annuncio fatto ad una platea da un altoparlante: tutti saranno in grado di sentire l’annuncio, ma solo la persona interessata risponderà attivamente. Analogamente tutti  i nodi della rete CAN riceveranno il messaggio, ma solo il nodo interessato ne processerà il contenuto. Per discriminare se un messaggio è rilevante o meno per un determinato nodo, il nodo stesso effettua una verifica del campo ID utilizzando opportuni filtri: se l’ID soddisfa uno dei criteri di matching imposti dai filtri il messaggio entrerà nel buffer di ricezione del nodo e ne verrà processato il contenuto, altrimenti l’intero messaggio verrà ignorato. L’identificatore determina anche la priorità del messaggio stesso in modo che i messaggi ricevuti da uno stesso nodo siano processati mediante un ordine di priorità ben definito.

Arbitraggio

Come già accennato è possibile che due o più nodi tentino la trasmissione contemporaneamente o durante una trasmissione già in corso. Il protocollo CAN prevede questo tipo di situazione che viene gestita con un sistema di arbitraggio. Innanzitutto un nodo non può iniziare una trasmissione se il bus non si trova nello stato idle (non occupato), per cui se una trasmissione è in corso, i nodi che intendono trasmettere attendono la fine della transazione. Il sistema di arbitraggio entra in gioco se due o più nodi  iniziano una trasmissione nello stesso istante. L’arbitraggio è basato sul meccanismo dell’AND cablato in cui uno “zero”  logico ha priorità  su un “uno” logico per cui un messaggio con un ID più basso ha priorità maggiore di uno con ID più alto. In particolare quando viene inviato un livello logico sul bus da parte di un nodo, il nodo stesso verifica anche che quel livello logico sia effettivamente presente sul bus. Se ciò non avviene significa che un messaggio di priorità più alta ha occupato il bus quindi il nodo in oggetto ritarda la trasmissione. In figura 3 un esempio di arbitraggio nel caso in cui vengano trasmessi i messaggi con ID pari a 0x005 e 0x006 contemporaneamente da parte di due nodi (nodo1 e nodo2 rispettivamente).

Figura 3. Esempio di contesa del bus da parte di due nodi

Figura 3. Esempio di contesa del bus da parte di due nodi

In questo caso i due nodi che tentano la trasmissione, riusciranno a trasmettere i primi 8 bit dell’ID perché identici per i due identificatori. Al tentativo di trasmissione del nono bit, il nodo2 rileverà una incongruenza tra il bit trasmesso (1) e il livello logico del bus (che sarà 0 perché imposto dalla trasmissione del nono bit da parte del nodo1) per cui il nodo2 sospende la trasmissione e resta in attesa che il bus si liberi. Il nodo1 continuerà invece la trasmissione grazie al fatto che l’ID del messaggio da trasmettere ha priorità sugli altri.

Bit Timing

Per una comunicazione CAN, si definisce bit-time TBIT il tempo richiesto per la trasmissione di un bit di un messaggio ed è pari all’inverso del baud rate. Ad esempio per una trasmissione effettuata ad 1MHz, il TBIT vale 1 microsecondo. Lo standard CAN suppone che ciascun bit-time sia suddiviso in quattro segmenti come mostra la figura 4:

  • Segmento di sincronizzazione
  • Segmento di propagazione
  • Segmento fase1
  • Segmento fase2

A sua volta, ciascun segmento può essere considerato come composto da un certo numero di unità temporali  detti quanti  temporali (Time Quanta) o semplicemente quanti (d’ora in avanti indicati con TQ). L’uso del quanto temporale è dettato dal fatto che la comunicazione CAN non prevede un segnale di sincronizzazione comune a tutti  i nodi pertanto ciascun nodo ha un oscillatore locale per la generazione del segnale di sincronizzazione basato appunto sul quanto temporale. Come illustrato nella figura 4, mentre il segmento di sincronizzazione è costituito da un solo quanto, gli altri tre segmenti possono essere composti da 1 a 8 quanti temporali.

Figura 4. La suddivisione in segmenti di un bit-time e la suddivisione dei segmenti in quanti temporali

Figura 4. La suddivisione in segmenti di un bit-time e la suddivisione dei segmenti in quanti temporali

INIZIALIZZAZIONE DEL MODULO CAN

Una volta noto il numero di quanti temporali utilizzati in ciascun segmento, è possibile inizializzare i registri C1CFG1 e C1CFG2 la cui struttura è riportata in figura 5.

Figura 5. I registri C1CFG1 e C1CFG2

Figura 5.  I registri C1CFG1 e C1CFG2

In particolare i bit PRSEG specificano il numero di quanti temporali nel segmento propagazione; i bit SEG1PH specificano il numero di quanti nel segmento fase 1; SEG2PH specificano il numero di quanti nel segmento fase 2; i bit BRP determinano il clock della comunicazione CAN ovvero il bit rate. Il bit CANCKS del registro C1CTRL, se posto a zero consente una maggiore risoluzione nella temporizzazione della comunicazione. Al reset il modulo CAN del dsPIC30F si trova in modalità configurazione pertanto non è in grado di inviare o ricevere dati fintanto che non viene posto nella modalità operativa. Questo viene fatto scrivendo uno zero logico nei bit 8-10 (REQOP0-REQOP2) del registro C1CTRL la cui struttura è riportata in figura 6.

Figura 6. Registro C1CTRL

Figura 6. Registro C1CTRL

A conferma del cambio della modalità di funzionamento gli stessi bit vengono automaticamente riportati in OPMO-DE2-OPMODE0 dello stesso registro. Prima di entrare in modalità operativa è comunque necessario abilitare le interruzioni per il modulo CAN.

RICEZIONE DI MESSAGGI

Il modulo  CAN del dsPIC30F può essere pensato suddiviso in due parti come mostra la figura 7: il blocco protocol engine che gestisce l’invio e ricezione dei messaggi ed il blocco buffers in cui vengono bufferizzati i messaggi in ingresso ed in uscita.

Figura 7. I due blocchi del modulo CAN

Figura 7. I due blocchi del modulo CAN

Alla ricezione di un messaggio i singoli bit vengono memorizzati nel buffer MAB per cui, alla fine della trasmissione da parte del nodo remoto trasmittente, l’intero messaggio si troverà nel buffer MAB di ciascun nodo della rete. Solo a questo punto l’ID del messaggio viene filtrato per la verifica dei criteri di matching. La struttura prevede due buffer RXB0 ed RXB1 a ciascuno dei quali  sono associati rispettivamente due (RXF0, RXF1) e quattro  (RXF2-RXF5) filtri. Oltre ai filtri  vi sono anche due maschere (RXM0, RXM1) associate rispettivamente ai due buffer RXB0 e RXB1. Se un messaggio soddisfa uno dei criteri imposti dai filtri e dalla maschera, il contenuto del buffer MAB viene spostato in RXB0 o RXB1 a seconda del filtro in corrispondenza del quale è avvenuto il matching.

I buffer di ricezione

La struttura dei buffer di ricezione è quella di figura 8.

Figura 8. Struttura dei buffer di ricezione

Figura 8. Struttura dei buffer di ricezione

Come si nota, ciascun buffer è composto da otto registri a 16 bit dei quali i primi tre contengono l’ID del messaggio ricevuto, i successivi quattro contengono il campo dati del messaggio, infine l’ultima word (C1RX1CON) costituisce un registro di controllo e di stato per l’intero buffer. Quando un messaggio passa in uno dei due buffer RXB, viene automaticamente settato il bit RXFUL (Receive Buffer Full) quindi generata una interruzione. Sarà cura dell’utente eseguire la lettura di tale buffer ed azzerare il bit RXFUL per rendere disponibile il sistema alla ricezione di un nuovo frame. Il bit 3 del registro C1RX1CON se ad uno indica che il messaggio ricevuto è di tipo Remote Transfer Request ovvero una richiesta di invio dati per quel nodo da parte di un nodo remoto. I bit 0-2 (FILHIT) indicano su quale dei filtri è stata soddisfatta la condizione di matching. Il buffer RXB0 ha la possibilità di utilizzare RXB1 come appoggio. Si supponga infatti che sia arrivato un messaggio e che questo sia stato accettato dal filtro RXF1 (associato a RXB0) e si supponga che il messaggio successivo soddisfi i criteri di matching del filtro RXF0 (anch’esso associato ad RXB0): in questo caso anziché generare un errore di Buffer Overflow e rifiutare il secondo messaggio, quest’ultimo viene memorizzato nel buffer RXB1 (che, chiaramente, dovrà essere vuoto per accettare il messaggio). Ovviamente è possibile attivare o disattivare tale comportamento semplicemente mettendo rispettivamente ad uno o a zero il bit 2 (DBEN) di C1RX0CON.

Una nota sui filtri e le maschere

Alla ricezione di un messaggio l’ID  del messaggio stesso viene comparato bit per bit con i valori contenuti  nei vari filtri e nelle maschere. La maschera determina quali, tra i bit dell’ID, verranno passati ai filtri per la successiva verifica: se un bit della maschera è a zero il relativo bit dell’ID sarà accettato dai successivi filtri indipendentemente dai criteri di matching. Il messaggio viene bufferizzato solo se l’ID, opportunamente mascherato, soddisfa il matching con uno dei filtri a cui è sottoposto. Ciascun filtro ha un bit EXIDE mediante il quale si discrimina se quel filtro verrà utilizzato per gli identificatori standard o per quelli estesi. Questo accorgimento permette al programmatore di scegliere il tipo di messaggio a cui associare il filtro. Le maschere hanno una struttura molto simile a quella dei filtri e possiedono un bit MIDE mediante il  quale è possibile determinare se considerare o meno il bit  EXIDE  dei vari filtri:  se MIDE=0 il bit EXIDE dei filtri viene ignorato per cui verranno controllati indistintamente e da tutti i filtri sia i messaggi con ID standard sia messaggi con ID esteso. La figura 9 mostra la struttura di un filtro.

Figura 9. Struttura di un filtro

Figura 9. Struttura di un filtro

TRASMISSIONE DI MESSAGGI

Il modulo CAN del dsPIC30F possiede tre buffer di trasmissione, identificati come TXB0, TXB1 e TXB2 (figura 7), uno solo dei quali può trasmettere dati ad un certo istante. In fase di trasmissione il buffer attivo trasferisce il proprio contenuto al blocco CAN protocol engine che si occuperà della trasmissione fisica e la gestione degli errori. La struttura di un buffer di trasmissione è riportata in figura 10.

Figura 10. Struttura dei buffer di trasmissione

Figura 10. Struttura dei buffer di trasmissione

Mediante il bit TXIDE si determina se il messaggio che verrà trasmesso ha identificatore standard o esteso mentre i quattro bit DLC indicano il numero di byte di cui è composto il campo dati. È possibile inviare anche dei messaggi speciali noti come RTR (Remote Transfer Request) i quali richiedono ad un nodo specifico l’invio di dati utilizzando un nuovo Data Frame. Un messaggio RTR è identificato come tale grazie al bit  TXRTR a livello alto e non contiene mai un campo dati. Una volta completata la composizione del messaggio in uno dei buffer TXB, la trasmissione ha inizio settando il bit TXREQ: da questo momento in poi il messaggio verrà inviato non  appena il bus risulta libero. Il bit TXREQ viene automaticamente azzerato al termine della trasmissione contestualmente alla generazione di una interruzione. Nel caso in cui il bit TXREQ risulta settato in più di un buffer di trasmissione, i  messaggi verranno  automaticamente accodati. A livello utente è possibile impostare una priorità per ciascun buffer, priorità scelta tra quattro livelli possibili determinati dallo stato dei due bit TXPRI: ‘00’ corrisponde alla priorità più bassa, mentre ‘11’ è il livello di priorità più elevato. Nel caso in cui due buffer abbiano lo stesso livello di priorità, verrà data precedenza al buffer di indice più elevato (ad esempio se TXB1 e TXB2 hanno la stessa priorità, TXB2 avrà comunque la precedenza).

INTERRUZIONI

Un modulo  CAN genera una sola interruzione cui corrisponde un unico vettore di interruzione. Tuttavia l’interruzione può essere causata da diversi eventi verificatisi all’interno del modulo  e ciascuno di questi eventi ha il proprio bit di abilitazione e flag per le interruzioni. Ecco le possibili cause di interruzione ed i relativi flag di notifica:

  1. Interruzione generata a seguito della ricezione di un messaggio in uno dei due buffer di ricezione (RX0IF, RX1IF);
  2. Interruzione generata da uno dei tre buffer di trasmissione al termine di una trasmissione conclusa con successo (TX0IF, TX1IF, TX2IF);
  3. Interruzione generata  se il micro è in modalità sleep ed il modulo CAN rileva attività sul bus (WAKIF);
  4. Interruzione generata se viene ricevuto un messaggio non valido (IVRIF);
  5. Interruzione generata da errore interno (ERRIF) ed in particolare:

5.1   Overflow su buffer di ricezione RXB0 (RX0OVR);
5.2   Overflow su buffer di ricezione RXB1 (RX1OVR);
5.3   Errore sul bus in trasmissione (TXWAR);
5.4   Trasmettitore in modalità Error Passive (TXBP);
5.5   Trasmettitore in modalità bus-off (TXBO);
5.6    Errore sul bus in ricezione (RXWAR);
5.7    Ricevitore un modalità error passive (RXBP);
5.8    Errore sul bus da parte del trasmettitore o del ricevitore (EWARN).

Il modulo CAN tiene traccia del numero di errori che si verificano sia in trasmissione che in ricezione incrementando appositi contatori. Quando i contatori raggiungono il valore 96 viene settato il bit EWARN fino ad entrare nella modalità error passive in cui il nodo riceve i messaggi ma non ne elabora il contenuto. La modalità error passive viene innescata al raggiungimento del valore 128 nel contatore di errori, mentre se viene raggiunto il valore 255 il nodo entra in bus-off, modalità in cui il nodo è completamente scollegato dal bus.

Un esempio di codice in C30

Come esempio dimostrativo sull’uso del modulo CAN del dsPIC30F, il listato1 mostra un frammento di codice C per l’inizializzazione del modulo CAN mentre il listato 2 mostra la routine di servizio per l’interruzione scatenata dal modulo CAN.

#include "can.h"

CAN1SetOperationModeNoWait(CAN_REQ_OPERMODE_CONFIG_NO_WAIT);

C1RXM0SID=0x1FFC;    //Impostazione della maschera

C1RXF0SID=0x1FFC;   //Impostazione del filtro F0


//Inizializz. modulo CAN
CAN1Initialize(CAN_BAUD_PRE_SCALE(20)&CAN_SYNC_JUMP_WIDTH2,
CAN_PROPAGATIONTIME_SEG_TQ(2)&CAN_PHASE_SEG1_TQ(4)&CAN_PHASE_SEG2_TQ(3));

CAN1SetOperationMode(CAN_REQ_OPERMODE_NOR&CAN_IDLE_CON&CAN_CAPTURE_DIS&CAN_
MASTERCLOCK_0);

//configurazione delle interruzioni per il modulo CAN
ConfigIntCAN1(0x3F,CAN_INT_PRI_5&CAN_INT_ENABLE);

Listato 1
void _ISR _C1Interrupt(void)
{
C1EC=0;
C1INTF=0;
IFS1bits.C1IF=0;

if((C1INTFbits.TXEP)||(C1INTFbits.RXEP))
{
C1CTRL|=0x400;
while((C1CTRL&0x80)==0);
C1CTRL&=0xF800;
}
if(!C1TX0CONbits.TXREQ)
{
//inserire qui il codice da eseguire all’avvenuto invio di un messaggio

}
if (C1RX0CONbits.RXFUL)
{
C1RX0CONbits.RXFUL=0;
//inserire qui il codice da eseguire all’avvenuta ricezione di un messaggio
}
}

Listato 2

Iscriviti e ricevi GRATIS
Speciale Pi

Fai subito il DOWNLOAD (valore 15€) GRATIS

7 Commenti

  1. Ernesto Sorrentino 16 dicembre 2015
  2. yesenergy 16 dicembre 2015
  3. maxein 4 febbraio 2016
    • Maurizio Di Paolo Emilio Maurizio 4 febbraio 2016
      • maxein 4 febbraio 2016
    • Emanuele Bonanni Emanuele 4 febbraio 2016
  4. maxein 4 febbraio 2016

Scrivi un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Iscriviti e ricevi GRATIS
Speciale Pi

Fai subito il DOWNLOAD (valore 15€) GRATIS