hola, es un trabajo que me han mandado y hay que hacer en ensamblador, si pudiera usar C lo haria porque he utilizado mas que esto.
el pic que uso es 16f874, creo que todo el codigo esta bien pero al cargar a la placa no funciona, no tengo ni idea que puede ser, no me da errores.tal vez pueda estar en la rutina de asociar cada tecla a una funcion pero no lo se. Agradeceria que me hechaseis un vistazo al codigo y me podais decir algo.Muchas gracias
El codigo:
;EJERCICIO persianas
;*******************************
LIST P=16F874
INCLUDE "P16F874.INC"
;************************************************************************
; Variables
TMP1 EQU 27h
TMP2 EQU 28h
PULS EQU 29
; Constantes de tiempo
klcdw EQU 0FFh
; Registros del micro
W EQU 0
F EQU 1
STATUS EQU 03h
PORTA EQU 05h
INTCON EQU 0Bh
PORTD EQU 08h
;**************************************************
;*************ASIGNACION DE PUERTOS DE LEDS**********
P_LED EQU PORTA
b_LED0 EQU 0
b_LED1 EQU 0
;***********************************************
;***********VARIABLES DEL CONVERSOR******
CAD0 EQU 2A
CAD1 EQU 2B
;***********************************************
;PUERTOS LCD
P_LCDen EQU PORTD
b_LCDen EQU 4
P_LCDrw EQU PORTD
b_LCDrw EQU 5
P_LCDdi EQU PORTD
b_LCDdi EQU 6
P_LCDDA EQU PORTD
;*********************************************
;CONFIGURACION LCD
lcd_set EQU b'00100000'
lcd_mod EQU b'00000110'
lcd_on EQU b'00001100'
lcd_off EQU b'00001000'
lcd_to EQU d'200'
;**********************************************
;Comandos LCD
lcd_clr EQU b'00000001'
cur_hm EQU b'00000010'
cur_on EQU b'00001010'
cur_off EQU b'00001000'
cur_rm EQU b'00010100'
cur_lm EQU b'00010000'
cur_12 EQU b'11000000'
;**********************************************
SAVEPCL EQU 20
SAVEFSR EQU 21
SAVEST EQU 22
SAVEW EQU 23
;*************************************
;puerto del teclado
PKYBD EQU PORTB
bKYBD EQU 0
;**************************************
;variables del teclado
TEC_numv EQU 24
TEC_ant EQU 25
TEC_flg EQU 26
F_rep EQU 0
;****************************************
;constantes del teclado
self1 EQU B'00000111'
self2 EQU B'00001011'
self3 EQU B'00001101'
self4 EQU B'00001110'
selfa EQU B'00000000'
nminv EQU 10
;***********************************************
ORG 003
GOTO PROGPPAL ;salto al programa principal
;*************************************************
;****************************************************
PROGPPAL
CALL KYBINIT
;*************************Inicializar teclado*********
BSF STATUS,RP0 ;Pone a "1" el bit RP0(el bit 5) del registro STATUS
MOVLW B'00000111' ;Mueve al acumulador "W" el literal 07h
MOVWF ADCON1&7F ;Mueve el contenido del acumulador a ADCON1 haciendo un AND de 7F
BCF P_LED,b_LED0 ;Pone a "0" el bit b_LED al registro P_LED
BCF P_LED,b_LED1
CALL LCDINIT ; Inicializar el LCD
CALL LCDDOUT ; Pone LCD como entrada
BCF STATUS,RP0 ;Pone a "0" el bit RP0 del registro STATUS
;**************************
; BSF INTCON,GIE
MOVLW cur_hm ; Cursor a home
CALL LCDIWR ; Se manda a la pantalla
MOVLW B'00001111' ; Enceder cursor
CALL LCDIWR ; Se manda a la pantalla
MOVLW B'00000110' ; Auto mover cursor a la derecha
CALL LCDIWR ; Se manda a la pantalla
LAZOPPAL:
CALL MENS
GOTO LAZOPPAL
;**********************************************
; LCDINIT
; Inicializa pantalla y puerto de pantalla
LCDINIT:
BSF STATUS, RP0 ; Se reconfigura puerto de datos LCD
MOVLW 0F0h ; 4 bits de datos = Salida
ANDWF P_LCDDA,F ;
BCF P_LCDdi,b_LCDdi ; Dato/instrucción = Salida
BCF P_LCDrw,b_LCDrw ; Read/Write = Salida
BCF P_LCDen,b_LCDen ; Strobe = Salida
BCF STATUS, RP0 ;
BCF P_LCDdi,b_LCDdi ; Dato/instrucción = Instrucción
BCF P_LCDrw,b_LCDrw ; Read/Write = Write
BCF P_LCDen,b_LCDen ; desactiva el strobe
MOVLW 0F0h ; Se prepara primer dato de inicialización de 4 bits
ANDWF P_LCDDA,F ; (que hay que enviar 3 veces)
MOVLW B'0011' ;
IORWF P_LCDDA,F ;
MOVLW D'20' ; Se esperan 20ms
CALL LCDWAIT ;
BSF P_LCDen,b_LCDen ; Primer envio
BCF P_LCDen,b_LCDen ; activa strobe / desactivar strobe
MOVLW D'5' ; Se esperan 5ms
CALL LCDWAIT ;
BSF P_LCDen,b_LCDen ; Primer envio
BCF P_LCDen,b_LCDen ; activa strobe / desactivar strobe
MOVLW D'1' ; Se esperan 1ms
CALL LCDWAIT ;
BSF P_LCDen,b_LCDen ; Primer envio
BCF P_LCDen,b_LCDen ; activa strobe / desactivar strobe
MOVLW D'5' ; Se esperan 5ms
CALL LCDWAIT ;
MOVLW 0F0h ; Se prepara segundo dato de inicialización de 4 bits
ANDWF P_LCDDA,F ;
MOVLW B'0010' ;
IORWF P_LCDDA,F ;
BSF P_LCDen,b_LCDen ; Envio
BCF P_LCDen,b_LCDen ; activar strobe / desactivar strobe
MOVLW D'5' ; Se esperan 5ms
CALL LCDWAIT ;
MOVLW lcd_set ; Se envia instrucción ara fijar tipo de pantalla
CALL LCDIWR ;
MOVLW D'5' ; Se esperan 5ms
CALL LCDWAIT ;
MOVLW lcd_off ; Se envia instrucción para apagar pantalla
CALL LCDIWR ;
MOVLW lcd_on ; Se envia instrucción para encender pantalla
CALL LCDIWR ;
MOVLW lcd_mod ; Se envia instrucción para forma de operar pantalla
CALL LCDIWR ;
MOVLW lcd_clr ; Se envia instrucción para limpiar pantalla
CALL LCDIWR ;
MOVLW D'100' ; Se esperan 100ms
CALL LCDWAIT ;
RETURN
;***********************************************
; LCDDWR
; LCD Data write
; Recibe: W=Dato a escribir
LCDDWR:
BSF P_LCDdi,b_LCDdi ; Dato/instrucción = Dato
GOTO LCDWRAUX ;
;***********************************************
; LCDIW
; LCD Instruction write
; Recibe: W=Dato a escribir
LCDIWR:
BCF P_LCDdi,b_LCDdi ; Dato/instrucción = instrucción
GOTO LCDWRAUX ;
LCDWRAUX:
BCF P_LCDrw,b_LCDrw ; Read/Write = Write
MOVWF TMP1 ; Se guarda dato para posterior uso
MOVLW 0F0h ; Se borran bits lsb del puerto
ANDWF P_LCDDA,F ;
SWAPF TMP1,W ; Se escribe el nible superior
ANDLW 00Fh ;
IORWF P_LCDDA,F ;
BSF P_LCDen,b_LCDen ; activa el strobe
BCF P_LCDen,b_LCDen ; desactiva el strobe
MOVLW 0F0h ; Se borran bits lsb del puerto
ANDWF P_LCDDA,F ;
MOVF TMP1,W ; Se escribe nible inferior
ANDLW 00Fh ;
IORWF P_LCDDA,F ;
BSF P_LCDen,b_LCDen ; activa el strobe
BCF P_LCDen,b_LCDen ; desactiva el strobe
CALL LCDBSY ;
RETURN ;
;***********************************************
; LCDWAIT
; Recibe: W=Número de milisegundos a esperar
LCDWAIT:
MOVWF TMP1 ; Se almacena el número de milisegundos en CONT1
LCDW1:
MOVLW klcdw ; Se almacena contador básico
MOVWF TMP2 ;
LCDW2:
NOP ; Ajustando al milisegundo
NOP ;
DECFSZ TMP2,F ; Se decrementa contador básico
GOTO LCDW2 ; hasta llegar a cero
DECFSZ TMP1,F ; Se repite el contador básico tantas
GOTO LCDW1 ; veces como número de milisegundos
RETURN ;
;************************************************
; LCDBSY
; LCD Busy: espera desocupación de LCD (con time-out)
; Retorna: W=0 desocupado / W=1 error time-out superado
LCDBSY:
MOVLW lcd_to ; Se prepara contador de time-out
MOVWF TMP1 ;
CALL LCDDIN ; Se pone el bus como entrada
BCF P_LCDdi,b_LCDdi ; Dato/instrucción = Instrucción
BSF P_LCDrw,b_LCDrw ; Read/Write = Read
LCDBS1:
BSF P_LCDen,b_LCDen ; activar strobe / desactivar strobe
BCF P_LCDen,b_LCDen ;
MOVF P_LCDDA,W ; Se lee nibble MSN con busy flag BF
BSF P_LCDen,b_LCDen ; acivar strobe / desactivar strobe
BCF P_LCDen,b_LCDen ;
ANDLW 08h ;
BTFSS STATUS,Z ; Si BF=0 el LCD esta desocupado
GOTO LCDBS2 ;
DECFSZ TMP1,F ; Se verifica si hay time-out
GOTO LCDBS1 ;
CLRF TMP1 ; Hay time-out
CALL LCDDOUT ;
RETLW 01 ; Retorna error por time-out
LCDBS2: ; Desocupado
CALL LCDDOUT ;
RETLW 00 ; Retorna desocupado sin errores
;******************************************************
; CURADD
; Lee dirección del cursor
; Retorna: W=dirección del cursor (0-79d)
CURADD:
CALL LCDDIN ; Se rconfigura puerto de datos LCD como entrada
BCF P_LCDdi,b_LCDdi ; Dato/instrucción = Instruccion
BSF P_LCDrw,b_LCDrw ; Read/Write = Write
BSF P_LCDen,b_LCDen ; activar strobe / desactivar strobe
BCF P_LCDen,b_LCDen ;
MOVF P_LCDDA,W ; Se lee nibble MSN
ANDLW 07h ;
MOVWF TMP1 ;
SWAPF TMP1,F ;
BSF P_LCDen,b_LCDen ; activar strobe / desactivar strobe
BCF P_LCDen,b_LCDen ;
MOVF P_LCDDA,W ; Se lee nibble MSN
ANDLW 0Fh ;
IORWF TMP1,W ;
CALL LCDDOUT ;
RETURN ;
;*********************************************************
; LCDIN
; Rutina de uso particular. Pone el bus de datos LCD como entrada
LCDDIN: ;
BSF STATUS, RP0 ; Se reconfigura puerto de datos LCD
MOVLW 00Fh ; como entrada
IORWF P_LCDDA,W ;
MOVWF P_LCDDA ;
BCF STATUS, RP0 ;
RETURN ;
;*********************************************************
; LCDOUT
; Rutina de uso particular. Pone el bus de datos LCD como salida
LCDDOUT: ;
BSF STATUS, RP0 ; Se reconfigura puerto de datos LCD
MOVLW 0F0h ; como salida
ANDWF P_LCDDA,W ;
MOVWF P_LCDDA ;
BCF STATUS, RP0 ;
MOVF TMP1,W ;
RETURN ;
;****************************************
INITTMR0:
BSF STATUS,RP0
MOVLW B'00000111'
MOVWF ADCON1&7F
BCF PKYBD,bKYBD
BCF STATUS,RP0
RETURN
;******************************
ORG 100
TRATECLA:
CLRF PCLATH
BSF PCLATH,0
BCF PCLATH,1
ADDWF PCL,F
RETLW 0
RETLW '1'
RETLW '2'
RETLW '3'
RETLW '4'
RETLW '5'
RETLW '6'
RETLW '7'
RETLW '8'
RETLW '9'
RETLW 'D'
RETLW 'A'
RETLW '0'
RETLW 'B'
RETLW 'C'
KYBINIT:
BSF STATUS,RP0
MOVLW B'11110000'
MOVWF PKYBD
BCF OPTION_REG&7F,NOT_RBPU
BCF STATUS,RP0
MOVLW selfa
MOVWF PKYBD
CLRF TEC_ant
CLRF TEC_flg
CLRF TEC_numv
RETURN
LEETECLADO:
CLRF TMP2
MOVLW selfa
MOVWF PKYBD
XORWF PKYBD,W
BTFSC STATUS,Z
GOTO LEETEC_RET
CLRF TMP1
INCF TMP1,F
MOVLW self1
CALL LEETEC1
MOVLW self2
CALL LEETEC1
MOVLW self3
CALL LEETEC1
MOVLW self4
CALL LEETEC1
LEETEC_RET:
MOVLW selfa
MOVWF PKYBD
MOVF TMP2,W
RETURN
LEETEC1:
MOVWF PKYBD
MOVF TMP2,F
BTFSS STATUS,Z
RETURN
BTFSS PKYBD,4
GOTO LEETEC2
INCF TMP1,F
BTFSS PKYBD,5
GOTO LEETEC2
INCF TMP1,F
BTFSS PKYBD,6
GOTO LEETEC2
INCF TMP1,F
BTFSS PKYBD,7
GOTO LEETEC2
INCF TMP1,F
RETURN
LEETEC2:
MOVF TMP1,W
MOVWF TMP2
RETURN
ELIMREB:
MOVWF TMP1
XORWF TEC_ant,W
BTFSC STATUS,Z
GOTO ELIM_IG
MOVF TMP1,W
MOVWF TEC_ant
CLRF TEC_numv
RETLW 0
ELIM_IG:
MOVLW nminv
SUBWF TEC_numv,W
BTFSC STATUS,Z
GOTO ELIM_EST
INCF TEC_numv,F
RETLW 0
ELIM_EST:
MOVF TMP1,W
RETURN
REPORTT:
IORLW 0
BTFSC STATUS,Z
GOTO RE_NTEC
RE_TEC:
BSF STATUS,Z
BTFSC TEC_flg,F_rep
RETLW 0
BSF TEC_flg,F_rep
BCF STATUS,Z
RETURN
RE_NTEC:
BCF TEC_flg,F_rep
ANDLW 0
RETURN
;***************************************
;******INICIALIZAR EL CONVERSOR***********
INITAD:
BSF STATUS, RP0
MOVLW B'10000101'
MOVWF ADCON1&7F
BSF TRISA&7F,0
BSF TRISA&7F,1
BSF TRISA&7F,3
BCF STATUS,RP0
BCF ADCON0,ADCS1
BCF ADCON0,ADCS0
BCF ADCON0,CHS2
BCF ADCON0,CHS1
BCF ADCON0,CHS0
BCF ADCON0,ADON
RETURN
;****************************************
;CAN0
;Fija el canal 0 para la conversion AD
BCF ADCON0,CHS2
BCF ADCON0,CHS1
BCF ADCON0,CHS0
RETURN
;****************************************
;CAN1
;Fija el canal 1 para la conversion AD
BCF ADCON0,CHS2
BCF ADCON0,CHS1
BSF ADCON0,CHS0
RETURN
;*****************************************
;CONVAD
;Conversion AD
CONVAD:
BSF ADCON0,GO
CONVAD1:
BTFSC ADCON0,GO
GOTO CONVAD1
MOVF ADRESH,W
MOVWF CAD1
BSF STATUS,RP0
MOVF ADRESL&7F,W
BCF STATUS,RP0
MOVWF CAD0
RETURN
; *******************************************
; LLamada a subrutina de mensajes a LCD
MENS:
CALL LEETECLADO
CALL TRATECLA
MOVWF PULS
BTFSC PULS,3
CALL COMP1
BTFSC PULS,3
RETURN
BTFSC PULS,2
CALL COMP2
BTFSC PULS,2
RETURN
BTFSC PULS,1
CALL COMP3
BTFSC PULS,1
RETURN
CALL MENSINITs1
RETURN
; ******************************************
; Comprobar el 8 y 9
COMP1:
BTFSC PULS,0
CALL MENSINITat
BTFSS PULS,0
CALL MENSINITa2
RETURN
;*******************************************
;COMPROBAR 4,5,6,7
COMP2:
BTFSC PULS,1
CALL COMP21
BTFSC PULS,1
RETURN
BTFSC PULS,0
CALL MENSINITb2
BTFSS PULS,0
CALL MENSINITb1
RETURN
;*******************************************
;COMPROBAR 6,7
COMP21:
BTFSC PULS,0
CALL MENSINITa1
BTFSS PULS,0
CALL MENSINITbt
RETURN
;******************************************
;COMPROBAR 2,3
COMP3:
BTFSC PULS,0
CALL MENSINITst
BTFSS PULS,0
CALL MENSINITs2
RETURN
;*******************************************
;*********SUBIR*****************************
SUBIR:
MOVLW A'S'
CALL LCDIWR
MOVLW A'U'
CALL LCDIWR
MOVLW A'B'
CALL LCDIWR
MOVLW A'I'
CALL LCDIWR
MOVLW A'R'
CALL LCDIWR
MOVLW A' '
CALL LCDIWR
MOVLW A'P'
CALL LCDIWR
MOVLW A'E'
CALL LCDIWR
MOVLW A'R'
CALL LCDIWR
MOVLW A'S'
CALL LCDIWR
MOVLW A'I'
CALL LCDIWR
MOVLW A'A'
CALL LCDIWR
MOVLW A'N'
CALL LCDIWR
MOVLW A'A'
CALL LCDIWR
RETURN
;*********BAJAR*****************************
BAJAR:
MOVLW A'B'
CALL LCDIWR
MOVLW A'A'
CALL LCDIWR
MOVLW A'J'
CALL LCDIWR
MOVLW A'A'
CALL LCDIWR
MOVLW A'R'
CALL LCDIWR
MOVLW A' '
CALL LCDIWR
MOVLW A'P'
CALL LCDIWR
MOVLW A'E'
CALL LCDIWR
MOVLW A'R'
CALL LCDIWR
MOVLW A'S'
CALL LCDIWR
MOVLW A'I'
CALL LCDIWR
MOVLW A'A'
CALL LCDIWR
MOVLW A'N'
CALL LCDIWR
MOVLW A'A'
CALL LCDIWR
RETURN
;*********MODO AUTOMATICO******************
AUTO:
MOVLW A'M'
CALL LCDIWR
MOVLW A'o'
CALL LCDIWR
MOVLW A'd'
CALL LCDIWR
MOVLW A'o'
CALL LCDIWR
MOVLW A' '
CALL LCDIWR
MOVLW A'a'
CALL LCDIWR
MOVLW A'u'
CALL LCDIWR
MOVLW A't'
CALL LCDIWR
MOVLW A'o'
CALL LCDIWR
MOVLW A'm'
CALL LCDIWR
MOVLW A'á'
CALL LCDIWR
MOVLW A't'
CALL LCDIWR
MOVLW A'i'
CALL LCDIWR
MOVLW A'c'
CALL LCDIWR
MOVLW A'o'
CALL LCDIWR
RETURN
;*********SUBIR PERSIANA 1******************
MENSINITs1:
CALL SUBIR
MOVLW A' '
CALL LCDIWR
MOVLW A'1'
CALL LCDIWR
BSF P_LED,b_LED0
RETURN
;*********SUBIR PERSIANA 2******************
MENSINITs2:
CALL SUBIR
MOVLW A' '
CALL LCDIWR
MOVLW A'2'
CALL LCDIWR
BSF P_LED,b_LED1
RETURN
;*********SUBIR PERSIANAS******************
MENSINITst:
CALL SUBIR
MOVLW A'S'
CALL LCDIWR
BSF P_LED,b_LED0
BSF P_LED,b_LED1
RETURN
;*******************************************
;*********BAJAR PERSIANA 1******************
MENSINITb1:
CALL BAJAR
MOVLW A' '
CALL LCDIWR
MOVLW A'1'
CALL LCDIWR
BCF P_LED,b_LED0
RETURN
;*********BAJAR PERSIANA 2******************
MENSINITb2:
CALL BAJAR
MOVLW A' '
CALL LCDIWR
MOVLW A'2'
CALL LCDIWR
BCF P_LED,b_LED1
RETURN
;*********BAJAR TODAS******************
MENSINITbt:
CALL BAJAR
MOVLW A'S'
CALL LCDIWR
BCF P_LED,b_LED0
BCF P_LED,b_LED1
RETURN
;********AUTO PERSIANA 1**************
MENSINITa1:
CALL AUTO
MOVLW A' '
CALL LCDIWR
MOVLW A'1'
CALL LCDIWR
RETURN
;********AUTO PERSIANA 2*************
MENSINITa2:
CALL AUTO
MOVLW A' '
CALL LCDIWR
MOVLW A'2'
CALL LCDIWR
RETURN
;********AUTO TODAS******************
MENSINITat:
CALL AUTO
RETURN
END