hola, estaba probando este tipo de comunicación entre dos PICs 16f876 y tengo un problema con las interrupciones en assembler.
Este es mi codigo:
include "modedefs.bas"
'--------------------------------------------------Modulo MSSP (Modo SPI)
SSPSTAT.7=0 'Leer los datos de entrada a mitad del tiempo de salida de los mismos
SSPSTAT.6=0 'CKE - Transmision en flanco de bajada con CKP=0
SSPBUF=%00000000 'Registro de transmisión/recepción (reseteo al inicio)
SSPCON=%00100000 'SPI habilitado, reloj en estado bajo normalmente, Modo maestro (frecuencia Fosc/4)
PIE1.3=1 'Interrupción MSSP habilitada
INTCON=%11000000 'Habilitadas solo interrupciones globales y periféricas
'--------------------------------------------------Configuración entradas/salidas y variables
ADCON1=%00000110 'Todo porta digital
trisc.5=0 'SDO habilitada = 0 (salida)
trisc.4=1 'SDI habilitada = 1 (entrada)
trisc.3=0 'Salida de la señal de reloj del MASTER
trisb=%00000001
portb=%00000000
trisa=%00000000
ledb2 var portb.2
wregistro var byte
variable var byte
i var word
variable=%11111111
'-------------------------------------------------Interrupción
DEFINE INTHAND myint 'Definir interrupción
wsave var byte $20 system 'Variables de guardado de la situación actual
ssave var byte bank0 system
psave var byte bank0 system
Goto start 'Bypass interrupción myint
asm
myint: movwf wsave ;Salvado de situación actual
swapf STATUS, W
clrf STATUS
movwf ssave
movf PCLATH, W
movwf psave
BTFSS PIR1,3 ;Ver si el flag del MSSP (PIR<3>) esta activado
goto salir
bcf PIR1,3 ;Borrar flag de interrupcion
movf SSPBUF,0 ;Muevo SSPBUF al registro
xorlw _variable ;XOR entre W y "variable"
movwf _wregistro ;Muevo W a "wregistro"
BTFSS STATUS,Z ;Comprobar que el flag de resultado 0 esta activado
goto salir
bsf _ledb2
salir: movf psave, W ;Recuperar situación anterior
movwf PCLATH
swapf ssave, W
movwf STATUS
swapf wsave, F
swapf wsave, W
retfie
endasm
'------------------------------------------------START
start
if portb.0=1 then
pause 500
SSPBUF=%10000001
pause 1000
porta=SSPBUF ;Mostrar contenido del registro SSPBUF en porta y portb.7:6
portb.6=SSPBUF.6
portb.7=SSPBUF.7
pause 1000
porta=variable ;Mostrar contenido de "variable" en porta y portb.7:6
portb.6=variable.6
portb.7=variable.7
pause 1000
porta=wregistro ;Mostrar contenido de "wregistro" en porta y portb.7:6
portb.6=wregistro.6
portb.7=wregistro.7
endif
'if SSPBUF=%11111111 then
'portb.2=1
'endif
goto start
end
El código es simple, al pulsar RB0 se manda "%10000001" y se recibe al mismo tiempo de otro PIC "%11111111", si en el buffer de recepción esta "%11111111" se enciende el portb.2.
El problema es que todo funciona bien si compruebo la condición en pic basic pro (esta como comentario casi al final del código), pero si activo la interrupción por transmisión/recepción para hacerlo en ensamblador no funciona.
Para comprobar que contenian el buffer de recepción (SSPBUF), "variable" y resultado XOR ("wregistro") los pongo secuencialmente y como salidas en los pines desde porb<7:6> y porta (cógico en pic basic arriba). Por esto pude comprobar que el fallo esta en el SSPBUF que no carga el valor que le pongo pulsando el portb.0 ("%100000001") ni el valor de vuelta ("%11111111), ni siquiera se realiza bien la operación XOR entre SSPBUFF y "variable". Si no hago ninguna operación con SSPBUFF durante la interrupción, por ejemplo solo enciendo el portb.2 la interrupción funciona bien.
Es como si durante el tiempo que dura la interrupción el SSPBUFF cambiara su valor quedando con un valor errático (quizás mezcla entre el SSPBUF de salida y el de entrada). Quizas lo que hiciera falta es tener un flag bit independiente cuando se transmite un dato o cuando se recibe, pero yo solo he encontrado el PIR.3 para todo. Tambien he pensado en algún retardo en la interrupción para dar tiempo al llenado del SSPBUFF con el dato de recepción.
La simulación la hago en Proteus.
¿Alguna sugerencia?
Gracias.