¿ Que tal estamos ?
Esto va a ser algo largo. Asi que sin mas entro en el tema.
Microchip tiene un tutorial sobre el modulo SPI, que podeis ver aqui:
http://ww1.microchip.com/downloads/en/DeviceDoc/spi.pdfEn resumen, el documento muestra como comunicar dos PIC's, Master y esclavo, y el soft correspondiente para cada uno. Ambos son 16F876.
El master corre un contador, cuyo valor se envia al esclavo. El esclavo pasa el valor recibido en el buffer SSPBUF a un puerto libre y configurado como output.
El valor recibido por el esclavo puede visualizarse mediante 8 leds conectados a ese puerto.
He implementado este tutorial en Isis. Aqui os muestro la pantalla:
Como se puede ver, he cambiado los micros; un 877A para el master y un 873A para el esclavo. ¿Por que?.....pues porque es lo que voy a utilizar
Tambien se puede ver que los relojes estan a 5000 Hz. Asi se puede ver tranquilamente el monitoreo de actividad SPI. El fichero completo lo teneis como adjunto (dosmicros_dsn.bin). Logicamente hay que quitarle la extension bin y dejarlo como DSN.
Los fuentes de master y eslave son estos:
Para el master:
; Master.asm
list p=16F877A
#include "p16F877A.inc"
__CONFIG _CP_OFF&_DEBUG_OFF&_WRT_OFF&_CPD_OFF&_LVP_OFF&_BODEN_OFF&_PWRTE_ON&_WDT_OFF&_XT_OSC
Ctr0 EQU 0x20 ; Variable con datos - SPI
Dly0 EQU 0x21 ; Variable funcion Delay (L-byte)
Dly1 EQU 0x22 ; Variable funcion Delay (H-byte)
#define CS 0x02 ; PORTA,2 chip select
ORG 0 ; Comienzo del codigo en direccion 0
nop ; FOR ICD. No implementations speed side effects.
; ****************Apoyo al SPI
; El pin RA2 del master se usa para soporte de la linea "Select Slave"
; La configuracion del puerto sera, por tanto "output, no analog"
BANKSEL TRISA ; Selecciona banco de TRISA: BANK 1
movlw 0x00 ; Preparar PortA, todo output.
movwf TRISA ; Hacerlo.
movlw 0x06 ; A/D DESACTIVADO
movwf ADCON1 ; Todo el portA es I/O digital
; El puerto C contiene el modulo SPI
BANKSEL TRISC ; Selecciona banco de TRISC (BANK 1)
movlw 0x10 ; SCK=output , SDI=input, SDO=output, others=output
movwf TRISC ; Hacerlo
movlw 0x40 ; 0100 0000. Sampled at middle
; SMP=0,Input data sampled at middle of data output time
; CKE=1,Data transmitted on rising edge of SCK
movwf SSPSTAT ;
BANKSEL SSPCON ; BANK 0
movlw 0x22 ; 0010 0001. SCK, SDO, SDI, and SS as serial port pins. CKP=LOW, SPI Master Mode, fosc/16
movwf SSPCON ;
; **************** Envio de datos a traves del modulo SPI del Master.
Send_DT
bcf PORTA,CS ; Enable Chip Select
movf Ctr0,W ; Counter a W.
movwf SSPBUF ; y a SSPBUF. Debe poner BF a 1
BANKSEL SSPSTAT ; BANK 1
Char1
btfss SSPSTAT,BF ; esperando Buffer Full
goto Char1 ; si no, otra vez
BANKSEL SSPBUF ; BANK0
movf SSPBUF,W ; leer desde SSPBUF. Debe poner BF a 0
bsf PORTA,CS ; Disable Chip Select Output (high)
; **************** conteo
Update_Test_Counter
incf Ctr0,F ; Incremento contador
Delay
movlw 0x01 ; Delay
movwf Dly1 ;
movlw 0x0F ;
movwf Dly0 ;
DlyLoop
decfsz Dly0,F ;
goto DlyLoop ;
decfsz Dly1,F ;
goto DlyLoop ;
; Done Delay ;
DoAgain
goto Send_DT ; Repetir envio de siguiente dato,
end
Para el esclavo:
; SPItstS0.asm
; SLAVE Rev 0
; Demonstrates SPI connection between 2 PICs
; Master sends data (a counter), Slave receives and outputs to LEDs
; on PORTB
list p=16F873A
#include "p16F873A.inc"
__CONFIG _CP_OFF&_DEBUG_OFF&_WRT_OFF&_CPD_OFF&_LVP_OFF&_BODEN_OFF&_PWRTE_ON&_WDT_OFF&_XT_OSC
slvdat EQU 0x21 ; Variable esclavo con datos - SPI
#define CS 0x20 ; PORTA,5 (HW SS pin)
ORG 0
nop ; FOR ICD
; Set up soporte SPI
BANKSEL TRISA ; BANCO 1
movlw CS ; pin Chip Select
movwf TRISA ; ...como input
movlw 0x06 ; A/D off
movwf ADCON1 ;
; Set up puerto output (leds)
BANKSEL TRISB ; BANCO 1
movlw 0x00 ; pins PORTB....
movwf TRISB ; ...como output
; ****************Setup del modulo SPI del Master.
; Set up SPI
BANKSEL TRISC ; BANCO 1
movlw 0x18 ; SCK input, SDI input. 0001 1000
movwf TRISC ; SDO output, otros output
movlw 0x40 ; 0100 0000. Sampled at middle, CKE=1
movwf SSPSTAT ;
BANKSEL SSPCON ; BANCO 0
movlw 0x24 ; 0010 0100. SCK, SDO, SDI, and SS as serial port pins. CKP=LOW, SPI Slave Mode, /SS Required
movwf SSPCON ; SSP on
movlw 0xAA;
movwf slvdat;
Chk4Dat
movlw SSPSTAT ; test
movwf FSR ; ....
btfss INDF,BF ; de BF
goto Chk4Dat ; si no 1, repetir test
BANKSEL SSPBUF ; BANCO 0
movf SSPBUF,W ; SSPBUF (dato) a W
BANKSEL PORTB ; BANK 0
movwf PORTB ; W a PORTB (leds)
DoAgain
movf slvdat,W ; dato esclavo a W
movwf SSPBUF ; ....y a SSPBUF.
goto Chk4Dat ; Receive Next Byte
end
Algunos detalles importantes:
- Proteus 7.2 sp6
- La comunicacion SPI se hace con polaridad de reloj 0 (CKP=0) y flanco de reloj 1 (CKE=1).
- El compilador es MPASMWIN de Microchip.
- La linea de comandos en la ventana "Source/Code Generation Tool..." de Isis para el compilador MPASMWIN es ** "%1" /q ** , el source es ASM y el objeto, HEX.
- El monitor SPI esta configurado como "monitor"
- En la ventana "Debug/Configure diagnostics....." se ha seleccionado el modo "debug" para ambos modulos SPI.
Y ahora.....el problema:
El esclavo deberia mandar el valor 0xAA siempre (lineas 36-37 y 50-51 de codigo del esclavo y segunda linea del log de simulacion). En su lugar, el master recibe 0xD5. En el log de simulacion (lo he modificado algo para se vea mejor) he marcado en ROJO dos de las lineas que no me encajan. Si el esclavo pone en bajo (0) la linea SDO y el master la muestrea como tal (0).....¿por que el registro SSPSR recibe un (1) ????????????
El esclavo recibe bien los datos siempre (contador)
Ahi va el log:
PC=0x001C. Slave mode: reset.
PC=0x0017. Slave mode: Slave select SS pin active. MSSP started immediately (CKE set). SSPSR=0xAA (170).
PC=0x0014. Master mode: stat write of 00000002 (2).
PC=0x0016. Master mode: drive SDO (L).
PC=0x0017. Master mode: clock edge (L->H). SAMPLE
PC=0x0017. Master mode: sample data (SDI=1). SSPSR=0bD5 (213). 1101 0101
PC=0x00lA. Slave mode: sample bit 0. SDI=0. SSPSR=0b02 (2). 0
PC=0x0016. Master mode: clock edge (H->L). TRANSMIT
PC=0x0016. Master mode: drive SDO (L).
PC=0x0018. Slave mode: drive SDO (H).
PC=0x0016. Master mode: clock edge (L->H). SAMPLE
PC=0x0016. Master mode: sample data (SDI=1). SSPSR=0bAB (171). 1010 1011
PC=0x0017. Slave mode: sample bit 1. SDI=0, SSPSR=0b04 (4). 0
PC=0x0017. Master mode: clock edge (H->L). TRANSMIT
PC=0x0017. Master mode: drive SDO (L).
PC=0x0019. Slave mode: drive SDO (L). PC=0x00l 6. Master mode: clock edge (L->H). SAMPLE
PC=0x0016. Master mode: sample data (SDI=0). SSPSR=0b57 (87). 0101 0111PC=0x0017. Slave mode: sample bit 2. SDI=0. SSPSR=0b08 ( 8 ). 0
PC=0x0016. Master mode: clock edge (H->L). TRANSMIT
PC=0x0016. Master mode: drive SDO (L).
PC=0x00lA. Slave mode: drive SDO (H).
PC=0x0017. Master mode: clock edge (L->H). SAMPLE
PC=0x0017. Master mode: sample data (SDI=1). SSPSR=0bAE (174). 1010 1110
PC=0x00l 8. Slave mode: sample bit 3. SDI=0. SSPSR=0bl0 (16). 0
PC=0x0016. Master mode: clock edge (H->L). TRANSMIT
PC=0x0016. Master mode: drive SDO (L).
PC=0x00l 7. Slave mode: drive SDO (L).
PC=0x0016. Master mode: clock edge (L->H). SAMPLE
PC=0x0016. Master mode: sample data (SDI=0). SSPSR=0b5D (93). 0101 1101
PC=0x00l 9. Slave mode: sample bit 4. SDI=0. SSPSR=0b20 (32). 0
PC=0x00l 7. Master mode: clock edge (H->L). TRANSMIT
PC=0x0017. Master mode: drive SDO (L).
PC=0x0017. Slave mode: drive SDO (H).
PC=0x00l 6. Master mode: clock edge (L->H). SAMPLE
PC=0x0016. Master mode: sample data (SDI=1). SSPSR=0bBA (186). 1011 1010
PC=0x00lA. Slave mode: sample bit 5. SDI=0. SSPSR=0b40 (64). 0
PC=0x0016. Master mode: clock edge (H->L). TRANSMIT
PC=0x0016. Master mode: drive SDO (H).
PC=0x0018. Slave mode: drive SDO (L).
PC=0x0017. Master mode: clock edge (L->H). SAMPLE
PC=0x0017. Master mode: sample data (SDI=0). SSPSR=0b75 (117). 0111 0101
PC=0x0017. Slave mode: sample bit 6. SDI=1, SSPSR=0b81 (129). 1
PC=0x0016. Master mode: clock edge (H->L). TRANSMIT
PC=0x0016. Master mode: drive SDO (L).
PC=0x0019. Slave mode: drive SDO (H).
PC=0x0016. Master mode: clock edge (L->H). SAMPLE
PC=0x0016. Master mode: sample data (SDI=1). SSPSR=0bEA (234). 1110 1010
PC=0x0017. Slave mode: sample bit 7. SDI=0. SSPSR=0b02 (2). 0
PC=0x00l 7. Master mode: clock edge (H->L). TRANSMIT
PC=0x0017. Master mode: drive SDO (L).
PC=0x0017. Master mode: transmission complete.
PC=0x001A. Slave mode: drive SDO (L).
PC=0x001A. Slave mode: reception complete. RSR=0x02 (2) transferred to SSPBUF.
PC=0x001C. Slave mode: slave Select (SS) pin inactive. MSSP has been reset.
PC=0x001C. Slave mode: reset.
Perdon por el tochazo, pero es que con menos no podia explicarlo.
Saludos a todos.