Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:
Hola:
Tengo medio hecho unos códigos del PIC16F84A-04, quiero grabar los Relay_1 al Relay_4 en la EEPROM, es decir, los últimos estados de los relés en ON o OFF. Aún así sigo intentado pero si les sale el código mejor que el mio, mejor que mejor.
;********************************* Meta_Control.asm ********************************
;
; ===================================================================
; Del libro "MICROCONTROLADOR PIC16F84. DESARROLLO DE PROYECTOS"
; E. Palacios, F. Remiro y L. López. www.pic16f84a.org
; Editorial Ra-Ma. www.ra-ma.es
; ===================================================================
;
; SISTEMA DE GOBIERNO DESDE ORDENADOR: Desde el teclado de un ordenador se desea comandar
; el movimiento de una estructura móvil, según la siguiente tabla:
;
; TECLA (Por ejemplo) MOVIMIENTO
; ------------------- ----------
; t Adelante
; b Atrás
; a Izquierda
; l Derecha
; Espacio Parada
;
; La pulsación de cualquiera de estas teclas activa el estado de las salidas correspondiente
; RB3 (Adelante), RB2 (Atrás), RB1 (Izquierda), RB0 (Derecha) y apaga el resto.
;
; El movimiento que se está realizando aparece reflejado en un mensaje en el visualizador LCD
; del sistema y también en la pantalla del ordenador.
;
; El programa debe permitir modificar facilmente en posteriores revisiones en el hardware de
; la salida. Es decir, para activar las salidas conviene utilizar el direccionamiento por bit
; en lugar de por byte (utilizar instrucciones "bsf" y "bcf", en lugar de "mov..").
;
; ZONA DE DATOS ****************************************************************
LIST P=16F84A
INCLUDE <P16F84A.INC>
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
CBLOCK 0x0C
TeclaPulsada ; Va a guardar el contenido de la tecla pulsada.
MensajeApuntado ; Va a guarda la dirección del mensaje apuntado.
Relay_1
Relay_2
Relay_3
Relay_4
ENDC
#DEFINE SalidaR1 PORTB,3 ; Define dónde se sitúan las salidas.
#DEFINE SalidaR2 PORTB,2
#DEFINE SalidaR3 PORTB,1
#DEFINE SalidaR4 PORTB,0
TECLA_RELE_1_ON EQU 'q' ; Código de las teclas utilizadas.
TECLA_RELE_1_OFF EQU 'a'
TECLA_RELE_2_ON EQU 'w'
TECLA_RELE_2_OFF EQU 's'
TECLA_RELE_3_ON EQU 'e'
TECLA_RELE_3_OFF EQU 'd'
TECLA_RELE_4_ON EQU 'r'
TECLA_RELE_4_OFF EQU 'f'
TECLA_INICIO EQU 'z'
TECLA_PARADA EQU ' '
TECLA_INFO EQU 'i' ; Código de la tecla espaciadora, (hay un espacio,
; tened cuidado al teclear el programa).
ENTER EQU 0x0A ; Código de tecla "Enter" o "Retorno de Carro".
CAMBIO_LINEA EQU 0x0D ; Código para el cambio de línea.
ORG 0x2100 ; Corresponde a la dirección 0 de la zona EEPROM
; de datos.
DE 0x00, 0x00, 0x00, 0x00
; ZONA DE CÓDIGOS *****************************************************************
ORG 0
Inicio
call LCD_Inicializa
call RS232_Inicializa
bsf STATUS,RP0 ; Configura como salidas las 4 líneas del
bcf SalidaR1 ; del Puerto B respetando la configuración del
bcf SalidaR2 ; resto de las líneas.
bcf SalidaR3
bcf SalidaR4
bcf STATUS,RP0
call Parado ; En principio todas las salidas deben estar
Principal ; apagadas.
call RS232_LeeDato ; Espera a recibir un carácter.
call TesteaTeclado
goto Principal
; "Mensajes" ----------------------------------------------------------------------------
;
Mensajes
addwf PCL,F
MensajeParado
DT "Sistema PARADO", 0x00
Mensaje_R1_ON
DT "RELE 1 ON", 0x00
Mensaje_R1_OFF
DT "RELE 1 OFF", 0x00
Mensaje_R2_ON
DT "RELE 2 ON", 0x00
Mensaje_R2_OFF
DT "RELE 2 OFF", 0x00
Mensaje_R3_ON
DT "RELE 3 ON", 0x00
Mensaje_R3_OFF
DT "RELE 3 OFF", 0x00
Mensaje_R4_ON
DT "RELE 4 ON", 0x00
Mensaje_R4_OFF
DT "RELE 4 OFF", 0x00
Mensaje_Info
; DT 0xC9, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xBB
; DT ENTER, CAMBIO_LINEA
DT 0xBA, " FirmWare v1.00 ", 0xBA
DT ENTER, CAMBIO_LINEA
DT 0xBA, " PIC16F84A ", 0xBA
DT ENTER, CAMBIO_LINEA
DT 0xBA, " 4 MHz ", 0xBA
; DT ENTER, CAMBIO_LINEA
; DT 0xCC, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xB9
DT ENTER, CAMBIO_LINEA
DT " metaconta@gmail.com", 0x00
Mensaje_Activar
DT "Todos activos", 0x00
; Subrutina "TesteaTeclado" -------------------------------------------------------------
;
; Testea el teclado y actúa en consecuencia.
TesteaTeclado
movwf TeclaPulsada ; Guarda el contenido de la tecla pulsada.
xorlw TECLA_RELE_1_ON ; ¿Es la tecla del movimiento hacia adelante?
btfsc STATUS,Z
goto R1_ON ; Sí, se desea movimiento hacia adelante.
;
movf TeclaPulsada,W ; Recupera el contenido de la tecla pulsada.
xorlw TECLA_RELE_1_OFF ; ¿Es la tecla del movimiento hacia atrás?
btfsc STATUS,Z
goto R1_OFF ; Sí, se desea movimiento hacia atrás.
;
movf TeclaPulsada,W ; Recupera el contenido de la tecla pulsada.
xorlw TECLA_RELE_2_ON ; ¿Es la tecla del movimiento hacia la izquierda?
btfsc STATUS,Z
goto R2_ON ; Sí, se desea movimiento hacia la izquierda.
;
movf TeclaPulsada,W ; Recupera el contenido de la tecla pulsada.
xorlw TECLA_RELE_2_OFF ; ¿Es tecla del movimiento hacia la derecha?
btfsc STATUS,Z
goto R2_OFF ; Sí, se desea movimiento hacia la derecha.
;
movf TeclaPulsada,W
xorlw TECLA_RELE_3_ON
btfsc STATUS,Z
goto R3_ON
;
movf TeclaPulsada,W
xorlw TECLA_RELE_3_OFF
btfsc STATUS,Z
goto R3_OFF
;
movf TeclaPulsada,W
xorlw TECLA_RELE_4_ON
btfsc STATUS,Z
goto R4_ON
;
movf TeclaPulsada,W
xorlw TECLA_RELE_4_OFF
btfsc STATUS,Z
goto R4_OFF
;
movf TeclaPulsada,W
xorlw TECLA_INICIO
btfsc STATUS,Z
goto Activar
;
movf TeclaPulsada,W
xorlw TECLA_INFO
btfsc STATUS,Z
goto Info
;
movf TeclaPulsada,W ; Recupera el contenido de la tecla pulsada.
xorlw TECLA_PARADA ; ¿Es la tecla de parada?.
btfss STATUS,Z
goto Fin ; No es ninguna tecla de movimiento. Sale.
Parado
bcf SalidaR1 ; Como se ha pulsado la tecla de parada se
bcf SalidaR2 ; desactivan todas las salidas.
bcf SalidaR3
bcf SalidaR4
movlw MensajeParado
goto Visualiza
R1_ON
bsf SalidaR1
movlw Mensaje_R1_ON
goto Visualiza
R1_OFF
bcf SalidaR1
movlw Mensaje_R1_OFF
goto Visualiza
R2_ON
bsf SalidaR2
movlw Mensaje_R2_ON
goto Visualiza
R2_OFF
bcf SalidaR2
movlw Mensaje_R2_OFF
goto Visualiza
R3_ON
bsf SalidaR3
movlw Mensaje_R3_ON
goto Visualiza
R3_OFF
bcf SalidaR3
movlw Mensaje_R3_OFF
goto Visualiza
R4_ON
bsf SalidaR4
movlw Mensaje_R4_ON
goto Visualiza
R4_OFF
bcf SalidaR4
movlw Mensaje_R4_OFF
goto Visualiza
Activar
bsf SalidaR1 ; Como se ha pulsado la tecla de parada se
bsf SalidaR2 ; desactivan todas las salidas.
bsf SalidaR3
bsf SalidaR4
movlw Mensaje_Activar
goto Visualiza
Info
movlw Mensaje_Info
; Según el estado de las salidas visualiza el estado del sistema en el visualizador LCD y en
; el monitor del ordenador.
Visualiza
movwf MensajeApuntado ; Guarda la posición del mensaje.
call LCD_Borra ; Borra la pantalla del modulo LCD.
movf MensajeApuntado,W ; Visualiza el mensaje en la pantalla
call LCD_Mensaje ; del visualizador LCD.
call RS232_LineasBlanco ; Borra la pantalla del ordenador.
movf MensajeApuntado,W
call RS232_Mensaje ; Lo visualiza en el HyperTerminal.
call RS232_LineasBlanco
Fin return
INCLUDE <RS232.INC>
INCLUDE <RS232MEN.INC>
INCLUDE <LCD_4BIT.INC>
INCLUDE <LCD_MENS.INC>
INCLUDE <RETARDOS.INC>
INCLUDE <EEPROM.INC>
END
Un cordial saludo.
EDITO:
Lo estoy intentado en esta parte:
R1_ON
clrw
call EEPROM_LeeDato
movwf Relay_1
movf Relay_1,W
call EEPROM_EscribeDato
bsf SalidaR1
movlw Mensaje_R1_ON
goto Visualiza
La idea es que si en el PORTB hay en la salida b'10100100', que se guarde ese valor del puerto B en la EEPROM. El motivo es por si se apaga la luz, se queda sin batería o cualquier otra cosa, al reiniciar el PIC de nuevo, lea los últimos valores que estaban antes de quedarse sin pilas.
Una pregunta: ¿el ir guardando datos en la EEPROM del PIC no va restando escrituras? ¿No llegará un momento en que la EEPROM no se pueda reescribir? Si cada vez que cambia el estado de una de las salidas la almacenas en la EEPROM ¿no estás acortando la vida de la EEPROM? ¿Por qué no almacenas esta información en una memoria externa al PIC?
Cierto. Tarda mucho tiempo en acortarse la vida. ¿Por qué voy a usar por ejemplo un 24LC256 si sólo voy a usar una celda de las 64 que hay en el propio PIC?
En las memorias externas también se acortan. En temas de configuración para eso está la EEPROM interna. En temas de muchos mensajes para LCD por ejemplo, se usa la EEPROM externa.
Sólo quiero lograr guardar los datos del puerto B en la EERPOM intermna, que para eso los fabrican, ejejejeje
EEPROM.INC
;************************** Librería "EEPROM.INC" *******************************
;
; Estas subrutinas permiten realizar las tareas básicas de escritura y lectura de la
; memoria EEPROM de datos del PIC.
;
; Subrutina "EEPROM_LeeDato" ------------------------------------------------------------
;
; El microcontrolador lee el dato que hay escrito en la posición de la EEPROM del PIC apuntada
; por el contenido del registro de trabajo W. El resultado se proporciona en el mismo W.
;
; Entrada: En (W) la dirección de la memoria EEPROM a leer.
; Salida : En (W) el byte leído.
EEPROM_LeeDato
bcf STATUS,RP0 ; Asegura que trabaja con el Banco 0.
movwf EEADR ; Dirección a leer.
bsf STATUS,RP0 ; Banco 1.
bsf EECON1,RD ; Orden de lectura.
EEPROM_SigueLeyendo
btfsc EECON1,RD ; El PIC indica que ha terminado la lectura
goto EEPROM_SigueLeyendo ; poniendo en bajo este bit.
bcf STATUS,RP0 ; Banco 0.
movf EEDATA,W ; El byte leído al registro W.
return
; Subrutina "EEPROM_EscribeDato" --------------------------------------------------------
;
; Escribe el dato introducido en el registro de trabajo W en la posición de memoria EEPROM del
; PIC apuntada por el registro EEADR.
;
; Como altera el valor del registro INTCON al posicionar el flag GIE, éste se debe guardar al
; principio de la subrutina y restaurarlo al final.
;
; Entradas: En el registro EEADR la dirección de la memoria EEPROM a escribir.
; En el registro W el byte a escribir.
;
CBLOCK
EEPROM_GuardaINTCON
ENDC
EEPROM_EscribeDato
bcf STATUS,RP0 ; Asegura que trabaja con el Banco 0.
movwf EEDATA ; El byte a escribir.
movf INTCON,W ; Reserva el valor anterior de INTCON
movwf EEPROM_GuardaINTCON
bsf STATUS,RP0 ; Acceso al Banco 1.
bcf INTCON,GIE ; Deshabilita todas las interrupciones.
bsf EECON1,WREN ; Habilita escritura.
;
; El fabricante especifica que hay que seguir esta secuencia para escritura en EEPROM:
;
movlw 0x55
movwf EECON2
movlw 0xAA
movwf EECON2
bsf EECON1,WR ; Inicia la escritura.
EEPROM_TerminaEscribir
btfsc EECON1,WR ; Comprueba que termina de escribir en la EEPROM.
goto EEPROM_TerminaEscribir
bcf EECON1,WREN ; Desautoriza la escritura en EEPROM.
bcf EECON1,EEIF ; Limpia este flag.
bcf STATUS,RP0 ; Acceso al Banco 0.
movf EEPROM_GuardaINTCON,W ; Restaura el valor anterior de INTCON.
movwf INTCON
return
PD: El Rover que tienes en el avatar uno lo ha hecho algo similar o un intento con PIC32, lo han presentado en el Teide a nivel de Europa. Si vas a fabricar alguno, avisa ejjejejejj
http://www.youtube.com/watch?v=5Ci6fHHchV8 " onclick="window.open(this.href);return false;
🙂
Según he leido la memoria EEPROM de datos del PIC permite un millón de escrituras. En principio parecen muchas, pero si como veo en tu código cada vez que haces un movimiento escribes en la EEPROM te la cargas relativamente rápido. Para un prototipo para ver que tal va, pues me parece bien, pero yo buscaría otra solución...
Si no quieres utilizar una memoria externa, una idea para alargar la vida de esa EEPROM que se me ocurre sería guardar los datos de la RAM mientras tengas alimentación normal, y cuando detectes la caida de alimentación del sistema, mediante una interupción, con la carga de un condensador que te mantenga la alimentación del micro el tiempo suficiente, mover los datos de la RAM a la EEPROM.
No se, igual es un disparate lo que digo, pero creo que es una idea para alargar la vida útil del sistema.
PD Lo del rover es algo que me gustaría hacer... cuando me sienta capacitado para llevarlo acabo ya te aviso. Por el momento estoy algo lejos de ello, pero todo llegará. 😀 😀
El_Pack, lo que comentas no se si se podrá hacer... Se que existe el BOR (Brown-out Reset, que es especialmente útil para no corromper el contenido de la EEPROM) que lo que hace es poner el micro en estado de RESET cuando se detecta un voltaje por debajo del que configuremos. Pero no he visto que se pueda lanzar una interrupción con este periférico.
No obstante, si sería una buena idea que funcionase como comentas. Quizás usando una linea del CAD para monitorizar el voltaje de la alimentación podría funcionar, pero escribir en la EEPROM es una operación un poco lenta... De todos modos, yo no escribiría en EEPROM sin usar el BOR, ya que te puede corromper los datos una bajada de tensión.