Guida alla Programmazione in C del PIC, 11° Parte

Guida alla Programmazione in C del PICNella Undicesima Parte della Guida si Parlerà del Protocollo di Comunicazione SPI Presentando un Esempio Con Codice e Schema per Comunicazone Master/Slave…


 
 
 
 




 

INTRO

L’SPI è una modalità di funzionamento del modulo Master Synchronous Serial Port (MSSP) ed è stato inizialmente creato per l’uso nei microprocessori. Questo è un modulo per comunicazione seriale per comunicare con altre periferiche come ADC, display, EEPROM o microcontrollori. Questo modulo, come detto prima può funzionare in due modalità:

  • Serial Peripherall Interface (SPI)
  • Inter-Integrated Circuit (I2C)
  • Full master mode
  • Slave mode (con indirizzo)

In un sistema che usa la comunicazione SPI, uno dispositivo si comporta come master e uno come slave, il che vuol dire che uno genera il clock e avvia la comunicazione, l’altro scambia dati. Molti microcontrollori PIC hanno al loro interno questo modulo. La comunicazione SPI è sincrona, quindi c’è il clock ed è full duplex, ovvero si può trasmettere e ricevere contemporaneamente. Inoltre vi è anche la funzione di abilitazione dello slave. Il modulo SPI è anche chiamato 4-fili, questo perché essendo sincrono full duplex con abilitazione, servono 4 fili per la comunicazione. In particolare le connessioni sono:

  • SCLK (Serial Clock): Questo PIN è segnale di clock. È generato dal master e ricevuto da tutti gli slave connessi.
  • MOSI (Master Out Slave In) o SDO(Serial Data Output): questo pin trasporta I dati dal master agli slave.
  • MISO (Master In Slave Out) o SDO(Serial Data Input): questo pin trasporta I dati dagli slave al master.
  • SS (Slave Select) o CS (Chip Select): Questo PIN permette al dispositivo master di avvertire gli slave che vuole trasmettere. Questo segnale è attivo basso, e se è basso vuol dire che la trasmissione è attiva.

Il segnale CS viene usato quando ci sono più di uno slave e può essere usato oppure no. Se ci sono più slave ci possono essere più segnali CS. Una classica connessione è così fatta:

spi-pic18f-pic16f
I vantaggi del SPI sono che è full duplex, ha una velocità maggiore degli altri protocolli del PIC, supporta diversi slave ma un solo master, il protocollo e semplice, il consumo di potenza piccolo e inoltre MIKROC dispone della libreria hardware. Gli svantaggi sono l’elevato numero di linee di comunicazione e che è una comunicazione per breve distanza come l’RS232.

 




 

MIKROC FOR PIC PER IL MODULO SPI

Utilizzare la comunicazione SPI  diventa molto semplice grazie a MIKROC che dispone di una completa libreria per la comunicazione. In MIKROC. Non tutti i PIC hanno il modulo SPI, per quelli che non lo hanno, si può usare la libreria software, anche se non consigliato visto che più lento e richiede più cicli. Alcuni microcontrollori non supportano alcune istruzioni e inoltre per i PIC16 è possibile scegliere i PIN di uscita. Vi sono varie subroutine che verranno spiegate qui di seguito:

  • SPI1_Init(); La seguente routine configura e abilita il modulo SPI con il seguente setting: to di Fosc, clock inattivo a livello basso, dati trasmessi sul fronte di salita del clock e dati campionati a metà dell’intervallo di clock. Il modulo SP1 per i PIC16 è inizializzato coi i pin RC3, RC4 e RC5 con le funzioni SCK, SDI e SDO. Per i PIC18F invece si hanno due moduli, SPI1 e SPI2 con i PIN RD6, RD5, e RD4 per le funzioni SCK, SDI e SDO.
  • SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV4, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH); Con questa subroutine è possibile scegliere la frequenza (_SPI_MASTER_OSC_DIV4, ovvero Fosc/4, _SPI _MASTER_OSC_DIV16, ovvero Fosc/16, _SPI _MASTER_OSC_DIV64, ovvero Fosc/64, _SPI_MASTER_TMR2 ovvero il clock arriva dal timer counter) inoltre è possibile scegliere se attivare il PIN SS oppure no (_SPI _SLAVE_SS_ENABLE e _SPI _SLAVE_SS_DIS).Si può inoltre scegliere quando campionare i dati (_SPI_DATA_SAMPLE_MIDDLE a metà periodo oppure _SPI _DATA_SAMPLE_END alla fine del periodo), si può scegliere lo stato IDLE ( se IDLE a livello basso _SPI _CLK_IDLE_LOW o a livello alto _SPI _CLK_IDLE_HIGH) e infine si può scegliere se i dati sono validi sul fronte di salita o discesa (_SPI_LOW_2_HIGH sul fronte di salita e _SPI_HIGH_2_LOW se i dati sono validi sul fronte di discesa).
  • SPIx_Read: Legge un byte dal buffer del protocollo SPI e ritorna il dato letto. La routine si utilizza nel seguente modo dato = SPI1_Read(buffer);.
  • SPIx_Write: Scrive un dato di dimensione un byte nel buffer dell’SPI. Per funzionare ha bisogno, come la routine precedente, dell’inizializzazione del modulo e si utilizza nel seguente modo SPI1_Write(dato);
  • SPI_Set_Active: Serve per settare quale modulo (o moduli) SPI vengono utilizzati. Ad esempio si può utilizzare un solo modulo per leggere e scrivere, oppure due moduli in cui uno legge e l’altro scrive. Per utilizzare questa funzione bisogna utilizzare la seguente stringa: SPI_Set_Active(&SPI2_Read, &SPI2_Write); in cui il modulo SPI2 legge e scrive i dati.

