Hola:
Siendo este código en asm para PIC16F84A (http://"http://ww1.microchip.com/downloads/en/DeviceDoc/35007C.pdf"), ya lo pasaré a PIC16F88 (http://"http://ww1.microchip.com/downloads/en/DeviceDoc/30487D.pdf").
; Implementar una tabla de la verdad mediante el manejo de tablas grabadas en ROM.
; Por ejemplo, la tabla será de 3 entradas y 6 salidas tal como la siguiente:
;
; C B A | S5 S4 S3 S2 S1 S0
; -----------|---------------------------
; 0 0 0 | 0 0 1 0 1 0 ; (Configuración 0).
; 0 0 1 | 0 0 1 0 0 1 ; (Configuración 1).
; 0 1 0 | 1 0 0 0 1 1 ; (Configuración 2).
; 0 1 1 | 0 0 1 1 1 1 ; (Configuración 3).
; 1 0 0 | 1 0 0 0 0 0 ; (Configuración 4).
; 1 0 1 | 0 0 0 1 1 1 ; (Configuración 5).
; 1 1 0 | 0 1 0 1 1 1 ; (Configuración 6).
; 1 1 1 | 1 1 1 1 1 1 ; (Configuración 7).
;
; Las entradas C, B, A se conectarán a las líneas del puerto A: RA2 (C), RA1 (B) y RA0 (A).
; Las salidas se obtienen en el puerto B:
; RB5 (S5), RB4 (S4), RB3 (S3), RB2 (S2), RB1 (S1) y RB0 (S0).
;
; ZONA DE DATOS **********************************************************************
LIST P=16F84A
INCLUDE <P16F84A.INC>
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
; ZONA DE CÓDIGOS ********************************************************************
ORG 0 ; El programa comienza en la dirección 0.
Inicio
bsf STATUS,RP0 ; Acceso al Banco 1.
clrf TRISB ; Las líneas del Puerto B se configuran como salida.
movlw b'00011111' ; Las 5 líneas del Puerto A se configuran como entrada.
movwf TRISA
bcf STATUS,RP0 ; Acceso al Banco 0.
Principal
movf PORTA,W ; Lee el valor de las variables de entrada.
andlw b'00000111' ; Se queda con los tres bits de entrada.
addwf PCL,F ; Salta a la configuración adecuada.
Tabla
goto Configuracion0
goto Configuracion1
goto Configuracion2
goto Configuracion3
goto Configuracion4
goto Configuracion5
goto Configuracion6
goto Configuracion7
Configuracion0
movlw b'00001010' ; (Configuración 0).
goto ActivaSalida
Configuracion1
movlw b'00001001' ; (Configuración 1).
goto ActivaSalida
Configuracion2
movlw b'00100011' ; (Configuración 2).
goto ActivaSalida
Configuracion3
movlw b'00001111' ; (Configuración 3).
goto ActivaSalida
Configuracion4
movlw b'00100000' ; (Configuración 4).
goto ActivaSalida
Configuracion5
movlw b'00000111' ; (Configuración 5).
goto ActivaSalida
Configuracion6
movlw b'00010111' ; (Configuración 6).
goto ActivaSalida
Configuracion7
movlw b'00111111' ; (Configuración 7).
ActivaSalida
movwf PORTB ; Visualiza por el puerto de salida.
goto Principal
END
Partiendo del código de arriba, quiero hacer una tabla de la verdad para un display de 7 segmentos y la otra tabla es para configuración a otra cosa. En dicho display debe contar del 1 al 4.
La idea consiste con un pulsador, incrementar las dos tablas de la verdad.
¿Esto es posible?
Si no entiendes, lo explico de otra manera.
Un saludo.
Buenas:
He modificado un poco el código. El esquema es este circuito.
(http://www.subeimagenes.com/img/pic-1043767.png)
Nueva tabla de la verdad corregida.
(http://www.subeimagenes.com/img/tabla-de-la-verdad-1043760.png)
La zona gris funciona de maravilla. El Display de 7 segmentos cuanta del 1 al 4 desde que pulse el pulsador. Si llega al 4, al pulsar una vez, llega al 1 así sucesivamente.
Fíjate ahora en la zona verde, es otra tabla de la verdad de datos, que se encienden los Led amarillos. Siempre es acorde al del display, por ejemplo.
Si en la tabla de la verdad zona gris del display es el número 2, tiene que estar acorde al mismo tiempo con el 2 de la zona verdad de datos.
(http://www.subeimagenes.com/img/sin-titulo-1-1043781.png)
El código lo hice más simple, solo funciona el Display del 1 al 4, pero no se que hacer para funcionar la zona verde de datos.
; Cada vez que presione el pulsador conectado al pin RA4 incrementa un contador visualizado
; en el display.
;
; ZONA DE DATOS **********************************************************************
LIST P=16F84A
INCLUDE <P16F84A.INC>
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
CBLOCK 0x0C
Contador ; El contador a visualizar.
ENDC
#DEFINE OE1 PORTA,0
#DEFINE OE2 PORTA,1
#DEFINE A21 PORTA,2
#DEFINE AUX PORTA,3
#DEFINE Pulsador PORTA,4 ; Pulsador conectado a RA4.
#DEFINE Display PORTB ; El display está conectado al Puerto B.
; ZONA DE CÓDIGOS ********************************************************************
ORG 0 ; El programa comienza en la dirección 0.
Inicio
bsf STATUS,RP0 ; Acceso al Banco 1.
clrf Display ; Estas líneas configuradas como salidas.
bcf OE1
bcf OE2
bcf A21
bcf AUX
bsf Pulsador ; Línea del pulsador configurada como entrada.
bcf STATUS,RP0 ; Acceso al Banco 0.
call InicializaContador ; Inicializa el Contador y lo visualiza.
Principal
btfsc Pulsador ; ¿Pulsador presionado?, ¿(Pulsador)=0?
goto Fin ; No. Vuelve a leerlo.
; call Retardo_20ms ; Espera que se estabilicen los niveles de tensión.
btfsc Pulsador ; Comprueba si es un rebote.
goto Fin ; Era un rebote y sale fuera.
call IncrementaVisualiza ; Incrementa el contador y lo visualiza.
EsperaDejePulsar
btfss Pulsador ; ¿Dejó de pulsar?. ¿(Pulsador)=1?
goto EsperaDejePulsar ; No. Espera que deje de pulsar.
Fin goto Principal
; Subrutina "IncrementaVisualiza" ---------------------------------------------------------
IncrementaVisualiza
incf Contador,F ; Incrementa el contador y comprueba si ha
movlw d'4' ; llegado a su valor máximo mediante una
subwf Contador,W ; resta. (W)=(Contador)-4.
btfsc STATUS,C ; ¿C=0?, ¿(W) negativo?, ¿(Contador)<4?
InicializaContador
clrf Contador ; No, era igual o mayor. Por tanto, resetea.
Visualiza
movf Contador,W
; call Numero_a_7Segmentos ; Lo pasa a siete segmento para poder ser
call Tabla
movwf Display ; visualizado en el display.
return
Tabla
addwf PCL,F
DT 06h, 5Bh, 4Fh, 66h ; Números 1, 2, 3 y 4.
INCLUDE <RETARDOS.INC> ; Subrutinas de retardo.
END ; Fin del programa.
¿Hay alguna idea?
Saludo.
Uhh hace mucho que no toco ASM pero ¿Porque no simplemente haces otra tabla?
IncrementaVisualiza
incf Contador,F ; Incrementa el contador y comprueba si ha
movlw d'4' ; llegado a su valor máximo mediante una
subwf Contador,W ; resta. (W)=(Contador)-4.
btfsc STATUS,C ; ¿C=0?, ¿(W) negativo?, ¿(Contador)<4?
InicializaContador
clrf Contador ; No, era igual o mayor. Por tanto, resetea.
Visualiza
movf Contador,W
; call Numero_a_7Segmentos ; Lo pasa a siete segmento para poder ser
call Tabla
movwf Display ; visualizado en el display.
movf Contador,W
call Tabla2
movwf PORTA
return
Tabla
addwf PCL,F
DT 06h, 5Bh, 4Fh, 66h ; Números 1, 2, 3 y 4.
Tabla2
addwf PCL,F
DT 02h, 05h, 06h, 0Ah
Gracias.
Una tabla es para el display, la otra para datos, control para otros dispositivos.
Me pasé al PIC16F88 porque usa oscilador interno, lo he configurado a 4 MHz y no estoy seguro si realmente lo he hecho bien. A pesar que en el simulador Proteus 7.10 funciona muy bien, la realidad es muy distinta.
(http://www.subeimagenes.com/img/sin-titulo-1-1044438.png)
A la hora de montarlo en una demoboard para probarlo, me da en el display carácteres raros en vez del 1 al 4. Los Led azules que ven son los amarillos del esquema de arriba que si funciona a la perfección.
(http://www.subeimagenes.com/img/p1180900-1044429.gif)
Los cables están bien. Lo que no se si este nuevo código está bien. En el proteus funciona, la realidad no.
;
; 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
; 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
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
; ----------------------------------------------------------------------------------------------------
; ******************************************************************************
END
Saludo.
¡Lo probe en MPLAB y no tuve ningún problema! Al menos no con tu código... que tuve problemas para configurar el compilador xD.
(http://i.imgur.com/yp1AMw8.jpg)
Buenas:
Tenía los conectores no muy bien colocados. Gracias por la ayuda e ideas. Ahora me funciona de maravilla.
(http://www.subeimagenes.com/img/p1180908-1044977.jpg)
El siguiente y último reto que nunca he usado la EEPROM interna del PIC16F88 (http://ww1.microchip.com/downloads/en/DeviceDoc/30487D.pdf), no me sale a pesar de leer bien su hoja de datos. En la página 29 del datasheet te dice códigos pero a mi no me funciona o no se hacerlo.
Lo que quiero hacer es guardar los últimos datos seleccionados por el pulsador de las dos tablas de la verdad. Por ejemplo, si estamos en el número 2 del Display, al apagarlo y encenderlo otra vez el PIC, aparezca precisamente el 2, que es el último número que se mostró. Se incluye también el guardado de la tabla de la verdad de datos.
(http://www.subeimagenes.com/img/tabla-de-la-verdad-1043760.png)
Los que sepan, una ayudita. Por lo que veo, no se me da para nada bien guardar y recuperar datos en la EEPROM interna del PIC. Fijándome bien, se necesita una celda para guardar los 8 bits o un byte de la Tabla de la verdad gris del Display, y otra celda o posición de memoria también de 8 bits o un byte en la Tabla de la verdad verde de datos.
(http://www.subeimagenes.com/img/sin-titulo-1-1044982.gif)
De todas formas, voy a intentarlo por si acaso.
Desde que funcione todo, subo un vídeo.
Saludo.
Algo he hecho que no se guarda los datos en la EEPROM.
;
; 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
call Leer_EEPROM ; Lectura de la EEPROM.
; 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
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
call Escribir_EEPROM
; 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.
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.
END
(http://www.subeimagenes.com/img/gif-1045078.gif)
El circuito funciona de maravilla, pero no guarda los datos.
Saludo.
Hay una forma muy sencilla de asociar los datos de las tablas.
La EEPROM es así:
(http://i.imgur.com/ERXMeHM.png)
Viendo la memoria así, lo primero que me vino a la mente fue:
(http://i.imgur.com/EDagTQ2.jpg)
Es decir en 0xh puedes guardar todo lo asociado a una tabla y en 1xh puedes guardar todo lo de otra tabla.
Si lo quieres ver en binario
00000000 <-Primera dirección, tabla 1.
00010000 <-Primera dirección, tabla 2.
Y esto es una manera muy sencilla de guardar/leer datos.
Y ahora para asociarlos con el contador lo puedes hacer muy sencillamente así:
movf contador, w ;Direccion 1 Tabla 1
xorlw b'00010000' ;Direccion1 Tabla 2
Puedes inclusive simplemente guardar los metodos de la datasheet y están listos para usarse.
LeerEEPROM:
BANKSEL EEADR ; Select Bank of EEADR
MOVF ADDR, W ;
MOVWF EEADR ; Data Memory Address
; to read
BANKSEL EECON1 ; Select Bank of EECON1
BCF EECON1, EEPGD; Point to Data memory
BSF EECON1, RD ; EE Read
BANKSEL EEDATA ; Select Bank of EEDATA
MOVF EEDATA, W ; W = EEDATA
;Seleciona el banco donde estabas antes de regresar
BANKSEL PORTA
return
Y lo usas así.
Para sacar el dato de la primera Tabla:
movf contador, w
movwf ADDR ;De preferencia cambia el nombre de la variable
call LeerEEPROM
movwf PORTB
movf contador, w
xorlw b'00010000'
movwf ADDR;
call LeerEEPROM
movwf PORTA
Y para guardar lo mismo, de lo que no me acuerdo es si la escritura a la EEPROM es solo de 1 byte a la vez.
EscribirEEPROM:
BANKSEL EECON1 ; Select Bank of
; EECON1
BTFSC EECON1, WR ; Wait for write
GOTO $-1 ; to complete
BANKSEL EEADR ; Select Bank of
; EEADR
MOVF ADDR, W ;
MOVWF EEADR ; Data Memory
; Address to write
MOVF VALUE, W ;
MOVWF EEDATA ; Data Memory Value
; to write
BANKSEL EECON1 ; Select Bank of
; EECON1
BCF EECON1, EEPGD ; Point to DATA
; memory
BSF EECON1, WREN ; Enable writes
BCF INTCON, GIE ; Disable INTs.
MOVLW 55h ;
MOVWF EECON2 ; Write 55h
MOVLW AAh ;
MOVWF EECON2 ; Write AAh
BSF EECON1, WR ; Set WR bit to
; begin write
BSF INTCON, GIE ; Enable INTs.
BCF EECON1, WREN ; Disable writes
return
GuardaDatos:
;Rutina para escribir los 8 bytes.
;1 Tabla 1 Direccion
movlw 00h
movwf ADDR
movlw 06h
movwf VALUE
call EscribirEEPROM
;2 Tabla 1 Direccion
movlw 10h
movwf ADDR
movlw b'00000010'
movwf VALUE
call EscribirEEPROM
;Y asi sigues agregando a la EEPROM
return ; o goto, dependiendo de lo que quieras hacer
Hola:
Por lo que cuentas, falta vovler en Escribir_EEPROM volver al banco 00, justo antes del return.
Por ahora lo he hecho así. Creo, solo creo, que no hace falta usar dos direcciones, solo uno, el del contador.
;
; 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
call Leer_EEPROM ; Lectura de la EEPROM.
; 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
Lo que no me guarda nada.
Cita de: Meta en 4 Agosto 2014, 21:49 PM
Hola:
Por lo que cuentas, falta vovler en Escribir_EEPROM volver al banco 00, justo antes del return.
Por ahora lo he hecho así. Creo, solo creo, que no hace falta usar dos direcciones, solo uno, el del contador.
Respecto a lo de seleccionar nuevamente el Banco 00 depende. Yo por lo general escribo a la memoria antes de entrar al loop del programa y al entrar al programa seleciono el banco 00.
No acabo de entender lo que quieres hacer con la EEPROM pero parece que quieres escribir el contador en la EEPROM. Tu rutina de escritura no especifica que informacion volcar en la EEPROM, simplemente la direccion.
Vaya lo que hace el PIC es basicamente escribir lo que haya EEDATA en la direccion EEADR, por eso necesitas usar las dos direcciones, una para especificar la direccion en donde guardar la informacion en la EEPROM y la otra para guardar la informacion en si.
Hola:
Pensé que guardando el valor contador, es suficiente con solo un byte recordar las dos tablas donde van. Voy a examinarlo mejor tu código.
Le has puesto dos variables. ADDR y VALUE para guardar.
Saludo.
Hola:
Ahora me funciona todo.
;
; 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.
; El Contador queda guardado en la EEPROM.
;
; (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
;
;*******************************************************************************
; Listado y condiciones de ensamblado
LIST P=16F88 ; 4 Mhz
INCLUDE <P16F88.INC>
;radix hex
ERRORLEVEL -302 ; Turn off banking message
;*******************************************************************************
; Fusibles
__CONFIG _CONFIG1, _CP_OFF & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _INTRC_IO
; _CP_OFF : Protección de código
; _DEBUG_OFF : Debug en circuito
; _WRT_PROTECT_OFF : Protección a escritura en memoria de programa
; _CPD_OFF : Protección de código de datos
; _LVP_OFF : Programación en baja tensión
; _BODEN_OFF : Reset por Brown-out
; _MCLRE_ON : Reset por pin externo
; _PWRTE_ON : Retraso al reset
; _WDT_OFF : Watchdog
; _XT_OSC : Oscilador externo del tipo XT
;*******************************************************************************
; Definiciones
; Máscaras de E/S de los puertos. 0 = salida, 1 = entrada
; |76543210|
#DEFINE PUERTO_A b'00010000'
#DEFINE PUERTO_B b'00000000'
; Incorporar sentencias de comprobación de la EEPROM
#DEFINE test_eeprom 0
;*******************************************************************************
; Variables
Variables UDATA_SHR
Contador RES 1 ; Contador en la SRAM
; ******************************************************************************
; EEPROM
; Dirección del Contador dentro de la EEPROM
EE_Contador EQU 0x02
; Debemos desplazarnos a la zona de memoria más allá del 0x2100, que corresponde
; a la zona de la EEPROM en la mayoría de los PIC (ver documentación).
; Este valor es el que se grabará en la EEPROM en el momento de grabar el programa
; en el µcontrolador.
ORG 0x2100 + EE_Contador
DE 0x01 ; valor inicial de ee_Contador
;*******************************************************************************
ORG 0x0000
Inicio
banksel ANSEL ; bank 1
clrf ANSEL ; puerto A digital
movlw PUERTO_A ; definir E/S puerto A
movwf TRISA
movlw PUERTO_B ; definir E/S puerto B
movwf TRISB
movlw b'01100000' ; 4 MHz
movwf OSCCON
call EEPROM_LeeDato
#if test_eeprom
; Comprobar que el Contador es correcto (esta parte es opcional)
decf Contador, w ; leemos el Contador y le quitamos 1
andlw 0x3 ; nos quedamos solo con los bits inferiores
addlw 0x1 ; volvemos a sumarle 1
movwf Contador ; y lo guardamos
#endif
goto Visualiza ; ir a presentar
; Bucle principal
Principal
btfsc PORTA, RA4 ; leer pulsador
goto Principal ; No, esperar
;
; Se ha pulsado el botón
call incrementa_Contador
Visualiza
call visualiza_Contador
call salida_hacia_A
; Esperar liberación del botón
Espera_levantar
call Retardo_100ms ; Esperar la suelta del botón
btfss PORTA, RA4 ; leer pulsador
goto Espera_levantar ; No, esperar
; Repetir
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 ; Si el Contador valía 4, ahora vale 0
incf Contador, f ; Incrementa el Contador
call EEPROM_EscribeDato
; ******************************************************************************
;; 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_var udata_shr
Retardo_100ms_d1 res 1
Retardo_100ms_d2 res 1
Retardo_code code
Retardo_100ms
;99993 cycles
movlw 0x1E
movwf Retardo_100ms_d1
movlw 0x4F
movwf Retardo_100ms_d2
Retardo_100ms_0
decfsz Retardo_100ms_d1, f
goto $+2
decfsz Retardo_100ms_d2, f
goto Retardo_100ms_0
;3 cycles
goto $+1
nop
;4 cycles (including call)
return
; ******************************************************************************
; Leer valor del Contador en la EEPROM
EEPROM_LeeDato
banksel EEADR ; bank 2
movlw EE_Contador ; dirección de la EEPROM a leer
movwf EEADR
banksel EECON1 ; bank 3
bcf EECON1, EEPGD ; acceso a la memoria de datos
bsf EECON1, RD ; inicia la lectura
banksel EEDATA ; bank 2
movf EEDATA, w ; dato leído en W
movwf Contador ; guardar en SRAM
;
banksel PORTA ; bank 0, durante el programa
return
; Escribe el Contador en la EEPROM
EEPROM_EscribeDato
banksel EECON1 ; bank 3
btfsc EECON1, WR ; esperar para poder escribir
goto $-1
banksel EEADR ; bank 2
movlw EE_Contador ; dirección donde vamos a escribir
movwf EEADR
movf Contador, w ; el valor que vamos a escribir
movwf EEDATA
banksel EECON1 ; bank 3
bcf EECON1, EEPGD ; acceso a la memoria de datos
bsf EECON1, WREN ; activa la escritura
; bcf INTCON, GIE ; desactivar interrupciones
movlw b'01010101' ; valores mágicos (requeridos)
movwf EECON2
movlw b'10101010'
movwf EECON2
bsf EECON1, WR ; comienza la escritura
; bsf INTCON, GIE ; reactiva interrupciones
bcf EECON1, WREN ; desactiva escrituras
banksel PORTA ; volvemos a bank 0
return
END
Gracias por tu tiempo. :D
Buenas:
Voy hacerles una pregunta. Sobre el código de arriba quiero hacer algo parecido del PIC16F88 (http://"http://ww1.microchip.com/downloads/en/DeviceDoc/30487D.pdf")al PIC16F630 (http://"http://ww1.microchip.com/downloads/en/DeviceDoc/40039F.pdf") para saber si realmente funciona. Hablo de adaptación del código y usando un decodificador 74LS48 (http://"https://www.physics.rutgers.edu/ugrad/327/sn74ls48rev5.pdf").
Transformar este esquema...
(http://www.subeimagenes.com/img/gif-1045078.gif)
Con este otro.
(http://www.subeimagenes.com/img/picd-1045168.png)
Habiendo el primer circuito con menos componentes. ¿Por qué usar el segundo esquema también?
Porque otras personas que quieren montar el circuito no pueden debido a que su local de electrónica favorita no tienen el PIC16F88 (http://"http://ww1.microchip.com/downloads/en/DeviceDoc/30487D.pdf") y si el PIC16F630 (http://"http://ww1.microchip.com/downloads/en/DeviceDoc/40039F.pdf") junto con el decodificador de 7 segmentos 74LS48 (http://"https://www.physics.rutgers.edu/ugrad/327/sn74ls48rev5.pdf").
Partiendo del código de abajo del PIC16F88 para analizarlo bien.
; 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.
; El Contador queda guardado en la EEPROM.
;
; (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
;
;*******************************************************************************
; Listado y condiciones de ensamblado
LIST P=16F88 ; 4 Mhz
INCLUDE <P16F88.INC>
;radix hex
ERRORLEVEL -302 ; Turn off banking message
;*******************************************************************************
; Fusibles
__CONFIG _CONFIG1, _CP_OFF & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _INTRC_IO
; _CP_OFF : Protección de código
; _DEBUG_OFF : Debug en circuito
; _WRT_PROTECT_OFF : Protección a escritura en memoria de programa
; _CPD_OFF : Protección de código de datos
; _LVP_OFF : Programación en baja tensión
; _BODEN_OFF : Reset por Brown-out
; _MCLRE_ON : Reset por pin externo
; _PWRTE_ON : Retraso al reset
; _WDT_OFF : Watchdog
; _XT_OSC : Oscilador externo del tipo XT
;*******************************************************************************
; Definiciones
; Máscaras de E/S de los puertos. 0 = salida, 1 = entrada
; |76543210|
#DEFINE PUERTO_A b'00010000'
#DEFINE PUERTO_B b'00000000'
; Incorporar sentencias de comprobación de la EEPROM
#DEFINE test_eeprom 0
;*******************************************************************************
; Variables
Variables UDATA_SHR
Contador RES 1 ; Contador en la SRAM
; ******************************************************************************
; EEPROM
; Dirección del Contador dentro de la EEPROM
EE_Contador EQU 0x02
; Debemos desplazarnos a la zona de memoria más allá del 0x2100, que corresponde
; a la zona de la EEPROM en la mayoría de los PIC (ver documentación).
; Este valor es el que se grabará en la EEPROM en el momento de grabar el programa
; en el µcontrolador.
ORG 0x2100 + EE_Contador
DE 0x01 ; valor inicial de ee_Contador
;*******************************************************************************
CODE 0x0000
Inicio
banksel ANSEL ; bank 1
clrf ANSEL ; puerto A digital
movlw PUERTO_A ; definir E/S puerto A
movwf TRISA
movlw PUERTO_B ; definir E/S puerto B
movwf TRISB
movlw b'01100000' ; 4 MHz
movwf OSCCON
call EEPROM_LeeDato
#if test_eeprom
; Comprobar que el Contador es correcto (esta parte es opcional)
decf Contador, w ; leemos el Contador y le quitamos 1
andlw 0x3 ; nos quedamos solo con los bits inferiores
addlw 0x1 ; volvemos a sumarle 1
movwf Contador ; y lo guardamos
#endif
goto Visualiza ; ir a presentar
; Bucle principal
Principal
btfsc PORTA, RA4 ; leer pulsador
goto Principal ; No, esperar
;
; Se ha pulsado el botón
call incrementa_Contador
Visualiza
call visualiza_Contador
call salida_hacia_A
; Esperar liberación del botón
Espera_levantar
call Retardo_100ms ; Esperar la suelta del botón
btfss PORTA, RA4 ; leer pulsador
goto Espera_levantar ; No, esperar
; Repetir
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 ; Si el Contador valía 4, ahora vale 0
incf Contador, f ; Incrementa el Contador
call EEPROM_EscribeDato
; ******************************************************************************
;; 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
; ----------------------------------------------------------------------------------------------------
Retardo_var udata_shr
Retardo_100ms_d1 res 1
Retardo_100ms_d2 res 1
Retardo_code code
Retardo_100ms
;99993 cycles
movlw 0x1E
movwf Retardo_100ms_d1
movlw 0x4F
movwf Retardo_100ms_d2
Retardo_100ms_0
decfsz Retardo_100ms_d1, f
goto $+2
decfsz Retardo_100ms_d2, f
goto Retardo_100ms_0
;3 cycles
goto $+1
nop
;4 cycles (including call)
return
; ******************************************************************************
; Leer valor del Contador en la EEPROM
EEPROM_LeeDato
banksel EEADR ; bank 2
movlw EE_Contador ; dirección de la EEPROM a leer
movwf EEADR
banksel EECON1 ; bank 3
bcf EECON1, EEPGD ; acceso a la memoria de datos
bsf EECON1, RD ; inicia la lectura
banksel EEDATA ; bank 2
movf EEDATA, w ; dato leído en W
movwf Contador ; guardar en SRAM
;
banksel PORTA ; bank 0, durante el programa
return
; Escribe el Contador en la EEPROM
EEPROM_EscribeDato
banksel EECON1 ; bank 3
btfsc EECON1, WR ; esperar para poder escribir
goto $-1
banksel EEADR ; bank 2
movlw EE_Contador ; dirección donde vamos a escribir
movwf EEADR
movf Contador, w ; el valor que vamos a escribir
movwf EEDATA
banksel EECON1 ; bank 3
bcf EECON1, EEPGD ; acceso a la memoria de datos
bsf EECON1, WREN ; activa la escritura
; bcf INTCON, GIE ; desactivar interrupciones
movlw b'01010101' ; valores mágicos (requeridos)
movwf EECON2
movlw b'10101010'
movwf EECON2
bsf EECON1, WR ; comienza la escritura
; bsf INTCON, GIE ; reactiva interrupciones
bcf EECON1, WREN ; desactiva escrituras
banksel PORTA ; volvemos a bank 0
return
END
(http://www.subeimagenes.com/img/coor-1058681.png)
Antes de tocar algo.
¿Debo saber algo más?
Un saludo.
PD: Espero que no sea mucho de machacarte las neuronas por una adapación en asm.