SPI nei PIC - 6




Codice assembler per lo SLAVE

Esaminiamo in dettaglio il codice assembler che implementa la funzione di SLAVE. Il file completo può essere scaricato: PIC_SPI_files

Si nota subito che la verifica degli errori è stata omessa dal codice di esempio per facilitare il codice.

La prima parte del programma comprende alcuni commenti sul programma e sulla sua  funzione. 
Avere un  codice ben documentato e commentato è buona pratica generale di scrittura.
; PIC_SPI_slave.asm
; SLAVE Rev 0
; Demonstrates SPI connection between 2 PICs
; Master sends data (a counter), Slave receives and outputs to LEDs
; on PORTB
Segue la sezione in cui si fissa il processore utilizzato ( 16f876 nel nostro caso) e si fissa la configurazione del micro mediate la 
direttiva
CONFIG.

I bit della configurazione devono essere settati altrimenti resteranno i valori di default stabiliti nel file di supporto del micro incluso
nel programma ( P16F876.inc ). La configurazione del micro e' la stessa di quella vista per il MASTER
Di seguito la descrizione dei vari termini della direttiva
_CONFIG

list p=16F876
#include "p16F876.inc"
__CONFIG _CP_OFF & _DEBUG_OFF & _WRT_ENABLE_OFF & _CPD_OFF
& _LVP_OFF & _BODEN_OFF & _PWRTE_ON & _WDT_OFF_ & _XT_OSC
_CP_OFF 			permette che la memoria di programma sia letta
_DEBUG_OFF
lascia il dispositivo funzionare senza il tool ICD
_WRT_ENABLE_OFF
disabilita la scrittura sulla memoria da programma
_CPD_OFF
disabilita la protezione dei dati su EEPROM
_LVP_OFF
disabilita la programmazione a bassa tensione permettendo l'uso della PORTB dopo la programmazione
_BODEN_OFF
Brownout di bassa tensione disabilitato
_PWRTE_ON
temporizzazione della partenza ( Power up timer)
_XT_OSC
oscillatore esterno quarzato
_WDT_OFF
watchdog disabilitato

Si definisce quindi mediante una direttiva #define il bit 5 della porta A come segnale SS. 
Laddove si scriverà SS si intende dire PORTA, 5.
#define SS 0x20 ; PORTA,5 (HW SS pin)
Finita la parte iniziale di settaggi del micro si passa al codice che inizia con la direttiva ORG 0 seguita da un nop 
che potrà essere sostituito con istruzioni di codice.
	ORG 0
nop ; FOR ICD
Si settano le porte: la PORTA è una porta con funzioni analogiche e si deve avere cura di settarla come 
DIGITALE e non come ANALOGICA disabilitando il convertitore A/D. Si setta il bit 5 come input.
La PORTB è settata per avere tutti i bit come uscita ( TRISB=0x00).
La PORTC è settata in modo da avere in pin SCK come ingresso essendo il clock trasmesso dal MASTER. 
Tutti i altri bit sono configurati come uscite. La direttiva BANKSEL è usata per potere raggiungere i registri
TRISA,TRISB, TRISC e ADCON1 nei rispettivi banchi di memoria diversi ( es BANK1).
; Set up the SPI Support
BANKSEL TRISA ; BANK 1
movlw 0x20 ; PORTA,5 is SS and it is input
movwf TRISA ;
movlw 0x06 ; Turn Off A/D mode for at least the
movwf ADCON1 ; Chip Select pin (all Digital mode)
; Set up output port
BANKSEL TRISB ; BANK 1
movlw 0x00 ; Configure all PORTB pins
movwf TRISB ; to be in output mode
; Set up the SPI
BANKSEL TRISC ; BANK 1
movlw 0x18 ; SCK is input (Slave), SDI is input,
movwf TRISC ; SDO is output, all others output
Si setta il modulo SSP per essere uno SPI in modalità slave.
; Set up the SPI
movlw 0x40 ; Mode 1,1 SPI with
movwf SSPSTAT ; middle of output time sampling
BANKSEL SSPCON ; BANK 0
movlw 0x34 ; Mode 1,1 SPI Slave Mode, /SS Required
movwf SSPCON ; SSP is on Here is the SPI Slave Code.

Il ciclo per la ricezione dei dati parte dalla etichetta Chk4Dat Si parte con il test sul bit BF del registro SSPSTAT.
Quando questo si setta, ovvero si e' riempito il buffer, la routine passa alla lettura del contenuto del SSPBUF (RX_Data ) che
rappresenta il dato trasmesso dal MASTER. Questo byte viene quindi caricato sulla PORTB che pilota gli 8 LED
che rappresenteranno visivamente  il valore del dato ricevuto ovvero il valore del contatore presente nel MASTER.
La routine si mette di ascolto sulla linea SDI  fino a che non arriva un dato che sarà poi visualizzato.

Chk4Dat 
	movlw 	SSPSTAT 	; Indirectly test
movwf FSR ; a register by loading FSR
btfss INDF,BF ; Here is the test
goto Skip_ND ; New data, do a transfer (below
RX_Data
	BANKSEL SSPBUF 		; BANK 0
movf SSPBUF,W ; put in SSPBUF into W
BANKSEL PORTB ; BANK 0
movwf PORTB ; Show the results on PORTB
DoAgain
; Optional customer code can go here
goto Chk4Dat ; Receive Next Byte
end