Per i microcontrollori con un solo modulo non serve indicare la x all’interno delle routine e ovviamente non serve la routine per indicare con quale modulo si legge e con quale si scrive.
 

CODICE

Proviamo a scrivere un semplice codice, in cui il trasmettitore semplicemente conta da 0 a 15 e invia il conteggio al ricevitore e il ricevitore semplicemente visualizza sulle PORTB il valore ricevuto.

Il codice per il trasmettitore è:

unsigned int short Dato, Cont, Buffer; //Variabili

void main() {
  TRISB = 0x00;                        //TRISB uscite   

  SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV64,
 _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_HIGH_2_LOW);

  Dato = 0x00;                         //inizializza variabili
  Cont = 0x00;

  while(1){                            //Ciclo infinito   

    if(Cont < 0x0f){                   //Se conta < 15
      Cont = Cont + 0x01;              //Incrementa 
      SPI1_Write(Cont);                //Invia il valore
      PORTB = Cont;                    //Visualizzalo sulle PORTB del TX  
      Delay_ms(1000);                  //Aspetta un secondo  
    }
    else if (Cont = 0x0f){             //Se conta = 15 resetta  
      Cont = 0x00;
      SPI1_Write(Cont);                //Invia il valore
      Delay_ms(1000);                  //Aspetta un secondo   
    }
  }
}

Prima di tutto si inizializza una variabile da un byte per il conteggio, poi nel programma principale si settano le PORTB come uscite e si setta l’SPI. Si utilizza la modalità master con una frequenza 1/64 della frequenza di oscillazione del microcontrollore, di campionare il dato a metà del periodo di clock, di avere lo stato di riposo quando il clock è a livello basso e inoltre di avere l’istante di campionamento sul fronte di discesa del clock.

Una volta inizializzato l’SPI si azzera la variabile “Cont” e si scrive il while(1); per il ciclo infinito.

Nel ciclo infinito si invia il valore di “Cont” sull’SPI e poi si aspetta 1 secondo prima di incrementare il valore di “Cont” e poi visualizzare il valore su PORTB. Se il valore di “Cont” è 15 si resetta il valore e si aspetta un secondo. Dopo di che ricomincia tutto il ciclo.

Il codice del ricevitore è:

unsigned int short Dato, Buffer;                //Inizializza variabili

void main() {                                   
  TRISB = 0x00;                                //Inizializza TRISB ed SPI
  SPI1_Init_Advanced(_SPI_SLAVE_SS_ENABLE, _SPI_DATA_SAMPLE_MIDDLE, 
_SPI_CLK_IDLE_LOW, _SPI_HIGH_2_LOW);

  Dato = 0x00;                                 //Inizializza a 0 le uscite
  PORTB = Dato;

  while(1){                                    //Ciclo infinito

    Dato = SPI1_Read(buffer);                  //Leggi dato
    PORTB = Dato;                              //Mostralo su PORTB 
  }
}

Nel codice del ricevitore si inizializzano due dati da un byte, una per il dato ricevuto uno per il buffer dell’SPI. Nel codice principale si settano le PORTB come uscite e si resetta la variabile “Dato” e si setta l’SPI come slave con il pin di Slave Select (SS) attivato.

La libreria mikroC non funziona senza abilitare questo pin.

Nel ciclo infinito si va a leggere il dato e si invia il dato appena letto sulle PORTB e questo continua all’infinito.

 

SCHEMA

Lo schema è il seguente:

schema

I cristalli X1 e X2 sono quarzi da 8MHz e con i due condensatori da 22pF per ogni microchip formano il circuito di oscillazione. La resistenza R1 ed R2 servono per evitare che il PIC18F252 si resettino, mentre ai pin 20 si hanno 5V e ai pin 19 e 8 la massa dell’alimentazione.

Il pin del clock del master ovvero pin 14, chip U1, è connesso al pin 14 dello slave, ovvero U2. Il pin d’uscita SDO ovvero pin 16 è connesso al pin 15 ovvero SDI. Sui primi 4 pin delle PORTB sono connessi i 4 LED con le 4 resistenze di protezione da 470ohm.

La configurazione dei fuses per il PIC18F è la seguente, mentre per il PIC16F è tutto disabilitato con oscillatore “HS”:

fuses PIC18F

È tutto disabilitato tranne il brownout reset e l’oscillatore è in configurazione HS con quarzo a 8MHz. Lo schema su breadboard ha il seguente aspetto:

schema-su-breadboard

 

DOWNLOAD

È possibile scaricare la simulazione, il file .hex e il file .c per il PIC18F e per il PIC16F al seguente LINK!!!




 

[Voti Totali: 0 Media Voti: 0]
Segui la Nostra Pagina Facebook: Facebook

Lascia un commento

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