TODOPIC
Microcontroladores PIC => * PROYECTOS * => Mensaje iniciado por: MaMu en 29 de Diciembre de 2006, 00:24:15
-
Estoy haciendo un proyectito, para controlar un estractor. El circuito se trata de un solo reloj, en segundos solamente, que es comun a dos horas programadas. Cada una de estas dos horas, representa el ciclo de trabajo, es decir, la primera hora programada es el tiempo que el estractor estara activo, y la segunda hora programada es el tiempo que estara inactivo. El segundero del reloj, comun a ambas horas, siempre esta corriendo, y afectando solo a una de las dos horas programadas, es decir, la hora del ciclo en curso. Por ejemplo, yo tengo como T1, programada 02:00, osea, el estractor estara encendido por 2Hs. Al correr los segundos, la hora del T1, se ira descontando hasta llegar a cero: 01:59, 01:58, 01:57 .... hasta llegar a 00:00, es ahi, cuando se conmutara la hora que es afectada, por lo tanto el segundero del reloj, trabajara ahora con T2, siendo este el tiempo de reposo del estractor. Al afectarse T2, T1 se resetea a la hora que habia sido programada, es decir 02:00 y no volvera a ser afectada hasta que T2 llegue a cero, en sintesis, el mismo procedimiento. El circuito trate de reducirlo lo mas que pude, de hecho hice una simulacion de como quedaria montado.
Necesito si alguno se toma la molestia de mirar el rediseño del circuito y emitir alguna opinion. Para tomar en cuenta, es que utilizo 3 interrupciones, TMR0 como temporizador, RB4..RB7 cuando al menos 1 pin cambia de estado y EEIE como fin de escritura en la EEPROM. Lo reduje lo mas que pude. No inclui fuente de alimentacion, ya que sera externa. En RA4 lo implemento como salida a otra etapa, para simular puse un led, recuerden que es en colector abierto esa salida. Sabiendo las interrupciones que uso, como ven el diseño? cambiarian algo? alguna sugerencia y/o modificacion que se les ocurra?
-
Hola MaMu ! :)
Yo no dejaría de hacerlo con un RTC.
Simplificarías mucho el software (creo) y sería más sencillo y fiable, tanto el soft, como el hard.
Eso es lo primero que creo.
Sigo mirando.
Saludos
Mario
-
Pense en hacerlo con RTC. Pero por el tipo de aplicacion de destino, no necesito presicion. EL software no es muy complicado. Se trata de mostrar todo el tiempo los 10 digitos, es decir, las 2 horas y el segundero comun. El retardo entre un display a otro, es de 2.5ms, como para engañar al ojo sin problemas. Luego, y aca viene la primera interrupcion, se programa al TMR0 para que desborde cada 1 segundo (aproximadamente...), cuando se atiende la interrupcion, se modifica cada uno de las posiciones de memoria donde esta contenido el valor de cada digito. Es decir, se incrementa 1 segundo, y se actua sobre los registros en consecuencia, cuestion de hacer cuentas. Utilizando la interrupcion de RB4..RB7, se hace el control del seteo de las horas, es decir, 4 botones, 2 para T1 y otros 2 para T2. Si los botones de T1 se presionan juntos, se detiene el reloj y se setea T1, pulsando de a uno, incrementa minutos y horas. Lo mismo con los otros 2 pulsadores para T2. Cuando se setea la hora, se almacena en la EEPROM, al saltar la int de escritura, se continua el ciclo. No es muy complicado, quizas si, son bastantes cosas, pero.. al 16F84 se le puede sacar mucho jugo toavia. De todas maneras, lo hago asi por que son los componentes que tengo, la idea es no gastar en nada.
Gracias y saludos.
-
yo te propongo el siguiente circuito
(http://img208.imageshack.us/img208/9394/ayudabu8.jpg)
te ahorras un monton de cableado, el pcb q seria un infierno, 7y todo consistiria en un solo chip, y se matienen tus 3 interrupciones, y ahi puedes mostrar tu reloj y algunas cosas mas, si tienes inconvenientes con el soft te puedo ayudar con los programas, por lo menos aca en el foro hay bastante info. exitos :-/
PD:ups cometi un error por apurado, los 4 pines del LCD se mandan al D4D5D6D7 no a los 4 primeros, nada mas. :D
-
Bueno micro_cadaver, despues de pensarlo un rato largo, te hice caso. Es impresionante lo que se reduce el circuito, ademas de quedar mucho mas profesional. Dejo una imagen de como me ha quedado.
Tengo las siguientes rutinas:
LCD_E Genera un pulso de 1µS por PORTB,2 patita 6 (Enable) del LCD. Si se usa una velocidad de micro diferente de 4MHz habrá que ajustar este tiempo.
LCD_BUSY Chequea si el LCD esta ocupado (BUSY) y retorna de la rutina cuando ya no lo este.
LCD_REG Pone al LCD en modo de recibir comandos , espera a que no este ocupado y va a LCD_E.
LCD_DATOS Pone el LCD en modo datos y manda el byte presente en W que será mostrado en pantalla.
LCD_INI Inicializacion del modulo LCD segun los tiempo marcados por el fabricante. Bus de 8 bits, 2 lineas de visualizacion y caracteres de 5 x 7 puntos.
LCD_PORT Configura los puertos del PIC para ser usados con el LCD.
Las cuales son:
LCD_E BSF RA,2 ;Activa señal E
NOP ;Espera 1uS
BCF RA,2 ;Desactiva señal E
RETURN
LCD_BUSY BSF RA,1 ;Pone el LCD en modo lectura
BSF STATUS,5 ;Selecciona el Banco 1
MOVLW 0xFF
MOVWF TRISB ;Puerta B act£a de entrada
BCF STATUS,5 ;Selecciona el Banco 0
BSF RA,2 ;Activa el LCD (Señal E)
NOP
L_BUSY BTFSC RB,7 ;Chequea el bit BUSY
GOTO L_BUSY ;Est a "1" (Ocupado)
BCF RA,2 ;Desactiva el LCD (Se¤al E)
BSF STATUS,5 ;Selecciona el Banco 1
CLRF TRISB ;Puerta B actua como salida
BCF STATUS,5 ;Selecciona el Banco 0
BCF RA,1 ;Pone el LCD en modo escritura
RETURN
LCD_REG BCF RA,0 ;Desactiva RS (Modo instruccion)
MOVWF RB ;Saca el codigo de instruccion
CALL LCD_BUSY ;Espera a que se libere el LCD
GOTO LCD_E ;Genera pulso en señal E
LCD_DATOS BCF RA,0 ;Desactiva RS (Modo instrucci¢n)
MOVWF RB ;Valor ASCII a sacar por RB
CALL LCD_BUSY ;Espera a que se libere el LCD
BSF RA,0 ;Activa RS (Modo dato)
GOTO LCD_E ;Genera pulso en señal E
LCD_INI MOVLW b'00111000'
CALL LCD_REG ;Codigo de instruccion
CALL DELAY_5MS ;Temporiza 5 mS.
MOVLW b'00111000'
CALL LCD_REG ;Codigo de instruccion
CALL DELAY_5MS ;Temporiza 5 mS.
MOVLW b'00111000'
CALL LCD_REG ;Codigo de instruccion
CALL DELAY_5MS ;Temporiza 5 mS.
RETURN
LCD_PORT BSF STATUS,5 ;Selecciona el banco 1 de datos
CLRF TRISB ;RB se programa como salida
MOVLW b'00011000' ;RA<4:3> se programan como entradas
MOVWF TRISA ;RA<2:0> se programan como salidas
BCF STATUS,5 ;Selecciona el banco 0 de datos
;MOVLW b'00000000'
;MOVWF INTCON ;Desactiva interrupciones
BCF RA,0 ;Desactiva RS del modulo LCD
BCF RA,2 ;Desactiva E del modulo LCD
;****************************************************************************
;DELAY_5MS genera una temporizacion de 5mS necesario para la secuencia de
;inicio del LCD
DELAY_5MS movlw 0x1a
movwf DATO_B
clrf DATO_A
DELAY_1 decfsz DATO_A,1
goto DELAY_1
decfsz DATO_B,1
goto DELAY_1
return
Que tal parecen estas rutinas?
Necesito opiniones, sugerencias, todo se agradece.
Esta basado todo en el PDF del 44780, que la gente amiga de x-robotics.com ofrece.
Saludos
-
añap jeje chevere ta bonito, y dime ya esta funcionando todo o hay algo mas en q se te pueda apoyar?? :mrgreen:
-
añap jeje chevere ta bonito, y dime ya esta funcionando todo o hay algo mas en q se te pueda apoyar?? :mrgreen:
Ya arme el circuito en Proteus para ir empezando las simulaciones. Todo de que es el programa, todavia no tengo algo concreto, sino partes sueltas, las cuales he ido probando, una suerte de depureo de rutinas, como probando las interrupciones, sacando algun que otro caracter por el LCD, guardando en la eeprom. Por ahora no me ha dado ningun problema. Pero tendria que armar un diagrama general de como seria el funcionamiento completo. Como voy a trabajar con unbus de 4 bit en el LCD se me ocurre, por ejempo, tener una variable segundos, la cual el LSB sea el digito de las unidades y el MSB el digito de las decenas, en BCD obviamente y asi con cada uno de los datos tiempo a desplegar. Si se les ocurre algo... bienvenido sea.
Gracias y saludos.
-
Volvi a hacer cambios, por ejemplo, las R de pullup del puerto B, estaban de mas, ya que puedo activar las internas. Conecte la linea R/W a masa, ya que solo voy a escribir en el display. Agregue un pulsador para prender y apagar el back light del LCD, un chiche!!!. A ver que les parece el cambio...
Adjunto tambien, el como se visualizarian los datos.
Gracias y saludos.
-
Estoy usando la libreia de retardos.inc que encontre por el foro, creo que es la del libro del 16F84 de editorial Ra-Ma, pero a la hora de simular, los retardos quedan como colgados, no se cumplen. Probe mandando un 1 a un pin del portb, llamo a un retardo de 1 segundo, y luego lo pongo a cero, y asi suscesivamente para ver el parpadeo, pero como que se queda colgado. Uso un cristal de 4MHz, no se que hacer. Que puede ser?
Saludos
-
A cual libreria te refieres?
Bueno, yo uso la libreria del link que adjunto y me funciona perfecto:
http://www.todopic.com.ar/foros/index.php?topic=5968.0
Pruebala y nos comentas.
Saludos.
-
Gracias veguepic, ya lo solucione, generando nuevamente los retardos, ahora anda todo de maravillas. Voy a ver si termino el programita y lo subo, ya estoy ancioso por armar la placa y sacar fotos!!!
Saludos.
-
Estoy atascado. No se porque, cuando atiendo la interrupcion, no me incrementa una variable ni me la cambia a otro valor (este ultimo es lo que deje, a modo de prueba). No se como ponerle orden, estoy mareado :(.
Adjunto lo que llevo hecho.
;//////////////////Encabezado///////////////////////////////////////////////////////////////
; Temporizador DC variable - por MGD "MaMu" 2006/2007
; Editado y Compilado con MPLAB 7.50
; Testeado con Proteus ISIS Professional - release 6.7 (SP3)
;///////////////////////////////////////////////////////////////////////////////////////////
list p=16F84A
list c=132 ;Listado a 132 caracteres
#include <p16F84A.inc>
radix hex
;//////////////////Configs//////////////////////////////////////////////////////////////////
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC
;/////////////////Definiciones//////////////////////////////////////////////////////////////
;Banco 0
#DEFINE BANCO0 bcf STATUS,RP0 ; selecciono Banco 0
#DEFINE BANCO1 bsf STATUS,RP0 ; selecciono Banco 1
#DEFINE IRQ_ENABLE bsf INTCON,GIE ; habilitamos todas las interrupciones
#DEFINE IRQ_DISABLE bcf INTCON,GIE ; deshabilitamos todas las interrupciones
#DEFINE RB47_ENABLE bsf INTCON,RBIE ; interrupcion PORTB pines RB4..RB7 On
#DEFINE RB47_DISABLE bcf INTCON,RBIE ; interrupcion PORTB pines RB4..RB7 Off
#DEFINE TMR0_ENABLE bsf INTCON,T0IE ; interrupcion TMR0 activada
#DEFINE TMR0_DISABLE bcf INTCON,T0IE ; interrupcion TMR0 desactivada
#DEFINE EXT_ENABLE bsf INTCON,INTE ; que sean interrupciones externas
#DEFINE EXT_DISABLE bcf INTCON,INTE ; que sean interrupciones externas
#DEFINE EEPROM_ENABLE bsf INTCON,EEIE ; interrupcion EEPROM activada
#DEFINE EEPROM_DISABLE bcf INTCON,EEIE ; interrupcion EEPROM desactivada
#DEFINE CLR_TOIF bcf INTCON,T0IF ; limpia flag TMR0
#DEFINE CLR_INTF bcf INTCON,INTF ; limpia flag EXT, RB0
#DEFINE CLR_RBIF bcf INTCON,RBIF ; limpia flag RB4..RB7
;Banco 1
#DEFINE CLR_EEIF bcf EECON1,EEIF ; limpia flag EEIF, escritura en EEPROM
;/////////////////variables////////////////////////////////////////////////////////////////
MEML equ 0x30 ;
MEME equ 0x31 ; EEPROM
DATOE equ 0x32 ;
contL1 equ 0x10 ; contador despliegue Linea 1
contL2 equ 0x10 ; contador despliegue Linea 2
segtcu equ 0x09 ; segundos del TC
segtcd equ 0x05
mint1u equ 0x00 ; valores T1
mint1d equ 0x00
hort1u equ 0x02
hort1d equ 0x01
segt1u equ 0x09
segt1d equ 0x05
mint2u equ 0x00 ; valores T2
mint2d equ 0x00
hort2u equ 0x02
hort2d equ 0x01
segt2u equ 0x09
segt2d equ 0x05
auxT2 equ 0x33
BLS equ 0x00 ; Back Ligth Status
;//////////////programa////////////////////////////////////////////////////////////////////
reset ORG 0x00
goto inicio
ORG 0x04
goto INTERR
;////////////////////Librerias Externas///////////////////////////////////////////////////
#include <lcd_4bit.inc>
#include <retardos.inc>
;////////////////////Tablas///////////////////////////////////////////////////////////////
TablaL1 addwf PCL,F ; se incrementa el contador de programa
nop
retlw b'01010100' ; T
retlw b'00110001' ; 1
retlw b'00111101' ; :
retlw 0x30+hort1d ; 1
retlw 0x30+hort1u ; 2
retlw b'00111010' ; :
retlw 0x30+mint1d ; 0
retlw 0x30+mint1u ; 0
retlw b'00111010' ; :
retlw 0x30+segt1d ; 0
retlw 0x30+segt1u ; 0
retlw b'00101101' ; -
retlw b'00101101' ; -
TablaL2 addwf PCL,F ; se incrementa el contador de programa
nop
retlw b'01010100' ; T
retlw b'00110010' ; 2
retlw b'00111101' ; :
retlw 0x30+hort2d ; 1
retlw 0x30+hort2u ; 2
retlw b'00111010' ; :
retlw 0x30+mint2d ; 0
retlw 0x30+mint2u ; 0
retlw b'00111010' ; :
retlw 0x30+segt2d ; 0
retlw 0x30+segt2u ; 0
retlw b'00101101' ; -
retlw b'00101101' ; -
TablaBKT1 addwf PCL,F ; para guardar en la EEPROM T1
retlw segt1u
retlw segt1d
retlw mint1u
retlw mint1d
retlw hort1u
retlw hort1d
TablaBKT2 addwf PCL,F ; para guardar en la EEPROM T2
retlw segt2u
retlw segt2d
retlw mint2u
retlw mint2d
retlw hort2u
retlw hort2d
;/////////////////Interrupciones//////////////////////////////////////////////////////////
irq IRQ_ENABLE ; habilito GIE
return
;//////////////////Inicializacion de variables////////////////////////////////////////////
init clrf TMR0 ; limpio TMR0
clrf MEME ; limpio addr de la EEPROM, escritura
clrf MEML ; limpio addr de la EEPROM, lectura
clrf auxT2 ; limpio aux de la EEPROM, backupT2
clrf BLS ; limpio Back Ligth Status
return
;///////////////Configuración de PUERTOS///////////////////////////////////////////////////
inicio BANCO1
movlw b'01000' ;puerto A como salida, salvo RA2 entrada
movwf TRISA
movlw b'00001111' ;RB0-3 Entradas, RB4-7 Salidas
movwf TRISB
BANCO0
clrf PORTA ;limpio Puerto A
clrf PORTB ;limpio Puerto B
;///para las Interrupciones///
BANCO1
movlw b'00000111' ; 1:256 como prescaler, Pull Up RB conectadas
movwf OPTION_REG
BANCO0
;////Para el LCD///
call irq ; habilito las interrupciones que quiera
call init ; inicio variables y contadores
call VERIFICA ; hay datos en la EEPROM? o es la primera vez? Sino, los carga
call LCD_Inicializa ; inicializa el display de LCD
bcf INTCON,2
movlw 0xD8 ; que valor al TMR0? (uso el complemento de lo que quiero)
movwf TMR0 ; cargo TMR0 con .216
TMR0_ENABLE ; habilito T0IE, INT de TMR0, (lo hago ahora, los ciclos de antes no cuentan
;<<<<<<----------------- INICIO PROGRAMA PRINCIPAL ------------------->>>>>>>
main
call VISUALIZA ; despliegue de datos en el LCD
goto main
;///////////////////////////Rutinas///////////////////////////////////////////////////////
VISUALIZA
Lin1 call LCD_Linea1 ; datos del T1 en linea 1
clrf contL1
bucle movf contL1,W
xorlw b'1101' ; verifica si el contador llegó a 13
btfsc STATUS,Z ; si no es así salta una línea
goto Lin2 ; si llegó a 13 termino y empieza T2
incf contL1,F ; incrementa el contador
movf contL1,W ; pasa el contador a w (índice)
call TablaL1 ; llama a la tabla
call LCD_Caracter ; sale caracter por pantalla
goto bucle
Lin2 clrf contL2 ; datos del T2 en linea 2
call LCD_Linea2
ciclo movf contL2,W
xorlw b'1101' ; verifica si el contador llegó a 13
btfsc STATUS,Z ; si no es así salta una línea
return ; si llegó a 13 termino y retorna a donde sea...
incf contL2,F ; incrementa el contador
movf contL2,W ; pasa el contador a w (índice)
call TablaL2 ; llama a la tabla
call LCD_Caracter ; sale caracter por pantalla
goto ciclo
RESTORE call RELOADT1
call RELOADT2
return
RELOADT1 movlw 0x00 ; recupera valores de T1 de la EEPROM
movwf MEML
call LECTURA
movwf segt1u
movlw 0x01
movwf MEML
call LECTURA
movwf segt1d
movlw 0x02
movwf MEML
call LECTURA
movwf mint1u
movlw 0x03
movwf MEML
call LECTURA
movwf mint1d
movlw 0x04
movwf MEML
call LECTURA
movwf hort1u
movlw 0x05
movwf MEML
call LECTURA
movwf hort1d
return
RELOADT2 movlw 0x10 ; recupera valores de T2 de la EEPROM
movwf MEML
call LECTURA
movwf segt2u
movlw 0x11
movwf MEML
call LECTURA
movwf segt2d
movlw 0x12
movwf MEML
call LECTURA
movwf mint2u
movlw 0x13
movwf MEML
call LECTURA
movwf mint2d
movlw 0x14
movwf MEML
call LECTURA
movwf hort2u
movlw 0x15
movwf MEML
call LECTURA
movwf hort2d
return
VERIFICA movlw 0x00 ; hay datos cargados en la EEPROM?
movwf MEML
call LECTURA
xorlw 0xFF
btfss STATUS,Z
call RESTORE
call BUP ; sino, los carga
CLR_TOIF
return
BUP call BACKUPT1
call BACKUPT2
return
BACKUPT1 movlw 0x0 ; T1=12:00:59
movwf MEME
cicloT1 movfw MEME
call TablaBKT1
movwf DATOE
call ESCRITURA
incf MEME,F
movfw MEME
xorlw b'0110'
btfss STATUS,Z
goto cicloT1
return
BACKUPT2 movlw 0x10 ; T2=12:00:59
movwf MEME
movlw 0x00
cicloT2 movfw auxT2
call TablaBKT2
movwf DATOE
call ESCRITURA
incf MEME,F
movfw MEME
incf auxT2,F
movfw auxT2
xorlw b'0110'
btfss STATUS,Z
goto cicloT2
return
;///////////////////////////Rutinas IRQ///////////////////////////////////////////////////
INTERR btfss INTCON,T0IF ; la int es TMR0 ?
goto sale ; no es, es otra asi que sale
goto muestra ; es!!! la atiende
goto sale ; despues sale...
muestra movlw 0x05 ; HAGO LAS CUENTAS
movwf hort1u
movf hort1u,W
goto sale
sale CLR_TOIF ;limpio la bandera que sea, ahora TMR0
clrf TMR0 ; recargo el TMR0 para el proximo disparo
movlw 0xD8
movwf TMR0
retfie
;/////////////////////Botones-Entradas////////////////////////////////////////////////////
BACKLIGHT btfss PORTA,3 ; esta en 1? encendido BackLigth
goto BLON ; lo prende
goto BLOFF ; lo apaga
return
BLON btfsc BLS,0
goto BLOFF_
goto BLON_
return
BLOFF btfss BLS,0
goto BLOFF_
goto BLON_
return
BLON_ bsf PORTA,1
bsf BLS,0
return
BLOFF_ bcf PORTA,1
clrf BLS
return
PULSAHT1 btfss PORTB,0 ; ACA DEJE... NO VA, es prueba nomas
goto suma
return
suma bsf PORTA,4
return
;/////////////////////Accesso a EEPROM////////////////////////////////////////////////////
LECTURA BANCO0 ; Selecciona banco 0
movfw MEML ; Dirección a leer de la EEPROM
movwf EEADR
BANCO1 ; Selecciona banco 1
bsf EECON1,RD ; Activar Lectura
ESPERAL btfsc EECON1,RD ; Espera final de lectura
goto ESPERAL
BANCO0 ; Selecciona banco 0
movf EEDATA,W ; W se carga con el valor leído en EEPROM
return
ESCRITURA BANCO0 ; Selecciona el banco 0
IRQ_DISABLE ; deshabilito todas las interrupciones
movfw MEME
movwf EEADR ; Escribe la dirección en EEADR
movfw DATOE
movwf EEDATA ; Se escribe el dato en EEDATA
BANCO1 ; Selecciona el banco 1
bsf EECON1,WREN ; Permiso de escritura
; Comienzo Secuencia de escritura
movlw 0x55
movwf EECON2 ; Se escribe el dato 55h en eecon2
movlw 0xAA
movwf EECON2 ; Se escribe AA h en eecon2
bsf EECON1,WR ; Comienza la escritura
ESPERAE btfsc EECON1,WR ; Espera a que termine la escritura
goto ESPERAE
BANCO0 ; Selecciona el banco 0
IRQ_ENABLE ; re habilito todas las interrupciones
return
;///////////////////Rutinas de Retardos///////////////////////////////////////////////////
;//////////////////////////NOTAS//////////////////////////////////////////////////////////
;
;///EEPROM
;Un sistema para comprobar si se ha producido la escritura correctamente en la memoria
;EEPROM consiste en restar el dato escrito con el que existe en el registro EEDATA.
;Si no se ha producido error el flag Z pasa a valer 1.
;Microchip recomienda que se deshabiliten las interrupciones globales durante la secuencia
;de R/W, añadiendo las instrucciones al principio y final de la secuencia.
;Proceso de verificación de la escritura. Dependiendo de la aplicación, es aconsejable
;que se compruebe que los datos se están escribiendo correctamente aunque esto no suele
;ser necesario en la mayoría de las ocasiones, para las posiciones de memoria EEPROM es
;aconsejable.
;/////////////////////The End/////////////////////////////////////////////////////////////
END
Algunas cosas estan de mas, pero las deje por las dudas, despues las voy eliminando.
Alguien me da una manito?
Saludos.
-
Estoy atascado. No se porque, cuando atiendo la interrupcion, no me incrementa una variable ni me la cambia a otro valor (este ultimo es lo que deje, a modo de prueba). No se como ponerle orden, estoy mareado :(.
Adjunto lo que llevo hecho.
;//////////////////Encabezado///////////////////////////////////////////////////////////////
; Temporizador DC variable - por MGD "MaMu" 2006/2007
; Editado y Compilado con MPLAB 7.50
; Testeado con Proteus ISIS Professional - release 6.7 (SP3)
;///////////////////////////////////////////////////////////////////////////////////////////
list p=16F84A
list c=132 ;Listado a 132 caracteres
#include <p16F84A.inc>
radix hex
;//////////////////Configs//////////////////////////////////////////////////////////////////
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC
;/////////////////Definiciones//////////////////////////////////////////////////////////////
;Banco 0
#DEFINE BANCO0 bcf STATUS,RP0 ; selecciono Banco 0
#DEFINE BANCO1 bsf STATUS,RP0 ; selecciono Banco 1
#DEFINE IRQ_ENABLE bsf INTCON,GIE ; habilitamos todas las interrupciones
#DEFINE IRQ_DISABLE bcf INTCON,GIE ; deshabilitamos todas las interrupciones
#DEFINE RB47_ENABLE bsf INTCON,RBIE ; interrupcion PORTB pines RB4..RB7 On
#DEFINE RB47_DISABLE bcf INTCON,RBIE ; interrupcion PORTB pines RB4..RB7 Off
#DEFINE TMR0_ENABLE bsf INTCON,T0IE ; interrupcion TMR0 activada
#DEFINE TMR0_DISABLE bcf INTCON,T0IE ; interrupcion TMR0 desactivada
#DEFINE EXT_ENABLE bsf INTCON,INTE ; que sean interrupciones externas
#DEFINE EXT_DISABLE bcf INTCON,INTE ; que sean interrupciones externas
#DEFINE EEPROM_ENABLE bsf INTCON,EEIE ; interrupcion EEPROM activada
#DEFINE EEPROM_DISABLE bcf INTCON,EEIE ; interrupcion EEPROM desactivada
#DEFINE CLR_TOIF bcf INTCON,T0IF ; limpia flag TMR0
#DEFINE CLR_INTF bcf INTCON,INTF ; limpia flag EXT, RB0
#DEFINE CLR_RBIF bcf INTCON,RBIF ; limpia flag RB4..RB7
;Banco 1
#DEFINE CLR_EEIF bcf EECON1,EEIF ; limpia flag EEIF, escritura en EEPROM
;/////////////////variables////////////////////////////////////////////////////////////////
MEML equ 0x30 ;
MEME equ 0x31 ; EEPROM
DATOE equ 0x32 ;
contL1 equ 0x10 ; contador despliegue Linea 1
contL2 equ 0x10 ; contador despliegue Linea 2
segtcu equ 0x09 ; segundos del TC
segtcd equ 0x05
mint1u equ 0x00 ; valores T1
mint1d equ 0x00
hort1u equ 0x02
hort1d equ 0x01
segt1u equ 0x09
segt1d equ 0x05
mint2u equ 0x00 ; valores T2
mint2d equ 0x00
hort2u equ 0x02
hort2d equ 0x01
segt2u equ 0x09
segt2d equ 0x05
auxT2 equ 0x33
BLS equ 0x00 ; Back Ligth Status
;//////////////programa////////////////////////////////////////////////////////////////////
reset ORG 0x00
goto inicio
ORG 0x04
goto INTERR
;////////////////////Librerias Externas///////////////////////////////////////////////////
#include <lcd_4bit.inc>
#include <retardos.inc>
;////////////////////Tablas///////////////////////////////////////////////////////////////
TablaL1 addwf PCL,F ; se incrementa el contador de programa
nop
retlw b'01010100' ; T
retlw b'00110001' ; 1
retlw b'00111101' ; :
retlw 0x30+hort1d ; 1
retlw 0x30+hort1u ; 2
retlw b'00111010' ; :
retlw 0x30+mint1d ; 0
retlw 0x30+mint1u ; 0
retlw b'00111010' ; :
retlw 0x30+segt1d ; 0
retlw 0x30+segt1u ; 0
retlw b'00101101' ; -
retlw b'00101101' ; -
TablaL2 addwf PCL,F ; se incrementa el contador de programa
nop
retlw b'01010100' ; T
retlw b'00110010' ; 2
retlw b'00111101' ; :
retlw 0x30+hort2d ; 1
retlw 0x30+hort2u ; 2
retlw b'00111010' ; :
retlw 0x30+mint2d ; 0
retlw 0x30+mint2u ; 0
retlw b'00111010' ; :
retlw 0x30+segt2d ; 0
retlw 0x30+segt2u ; 0
retlw b'00101101' ; -
retlw b'00101101' ; -
TablaBKT1 addwf PCL,F ; para guardar en la EEPROM T1
retlw segt1u
retlw segt1d
retlw mint1u
retlw mint1d
retlw hort1u
retlw hort1d
TablaBKT2 addwf PCL,F ; para guardar en la EEPROM T2
retlw segt2u
retlw segt2d
retlw mint2u
retlw mint2d
retlw hort2u
retlw hort2d
;/////////////////Interrupciones//////////////////////////////////////////////////////////
irq IRQ_ENABLE ; habilito GIE
return
;//////////////////Inicializacion de variables////////////////////////////////////////////
init clrf TMR0 ; limpio TMR0
clrf MEME ; limpio addr de la EEPROM, escritura
clrf MEML ; limpio addr de la EEPROM, lectura
clrf auxT2 ; limpio aux de la EEPROM, backupT2
clrf BLS ; limpio Back Ligth Status
return
;///////////////Configuración de PUERTOS///////////////////////////////////////////////////
inicio BANCO1
movlw b'01000' ;puerto A como salida, salvo RA2 entrada
movwf TRISA
movlw b'00001111' ;RB0-3 Entradas, RB4-7 Salidas
movwf TRISB
BANCO0
clrf PORTA ;limpio Puerto A
clrf PORTB ;limpio Puerto B
;///para las Interrupciones///
BANCO1
movlw b'00000111' ; 1:256 como prescaler, Pull Up RB conectadas
movwf OPTION_REG
BANCO0
;////Para el LCD///
call irq ; habilito las interrupciones que quiera
call init ; inicio variables y contadores
call VERIFICA ; hay datos en la EEPROM? o es la primera vez? Sino, los carga
call LCD_Inicializa ; inicializa el display de LCD
bcf INTCON,2
movlw 0xD8 ; que valor al TMR0? (uso el complemento de lo que quiero)
movwf TMR0 ; cargo TMR0 con .216
TMR0_ENABLE ; habilito T0IE, INT de TMR0, (lo hago ahora, los ciclos de antes no cuentan
;<<<<<<----------------- INICIO PROGRAMA PRINCIPAL ------------------->>>>>>>
main
call VISUALIZA ; despliegue de datos en el LCD
goto main
;///////////////////////////Rutinas///////////////////////////////////////////////////////
VISUALIZA
Lin1 call LCD_Linea1 ; datos del T1 en linea 1
clrf contL1
bucle movf contL1,W
xorlw b'1101' ; verifica si el contador llegó a 13
btfsc STATUS,Z ; si no es así salta una línea
goto Lin2 ; si llegó a 13 termino y empieza T2
incf contL1,F ; incrementa el contador
movf contL1,W ; pasa el contador a w (índice)
call TablaL1 ; llama a la tabla
call LCD_Caracter ; sale caracter por pantalla
goto bucle
Lin2 clrf contL2 ; datos del T2 en linea 2
call LCD_Linea2
ciclo movf contL2,W
xorlw b'1101' ; verifica si el contador llegó a 13
btfsc STATUS,Z ; si no es así salta una línea
return ; si llegó a 13 termino y retorna a donde sea...
incf contL2,F ; incrementa el contador
movf contL2,W ; pasa el contador a w (índice)
call TablaL2 ; llama a la tabla
call LCD_Caracter ; sale caracter por pantalla
goto ciclo
RESTORE call RELOADT1
call RELOADT2
return
RELOADT1 movlw 0x00 ; recupera valores de T1 de la EEPROM
movwf MEML
call LECTURA
movwf segt1u
movlw 0x01
movwf MEML
call LECTURA
movwf segt1d
movlw 0x02
movwf MEML
call LECTURA
movwf mint1u
movlw 0x03
movwf MEML
call LECTURA
movwf mint1d
movlw 0x04
movwf MEML
call LECTURA
movwf hort1u
movlw 0x05
movwf MEML
call LECTURA
movwf hort1d
return
RELOADT2 movlw 0x10 ; recupera valores de T2 de la EEPROM
movwf MEML
call LECTURA
movwf segt2u
movlw 0x11
movwf MEML
call LECTURA
movwf segt2d
movlw 0x12
movwf MEML
call LECTURA
movwf mint2u
movlw 0x13
movwf MEML
call LECTURA
movwf mint2d
movlw 0x14
movwf MEML
call LECTURA
movwf hort2u
movlw 0x15
movwf MEML
call LECTURA
movwf hort2d
return
VERIFICA movlw 0x00 ; hay datos cargados en la EEPROM?
movwf MEML
call LECTURA
xorlw 0xFF
btfss STATUS,Z
call RESTORE
call BUP ; sino, los carga
CLR_TOIF
return
BUP call BACKUPT1
call BACKUPT2
return
BACKUPT1 movlw 0x0 ; T1=12:00:59
movwf MEME
cicloT1 movfw MEME
call TablaBKT1
movwf DATOE
call ESCRITURA
incf MEME,F
movfw MEME
xorlw b'0110'
btfss STATUS,Z
goto cicloT1
return
BACKUPT2 movlw 0x10 ; T2=12:00:59
movwf MEME
movlw 0x00
cicloT2 movfw auxT2
call TablaBKT2
movwf DATOE
call ESCRITURA
incf MEME,F
movfw MEME
incf auxT2,F
movfw auxT2
xorlw b'0110'
btfss STATUS,Z
goto cicloT2
return
;///////////////////////////Rutinas IRQ///////////////////////////////////////////////////
INTERR btfss INTCON,T0IF ; la int es TMR0 ?
goto sale ; no es, es otra asi que sale
goto muestra ; es!!! la atiende
goto sale ; despues sale...
muestra movlw 0x05 ; HAGO LAS CUENTAS
movwf hort1u
movf hort1u,W
goto sale
sale CLR_TOIF ;limpio la bandera que sea, ahora TMR0
clrf TMR0 ; recargo el TMR0 para el proximo disparo
movlw 0xD8
movwf TMR0
retfie
;/////////////////////Botones-Entradas////////////////////////////////////////////////////
BACKLIGHT btfss PORTA,3 ; esta en 1? encendido BackLigth
goto BLON ; lo prende
goto BLOFF ; lo apaga
return
BLON btfsc BLS,0
goto BLOFF_
goto BLON_
return
BLOFF btfss BLS,0
goto BLOFF_
goto BLON_
return
BLON_ bsf PORTA,1
bsf BLS,0
return
BLOFF_ bcf PORTA,1
clrf BLS
return
PULSAHT1 btfss PORTB,0 ; ACA DEJE... NO VA, es prueba nomas
goto suma
return
suma bsf PORTA,4
return
;/////////////////////Accesso a EEPROM////////////////////////////////////////////////////
LECTURA BANCO0 ; Selecciona banco 0
movfw MEML ; Dirección a leer de la EEPROM
movwf EEADR
BANCO1 ; Selecciona banco 1
bsf EECON1,RD ; Activar Lectura
ESPERAL btfsc EECON1,RD ; Espera final de lectura
goto ESPERAL
BANCO0 ; Selecciona banco 0
movf EEDATA,W ; W se carga con el valor leído en EEPROM
return
ESCRITURA BANCO0 ; Selecciona el banco 0
IRQ_DISABLE ; deshabilito todas las interrupciones
movfw MEME
movwf EEADR ; Escribe la dirección en EEADR
movfw DATOE
movwf EEDATA ; Se escribe el dato en EEDATA
BANCO1 ; Selecciona el banco 1
bsf EECON1,WREN ; Permiso de escritura
; Comienzo Secuencia de escritura
movlw 0x55
movwf EECON2 ; Se escribe el dato 55h en eecon2
movlw 0xAA
movwf EECON2 ; Se escribe AA h en eecon2
bsf EECON1,WR ; Comienza la escritura
ESPERAE btfsc EECON1,WR ; Espera a que termine la escritura
goto ESPERAE
BANCO0 ; Selecciona el banco 0
IRQ_ENABLE ; re habilito todas las interrupciones
return
;///////////////////Rutinas de Retardos///////////////////////////////////////////////////
;//////////////////////////NOTAS//////////////////////////////////////////////////////////
;
;///EEPROM
;Un sistema para comprobar si se ha producido la escritura correctamente en la memoria
;EEPROM consiste en restar el dato escrito con el que existe en el registro EEDATA.
;Si no se ha producido error el flag Z pasa a valer 1.
;Microchip recomienda que se deshabiliten las interrupciones globales durante la secuencia
;de R/W, añadiendo las instrucciones al principio y final de la secuencia.
;Proceso de verificación de la escritura. Dependiendo de la aplicación, es aconsejable
;que se compruebe que los datos se están escribiendo correctamente aunque esto no suele
;ser necesario en la mayoría de las ocasiones, para las posiciones de memoria EEPROM es
;aconsejable.
;/////////////////////The End/////////////////////////////////////////////////////////////
END
Algunas cosas estan de mas, pero las deje por las dudas, despues las voy eliminando.
Alguien me da una manito?
Saludos.
Creo que tu problema esta en que no guardas el estado de W y el registro Status al entrar a la interrupcion, ni lo repones al salir de ella.
Recuerda que la interrupcion cae en cualquier parte del programa, por lo tanto es tu responsabilidad como programador guardar estos registros y levantarlos nuevamente al salir de la interrupcion.
Tampoco es bueno lo que haces de volver a cargar en W un valor que no sabes cuando lo estas utilizando...
Espero haber ayudado... lee bien las recomendaciones de Microchip para cuando se trabaja con interrupciones, son maravillosas si sabes utilizarlas, pero si te equivocas recibiras grandes dolores de cabeza, lo digo por experiencia. :D :D :D :D