Hola a todos!
Tengo una gran pregunta en comunicación SPI, he leído el datasheet, buscado ejemplos pero no logro ver por qué funciona aveces si y otras no mi programa. Para entender bien esta comunicación hice el código para que un atmega48 mande el contenido de 1 registro (dado=5) cuando presione un pulsador y regrese a cero, a otro atmega48 y este último lo despliegue por el puerto D, el problema es que a veces lo hace y otras no y realmente no se que pasa, ¿hay algo que me falta? me ayudaría mucho que me mencionaran cualquier error que noten. Yo creo que tiene que ver con la sincronía pero no encuentro el error.
El código de MASTER es el siguiente:
.include "m48def.inc" ;LIBRERIA PRINCIPAL
.device ATmega48
.DEF AUX = R16 ;DEFINICION DE REGISTROS AUXILIARES
.DEF AUX2 = R17
.DEF AUX3 = R18
.DEF AUX4 = R19
.DEF XOR = R20
.DEF DADO = R21
.DEF OTRO = R22
RCALL DELAY
LDI AUX, 0B10000000 ;PUERTO D COMO ENTRADA
OUT DDRD,AUX
LDI DADO,0B00000110
LDI AUX2,0B00000000
BOTON_1:
LDI AUX,0B10000000
OUT DDRD,AUX
IN AUX2,PIND ;LEE PIND CONSTANTEMENTE PARA REVISAR SI SE PRESIONA EL BOTÓN
SBIC PIND,0
RJMP BOTON_0
RJMP BOTON_1
BOTON_0:
LDI AUX,0B10000000
OUT DDRD,AUX
IN AUX2,PIND ;LEE PIND CONSTANTEMENTE PARA REVISAR SI SE DEJA DE PRESIONAR
SBIC PIND,0 ;EL BOTÓN
RJMP BOTON_0
RCALL SPI_MASTERINIT
RCALL SPI_MASTERTRANSMIT
RJMP BOTON_1
SPI_MASTERINIT:
;SET MOSI & SCK & SS COMMO SALIDAS, LAS DEMÁS COMO ENTRADAS
LDI AUX2,(1<<DDB3)|(1<<DDB5)|(1<<DDB2)
OUT DDRB, AUX2
LDI AUX2, (1<<SPE)|(1<<MSTR)|(1<<SPR1) ;HABILITA SPI, MASTER, SET CLOCK RATE FCK/64
OUT SPCR, AUX2
;************************************************************
LDS XOR, PRR ; REGISTRO DE REDUCCION DE ENERGÍA (PRR)
CBR XOR, 2 ;CAMBIAR PRSPI A 0 PARA ACTIVAR EL USO DE RELOJ
STS PRR, XOR
;*********************************************************************
RET
SPI_MASTERTRANSMIT:
SBI PORTB,2 ;SS=0, COMIENZA TRANSMISIÓN DE DATOS (DADO)
OUT SPDR,DADO
CBI PORTB,2
WAIT_TRANSMIT:
;ESPERA QUE LA TRANSMISIÓN SEA COMPLETADA
IN OTRO,SPSR
SBRS OTRO,SPIF
RJMP WAIT_TRANSMIT
;************************************************************
LDS XOR, PRR ; REGISTRO DE REDUCCION DE ENERGÍA (PRR)
SBR XOR, 2 ;CAMBIAR PRSPI A 1 PARA DESACTIVAR EL USO DE RELOJ
STS PRR, XOR
;**********************************************************************
RET
;*************************
;SUBRUTINA DE RETARDO
;*************************
DELAY: ;MENOS DE 1 SEG
ldi R31, $09
ldi R30, $BC
LOOP1: ldi R29, $C4
LOOP2: dec R29
brne LOOP2
dec R30
brne LOOP1
nop
RET
El del SLAVE es este:
.include "m48def.inc" ;LIBRERIA PRINCIPAL
.device ATmega48
.DEF AUX = R16 ;DEFINICION DE REGISTROS AUXILIARES
.DEF AUX2 = R17
.DEF AUX3 = R18
.DEF AUX4 = R19
.DEF XOR = R20
.DEF DADO = R21
.DEF OTRO = R22
REGRESA:
LDI AUX3,0B11111111 ;PUERTO D SALIDA
OUT DDRD,AUX3
LDI AUX2,0B00000000
RCALL SPI_SLAVEINIT
RCALL SPI_SLAVERECEIVE
OUT PORTD, DADO
RCALL DELAY
RJMP REGRESA
SPI_SLAVEINIT: ;SET MISO OUTPUT, ALL OTHERS INPUT
LDI AUX2, (1<<DDB4)
OUT DDRB, AUX2
;************
;ENABLE SPI
;************
LDI AUX2, (1<<SPE)
OUT SPCR, AUX2
RET
SPI_SLAVERECEIVE:
IN AUX4, PINB
SBIC PINB,2
RJMP SPI_SLAVERECEIVE
SIGUE: ;WAIT FOR RECEPTION COMPLETE
LDS AUX,SPSR
SBRS AUX,SPIF
RJMP SIGUE
IN DADO, SPDR
SBI PORTC,5 ;READ RECEIVED DATA
RET
;*************************
;SUBRUTINA DE RETARDO
;*************************
DELAY: ;MENOS DE 1 SEG
ldi R31, $09
LOOP0: ldi R30, $BC
LOOP1: ldi R29, $C4
LOOP2: dec R29
brne LOOP2
dec R30
brne LOOP1
nop
RET
Muchas gracias
P.D. Lo estoy manejando con clock interno a 8MHz