Interesante proyecto, permaneceré atento a tus progresos.
Una curiosidad, ¿por qué ese PIC?
Tiene buena pinta ese modulito. Yo tengo experiencia con la serie SIM900 pero este parece mucho más pequeño.No conocía ese módulo, parece interesante para aplicaciones GSM/GPRS
Recuerdo que en mi aplicación (en lenguaje C) recibía líneas enteras hasta detectar el retorno de carro, y luego hacía una búsqueda de un string dentro de otro (strstr) y en caso de encontrar GPRMC, iba extrayendo los trozos de cadena que me interesaban.
Jorge, ¿el lenguaje que vas a usar no tiene rutinas de tratamiento de strings?Hola, te comento que en todo este proyecto, el código lo hice en ASM (assembler) o como le llames.
; INICIALIZAR RX TX USART
bcf STATUS,RP1 ;apuntar
bsf STATUS,RP0 ;banco1
; Ajustar divisor para 9600 baudios para xtal de 8MHZ
movlw 0x33 ; cargar el divisor baurate con 51 (33h), da 9615 = 8.000.000/(16*(51+1) , manual pag. 71
movwf SPBRG ;para clock 8MHz da 9615 o sea +0,16 de error;
;
bsf TXSTA,BRGH ;poner el modo High Speed
bcf TXSTA,SYNC ;poner modo asincronico
;
bcf STATUS,RP0 ;apuntar banco 0
bsf RCSTA,SPEN ;conectar RB1 y RB2 como RX y TX, TRISB 1y2 deben ser 1 (buffer de salida desconectado)
bsf STATUS,RP0 ;apuntar banco 1
bsf TXSTA,TXEN ;Habilitar transmison , queda esperando el dato a transmitir
bsf PIE1,RCIE ;Habilitar interrupcion de recepcion
bcf STATUS,RP0 ;Apuntar banco 0
bsf RCSTA,CREN ;Habilitar recepcion de datos seriales en RB1 (RXD)
;Habilitar interrupciones
bsf INTCON,PEIE ; periheral interrup enable (incluye usart)
bsf INTCON,GIE ; all interrup enable
ORG 0x0004 ; interrupt vector location
movwf WTEMP ; salvar el W
movfw STATUS,W ; salvar el
movwf STEMP ; STATUS
bcf STATUS,RP1 ; apuntar
bcf STATUS,RP0 ; banco 0
call usa_rt ; llamando al procesar del dato que llegó
;
movf STEMP,W ; recuperar W y STATUS
movwf STATUS ;
movf WTEMP,W
retfie ; return from interrupt
;-------------------------------------------------------------------------------------------------------------------
usa_rt
;
bsf PORTB,AZA4 ;apagar el Led indicador de errores
;
btfss PIR1,RCIF ; llego un caracter, ver como esta el flag de recepcion, debe estar encendido sino es ilogico
goto err_flag ;hay algun error ilogico!!!
ckc_ferr ; llego un dato, primero procesar errores
btfsc RCSTA,FERR ;ver si hay error FRAME (o sea que NO se detecto el bit de STOP )
goto err_ferr ; si hay error FRAME
ckc_over
btfsc RCSTA,OERR ;ver si hay error OVERRUN, si llego un dato y el anterior no se leyó!
goto err_over ; si hay error Over
sin_error ;ninguno de los dos errores fue detectado
movf RCREG,w ; se resetea el flag de interrupcion RCIF, el FERR y el dato recibido pasa al W
movwf RCDATO ;se guarda el dato recibido
goto case_00 ; ir a procesar el Dato recibido!
;
;procesar errores, enciende LED indicador y resetea Flags de errores, el dato se procesa igual
err_flag
err_ferr
; encender el Led indicador de error, el proximo caracter correcto lo apaga
bcf PORTA,AZA4 ;encender el indicador de error
goto sin_error ; si el Led enciende permanente hay un problema
err_over
bcf RCSTA,CREN ;resetear error Overrun
nop
bsf RCSTA,CREN ;habilitar RX
goto err_flag ; encender el Led indicador de errores y continuar
;
;-------------------------------------------------------------------------------------
case_00
;
case_00 ;procesar estado 0 (reposo) de la máquina de estados
;
movfw ESTADO ; Comparar
xorlw 0x00 ; con estado 0
btfss STATUS,Z ;si son iguales saltar
goto case_01 ; no es 0, continuar
;el estado es 0, procesarlo
movfw RCDATO ;el ESTADO es 0 (reposo), verifcar si llego $
xorlw 0x24 ; comparar con $, el primer caracter del encabezamiento $GNRMC
btfsc STATUS,Z ; ver si llego $, si no llego saltear cambio de ESTADO
goto si_PP ;exito!, estado 0 y llego un $ ,
clrf ESTADO ;no exito, esta en 0 pero no es $ lo que llegó
return ;resetear ESTADO y volver (aca no haria falta resetear)
si_PP ;en ESTADO 0 llego un $, pasar al estado 1 y no echoar dato
movlw 0X01 ; cargar el estado 01
movwf ESTADO ;pasar al estado 01 de la maquina de estados
return
;
case_01 ;procesar estado 1 y caracter "G"
;
movfw ESTADO ; Comparar
xorlw 0x01 ; con estado 1
btfss STATUS,Z ;si son iguales saltar
goto case_02 ; no es 1, continuar
movfw RCDATO ;el ESTADO es 1, verifcar si llego el caracter G
xorlw 0x47 ; comparar con "G" (código ASCII en exadecimal)
btfsc STATUS,Z ; ver si llego G, si no llego saltear cambio de ESTADO
goto si_GG ;exito, estado en 1 y llego un G
clrf ESTADO ;no exito, esta en 1 pero no es G
return ;resetear ESTADO y volver, la secuencia exitosa se abortó
si_GG ;en ESTADO 1 llego un G, pasar al estado 2 y no echoar dato
movlw 0x02
movwf ESTADO ;pasar al estado 02
;call echo_ar ;NO hacer eco del dato G a la PC
return
;
case_02 ;procesar estado 2 y "N"
movfw ESTADO ; Comparar
xorlw 0x02 ; con estado 2
btfss STATUS,Z ;si son iguales saltar
goto case_03 ; no es 2, continuar
movfw RCDATO ;el ESTADO es 2, verifcar si llego "N"
xorlw 0x4E ; comparar con N en ASCII exadecimal
btfsc STATUS,Z ;ver si llego N, si no llego saltear cambio de ESTADO
goto si_NN ;exito, esta en estado 1 y llego un G
clrf ESTADO ;no exito, esta en 1 pero no es G
return ;resetear ESTADO y volver
si_NN ;en ESTADO 2 y llego una N, pasar al estado 3 y no echoar dato
movlw 0x03
movwf ESTADO ;pasar al estado 03
;call echo_ar ;hacer eco del dato N a la PC
return
;
case_03 ;procesar estado 3 y R
movfw ESTADO ; Comparar
xorlw 0x03 ; con estado 3
btfss STATUS,Z ;si son iguales saltar
goto case_04 ; no es 3, continuar
movfw RCDATO ;el ESTADO es 3, verifcar si llego "R"
xorlw 0x52 ; comparar con R
btfsc STATUS,Z ;ver si llego M, si no llego saltear cambio de ESTADO
goto si_RR ;exito, estado en 3 y llego un R
clrf ESTADO ;no exito, esta en 3 pero no es R
return ;resetear ESTADO y volver
si_RR ;en ESTADO 3 llego un R, pasar al estado 4 y no echoar dato
movlw 0x04
movwf ESTADO ;pasar al estado 04
;call echo_ar ;hacer eco del dato G a la PC
return
;
case_04 ;procesar estado 4 y M
movfw ESTADO ; Comparar
xorlw 0x04 ; con estado 4
btfss STATUS,Z ;si son iguales saltar
goto case_05 ; no es 0, continuar
movfw RCDATO ;el ESTADO es 4, verifcar si llego "M"
xorlw 0x4D ; comparar con "M"
btfsc STATUS,Z ;ver si llego M, si no llego saltear cambio de ESTADO
goto si_MM ;exito, estado en 4 y llego un M
clrf ESTADO ;no exito, estado en 4 pero no es M
return ;resetear ESTADO y volver
si_MM ;en ESTADO 4 llego un M, pasar al estado 5 y no echoar dato
movlw 0x05
movwf ESTADO ;pasar al estado 05
;call echo_ar ;hacer eco del dato M a la PC
return
;
case_05 ;procesar estado 5 y "C"
movfw ESTADO ; Comparar
xorlw 0x05 ; con estado 5
btfss STATUS,Z ;si son iguales saltar
goto case_06 ; no es estado 5, continuar
movfw RCDATO ;el ESTADO es 5, verifcar si llego "C"
xorlw 0x43 ; comparar con C
btfsc STATUS,Z ;ver si llego C, si no llego saltear cambio de ESTADO
goto si_CC ;exito, estado en 5 y llego un C
clrf ESTADO ;no exito, estado en 5 pero no es C
return ;resetear ESTADO y volver
si_CC ;en ESTADO 5 llego un C, pasar al estado 6 y no echoar dato
movlw 0x06
movwf ESTADO ;pasar al estado 06
;call echo_ar ;hacer eco del dato C a la PC
return
;
case_06 ;procesar estado 6 y , procesar la coma "," que sigue al encabezamiento
movfw ESTADO ; Comparar
xorlw 0x06 ; con estado 6
btfss STATUS,Z ;si son iguales saltar
goto case_10 ; no es 6, continuar
movfw RCDATO ;el ESTADO es 6, verifcar si llego ","
xorlw 0x2C ; comparar con , o 2E es . punto
btfsc STATUS,Z ;ver si llego "," , si no llego saltear cambio de ESTADO
goto si_CO ;exito, estado en 6 y llego un , pongo CO la , molesta
clrf ESTADO ;no exito, esta en 6 pero no es ,
return ;resetear ESTADO y volver
si_CO ;en ESTADO 6 llego una ,, pasar al estado 10 y no echoar dato
movlw 0x10 ;
movwf ESTADO ;pasar al estado 10
;call echo_ar ;hacer eco del dato M a la PC
return
;
;La detección del encabezamiento fue exitosa, comienza recolección de datos de Hora
;
case_10 ;Recibiendo HORHIG (las decenas de Hora, viene en ASCII, o una segunda coma si no hay datos)
case_10 ;Recibiendo HORHIG , el dígito Decenas de Horas, viene en ASCII
;o la segunda coma si todavía no hay datos (módulo inicializandose)
; , o el botón para mostrar Posición Geográfica
movfw ESTADO ; Comparar
xorlw 0x10 ; con estado 10
btfss STATUS,Z ;si son iguales saltar
goto case_11 ; no es estado 10, continuar
movfw RCDATO ;el ESTADO es 10, llega HORHIG en ASCII, le sobran 30 para obtener el número a mostrar
xorlw 0x2C ; comparar con la segunda coma para detectar el mensaje de NO DATA $GNRMC,,V,,,,,,,,,,N*4D
btfsc STATUS,Z ; si no es coma, continuar, pues no es el mensaje de NO DATA (el módulo aún no no adquiere info de los GNSS)
goto es_coma ;se detecta la segunda coma, todavia no llegan los datos válidos
movfw RCDATO ;si no es coma, recuperar dato recibido y procesarlo
andlw 0x0F ; mascara para borrar ASCII, sacarle el 30; el 30 queda en 00, 31 en 01 etc.
movwf HORHIX ; cargar el digito de hora en registro auxiliar HORHIX (es hora UTC, no local)
;chequear boton de solicitud de mostrar Posición geográfica
btfss PORTB,BTB3 ;si el boton no fue apretado,esta en 1, seguir, saltar
goto bot_on ;si hay boton oprimido, ir a procesar latitud/longitud ; si no continuar normal con hora y fecha
movlw 0x11
movwf ESTADO ;pasar al estado 11
call echo_ar ;hacer eco del dígito de Hora HORHIG a la PC para chequear su validez
return
;
bot_on ;el boton esta oprimido, ir a recoger latitud y longitud y mostrala. Ya se recibio HORHIG pero ese valor se descarta
movlw 0x02 ;cargar el contador de comas a saltear dentro del mensaje, son 2
movwf ESTAUX ; en ESTAUX
movlw 0x40 ; el proximo estado de la maquina de estados sera el 40, arranca la secuencia de recoger latitud y longitud
movwf ESTADO ;pasar al estado 40
return
es_coma ;se detecto una segunda coma despues de la primera, el mensaje completo $GNRMC con todos los datos todavia no llega
movlw 0x36 ; estado final 36, para no mandar nada pues esta llegando el mensaje sin data $GNRMC,,V,,,,,,,,,,N*4D
movwf ESTADO ;pasar al estado 36, solo para mandar $+CR+LF e ir al estado de reposo 38, el último estado de la maquina
movlw 0x24 ;echoar el signo $ a la PC, luego CR,LF; la HiperTerminal de monitoreo mostrará el signo $, una linea por segundo
call tx_dato ; mientras no llega Data (el módulo GPS esta en inicialización o perdió toda señal)
return ;
;No hubo segunda coma , no hubo Boton, la secuencia continua normalmente recogiendo los dígitos de Hora
case_11 ;Recibiendo el dígito de Unidades de Hora, se guarda en registro HORLOX , viene en ASCII
movfw ESTADO ; Comparar
xorlw 0x11 ; con estado 11
btfss STATUS,Z ;si son iguales saltar
goto case_12 ; no es 11, continuar
movfw RCDATO ;el ESTADO es 11, llega el dígito de unidades de Horas HORLOX en ASCII, le sobran 30
andlw 0x0F ; mascara para borrar ASCII, 30 queda en 00, 31 en 01 etc.
movwf HORLOX ; cargar el digito de hora en registro auxiliar HORLOX para corregir hora UTC a hora local
movlw 0x12
movwf ESTADO ;pasar al estado 12
call echo_ar ;hacer eco del dígito a la PC
return
;
case_12 ;Recibiendo decenas de Minutos, se guarda en el registro MINHIG , viene en ASCII
movfw ESTADO ; Comparar
xorlw 0x12 ; con estado 12
btfss STATUS,Z ;si son iguales saltar
goto case_13 ; no es 12, continuar
movfw RCDATO ;el ESTADO es 12, llega MINHIG en ASCII, le sobran 30
andlw 0x0F ; mascara para borrar ASCII, 30 queda en 00, 31 en 01 etc
movwf MINHIG ; cargar el digito de MINHIG
movlw 0x13
movwf ESTADO ;pasar al estado 13
call echo_ar ;MINHIG a la PC
return
;
case_13 ;Recibiendo unidades de minutos, se guarda en MINLOW , viene en ASCII
movfw ESTADO ; Comparar
xorlw 0x13 ; con estado 13
btfss STATUS,Z ;si son iguales saltar
goto case_14 ; no es 13, continuar
movfw RCDATO ;el ESTADO es 13, llega MINLOW en ASCII, le sobran 30
andlw 0x0F ; mascara para borrar ASCII, 30 queda en 00, 31 en 01 etc
movwf MINLOW ; cargar el digito MINLOW
movlw 0x14
movwf ESTADO ;pasar al estado 14
call echo_ar ;hacer eco de MINLOW a la PC
return
;
case_14 ;Recibiendo digito de decenas de Segundos, guardar en SEGHIG , viene en ASCII
movfw ESTADO ; Comparar
xorlw 0x14 ; con estado 14
btfss STATUS,Z ;si son iguales saltar
goto case_15 ; no es 14, continuar
movfw RCDATO ;el ESTADO es 14, llega SEGHIG en ASCII, le sobran 30
andlw 0x0F ; mascara para borrar ASCII, 30 queda en 00, 31 en 01 etc
movwf SEGHIG ; cargar el digito SEGHIG
movlw 0x15
movwf ESTADO ;pasar al estado 15
call echo_ar ;hacer eco de SEGHIG a la PC
return
;
case_15 ;Recibiendo unidades de Segundos, guardar en SEGLOW ,
movfw ESTADO ; Comparar
xorlw 0x15 ; con estado 15
btfss STATUS,Z ;si son iguales saltar
goto case_16 ; no es 15, continuar a 16
movfw RCDATO ;el ESTADO es 15, llega SEGLOW en ASCII, le sobran 30
andlw 0x0F ; mascara para borrar ASCII, 30 queda en 00, 31 en 01 etc
movwf SEGLOW ; cargar el digito SEGLOW
movlw 0x16
movwf ESTADO ;pasar al estado 16
call echo_ar ;hacer eco de SEGLOW a la PC
return
;
case_16 ;Recibiendo el punto decimal de las centecimas de Segundos en el mensaje, viene en ASCII
movfw ESTADO ; Comparar
xorlw 0x16 ; con estado 16
btfss STATUS,Z ;si son iguales saltar
goto case_17 ; no es 16, ir a 17
movfw RCDATO ;el ESTADO es 16, verifcar si llego el "."
xorlw 0x2E ; comparar con . punto
btfsc STATUS,Z ; si no llego, hay error, en ese lugar debe haber un punto, si no está hay error, ergo resetear estado
goto si_PU ; si se detecta el "." ir a seguir la secuencia exitosa
clrf ESTADO ;no se detecto el "."
return ;resetear ESTADO y volver
si_PU ;
movlw 0x17
movwf ESTADO ;pasar al estado 17
call echo_ar ;hacer eco del punto decimal a la PC
return
case_17 ;Recibiendo el cero 0X de las centecimas de Segundo en el mensaje, viene en ASCII
movfw ESTADO ; Comparar
xorlw 0x17 ; con estado 17
btfss STATUS,Z ;si son iguales saltar
goto case_18 ; el estado no es 17,
movfw RCDATO ;el ESTADO es 17, verifcar si llego 0 (el modo del módulo no reporta decimales, estos siempre serán ceros)
xorlw 0x30 ; comparar con 0
btfsc STATUS,Z ; si no llego 0, hay error, resetear estado
goto si_0X ; si llego el 0, seguir secuencia
clrf ESTADO ;no era 0
return ;resetear ESTADO y volver
si_0X ;
movlw 0x18
movwf ESTADO ;pasar al estado 18
movlw 0x0D ; en lugar de mandar las centesimas que siempre son 00, mandar CR(0Dh), luego LF (0Ah)
call tx_dato ; para que la linea del HiperTerminal de monitoreo muestre la Hora y avance una linea
return
case_18 ;Recibiendo el cero x0 o segundo cero de las centecimas, viene en ASCII
movfw ESTADO ; Comparar
xorlw 0x18 ; con estado 18
btfss STATUS,Z ;si son iguales saltar
goto case_20 ; no es 18, sera 20?
movfw RCDATO ;el ESTADO es 18, verifcar si llego 0
xorlw 0x30 ; comparar con 0 en ASCII
btfsc STATUS,Z ; si no llego 0, hay error, resetear estado
goto si_X0 ; si llego el 0 , seguir secuencia
clrf ESTADO ;no era "0"
return ;resetear ESTADO y volver
si_X0 ;
movlw 0x08 ; ACA cargar el contador de comas a saltear, parámetros que no son requeridos son salteados, SON 8!
movwf ESTAUX ; en el registro ESTAUX
movlw 0x20
movwf ESTADO ;pasar al estado 20 de la máquina de estados
movlw 0x0A ; mandar LF (0Ah) para completar la linea en la HiperTerminal
call tx_dato ;
return
case_20 ;aqui se cuentan las 8 comas que separan la Hora de la Fecha en el mensaje, luego se recoje la Fecha con secuencia
;de estados similar a la Hora y se cargan sus registros.
;
off_hor ;Calcular la hora local aplicando el Offset a la hora UTC leida (Argentina es Offset -3)
; la hora UTC leida del módulo GPS se guarda en los auxiliares HORHIX y HORLOX)
;
swapf HORHIX,0 ;invertir los nibles, queda en W, el HORHIX no cambia
andlw 0xF0 ;limpiar los bits de < peso
iorwf HORLOX,0 ; sumo ambos , la hora de dos digitos esta ahi
addwf OFFSEX,0 ;sumarle el OFFSEX de 5 (8-3=5)
;conversion por tabla eprom, el numero de entrada viene en w
; sumar el offset dentro de la eeprom EL OFFSET para esta tabla ES 00
bsf STATUS, RP0 ;apuntar banco 1
movwf EEADR ;cargar en el puntero address eeprom
bsf EECON1,RD ;iniciar el READ
movfw EEDATA ;pasar el dato eeprom al w
bcf STATUS, RP0 ;banco 0
movwf HORLOW ; pasar el valor completo, solo los 4 bits < peso se usan para mostrar. HORLOW es unidades de Hora corregida
movwf HORHIG ; pasar el valor completo, solo los 4 bits < peso se usan para mostrar. HORHIG es decenas de Hora corregida
swapf HORHIG,1 ;invertir otra vez los nibles ;y mostrar
return
;----------------------------------------------------------------------------------------
ORG 0X2100 ;LUGAR de la EEPROM
;TABLA DE OFFSETS ---- de UTC a LOCAL, verla completa mas abajo
;offset tabulados -5, -6, -4, -3
;(00) Comienzo de la tabla de offsets
de 0xFF ; 00
de 0xFF ; 01
de 0x18 ; 02
de 0x19 ; 03
de 0x20 ; 04
de 0x21 ; 05
de 0x22 ; 06
de 0x23 ; 07
de 0x00 ; 08
de 0x01 ; 09
de 0x02 ; 0A
de 0x03 ; 0B
de 0x04 ; 0C
de 0x05 ; 0D
de 0x06 ; OE
de 0xFF ; OF
;(10)
de 0xFF ; 10 16
de 0xFF ; 11 17
de 0x04 ; 12 18
de 0x05 ; 13 19
de 0x06 ; 14 20
de 0x07 ; 15 21
de 0x08 ; 16 22
de 0x09 ; 17 23
de 0x10 ; 18 24
de 0x11 ; 19 25
de 0x12 ; 1A 26
de 0x13 ; 1B 27
de 0x14 ; 1C 28
de 0x15 ; 1D 29
de 0x16 ; 1E 30
de 0xFF ; 1F 31
;(20)
de 0xFF ;20 32
de 0xFF ;21 33
de 0x14 ;22 34
de 0x15 ;23 35
de 0x16 ;24 36
de 0x17 ;25 37
de 0x18 ;26 38
de 0x19 ;27 39
de 0x20 ;28 40 fin de la tabla de offset
de 0xFF ;29 41
de 0xFF ;2A 42
de 0xFF ;2B 43
de 0xFF ;2C 44
de 0xFF ;2D 45
de 0xFF ;2E 46
de 0xFF ;2F 47
;En DIAHIX la ISR guardó las decenas del Día UTC recibido del módulo GPS
;En DIALOX la ISR guardó las unidades del Día UTC recibido del módulo GPS
;
swapf DIAHIX,0 ;invertir los nibles, el resultado queda en W
andlw 0xF0 ;limpiar los bits de < peso por las dudas
iorwf DIALOX,1 ; sumo ambos, el resultado queda en DIALOX , el dia de dos digitos esta ahi
movfw DIALOX ;salvar el dia en w
decfsz DIALOX,1 ; chequear si el día es 01
goto mes_nor ; el dia NO es 01, procesar mes normal
goto mes_ant ; el día ES 01 , hay que buscar el dia anterior en el mes anterior
;
mes_nor ;
movwf DIALOX ;el día UTC se recupera en DIALOX
movlw 0x10 ; comparar el dia con 10, 20 y 30
subwf DIALOX,0 ;comparar el dia primero con 10
btfss STATUS,Z ; el decremento directo dara 0F, valor que no va
goto noes_10 ;continuar porque no es 10
movlw 0x09 ;el día es 10, cargar entonces directamente el día anterior 09
goto mes_out
noes_10
movlw 0x20 ;
subwf DIALOX,0 ;comparar el dia con 20
btfss STATUS,Z ;
goto noes_20 ; continuar porque no es 20
movlw 0x19 ;el día es 20, cargar directamente el día anterior 19
goto mes_out
noes_20
movlw 0x30 ;
subwf DIALOX,0 ;comparar el dia con 30
btfss STATUS,Z ;
goto noes_30 ; no es 30, continuar
movlw 0x29 ;el día es 30, cargar directamente con 29
goto mes_out
noes_30 ;el dia no es ni 01, ni 10, ni 20 ni 30
decf DIALOX,1 ; entonces decrementarlo directamente
movfw DIALOX ; el día anterior está en DIALOX
mes_out
movwf DIALOW ; pasar el valor completo, pues solo los 4 bits < peso se usarán para mostrar en el display
movwf DIAHIG ;
swapf DIAHIG,1 ;invertir otra vez los nibles ;sólo los 4 bits de < p se usan para mostrar en el display
return ; y salir...............
;
mes_ant ; es primero de mes o sea dia 01, hay que pasar al ultimo dia del mes anterior, con el indice del mes UTC
swapf MESHIG,0 ;invertir los nibles, el resultado, queda en W, el MESHIG no cambia
andlw 0xF0 ;limpiar los bits de < peso por las dudas
iorwf MESLOW,0 ; sumo ambos , el dia de dos digitos esta en W
;conversion por tabla eprom OFFSET 60,
addlw 0x60 ; sumar el offset de eeprom EL OFFSET para esta tabla ES 60
bsf STATUS, RP0 ;apuntar banco 1
movwf EEADR ;cargar en el puntero address eeprom
bsf EECON1,RD ;iniciar el READ
movfw EEDATA ;pasar el dato eeprom al w, alli está el dia anterior o último día del mes anterior
bcf STATUS, RP0 ;banco 0
goto mes_out ;
;
;
ORG 0X2100 ;LUGAR de la EEPROM
;Offset de EEPROM (60) ;TABLA DE MES -Debe atrazarse el dia por la correccion UTC, y el dia es 01,
;
de 0xFF ; 60 96 00 mes UTC 00 no existe
de 0x31 ; 61 97 01 mes 01 enero, mes anterior diciembre, el dia anterios al 01/01 es 31
de 0x31 ; 62 98 02 mes 02 feb, mes anterior enero tiene 31
de 0x28 ; 63 99 03 febrero 28
de 0x31 ; 64 100 04 marzo 31
de 0x30 ; 65 101 05 abril 30
de 0x31 ; 66 102 06 mayo 31
de 0x30 ; 67 103 07 junio 30
de 0x31 ; 68 104 08 julio 31
de 0x31 ; 69 105 09 agosto 31
de 0xFF ; 6A 106 0A NOVA
de 0xFF ; 6B 107 0B
de 0xFF ; 6C 108 0C
de 0xFF ; 6D 109 0D
de 0xFF ; 6E 110 0E
de 0xFF ; 6F 111 0F NOVA
;(70)
de 0x30 ; 70 112 10 setiembre 30
de 0x31 ; 71 113 11 octubre 31
de 0x30 ; 72 114 12 novimbre 30 FIN TABLA MES ANTERIOR
;---------
;
;------------------------------------------------------------------------------
;--- MOSTRAR HORA, MIN, SEG EN EL DISPLAY, SHIFTEANDO LOS BITS EN LOS REGISTROS
;------------------------------------------------------------------------------
;
; El orden de envio serial de los números será HU, MD, MU, SD, SU, y HD que será 0 o 1
; luego se envían los bits de Back Light
;
mos_hor ; mostrar hora,min,seg, "SHIFtiando" el dato de memoria en los registros de desplazamiento
;CKB7 (RB7) es el Clock (CK) de los registros. Recordar que los transistores de cambio de tensión
;DTB6 (RB6) es el Dato (DT) de los registros invierten las señales CK y DT
;
;mandar hora low HU, las unidades de Hora están en los 4 bits < peso de HORLOW
bsf PORTB,DTB6 ; Poner Datos a 1, o sea 0 en los registros (el Transistor invierte)
btfsc HORLOW,0 ; si el bit esta en 0 no hacer nada, el T ya esta en 0
bcf PORTB,DTB6 ; si el bit esta en 1, poner DT a 0 pues el T invierte y estara en 1
call Pulso ; Pulsar CK para cargar/shiftear el bit en los registros
btfsc HORLOW,1 ; continuar con los restantes 3 bits del registro
bcf PORTB,DTB6 ;
call Pulso
btfsc HORLOW,2 ;
bcf PORTB,DTB6 ;
call Pulso
btfsc HORLOW,3 ;
bcf PORTB,DTB6 ;
call Pulso
;
;mandar minutos high MD, las decenas de Minutos están en los 4 bits < peso de MINHIG
btfsc MINHIG,0 ;
bcf PORTB,DTB6 ;
call Pulso
btfsc MINHIG,1 ;
bcf PORTB,DTB6 ;
call Pulso
btfsc MINHIG,2 ;
bcf PORTB,DTB6 ;
call Pulso
btfsc MINHIG,3 ;
bcf PORTB,DTB6 ;
call Pulso
;
;mandar minutos low MU
btfsc MINLOW,0 ;
bcf PORTB,DTB6 ;
call Pulso
btfsc MINLOW,1 ;
bcf PORTB,DTB6 ;
call Pulso
btfsc MINLOW,2 ;
bcf PORTB,DTB6 ;
call Pulso
btfsc MINLOW,3 ;
bcf PORTB,DTB6 ;
call Pulso
;
;mandar segundos high SD
btfsc SEGHIG,0 ;
bcf PORTB,DTB6 ;
call Pulso
btfsc SEGHIG,1 ;
bcf PORTB,DTB6 ;
call Pulso
btfsc SEGHIG,2 ;
bcf PORTB,DTB6 ;
call Pulso
btfsc SEGHIG,3 ;
bcf PORTB,DTB6 ;
call Pulso
;
;mandar segundos low SU
btfsc SEGLOW,0 ; Si el bit es UNO
bcf PORTB,DTB6 ; apagar o sea encender el T
call Pulso ; pulsa el Clock y deja en cero la salida
btfsc SEGLOW,1 ;
bcf PORTB,DTB6 ; apagar o sea encender
call Pulso
btfsc SEGLOW,2 ;
bcf PORTB,DTB6 ; apagar/encender
call Pulso
btfsc SEGLOW,3 ;
bcf PORTB,DTB6 ;
call Pulso
;
;mandar hora high HD, Decenas de Horas el HD es "apagado o 1"
btfsc HORHIG,0 ; HORHIG sera 0000 entonces apagar
bcf PORTB,DTB6 ; HORHIG = 0001 entonces encender el 1 del medio digito
call Pulso
;Aqui se mandan los 3 bits del RGB del back light
btfsc BACLIG,0 ; mandar el bit R serán Q1, Q2 y Q3 del ultimo registro
bcf PORTB,DTB6 ;
call Pulso
btfsc BACLIG,1 ;mandar el bit G Mandar el estado del contador de BACLIG
bcf PORTB,DTB6 ;
call Pulso
btfsc BACLIG,2 ; mandar el bit B
bcf PORTB,DTB6 ;
call Pulso
;
return
;---------------- FIN DE MOSTRAR HORA
Pulso ; el Clock de los registros de desplazamiento
nop ;Los NOPs regulan el ancho de pulso y los tiempos de bajada y subida
nop ; los colectores de los transistores con resistencia manejando entradas CMOS dan un tiempo de subida de 2 uS
nop ;
nop ;estabilizar la salida con NOPs
nop
nop
bcf PORTB,CKB7 ;flanco descendente, flanco ascendente en los registros, se produce el SHIFT
nop ; el tiempo que el PULSO esta en 0 (1)
nop
nop
nop ;estabilizar la salida
nop
nop
bsf PORTB,CKB7 ;pasa a 1 (cero) el pulso
nop ;estabilizar la salida
nop
nop
nop
nop
nop
bsf PORTB,DTB6 ; y dejar la salida en 1 (0) Los transistores invierten
return
;-------------------------------------------------------------------------------------------
;
; La rutina de proceso del Back Light, es llamada cada de 7 a 10 minutos para el cambio de código de color
baklig
;AQUI PROCESAR EL BACKLIGHT
incf CONLIG,1 ;incrementar el contador de espera de cambio de color
btfss CONLIG,0X07 ;1000.0000 contador de espera para cambiar el color
return ; si no llegó todavia, entonces volver
clrf CONLIG ; si llegó, resetear contador de espera y procesar backlight
btfss SEGLOW,0 ; Agrego este toque pseudoramdom, depende como se encuentren los bits del SEGLOW, salto el color
incf BACLIG,1 ; este incremento es random <Para que la secuencia de color de fondo no sea siempre la misma>
btfss SEGLOW,1 ; Otro toque pseudoranmdom <se agrega un toque pseudorandom de acuerdo al estado de los bits de los>
incf BACLIG,1 ; este incremento es random <segundos en el momento de cambiar de codigo de color>
incf BACLIG,1 ;incrementar el registro de Back Light, ESTE se hace siempre
btfsc BACLIG,0X03 ; detectar 0000.1000 ó 0000.1XXX para que solo se manejen 3 bits
clrf BACLIG ;poner a cero si llego a 8 o se pasó a 9 0 A por el random
return
;-------------FIN DE BACK LIGHT ----------
;
¡Qué chulo te ha quedado, enhorabuena! :-/
act_alm
;actualizar variables de almanaque antes de enviar las variable a los registros externos y encender los Leds
;Las variables que se usan y su asignación:
; Posiciones de bits; 7 6 5 4 3 2 1 0
;P0SDI3 Variable de LEDs de posición y tres dias: LON,GRA,MIN,LAT,LIBRE,LUN,MAR,MIE
;DI4ME4 Variable de LEDs de 4 dias y 4 meses: JUE,VIE,SAB,DOM, ENE,FEB,MAR,ABR
;MESES8 Variable de LEDs de 8 meses: MAY,JUN,JUL,AGO, SEP,OCT,NOV,DIC
;Uso las auxiliares COUNT0, COUNT1, COUNT3
;
;--------primero procesar mes -----------------------------------
;
clrf MESES8 ; acerar variables del almanaque
clrf DI4ME4 ;
clrf POSDI3 ;
;Recuperar el mes mostrado en el display, armar las variables de almanaque y mandarlas a los registros externos
swapf MESHIG,0 ;invertir los nibles, queda en W, el MESHIG no cambia (MESHIG son las decenas de Mes)
andlw 0xF0 ;limpiar los bits de < peso por las dudas
iorwf MESLOW,0 ; sumo ambos, el dato queda en W, el MESLOW no cambia
movwf COUNT0 ; salvar el mes en la auxiliar COUNT0, el mes expresado en BCD está ahi
;
;-------------------------------------------------------
movfw COUNT0 ; recuperar el mes en BCD
xorlw 0x12 ; ver si es 12 (diciembre)
btfss STATUS,Z
goto no_12
bsf MESES8,0 ; es 12 diciembre, encender el bit del led
movlw 0x03 ;el 01/12/21 es miercoles OJO , Código ACTUALIZADO AL 2021
movwf COUNT1 ; uso la auxiliar COUNT1 para guardar el indice del primer dia del mes
goto dia_alm ;
no_12 ; Indice que se guarda en COUNT1 es : 1-lun,2-mar,3-mie,4-jue,5-vie,6-sab,7-dom
movfw COUNT0 ;
xorlw 0x11
btfss STATUS,Z
goto no_11
bsf MESES8,1 ; es 11 (nov), encender el led
movlw 0x01 ;el 01/11/21 es lunes
movwf COUNT1 ;inicializar COUNT1
goto dia_alm
no_11
movfw COUNT0 ;
xorlw 0x10
btfss STATUS,Z
goto no_10
bsf MESES8,2 ; es 10 octubre, encender el led
movlw 0x05 ;el 01/10/21 es viernes
movwf COUNT1 ;inicializar COUNT1
goto dia_alm
no_10
movfw COUNT0 ;
xorlw 0x09
btfss STATUS,Z
goto no_09
bsf MESES8,3 ; es 09 septiembre, encender el led
movlw 0x03 ;el 01/09/21 es miercoles
movwf COUNT1 ;inicializar COUNT1
goto dia_alm
no_09
movfw COUNT0 ;
xorlw 0x08
btfss STATUS,Z
goto no_08
bsf MESES8,4 ; es 08 agosto, encender el led
movlw 0x07 ;el 01/08/21 es domingo
movwf COUNT1 ;inicializar COUNT1
goto dia_alm
no_08
movfw COUNT0 ;
xorlw 0x07
btfss STATUS,Z
goto no_07
bsf MESES8,5 ; es 07 julio, encender el led
movlw 0x04 ;el 01/07/21 es jueves
movwf COUNT1 ;inicializar COUNT1
goto dia_alm
no_07
movfw COUNT0 ;
xorlw 0x06
btfss STATUS,Z
goto no_06
bsf MESES8,6 ; es 06 junio, encender el led
movlw 0x02 ;el 01/06/21 es martes
movwf COUNT1 ;inicializar COUNT1
goto dia_alm
no_06
movfw COUNT0 ;
xorlw 0x05
btfss STATUS,Z
goto no_05
bsf MESES8,7 ; es 05 mayo , encender el led
movlw 0x06 ;el 01/12/21 es sabado
movwf COUNT1 ;inicializar COUNT1
goto dia_alm
no_05
movfw COUNT0 ;
xorlw 0x04
btfss STATUS,Z
goto no_04
bsf DI4ME4,0 ; es 04 abril, encender el led
movlw 0x04 ;el 01/04/21 es jueves
movwf COUNT1 ;inicializar COUNT1
goto dia_alm
no_04
movfw COUNT0 ;
xorlw 0x03
btfss STATUS,Z
goto no_03
bsf DI4ME4,1 ; es 03 marzo, encender el led
movlw 0x01 ;el 01/03/21 es lunes
movwf COUNT1 ;inicializar COUNT1
goto dia_alm
no_03
movfw COUNT0 ;
xorlw 0x02
btfss STATUS,Z
goto no_02
bsf DI4ME4,2 ; es 02 febrero, encender el led
movlw 0x01 ;el 01/02/21 es lunes
movwf COUNT1 ;inicializar COUNT1
goto dia_alm
no_02 ; entonces es 01
bsf DI4ME4,3 ; es 01 enero, encender el led
movlw 0x05 ;el 01/01/21 es viernes
movwf COUNT1 ;inicializar COUNT1
dia_alm
;
;--------aqui procesar dia de la semana -----------------------------------
;
; ;
dia_alm
;procesando el día de la semana encender en el almanaque
;
swapf DIAHIG,0 ;invertir los nibles, queda en W, el DIAHIG no cambia (son las decenas de Dia)
andlw 0xF0 ;limpiar los bits de < peso por las dudas
iorwf DIALOW,0 ; sumo ambos, el dato queda en W, el DIALOW no cambia (son las unidades de Dia)
movwf COUNT3 ; salvar el dia en la auxiliar COUNT3, el dia esta en BCD
clrf COUNT0 ;inicializar contador
;
; arranca el lazo de cuenta, hasta igualar COUNT0 con COUNT3,
; mientras se cuenta en COUNT1 con modulo 7
;cuando COUNT0 iguala a COUNT3, en COUNT1 estará el puntero de dia de la semana
;previamente COUNT1 lo precargo con el OFFSET del día de principio de mes que le cargué arriba
laz_alm ;lazo de cuenta
incf COUNT0,1 ; incrementar COUNT0
movfw COUNT0 ; salvar en w
andlw 0x0F ;
xorlw 0x0A ; ver si el COUNT0 llego a 0A (10) o 1A o 2A
btfss STATUS,Z ; saltar si no es XA
goto no_xxx ; si aun no es A, no corregir
movfw COUNT0 ; si ya es A
addlw 0x06 ; sumar 6 y saltear los valores exadecimales. Si era 0A ahora es 10
movwf COUNT0; actualizar COUNT0, si era 1A ahora es 20, si era 2A ahora es 30
no_xxx
movfw COUNT0 ;recuperar COUNT0
xorwf COUNT3,0 ;comparar con el día mostrado en el display guardado en COUNT3, esta en BCD
btfsc STATUS,Z ;si son iguales, se llego al fin de la cuenta
goto fin_cue ;si no se llego al fin de cuenta, seguir incrementando el puntero de dia de la semana
;aca está la cuenta en modulo 7
incf COUNT1,1 ; ir contando el día de la semana en modulo7, que ya viene con el OFFSET cargado arriba
bcf COUNT1,3 ; si llego a 0000.1000 dejarlo en 0000.0000 (modulo 8)
movf COUNT1,1 ;solo para mover el Z y saber s iquedo en 0
btfsc STATUS,Z ;si es 0000.0000 pasarlo a 0000.0001, o sea saltear el 0
incf COUNT1,1 ; o sea que la cuenta sea 1,2,3,4,6,7, 1,2,3,4,5,6,7 .... cuenta en módulo 7 de los 7 días de la semana
goto laz_alm ;retornar al lazo de cuenta
; la cuenta termino,
fin_cue ;en COUNT1 esta el puntero de día de la semana ya corregido y con el offset de arranque de mes
;------------------------------------------------------------
movfw COUNT1 ;
xorlw 0x01 ; ver si es 01, lunes
btfss STATUS,Z
goto no_lu ; no es lunes
bsf POSDI3,2 ;encender el bit del Led del lunes
return
no_lu
movfw COUNT1 ;
xorlw 0x02 ; ver si es 02, martes
btfss STATUS,Z
goto no_ma ; no es martes
bsf POSDI3,1 ;encender el martes
return
no_ma
movfw COUNT1 ;
xorlw 0x03 ; ver si es 03, miercoles
btfss STATUS,Z
goto no_mi ; no es miercoles
bsf POSDI3,0 ;encender el miercoles
return
no_mi
movfw COUNT1 ;
xorlw 0x04 ; ver si es 04, jueves
btfss STATUS,Z
goto no_ju ; no es jueves
bsf DI4ME4,7 ;encender el jueves
return
no_ju
movfw COUNT1 ;
xorlw 0x05 ; ver si es 05, viernes
btfss STATUS,Z
goto no_vi ; no es viernes
bsf DI4ME4,6 ;encender el viernes
return
no_vi
movfw COUNT1 ;
xorlw 0x06 ; ver si es 06, sabado
btfss STATUS,Z
goto no_sa ; no es sabado
bsf DI4ME4,5 ;encender el sabado
return
no_sa ;entonces es domingo
movfw COUNT1 ;
xorlw 0x07 ; ver si es 06, sabado
btfss STATUS,Z
goto no_di ; no es ningun dia
bsf DI4ME4,4 ;encender el domingo
return
no_di ;entonces no es nin gun dia
movlw 0xFF ;encender todos los Leds
movwf DI4ME4 ;para indicar el error
return
;P0SDI3, DI4ME4, MESES8 quedan actualizadas listas para enviar a los registros
;-----------------------------------------------------
;----------- FIN DE ACTUALIZAR ALMANAQUE -------------
Ese tipo de displays no los había visto nunca :DEstos son muy viejos, unos 50 años. Desconozco si se siguen fabricando :shock: