;
; Un pulsador en RA4 va incrementando un contador, entre [1-4].
; La salida se envía a un display de 7 seg. en PORTB, y hacia salidas en PORTA.
;
; (Contador) |RB 76543210 |RA 76543210
; ------------|------------------------
; 1 | 00000011 | 00000010
; 2 | 00100100 | 00000101
; 3 | 00001100 | 00000110
; 4 | 00111100 | 00001001
;
; PORTA:
; RA0 : OE1
; RA1 : OE2
; RA2 : A21
; RA3 : AUX
; RA4 : Pulsador
; PORTB : display de 7 segmentos. a = RB0
;
; ZONA DE DATOS ****************************************************************
;*******************************************************************************
; Listado y condiciones de ensamblado
LIST P=16F88 ; 4 Mhz
radix dec
errorlevel -302 ; Turn off banking message
;*******************************************************************************
; Bibliotecas
INCLUDE <P16f88.INC>
;*******************************************************************************
; Fusibles
__CONFIG _CONFIG1, _CP_OFF & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _INTRC_IO
;_XT_OSC
; _CP_OFF: Protección de código DESACTIVADO.
; _DEBUG_OFF: Debug en circuito DESACTIVADO.
; _WRT_PROTECT_OFF: Protección a escritura en memoria de programa DESACTIVADO.
; _CPD_OFF: Protección de código de datos DESACTIVADO.
; _LVP_OFF: Programación en baja tensión DESACTIVADO.
; _BODEN_OFF: Reset por Brown-out DESACTIVADO.
; _MCLRE_ON: Reset por pin externo ACTIVADO.
; _PWRTE_ON: Retraso al reset ACTIVADO.
; _WDT_OFF: Watchdog DESACTIVADO.
; _XT_OSC: Oscilador externo del tipo XT.
__CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF
; _IESO_OFF: Modo de intercambio de externo a interno DESACTIVADO.
; _FCMEN_OFF: Monitor de CLK DESACTIVADO.
;*******************************************************************************
; Definiciones
; Máscaras de E/S de los puertos
; 0 = salida, 1 = entrada
; |76543210|
#define PORTA_ES b'00010000'
#define PORTB_ES b'00000000'
;*******************************************************************************
; Variables
area_compartida: udata_shr
contador res 1 ; Contador [1-4]
; ZONA DE CÓDIGOS **************************************************************
programa: code
ORG 000h
Inicio:
banksel ANSEL ; bank 1
clrf ANSEL ; Puerto analógico a digital.
movlw PORTA_ES ; definir E/S puerto A
movwf TRISA
movlw PORTB_ES ; definir E/S puerto B
movwf TRISB
;
movlw 0 ; inicializamos contador
movwf contador
; ###############################################################################
BANKSEL EEADR
clrf EEADR ; Selecciona dirección 00 de EEPROM.
call Leer_EEPROM ; Lectura de la EEPROM.
BANKSEL EEDATA
movlw 0xFF
subwf EEDATA,W
BANKSEL PORTA ;Banco 0
btfss STATUS,Z ;Es la 1ª vez que se usa la EEPROM ??
goto Inicializado ;No, el sistema ya se ha usado.
clrf contador
; ###############################################################################
; Bucle principal
BANKSEL OSCCON
movlw b'01100000' ; 4 MHz
movwf OSCCON
banksel PORTA ; bank 0, siempre
goto Inicializado
Principal:
movf PORTA, w ; leer puerto A
andlw PORTA_ES ; nos quedamos sólo con lo interesante
btfss STATUS, Z ; ¿Se ha pulsado? Lo está si RA4 == 0
goto Principal ; No, esperar
;
; Aquí llegamos con el botón pulsado
Inicializado:
call incrementa_contador
call visualiza_contador
call salida_hacia_A
; Esperamos que levante el botón
Espera_levantar:
call Retardo_100ms ; Esperar la suelta del pulsador
movf PORTA, w ; leer puerto A
andlw PORTA_ES ; nos quedamos sólo con lo interesante
btfsc STATUS, Z ; ¿Sigue pulsado? Lo está si RA4 == 0
goto Espera_levantar ; No, esperar
;
goto Principal
; ******************************************************************************
;; salida_hacia_A
;
; Según el valor del contador ([1-4]), lo transforma en otro, basado en una
; tabla y lo saca por el puerto A
;
salida_hacia_A: call transforma_contador
movwf PORTA ; visualiza en puerto A
return
transforma_contador:
decf contador,w ; leemos el contador y le restamos 1
addwf PCL, f ; saltamos dentro de la tabla
; |76543210|
retlw b'00000010'
retlw b'00000101'
retlw b'00000110'
retlw b'00001001'
; ******************************************************************************
;; incrementa_contador
;
; Incrementa el valor de la variable contador, entre 1 y 4, inclusives.
;
incrementa_contador:
bcf contador,2
incf contador
call Escribir_EEPROM ; Escribir dato en la EEPROM.
return
; ******************************************************************************
;; visualiza_contador
;
; Muestra el valor del contador en el display de 7 segmentos
;
visualiza_contador:
movfw contador ; leemos contador
call w_a_digito ; transformación a dígito 7 segmentos
movwf PORTB ; visualiza en puerto B
return
w_a_digito: addwf PCL, f ; salta al dígito indexado por w
; |76543210|
retlw b'00111111' ; 0
retlw b'00000110' ; 1
retlw b'01011011' ; 2
retlw b'01001111' ; 3
retlw b'01100110' ; 4
retlw b'01101101' ; 5
retlw b'01111101' ; 6
retlw b'00000111' ; 7
retlw b'01111111' ; 8
retlw b'01101111' ; 9
; ----------------------------------------------------------------------------------------------------
; Espera = 100ms
; Frecuencia de reloj = 4Mhz
;
; Espera real = 0.1 segundos = 100000 ciclos
; Error = 0.00 %
Retardo_par: udata_shr
Retardo_100ms_d1 res 1
Retardo_100ms_d2 res 1
Retardo_code: code
Retardo_100ms:
;99993 ciclos
movlw 0x1E
movwf Retardo_100ms_d1
movlw 0x4F
movwf Retardo_100ms_d2
Retardo_100ms_loop:
decfsz Retardo_100ms_d1, f
goto $+2
decfsz Retardo_100ms_d2, f
goto Retardo_100ms_loop
;3 ciclos
goto $+1
nop
;4 ciclos (incluyendo la llamada)
return
; Generado por delay_pic.pl (Joaquín Ferrero. 2014.07.22)
; ./delay_pic.pl -s Retardo_100ms 4Mhz 100ms
; mar 22 jul 2014 19:22:23 CEST
; http://perlenespanol.com/foro/generador-de-codigos-de-retardo-para-microcontroladores-pic-t8602.html
; ----------------------------------------------------------------------------------------------------
; ******************************************************************************
;Subrutinas EEPROM -----------------------------------------------------------
Leer_EEPROM
BANKSEL EEADR ; Selecciona el registro EEADR.
movf contador, W
movwf EEADR ; Dato dirección de momoria a leer.
BANKSEL EECON1 ; Selecciona el banco EECON1.
bcf EECON1, EEPGD ; Punto a memoria de datos
bsf EECON1, RD ; a Leer.
BANKSEL EEDATA ; Seleccionar banco de EEDATA.
movf EEDATA, W ; W = EEDATA.
BANKSEL PORTA
return
Escribir_EEPROM
BANKSEL EECON1 ; Selecciona banco de EECON1.
btfsc EECON1, WR ; Espera para escribir
goto $-1 ; a completar.
BANKSEL EEADR ; Selecciona el banco EEADR.
movf contador, W
movwf EEADR ; Dirección dato de memoria a escribir.
BANKSEL EECON1 ; Selecciona el banco EECOn1.
bcf EECON1, EEPGD ; Punto a dato de memoria.
bsf EECON1, WREN ; Activar escritura.
bcf INTCON, GIE ; Desactiva interrupciones.
; El fabricante especifica que hay que seguir esta secuencia para escritura en EEPROm.
movlw 0x55
movwf EECON2 ; Escribe 55h.
movlw 0xAA
movwf EECON2 ; Escribe AAh.
bsf EECON1, WR
bsf INTCON, GIE ; Activa interrupciones.
bcf EECON1, WREN ; Desactiva escrituras.
BANKSEL PORTA
return
END