Hola, después de un rato pegandome con el programa he conseguido que me funcione, pero hay un pequeño error que no consigo ver, primero el código completo y luego lo que me pasa
list p=16F877a
#include p16F877a.inc
__CONFIG _CP_OFF & _WDT_OFF & _HS_OSC & _LVP_OFF & _BODEN_OFF
;******************************* DEFINICIONES***************************************************
#DEFINE LED1 PORTA,3 ;Rojo
#DEFINE LED2 PORTA,5 ;Azul
#DEFINE LED3 PORTC,5 ;Verde
#DEFINE PULSADOR2 PORTA,1
#DEFINE DATO0 PORTD,0
#DEFINE DATO1 PORTD,1
#DEFINE DATO2 PORTD,2
#DEFINE DATO3 PORTD,3
#DEFINE DATO4 PORTD,4
#DEFINE DATO5 PORTD,5
#DEFINE DATO6 PORTD,6
#DEFINE DATO7 PORTD,7
#DEFINE ENABLE PORTE,2
#DEFINE RS PORTE,0
#DEFINE W_R PORTE,1
#DEFINE LCD_DATOS PORTD
#DEFINE LCD_CTRL PORTE
#DEFINE IR PORTB,0
#DEFINE PIN_PRUEBA PORTA,0
#DEFINE PIN_PRUEBA2 PORTA,2
#DEFINE PIN_PRUEBA3 PORTC,0
;****************************** REGISTROS RAM ***************************************************
cblock 0x20
Delay0 ; Assign an address to label Delay1
Delay1
Delay2
Delay3
DELAY4
DELAY5
W_TEMP
STATUS_TEMP
CUENTA
UNIDADES
DECENAS
CENTENAS
DATO1IR
DATO2IR
TICTAC
INT_CONTROL
INT_CONTROL_OLD
CONTADOR1
endc
;**************************** POSICIONES *********************************************************
ORG 0 ; Posición de memoria donde se coloca la instrucción.
GOTO Start ; Salto a Start, se ejecutará la instrucción debajo de Start.
ORG 4
GOTO ISR
ORG 5 ; Salta el vector de interrupción
;***************************** CONFIGURAR REGISTROS ************************************************
Start ; Inicio del programa
; ****************** BANCO 0 **************************************************************
BCF STATUS, RP0
BCF STATUS, RP1 ; Seleciona el Bank0
CLRF PORTA ; Initialize poerts by clearing output
CLRF PORTB ; data latches
CLRF PORTC
CLRF PORTD
CLRF PORTE
MOVLW B'10010000'
MOVWF INTCON ;GIE e INTE, bit 1 flag de INTE
; ******************** BANCO 1 **************************************************************
BSF STATUS,RP0 ; select Register Page 1
BCF OPTION_REG,INTEDG ;Flanco de bajada
MOVLW B'00000000' ;Interruptores son entradas
MOVWF TRISA
MOVLW B'00000001'
MOVWF TRISB
CLRF TRISC
CLRF TRISD
CLRF TRISE
MOVLW 0X06 ;Configurar los pin de A
MOVWF ADCON1 ;como entradas digitales.
BCF STATUS, RP0 ;Bank0
;************************ INICIO SOFT ****************************************************************
BSF LED2 ;Parpadeo de Reset
CALL Delay_2
BCF LED2
CALL INICIALIZA_LCD
MOVLW B'00000001' ;Clear Display
CALL LCD_COMANDO
MOVLW B'00000110' ;Entry mode set
CALL LCD_COMANDO
MOVLW B'00001110' ;Activa lcd y cursor
CALL LCD_COMANDO
BCF PIN_PRUEBA2
BCF PIN_PRUEBA
;************************** PROGRAMA PRINCIPAL ********************************************************
MAIN_LOOP
BSF LED1
CALL Delay_2
BCF LED1
CALL Delay_2
GOTO MAIN_LOOP
;*************************** INTERRUPCIONES*************************************************************
ISR
MOVWF W_TEMP ;Salva W y Status
SWAPF STATUS,0
MOVWF STATUS_TEMP
BSF LED2
BCF LED1
BCF LED3
CLRF TICTAC
CLRF DATO1IR
CLRF DATO2IR
CLRF CONTADOR1
CLRF INT_CONTROL ;bit 7 entrada IR, bit 3 y 4 cambio de byte y salida, bit 0:2 contador
CLRF INT_CONTROL_OLD
BCF PIN_PRUEBA
BCF PIN_PRUEBA2
BCF PIN_PRUEBA3
ISR_LOOP
; ********* Se mira el pin de entrada, si no cambia se va a SUBIR_TIC ************************
BTFSS IR ;Si es cero se ejecuta la siguiente,PORTB,0 ;0.2
GOTO PONER_A_CERO ;---->0.6
BSF INT_CONTROL,7 ;0.6
GOTO COMP_ENTRADA ;---->1
PONER_A_CERO ;<----0.6
NOP ;0.8
BCF INT_CONTROL,7 ;1
COMP_ENTRADA ;<----1
MOVFW INT_CONTROL_OLD ;1.2
XORWF INT_CONTROL,W ;Si son iguales Z=1 ;1.4
BTFSS STATUS,Z ;Si es 0 se ejecuta la siguiente ;1.6
GOTO COMPARAR_TIC ;--->2
;************************** Incrementar el TIC **********************************************************
NOP ;2
NOP ;2.2
NOP ;2.4
NOP ;2.6
SUBIR_TIC ;<--2.6
NOP ;2.8
MOVLW D'140' ;1 Tics = 0.1 mS ;3
SUBWF TICTAC,W ;3.2
BTFSC STATUS,C ;Si TICTAC-W mayor que 0, ejecuta la siguiente ;3.6
GOTO ERROR_IR ;
INCF TICTAC,F ;3.8
;
MOVLW D'158' ;4
MOVWF DELAY5 ;4.2
Delay_5loop ;3*0.2*158=94.8
DECFSZ DELAY5,f ;
GOTO Delay_5loop ;
MOVFW INT_CONTROL ;99.2
MOVWF INT_CONTROL_OLD ;99.4
NOP ;99.6
GOTO ISR_LOOP ;100
; ********* El pin de entrada a cambiado, en función de los tics damos 1 o 0 *****************
; ********* TIC menos 8 mS error, mayor de 8 mS escribir cero, mayor 1.7 mS escribir uno *****
; ********** Si es el flanco de subida no comparamos ***************************************
COMPARAR_TIC
BTFSC IR
GOTO SUBIR_TIC
MOVLW D'26' ;1 Tics = 0.1 mS
SUBWF TICTAC,W
BTFSC STATUS,C ;Si TICTAC-W mayor que 0, ejecuta la siguiente
GOTO COMPARAR_SALIDA
MOVLW D'17' ;1 Tics = 0.1 mS
SUBWF TICTAC,W
BTFSC STATUS,C ;Si TICTAC-W mayor que 0, ejecuta la siguiente
GOTO ALMACENAR_UNO
MOVLW D'8' ;1 Tics = 0.1 mS
SUBWF TICTAC,W
BTFSC STATUS,C ;Si TICTAC-W mayor que 0, ejecuta la siguiente
GOTO ALMACENAR_CERO
GOTO ERROR_IR
COMPARAR_SALIDA
MOVFW INT_CONTROL
MOVWF INT_CONTROL_OLD
CLRF TICTAC
GOTO ISR_LOOP
ERROR_IR
BCF LED2
GOTO POP
ALMACENAR_CERO
BTFSC INT_CONTROL,3 ;Si el bit 3 es uno se ejecuta la siguiente, vale 8 o mas.
GOTO ALMACENAR_DATO2
RLF DATO1IR,F
INCF INT_CONTROL,F
GOTO ALMACENAR_SALIDA
ALMACENAR_DATO2
RLF DATO2IR,F
INCF INT_CONTROL,F
GOTO ALMACENAR_SALIDA
ALMACENAR_UNO
BTFSC INT_CONTROL,3 ;Si el bit 3 es uno se ejecuta la siguiente, vale 8 o mas.
GOTO ALMACENAR_DATO2_1
RLF DATO1IR,F
INCF DATO1IR,F
INCF INT_CONTROL,F
GOTO ALMACENAR_SALIDA
ALMACENAR_DATO2_1
RLF DATO2IR,F
INCF DATO2IR,F
INCF INT_CONTROL,F
GOTO ALMACENAR_SALIDA
ALMACENAR_SALIDA
BTFSC INT_CONTROL,4 ;Si el bit 4 es uno se ejecuta la siguiente, vale 16 o mas.
GOTO DATOS_A_LCD
GOTO COMPARAR_SALIDA
DATOS_A_LCD
MOVLW B'10000000'
CALL LCD_COMANDO
MOVFW DATO1IR
CALL BINARIO_LCD
MOVFW CENTENAS
CALL LCD_ESCRIBIR
MOVFW DECENAS
CALL LCD_ESCRIBIR
MOVFW UNIDADES
CALL LCD_ESCRIBIR
MOVLW B'11000000'
CALL LCD_COMANDO
MOVFW DATO2IR
CALL BINARIO_LCD
MOVFW CENTENAS
CALL LCD_ESCRIBIR
MOVFW DECENAS
CALL LCD_ESCRIBIR
MOVFW UNIDADES
CALL LCD_ESCRIBIR
POP
SWAPF STATUS_TEMP,0
MOVWF STATUS
MOVFW W_TEMP
BCF INTCON,INTF
BCF LED2
RETFIE
;********************************** LCD ****************************************************************
INICIALIZA_LCD
CALL Delay
CLRF LCD_CTRL
MOVLW B'00111000' ;8 bits, 2 líneas y 5x8 puntos
MOVWF LCD_DATOS
CALL LCD_E
CALL Delay
RETURN
LCD_E
BSF ENABLE
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
BCF ENABLE
RETURN
LCD_COMANDO
CLRF LCD_CTRL
MOVWF LCD_DATOS
CALL LCD_E
CALL Delay
RETURN
LCD_ESCRIBIR
CLRF LCD_CTRL
BSF RS
MOVWF LCD_DATOS
CALL LCD_E
CALL Delay
RETURN
;********************************** BINARIO A LCD *****************************************************
BINARIO_LCD ;Para registros de 8 bits, convierte a centenas, decenas y unidades.
MOVWF CUENTA
CLRF UNIDADES
CLRF DECENAS
CLRF CENTENAS
CENT_LOOP
MOVLW D'100'
SUBWF CUENTA,W
BTFSS STATUS,C
GOTO DEC_LOOP
INCF CENTENAS,F
MOVWF CUENTA
GOTO CENT_LOOP
DEC_LOOP
MOVLW D'10'
SUBWF CUENTA,W
BTFSS STATUS,C
GOTO UNIDAD
INCF DECENAS,F
MOVWF CUENTA
GOTO DEC_LOOP
UNIDAD
MOVF CUENTA,W
MOVWF UNIDADES
MOVLW B'00110000'
ADDWF CENTENAS,1
ADDWF DECENAS,1
ADDWF UNIDADES,1
RETURN
;********************************** DELAYS *************************************************************
Delay ;20 mS
MOVLW D'65'
MOVWF Delay1
Delay_loop
decfsz Delay0,f ; Waste time.
goto Delay_loop ; The Inner loop takes 3 instructions per loop * 256 loopss = 768 instructions
decfsz Delay1,f ; The outer loop takes and additional 3 instructions per lap * 256 loops
goto Delay_loop ; (768+3) * 256 = 197376 instructions / 1M instructions per second = 0.197 sec.
; call it a two-tenths of a second.
RETURN
Delay_2 ;0.86 s
MOVLW D'22'
MOVWF Delay2
Delay_2loop
decfsz Delay0,f ; Waste time.
goto Delay_2loop ; The Inner loop takes 3 instructions per loop * 256 loopss = 768 instructions
decfsz Delay1,f ; The outer loop takes and additional 3 instructions per lap * 256 loops
goto Delay_2loop ; (768+3) * 256 = 197376 instructions / 1M instructions per second = 0.197 sec.
; call it a two-tenths of a second.
decfsz Delay2,f
goto Delay_2loop
return
Delay_3 ;50.2 uS
MOVLW D'82'
MOVWF Delay3
Delay_3loop
DECFSZ Delay3,f
GOTO Delay_3loop
RETURN
end
Con este programa estoy capturando los botones de un mando JVC, y sacando por la pantalla de un LCD los dos bytes que manda convertidos a decimal, la rutina de convertir a decimal un registro de 8 bits cargado en w funciona correctamente, la captura de los botones más o menos bien, me captura el valor que mando pero me lo da con un menos, es decir que si el mando envia 245 115 yo recibo 244 114, si envia 197 120 yo recibo 196 119, no sé donde puede estar el fallo, la parte del código encargada de almacenar los botones e sla siguiente
ALMACENAR_CERO
BTFSC INT_CONTROL,3 ;Si el bit 3 es uno se ejecuta la siguiente, vale 8 o mas.
GOTO ALMACENAR_DATO2
RLF DATO1IR,F
INCF INT_CONTROL,F
GOTO ALMACENAR_SALIDA
ALMACENAR_DATO2
RLF DATO2IR,F
INCF INT_CONTROL,F
GOTO ALMACENAR_SALIDA
ALMACENAR_UNO
BTFSC INT_CONTROL,3 ;Si el bit 3 es uno se ejecuta la siguiente, vale 8 o mas.
GOTO ALMACENAR_DATO2_1
RLF DATO1IR,F
INCF DATO1IR,F
INCF INT_CONTROL,F
GOTO ALMACENAR_SALIDA
ALMACENAR_DATO2_1
RLF DATO2IR,F
INCF DATO2IR,F
INCF INT_CONTROL,F
GOTO ALMACENAR_SALIDA
ALMACENAR_SALIDA
BTFSC INT_CONTROL,4 ;Si el bit 4 es uno se ejecuta la siguiente, vale 16 o mas.
GOTO DATOS_A_LCD
GOTO COMPARAR_SALIDA
Si llamo a almacenar cero, desplaza a la izquierda el dato 1 (dato1ir) e incrementa un contador, si llamo a almacenar uno desplaza a la izquierda e incrementa el registro en 1, por cada desplazamiento se incrementa un contador (int_control), cuando este alcanza el valor 8 se pasa a almacenar los unos y ceros entrantes en el dato2, cuando vale 16 el contador manda la salida al lcd y sale de la interrupción.
La captura de unos y cero parece que funciona bien, cualquier botón del mando me da su valor correcto menos 1, repasando el código no veo que me puede estar pasando, llevo poco en esto, es posible simular con el mplab este programa y asignar valores a la entrada? o una simulación se haría eterna debida a tanto bucles.
Con un programador como el icd2 sería posible hacer un debug poniendo los breakpoints donde yo quisiese? aunque en este caso de poco serviría porque el programa depende del tiempo de envio del mando.
No sé me esta restando por ahí un 1 a mi resultado final que no se de donde sale, (una solución rápida puede ser incf dato1r,f) pero me gustaría ver donde me equivoco, la instrucción de incremento tb podría ir al final, y con una basta en lugar de 4. Gracias. S2