PDA

Ver la versión completa : Et voila... Mi nueva centralita funcionando...



Dedalo
12/05/2010, 00:49
Mi nueva centralita funcionando...

Aqui os envio unas imagenes que hice durante el montaje.

Aunolose
12/05/2010, 03:27
Joe, que nivel, con pantalla gráfica y to, pero ¿eso está hecho en ensamblador?, pues vaya faena...
Parecen menús como los del movil. ¿está ya comprobada?

Dedalo
12/05/2010, 10:37
Efectivamente esta hecho en ensamblador.

El menu principal tiene 5 funciones:
1- 220V
2 - Carga de baterias
3 - Nivel de baterias
4 - vaciado de depositos
5 - Nivel de depositos.

La primera opcion simplemente enciende o apaga el inversor de 220V (solo en caso de no estar conectado a 220V exteriores).

La segunda opcion nos lleva a la pantalla de carga de baterias. En esta pantalla se puede seleccionar manualmente la fuente de carga de cada una de las baterias (Placa solar, alternador del motor o cargador de 220V) o simplemente dejarlo en automatico.

La tercera opcion carga una pantalla que muestra el estado de las baterias, el voltaje de las tres baterias y las intensidades (carga o descarga) de las dos baterias de la vivienda. En la bateria de motor no he puesto ningun shunt para medir la intensidad.

La cuarta opcion carga una ventana desde la que se puede activar o desactivar las valvulas electricas de vaciado de los depositos de aguas grises y negras.

La quinta opcion carga una ventana en la que aparecen los depositos y suy porcentaje de llenado.

Cada pantalla es un grafico de 240 x 64 puntos que hice con paint y que pasé a binario. Los graficos estan almacenados en una 24C256.

El procesador es un ATMEL AT89C51.

Aqui va el esquema completo:

29086

He puesto optoacopladores de sobra para poder ampliar funciones en el futuro. Modificando el programa solo es cuestion de imaginacion aumentar las prestaciones.

Dedalo
12/05/2010, 10:45
¿está ya comprobada?

Ya esta todo funcionando excepto los niveles de agua. Fijate que en la fotografia los tres niveles marcan 50%. Si recuerdas monté un invento con un indicador analogico de estilo retro. Este indicador lleva una PAL que permite que la centralita lea en formato serie los datos de los niveles, y sobre la mesa funciona, pero en la AC, con varios metros de cable no funciona, debe ser por los niveles logicos, que son TTL y no se puede estirar las longitudes de los cables mas de un par de metros. La idea es reformar el circuito para crear bucles de intensidad, que soportan mas distancia en los cables que los niveles TTL. Eso es facil de hacer con optoacopladores. Todo a su tiempo...

Aunolose
12/05/2010, 12:24
Ya esta todo funcionando excepto los niveles de agua. Fijate que en la fotografia los tres niveles marcan 50%. Si recuerdas monté un invento con un indicador analogico de estilo retro. Este indicador lleva una PAL que permite que la centralita lea en formato serie los datos de los niveles, y sobre la mesa funciona, pero en la AC, con varios metros de cable no funciona, debe ser por los niveles logicos, que son TTL y no se puede estirar las longitudes de los cables mas de un par de metros. La idea es reformar el circuito para crear bucles de intensidad, que soportan mas distancia en los cables que los niveles TTL. Eso es facil de hacer con optoacopladores. Todo a su tiempo...


Los circuitos de intensidad son más complicados que mandar 12V y que lleguen solo 8, aunque te serviría para detectar "cable abierto" o "cable en corto". eso requiere más circuitería.
0mA= circuito abierto, cable desconectado
4mA= cero lógico
20mA= uno lógico
>20mA= cortocircuito.

Los circuitos de intensidad que conozco se usan para niveles analógicos, de 4 a 20mA, te da una gama "infinita" de niveles.

Por cierto, ¿no lo ibas a hacer con un PIC? :D

Dedalo
12/05/2010, 13:51
Por cierto, ¿no lo ibas a hacer con un PIC? :D

Pues si, me estoy planteando rehacer de nuevo todo el circuito de niveles. De hecho he estado mirando unos sensores de presion diferencial que tiene farnell de 0 a 10 kPa que son ideales para medir la altura del agua en los depositos. Colocados uno en el fondo de cada deposito tendria 10 Pa de presion por cada cm de altura del agua sobre el nivel del sensor, como son de rango 0-5V tendria un rango analogico de 0 a 1,5V por los 30 Cm que tienen los depositos de altura.

Aunolose
12/05/2010, 16:55
¿Y cuanto cuestan? y ya puestos ¿cuanto cuesta la pantalla gráfica?

Aquí quieren hacer un modelo en el que hay que medir niveles, pero en depósitos pequeños, ¿cual es la presión mínima que miden?.

Dedalo
17/05/2010, 13:08
Bueno, pues este fin de semana ya he marchado con la centralita nueva. He estado en la albufereta, en Alicante.

Todo funciona al 100%. Solo hay un par de problemas que son errores de software.

Uno de ellos es que la misma tecla del menu principal que nos lleva al menu de vaciado es la tecla de apertura de las aguas grises, por lo que si no te andas listo, la pulsas, cambia el menu y medio segundo despues se pone a vaciar las aguas grises sin previo aviso. La solucion es cambiar de lugar en el menu principal las opciones de niveles de depositos y vaciados, asi al entrar en vaciado, si dejas el dedo pegado mas de medio segundo en lugar de abrir cierras. Es preferible cerrar antes de tiempo que abrir donde no se debe y dejar un charco debajo de la AC.

El segundo error es que cuando estas vaciando hay que volver al menu principal para ver como va el nivel de los depositos. Se me ocurre que se puede programar una de las teclas libres de la pantalla de vaciado para pasar a ver los niveles y viceversa, es decir, una tecla libre de la pantalla de niveles para ir al menu de vaciado.

Vamos, que con unos retoques de software se queda de lujo...

Aunolose
17/05/2010, 13:51
Dedalo, cuéntame algo de los sensores de presión.

Dedalo
17/05/2010, 15:03
Sobre los sensores de presion, he encontrado algunos en Farnell y en RS, desde unos pocos euros hasta varios cientos. Para la precision que necesitamos en los depositos es suficiente con uno de los mas baratos. Yo he pensado en poner este:

Honeywell | Control de Procesos Industriales | Sensores y Transductores | Sensores de Presión | Sensores Piezoresistivos |SCC15ASMT (http://es.rs-online.com/web/search/searchBrowseAction.html?method=getProduct&R=6670967)

o este otro, un poco mas caro:

Honeywell | Control de Procesos Industriales | Sensores y Transductores | Sensores de Presión | Sensores Piezoresistivos |24PCEFA6G (http://es.rs-online.com/web/search/searchBrowseAction.html?method=getProduct&R=2355762)

El primer sensor es de 0 a 15 PSI, es decir, que su rango es de 0 a +/- 10 metros de nivel de agua.

El segundo es de 0 a 0,5 PSI, o lo que es lo mismo, entre 0 y +/- 30 cm de nivel de agua. Ideal para un deposito de la AC.

Sobre los indicadores graficos, yo he utilizado uno que tenia en casa de experimentos anteriores, creo que me costó unos 50 euros hace ya un par de años, pero los he visto ya en color y de una resolucion parecida entre los 30 y 50 euros.

Aunolose
17/05/2010, 20:06
Gracias, no me queda claro que el segundo sea para líquidos ¿o es eso del LPPC?

30cm sigue siendo demasiado para lo que busco, tendremos que ver si es suficiente.

¿y como pasas el BMP a la pantalla?, no me ha quedado muy claro, ¿o lo haces a mano "uno cero cero uno...."?

Dedalo
17/05/2010, 22:58
LPPC (Libras por pulgada cuadrada) es la traduccion a español de PSI, (Pound by Square Inch).

Las especificaciones dicen literalmente:



Media (P1&P2): Limited only to those media which not attack polietherimide, silicon and fluorosilicone seal.


Que se puede traducir por: limitado solo a los ambientes que no ataquen... los elementos de las juntas internas. Supongo que el agua no atacará a esas siliconas ni al silicio. En todo caso se puede inventar algo para interponer una membrana entre el agua y el sensor, asi se deja una camara de aire del lado del sensor sin afectar a la presion.

Dedalo
17/05/2010, 23:21
¿y como pasas el BMP a la pantalla?, no me ha quedado muy claro, ¿o lo haces a mano "uno cero cero uno...."?

Para pasar los BMP a la pantalla grafica me hice un programa en el PC que pasa un grafico BMP monocromo a bytes en el mismo formato que los necesita el display grafico, es decir, de cada byte solo son utiles los primeros 6 bits, cada pantalla esta compuesta por 64 lineas, cada una de ellas utiliza 40 bytes (40 x 6 bits), en total 2560 bytes.

El programa me graba un archivo en formato intel.hex que utilizo directamente para grabar la memoria EEPROM

Podria haber comprimido mas la imagen utilizando los 8 bits, pero como dispongo de memoria de sobra asi simplifico el programa en assembler que copia bloques desde la memoria EEPROM a la RAM del display.

El programa (en Delphi):
29262

Aunolose
19/05/2010, 13:33
He comentado lo de los sensores en el agua y alguno ya los conoce, cree que si dará problemas si entra agua, aunque como no son caros, se puede probar,

El problema lo tenemos en el rango, para lo que nosotros queremos (que es algo más de un vaso de agua) no llega a ser preciso.

¿sabes si delphi funciona todavía en Windows 7? aunque me pase al CBuilder, también de Borland, igual de rápido para diseñar cosas, pero en C++ lo que pasa es me quede en la versión 5... allá por el ¿98?

Dedalo
19/05/2010, 14:20
Supongo que funcionará. Yo lo utilizo porque me he dedicado en los ultimos años a hacer programas de gestion y es mas eficiente que C++ para esa aplicacion.

Para este tipo de programas me gusta mas C que Pascal, pero es lo que tengo instalado y para una cosita rapida como esta me sirve, ademas no tengo ahora ningun C actualizado, pues el ultimo C que utilicé fué el Borland C++ V 4.5 para Windows 3.11

navegante 420
10/06/2010, 11:22
Mi nueva centralita funcionando...

Aqui os envio unas imagenes que hice durante el montaje.


La madre que te matriculo!!!!!!!!!!!!!!!

Hace dias que me rondava la idea de buscar info sobre como manejar un LCD gráfico, pero me daba pereca porque pensaba que era muy complejo, pero viendo esto...... y en esamblador........ ya me estas pasando las subrutinas....... y explica explica......

¿ y si fuera en color ?

con el 16f877 puedo manejarlo sin problemas?????

Al final mi mujer me pide el divorcioo por vuestra culpa :toothy7::toothy7::toothy7:

navegante 420
10/06/2010, 12:16
Cada pantalla es un grafico de 240 x 64 puntos que hice con paint y que pasé a binario. Los graficos estan almacenados en una 24C256.



Con el paint?????

y ya esta?????

la de cosas que se me estan ocurriendo????

navegante 420
10/06/2010, 12:25
Para pasar los BMP a la pantalla grafica me hice un programa en el PC que pasa un grafico BMP monocromo a bytes en el mismo formato que los necesita el display grafico, es decir, de cada byte solo son utiles los primeros 6 bits, cada pantalla esta compuesta por 64 lineas, cada una de ellas utiliza 40 bytes (40 x 6 bits), en total 2560 bytes.

El programa me graba un archivo en formato intel.hex que utilizo directamente para grabar la memoria EEPROM

Podria haber comprimido mas la imagen utilizando los 8 bits, pero como dispongo de memoria de sobra asi simplifico el programa en assembler que copia bloques desde la memoria EEPROM a la RAM del display.

El programa (en Delphi):
29262

AHHHHH!!!!!! este es el secreto......

Aunque no me he enterado muy bien del tema.....

Si quisiera usar una de color??? es posible que encuentre algun programita ya hecho al estilo del de toni pero para color????

Y si en vez de programarlo en ensablador lo quiero hacer usando el CCS A que formato tengo que grabar la imagen???

Si Oscar, CCS, Digamos que tras mucho esfuerzo, horas y horas probando programar, he conseguido completar el curri del curso, osea C básico, funciones y punteros. Y con el titular de sistemas microprogramables, que no tenia muchas granas de explicar cosas, le obligue a que por lo menos hiciera una intro al CCS.

Aunolose
10/06/2010, 19:30
Ya verás como con el C todo la parte de programación va más rápido. Te recomiendo que te vayas guardando las funciones (ya comprobadas) que hagan cosas especiales, importantes o simplemente repetitivas, luego será copiar y pegar, funcionando a la primera.

Los punteros en C son muy potentes y también muy jodi..os, sobre todo cuando te equivocas y no sabes porque...

Dedalo
11/06/2010, 11:00
Antes de empezar ningun programa te tienes que empollar la hoja de caracteristicas del display, y segun vayas leyendo te daras cuenta de la forma mas facil de meterle los datos. Si es de color, probablemente tenga por cada punto una zona de memoria de 1, 2 ó 3 bytes para colocar en ella el color de ese pixel. Tambien puede ser que sea como los TFT, es decir, que en realidad esta compuesto de lineas y puntos como si fuese monocromo, pero luego en las lineas pares, los puntos pares son rojos y los impares verdes y en las lineas impares los puntos se alternan verdas y azules. Todo depende de la arquitectura del display.

Mira el codigo de esa centralita (Aun sin terminar)


$MOD51
$TITLE(FRONTAL)
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Puertos
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LCD_D EQU P0 ; Datos display LCD
LCD_ILUM BIT P2.3 ; Alimentacion display LCD
LCD_WR BIT P2.4 ; señal RW display LCD
LCD_RD BIT P2.5 ; señal RD display LCD
LCD_CE BIT P2.6 ; señal CE display LCD
LCD_RS BIT P2.7 ; señal RS display LCD
I2C_SDA BIT P2.0 ; Datos bus I2C
I2C_SCL BIT P2.1 ; Reloj bus I2C
BAT0 BIT P1.0
BAT1 BIT P1.1
BAT2 BIT P1.2
ANEGRAS BIT P1.3
CNEGRAS BIT P1.4
AGRISES BIT P1.5
LIBRE BIT P1.6
RLCONV BIT P1.7
KL0 BIT P0.0
KL1 BIT P0.1
KL2 BIT P0.2
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; RAM
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BTECLAS DATA 20h
BOPTOA DATA 21h
BOPTOB DATA 22h
BANDERAS DATA 23h
I2C_Flags DATA 24h ;Banderas I2C.
BAux1 DATA 25h
BAux2 DATA 26h
BMotor DATA 27h
TECLA_1I BIT BTECLAS.7
TECLA_2I BIT BTECLAS.6
TECLA_3I BIT BTECLAS.5
TECLA_1D BIT BTECLAS.4
TECLA_2D BIT BTECLAS.3
TECLA_3D BIT BTECLAS.2
CHG_V BIT BOPTOA.7
CHG_A BIT BOPTOA.6
CNV_ERR BIT BOPTOA.5
CNV_ON BIT BOPTOA.4
OPTO_5 BIT BOPTOA.3
OPTO_6 BIT BOPTOA.2
OPTO_7 BIT BOPTOB.7
OPTO_8 BIT BOPTOB.6
OPTO_9 BIT BOPTOB.5
OPTO_A BIT BOPTOB.4
OPTO_B BIT BOPTOB.3
OPTO_C BIT BOPTOB.2
T_VAR BIT BANDERAS.0
O_VAR BIT BANDERAS.1
CONV_ON BIT BANDERAS.2

I2C_Ack BIT I2C_Flags.0 ;ACK I2C.
I2C_Err BIT I2C_Flags.1 ;Error bus I2C.
I2C_Busy BIT I2C_Flags.2 ;Bus I2C ocupado.
TapagadoL DATA 30h
TapagadoH DATA 31h
I2C_BitCnt DATA 33h ;Contador de bits I2C
I2C_SlvAdr DATA 34h ;Direccion de chip I2C
GRAlto DATA 35h
GRBajo DATA 36h
Nivel_Aux1 DATA 37h
Nivel_Aux2 DATA 38h
Nivel_Motor DATA 39h
Nivel_Limpia DATA 3Ah
Nivel_Gris DATA 3Bh
Nivel_Negra DATA 3Ch
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Constantes
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CTE_TEMPH EQU HIGH(-2000) ; Constante para 1 mS
CTE_TEMPL EQU LOW(-2000)
EEPROM EQU 0A4h ; Direccion I2C de la memoria
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; REGISTROS
; R0=POINTER
; R1=POINTER EN IRQ
; R2=CMD 2 LCD
; R3=CMD 1 LCD
; R4=
; R5=
; R6=CONTADOR generico
; R7=CONTADOR IRQ
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Vectores
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ORG 0000h
SJMP INICIO
ORG 000Bh
LJMP T0_ISR
ORG 00023h
LJMP UART_ISR
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Inicio del procesador
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ORG 0030h
INICIO:
CLR EA ; Deshabilitamos Interrupciones
MOV R6,#60h ; Primero limpiamos la RAM
MOV R0,#20h
LIMPIA_RAM:
MOV @R0,#0
INC R0
DJNZ R6,LIMPIA_RAM
INICIO1:
MOV TapagadoH,#60 ; Tiempo de apagado 15 Segundos
MOV TMOD,#01h ; T0 en modo 1 y T1 en modo 2
SETB TF0 ; Fuerza IRQ T0
MOV IP,#02h ; Fija la prioridad para la IRQ de T0
MOV IE,#82h ; Habilita IRQ UART, IRQ T0 e IRQ General
CALL LCD_INIT ; Iniciamos LCD
MOV GRAlto,#00h
MOV GRBajo,#00h
CALL LCD_GRAFICO
CALL SEGUNDO
CALL SEGUNDO
CALL SEGUNDO
CALL SEGUNDO
CALL SEGUNDO
CALL LCD_BORRAR
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Ajustar valores iniciales
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MOV BAux1,#00h
MOV BAux2,#00h
MOV BMotor,#00h
CLR CONV_ON
MOV NIVEL_Aux1,#0A7h
MOV NIVEL_Aux2,#0A3h
MOV NIVEL_Motor,#0B2h
MOV Nivel_Limpia,#50h
MOV Nivel_Gris,#50h
MOV Nivel_Negra,#50h
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Menu principal
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MENU0:
CALL LCD_BORRARTXT
MOV GRAlto,#0Ah
MOV GRBajo,#00h
CALL LCD_GRAFICO

JB CONV_ON,MENU0_C
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MOV R2,#20h ; TEST
MOV R3,#00h
MOV DPTR,#TXT_NO
CALL LCD_TEXTO
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MOV R2,#01h
MOV R3,#00h
CALL LCD_POSICION
MOV A,#82h
CALL LCD_BYTE
MOV A,#83h
CALL LCD_BYTE
MOV R2,#01h
MOV R3,#01h
CALL LCD_POSICION
MOV A,#92h
CALL LCD_BYTE
MOV A,#93h
CALL LCD_BYTE
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
JMP MENU0_D ; TEST
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MENU0_C:
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MOV R2,#20h ; TEST
MOV R3,#00h
MOV DPTR,#TXT_OK
CALL LCD_TEXTO
MENU0_D:
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CLR T_VAR
MENU0_1:
JNB T_VAR,MENU0_1
CLR T_VAR
JB Tecla_1I,O_T220V
JB Tecla_2I,O_CARGAB
JB Tecla_3I,O_NIVELB
JB Tecla_2D,O_VACIAR
JB Tecla_3D,O_NIVELA
SJMP MENU0_1

O_T220V:
JNB Tecla_1D,O_T220V1
JMP TEST
O_T220V1:
CALL T220V
JMP MENU0
O_CARGAB:
CALL CARGAB
JMP MENU0
O_NIVELB:
CALL NIVELB
JMP MENU0
O_VACIAR:
CALL VACIAR
JMP MENU0
O_NIVELA:
CALL NIVELA
JMP MENU0
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Tratamiento tecla 220V
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
T220V:
CPL CONV_ON
JB CONV_ON,T220V1
SETB RLCONV
SJMP T220V2
T220V1:
CLR RLCONV
T220V2:
JB Tecla_1I,T220V2
RET
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Menu carga de baterias
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CARGAB:
CALL LCD_BORRARTXT
MOV GRAlto,#14h
MOV GRBajo,#00h
CALL LCD_GRAFICO
MOV DPTR,#TXT_C_Placa
JB BAux1.0,CARGAB_1
MOV DPTR,#TXT_C_ALT
JB BAux1.1,CARGAB_1
MOV DPTR,#TXT_C_220
JB BAux1.2,CARGAB_1
MOV DPTR,#TXT_C_Auto
CARGAB_1:
JB BAux1.3,CARGAB_2
MOV R2,#02h
MOV R3,#02h
CALL LCD_TEXTO
CARGAB_2:
MOV DPTR,#TXT_C_Placa
JB BAux2.0,CARGAB_3
MOV DPTR,#TXT_C_ALT
JB BAux2.1,CARGAB_3
MOV DPTR,#TXT_C_220
JB BAux2.2,CARGAB_3
MOV DPTR,#TXT_C_Auto
CARGAB_3:
JB BAux2.3,CARGAB_4
MOV R2,#02h
MOV R3,#05h
CALL LCD_TEXTO
CARGAB_4:
MOV DPTR,#TXT_C_Placa
JB BMotor.0,CARGAB_5
MOV DPTR,#TXT_C_ALT
JB BMotor.1,CARGAB_5
MOV DPTR,#TXT_C_220
JB BMotor.2,CARGAB_5
MOV DPTR,#TXT_C_Auto
CARGAB_5:
JB BMotor.3,CARGAB_6
MOV R2,#22h
MOV R3,#04h
CALL LCD_TEXTO
CARGAB_6:
CLR T_VAR
CARGAB_7:
JNB T_VAR,CARGAB_7
CLR T_VAR
JB Tecla_1I,CARGA_AUX1
JB Tecla_2I,CARGA_AUX
JB Tecla_3I,CARGA_AUX2
JB Tecla_2D,CARGA_Motor
JNB Tecla_1D,CARGAB_7
RET
CARGA_AUX1:
JNB BAux1.0,CARGA_AUX1_1 ; Estamos a Placa
MOV BAux1,#02h ; Pasamos a Alt
JMP CARGAB
CARGA_AUX1_1:
JNB BAux1.1,CARGA_AUX1_2 ; Estamos en Alt
MOV BAux1,#04h ; Pasamos a 220
CLR BAux2.2
CLR BMotor.2
JMP CARGAB
CARGA_AUX1_2:
JNB BAux1.2,CARGA_AUX1_3 ; Estamos en 220
MOV BAux1,#08h ; Pasamos a No
JMP CARGAB
CARGA_AUX1_3:
JNB BAux1.3,CARGA_AUX1_4 ; Estamos en No
MOV BAux1,#00h ; Pasamos a Auto
JMP CARGAB
CARGA_AUX1_4:
MOV BAux1,#01h ; Pasamos a Placa
CLR BAux2.0
CLR BMotor.0
JMP CARGAB
CARGA_AUX:
JNB BAux1.3,CARGA_AUX_1 ; Estamos en No
MOV BAux1,#00h ; Pasamos a Auto
MOV BAux2,#00h ; Pasamos a Auto
JMP CARGAB
CARGA_AUX_1:
MOV BAux1,#08h ; Pasamos a No
MOV BAux2,#08h ; Pasamos a No
JMP CARGAB
CARGA_AUX2:
JNB BAux2.0,CARGA_AUX2_1 ; Estamos a Placa
MOV BAux2,#02h ; Pasamos a Alt
JMP CARGAB
CARGA_AUX2_1:
JNB BAux2.1,CARGA_AUX2_2 ; Estamos en Alt
MOV BAux2,#04h ; Pasamos a 220
CLR BAux1.2
CLR BMotor.2
JMP CARGAB
CARGA_AUX2_2:
JNB BAux2.2,CARGA_AUX2_3 ; Estamos en 220
MOV BAux2,#08h ; Pasamos a No
JMP CARGAB
CARGA_AUX2_3:
JNB BAux2.3,CARGA_AUX2_4 ; Estamos en No
MOV BAux2,#00h ; Pasamos a Auto
JMP CARGAB
CARGA_AUX2_4:
MOV BAux2,#01h ; Pasamos a Placa
CLR BAux1.0
CLR BMotor.0
JMP CARGAB

CARGA_Motor:
JNB BMotor.0,CARGA_Motor_1 ; Estamos a Placa
MOV BMotor,#02h ; Pasamos a Alt
JMP CARGAB
CARGA_Motor_1:
JNB BMotor.1,CARGA_Motor_2 ; Estamos en Alt
MOV BMotor,#04h ; Pasamos a 220
CLR BAux2.2
CLR BAUX1.2
JMP CARGAB
CARGA_Motor_2:
JNB BMotor.2,CARGA_Motor_3 ; Estamos en 220
MOV BMotor,#08h ; Pasamos a No
JMP CARGAB
CARGA_Motor_3:
JNB BMotor.3,CARGA_Motor_4 ; Estamos en No
MOV BMotor,#00h ; Pasamos a Auto
JMP CARGAB
CARGA_Motor_4:
MOV BMotor,#01h ; Pasamos a Placa
CLR BAux2.0
CLR BAUX1.0
JMP CARGAB
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Niveles de las baterias
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
NIVELB:
CALL LCD_BORRARTXT
MOV GRAlto,#14h
MOV GRBajo,#00h
CALL LCD_GRAFICO
MOV R2,#01h
MOV R3,#02h
CALL LCD_POSICION
MOV A,NIVEL_Aux1
CALL NivelB_OUT
MOV R2,#01h
MOV R3,#05h
CALL LCD_POSICION
MOV A,NIVEL_Aux2
CALL NivelB_OUT
MOV R2,#22h
MOV R3,#04h
CALL LCD_POSICION
MOV A,NIVEL_Motor
CALL NivelB_OUT
CALL SEGUNDO
CLR T_VAR
NIVELB_1:
JNB T_VAR,NIVELB_1
CLR T_VAR
JNB Tecla_1D,NIVELB_1
RET
NIVELB_OUT:
PUSH ACC
JNB ACC.7,NIVELB_OUT_1 ; El bit 7 del valor es el "1" inicial
MOV A,#'1'
CALL LCD_CHAR
POP ACC
CLR ACC.7 ; Si estaba puesto lo eliminamos del valor
SJMP NIVELB_OUT_2 ; y el resto son los digitos restantes
NIVELB_OUT_1:
MOV A,#'0'
CALL LCD_CHAR
POP ACC
ADD A,#020h ; Si no añadimos 2 al nybble alto
NIVELB_OUT_2:
PUSH ACC
SWAP A
ANL A,#0Fh
ADD A,#'0'
CALL LCD_CHAR
MOV A,#','
CALL LCD_CHAR
POP ACC
ANL A,#0Fh
ADD A,#'0'
CALL LCD_CHAR
MOV A,#' '
CALL LCD_CHAR
MOV A,#'V'
JMP LCD_CHAR
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Menu 4
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
VACIAR:
CALL LCD_BORRARTXT
MOV GRAlto,#1Eh
MOV GRBajo,#00h
CALL LCD_GRAFICO
JB AGRISES,VACIAR_1
MOV DPTR,#TXT_ABIERTO
MOV R2,#20h
MOV R3,#03h
CALL LCD_TEXTO
VACIAR_1:

JB Tecla_2I,ABRE_NEGRAS
JB Tecla_3I,CIERRA_NEGRAS
JB Tecla_2D,ABRE_GRISES
JB Tecla_3D,CIERRA_GRISES
JNB Tecla_1D,VACIAR_1
RET
ABRE_NEGRAS:
CALL LCD_BORRARTXT
MOV DPTR,#TXT_ABRIENDO
MOV R2,#00h
MOV R3,#03h
CALL LCD_TEXTO
SETB CNEGRAS
CLR ANEGRAS
ABRE_NEGRAS_1:
JB Tecla_2I,ABRE_NEGRAS_1
SETB ANEGRAS
JMP VACIAR
CIERRA_NEGRAS:
CALL LCD_BORRARTXT
MOV DPTR,#TXT_CERRANDO
MOV R2,#00h
MOV R3,#07h
CALL LCD_TEXTO
SETB ANEGRAS
CLR CNEGRAS
CIERRA_NEGRAS_1:
JB Tecla_3I,CIERRA_NEGRAS_1
SETB CNEGRAS
JMP VACIAR
ABRE_GRISES:
CLR AGRISES
CLR RLCONV
CLR T_VAR
ABRE_GRISES_1:
JNB T_VAR,ABRE_GRISES_1
JMP VACIAR
CIERRA_GRISES:
SETB AGRISES
JB CONV_ON,CIERRA_GRISES_1
SETB RLCONV
SJMP CIERRA_GRISES_2
CIERRA_GRISES_1:
CLR RLCONV
CIERRA_GRISES_2:
CLR T_VAR
CIERRA_GRISES_3:
JNB T_VAR,CIERRA_GRISES_3
JMP VACIAR
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Menu 6
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
NIVELA:
CALL LCD_BORRARTXT
MOV GRAlto,#28h
MOV GRBajo,#00h
CALL LCD_GRAFICO

MOV R2,#03h
MOV R3,#03h
CALL LCD_POSICION
MOV A,NIVEL_Limpia
CALL NivelA_OUT
MOV R2,#10h
MOV R3,#03h
CALL LCD_POSICION
MOV A,NIVEL_Gris
CALL NivelA_OUT
MOV R2,#1Bh
MOV R3,#03h
CALL LCD_POSICION
MOV A,NIVEL_Negra
CALL NivelA_OUT

CALL SEGUNDO
CLR T_VAR
NIVELA_1:
JNB T_VAR,NIVELA_1
CLR T_VAR
JNB Tecla_1D,NIVELA_1
RET
NIVELA_OUT:
PUSH ACC
SWAP A
ANL A,#0Fh
ADD A,#'0'
CALL LCD_CHAR
POP ACC
ANL A,#0Fh
ADD A,#'0'
CALL LCD_CHAR
MOV A,#' '
CALL LCD_CHAR
MOV A,#'%'
JMP LCD_CHAR
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Rutinas lectura niveles
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

NIV_DECO:
JB ACC.3,NIV_DECO1 ; No esta lleno, saltamos 0xxx (0000)
XRL A,#99h
RET ; Esta lleno, salimos 99%=ok 92..98= error sensor
NIV_DECO1:
JB ACC.2,NIV_DECO2 ; No esta al 75%, saltamos 10xx (1000)
XRL A,#7Dh
RET ; Esta al 75%=ok 74,77,76= error sensor
NIV_DECO2:
JB ACC.1,NIV_DECO3 ; No esta al 50%, saltamos 110x (1100)
XRL A,#5Ch
RET ; Esta al 50%=ok 51=error sensor
NIV_DECO3:
JB ACC.0,NIV_DECO4 ; No esta al 25%, saltamos 1110
MOV A,#25h
RET
NIV_DECO4: ; Esta vacio 1111
MOV A,#00h
RET

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Rutinas LCD
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LCD_INIT:
CLR LCD_ILUM ; Iluminacion LCD
MOV R2,#00h
MOV R3,#00h
MOV A,#40h ; Inicio RAM texto
CALL LCD_TXCMD
MOV R2,#00h
MOV R3,#02h
MOV A,#42h ; Inicio RAM Graficos
CALL LCD_TXCMD
MOV R2,#28h
MOV R3,#00h
MOV A,#41h ; Anchura texto
CALL LCD_TXCMD
MOV R2,#28h
MOV R3,#00h
MOV A,#43h ; Anchura graficos
CALL LCD_TXCMD

MOV R2,#03h
MOV R3,#03h
MOV A,#22h ; RAM Caracteres de usuario
CALL LCD_TXCMD ; 0001 1Hxx xxxx xlll
CALL LCD_CARGAUDG
MOV A,#80h ; Modo
CALL LCD_TXC
MOV A,#9Ch ; Display
CALL LCD_TXC
MOV R2,#00h
MOV R3,#00h
MOV A,#21h ; Cursor en 0,0
CALL LCD_TXCMD
LCD_BORRARTXT:
MOV R2,#00h
MOV R3,#00h
MOV A,#24h ; Pointer en 0000h
CALL LCD_TXCMD
MOV A,#0B0h ; Inicio datos
CALL LCD_TXC
MOV R2,#00h ; Contador para 512 bytes
MOV R3,#02h
SJMP LCD_BORRAR1
LCD_BORRAR:
MOV R2,#00h
MOV R3,#00h
MOV A,#24h ; Pointer en 0000h
CALL LCD_TXCMD
MOV A,#0B0h ; Inicio datos
CALL LCD_TXC
MOV R2,#00h ; Contador para 8 Kbytes
MOV R3,#20h
LCD_BORRAR1:
MOV A,#00h
CALL LCD_TXD
DJNZ R2,LCD_BORRAR1 ; Repetimos hasta el final
DJNZ R3,LCD_BORRAR1
MOV A,#0B2h
SJMP LCD_TXC ; Fin de datos
LCD_LIBRE:
PUSH ACC
LCD_LIBRE1:
SETB LCD_RS ; Leemos Status
CLR LCD_CE
CLR LCD_RD
MOV A,LCD_D
SETB LCD_RD
SETB LCD_CE
JNB ACC.0,LCD_LIBRE1 ; Si no esta listo esperamos
JNB ACC.1,LCD_LIBRE1 ; Si no esta listo esperamos
POP ACC
RET
LCD_TXD:
CALL LCD_LIBRE
CLR LCD_RS ; Modo de datos
MOV LCD_D,A ; Dato al puerto
CLR LCD_CE
CLR LCD_WR
SETB LCD_WR
SETB LCD_CE
MOV LCD_D,#0FFh ; Reponemos puerto
RET
LCD_CHAR:
CLR CY
SUBB A,#20h
LCD_BYTE:
CALL LCD_TXD
MOV A,#0C0h
SJMP LCD_TXC
LCD_POSICION:
MOV A,R3 ; Valor Y
RL A
RL A
RL A ; Multiplicado x 8
XCH A,R2
ADD A,R2 ; Se suma al valor X
XCH A,R2
RL A
RL A ; Multiplicado por 20h
XCH A,R2
ADD A,R2 ; Se suma al valor X
MOV R2,A
CLR A
ADDC A,#00h
MOV R3,A
MOV A,#24h
LCD_TXCMD:
PUSH ACC
MOV A,R2
CALL LCD_TXD
MOV A,R3
CALL LCD_TXD
POP ACC
LCD_TXC:
CALL LCD_LIBRE
MOV LCD_D,A ; Comando al puerto
CLR LCD_CE
CLR LCD_WR
SETB LCD_WR
SETB LCD_CE
MOV LCD_D,#0FFh ; Reponemos puerto
RET
LCD_TEXTO:
CALL LCD_POSICION
MOV A,#0B0h ; Inicio datos
CALL LCD_TXC
LCD_TEXTO1:
CLR A
MOVC A,@A+DPTR
JZ LCD_TEXTO2
CLR CY
SUBB A,#20h
CALL LCD_TXD
INC DPTR
SJMP LCD_TEXTO1
LCD_TEXTO2:
MOV A,#0B2h
JMP LCD_TXC ; Fin de datos
LCD_GRAFICO:
MOV R2,#00h
MOV R3,#02h
MOV A,#24h ; Pointer en 0200
CALL LCD_TXCMD
MOV A,#0B0h ; Inicio datos
CALL LCD_TXC
MOV A,#EEPROM ; Direccion de escritura en EEPROM
CALL I2C_CALL ; Llama al periferico
JNB I2C_ACK,LCD_ERR ; Si error salimos
MOV A,GRAlto
CALL I2C_TX ; Se envia direccion alta
JNB I2C_ACK,LCD_ERR ; Si error salimos
MOV A,GRBajo
CALL I2C_TX ; Se envia direccion baja
JNB I2C_ACK,LCD_ERR ; Si error salimos
CALL I2C_START ; Empezamos la lectura
MOV A,#EEPROM ; Direccion de escritura en EEPROM
SETB ACC.0 ; ya es lectura
CALL I2C_CALL ; Llama al periferico
MOV R6,#00h ; COntador para 0780h bytes
MOV R5,#0Ah
LCD_CARGA_RAM:
CLR I2C_ACK ; Ponemos ACK
CALL I2C_RX ; Traemos un byte
CALL LCD_TXD ; y lo enviamos al LCD
DJNZ R6,LCD_CARGA_RAM
DJNZ R5,LCD_CARGA_RAM ; Repetimos hasta terminar
SETB I2C_ACK ; Borramos ACK (ultimo byte)
CALL I2C_RX ; Traemos el ultimo byte
MOV A,#0B2h
JMP LCD_TXC ; Fin de datos

LCD_ERR:
CALL I2C_STOP ; Cierra bus
CALL LCD_BORRAR ; Mensaje de error
MOV R2,#10h
MOV R3,#04h
MOV DPTR,#TXT_NoEEPROM
CALL LCD_TEXTO
JMP SEGUNDO
LCD_CARGAUDG:
MOV R2,#00h
MOV R3,#1Ch
MOV A,#24h ; Pointer en 1C00
CALL LCD_TXCMD
MOV A,#0B0h ; Inicio datos
CALL LCD_TXC
MOV A,#EEPROM ; Direccion de escritura en EEPROM
CALL I2C_CALL ; Llama al periferico
JNB I2C_ACK,LCD_ERR ; Si error salimos
MOV A,# 7Ch
CALL I2C_TX ; Se envia direccion alta
JNB I2C_ACK,LCD_ERR ; Si error salimos
CLR A
CALL I2C_TX ; Se envia direccion baja
JNB I2C_ACK,LCD_ERR ; Si error salimos
CALL I2C_START ; Empezamos la lectura
MOV A,#EEPROM ; Direccion de escritura en EEPROM
SETB ACC.0 ; ya es lectura
CALL I2C_CALL ; Llama al periferico
MOV R6,#00h ; COntador para 0400h bytes
MOV R5,#04h
JMP LCD_CARGA_RAM ; Terminamos la carga en RAM
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Utiles I2C
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Pone SCL Alto y espera SCL libre
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I2C_SCLH:
SETB I2C_SCL ; Pone SCL alto
JNB I2C_SCL,$ ; Espera SCL alto
RET
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; I2C_START Inicia una transferencia
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I2C_START:
CLR I2C_ERR ; Borramos el estado de error
SETB I2C_SDA ; Liberamos SDA y SCL
CALL I2C_SCLH
JNB I2C_SCL,I2C_FAULT ; Comprobamos bus libre
JNB I2C_SDA,I2C_FAULT ; Comprobamos bus libre
CLR I2C_SDA ; Iniciamos un START
; CALL I2C_BITDLY
CLR I2C_SCL
; CALL I2C_BITDLY
RET
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; I2C_FAULT pone la bandera de error
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I2C_FAULT:
SETB I2C_ERR ; Señalamos error de bus
RET ; y salimos
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; I2C_CALL llama a un periferico
; ACC = Direccion
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I2C_CALL:
SETB I2C_ACK ; Ponemos ACK
CLR I2C_ERR ; Borramos el estado de error
CALL I2C_START
JNB I2C_ERR,I2C_TX
RET
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; I2C_TX envia un byte por el bus
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I2C_TX:
MOV I2C_BitCnt,#08h ; 8 bits
I2C_TX1:
RLC A ; bit en CY
MOV I2C_SDA,C ; bit en SDA
CALL I2C_SCLH ; Pulso en CLK
; CALL I2C_BITDLY
CLR I2C_SCL
; CALL I2C_BITDLY
DJNZ I2C_BitCnt,I2C_TX1 ; Repite hasta 8 bits
SETB I2C_SDA ; Liberamos SDA
CALL I2C_SCLH
; CALL I2C_BITDLY
JNB I2C_SDA,I2C_TX2 ; Verifica ACK
CLR I2C_ACK ; Ajusta bandera ACK
I2C_TX2:
CLR I2C_SCL ; Finaliza ACK
; CALL I2C_BITDLY
RET
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; I2C_RX recibe un byte del bus
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I2C_RX:
SETB I2C_SDA ; Liberamos SDA
MOV I2C_BitCnt,#08h ; 8 bits
I2C_RX1:
CALL I2C_SCLH
; CALL I2C_BITDLY
MOV C,I2C_SDA ; Tomamos un bit
RLC A ; Al acumulador
CLR I2C_SCL ; Bajamos SCL
; CALL I2C_BITDLY
DJNZ I2C_BitCnt,I2C_RX1 ; Repetimos para 8 bits
JNB I2C_ACK,I2C_RX2
SETB I2C_SDA ; Si es ultimo enviamos NACK
SJMP I2C_RX3
I2C_RX2:
CLR I2C_SDA ; Si no es ultimo enviamos ACK
I2C_RX3:
CALL I2C_SCLH
; CALL I2C_BITDLY
CLR I2C_SCL
SETB I2C_SDA
; CALL I2C_BITDLY
RET
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; I2C_BITDLY Retardo de bit. (No usado a esta frecuencia)
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I2C_BITDLY:
; NOP
; RET
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; I2C_STOP Termina bus I2C
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I2C_STOP:
CLR I2C_SDA ; SDA bajo
CALL I2C_SCLH ; SCL alto
; CALL I2C_BITDLY
SETB I2C_SDA ; SDA alto (stop).
; CALL I2C_BITDLY
RET
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Rutinas de tiempo
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SEGUNDO:
MOV R6,#10
SJMP DECIMA1
DECIMA:
MOV R6,#1
DECIMA1:
; JNB T_VAR,DECIMA2
; RET
DECIMA2:
MOV R7,#100
DECIMA3:
MOV A,R7
JNZ DECIMA3
DJNZ R6,DECIMA1
RET
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Rutina de servicio UART
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
UART_ISR:
PUSH PSW
PUSH ACC
SJMP FIN_IRQ
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Rutina de servicio de Timer1
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Reactivar el timer
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
T0_ISR:
CLR TR0 ; Timer 0 apagado
MOV TH0,#CTE_TEMPH ; Cargamos timer 0
MOV TL0,#CTE_TEMPL ; Para 1 ms de espera
SETB TR0 ; Activamos de nuevo Timer 0
PUSH PSW ; Salvamos el contexto
PUSH ACC
;==============================================================================;
; Buscar variaciones en las teclas
;==============================================================================;
MOV A,P0
PUSH ACC
LEE_TECLA:
MOV P0,#0FFh
MOV P3,#0FFh
CLR KL0
SETB KL1
SETB KL2
MOV A,P3 ; Leemos fila de teclas
CPL A ; Logica positiva
ANL A,#0FCh ; Aislamos bits utiles
XCH A,BTECLAS ; Salvamos estado teclas
XRL A,BTECLAS ; Comparamos con estado anterior
JZ LEE_TECLA1
MOV TapagadoH,#60 ; Reponemos tiempo de apagado
CLR LCD_ILUM ; Iluminamos el LCD
SETB T_VAR ; Señalamos tecla alterada
LEE_TECLA1:
SETB KL0
CLR KL1
MOV A,P3 ; Leemos fila de teclas
CPL A ; Logica positiva
ANL A,#0FCh ; Aislamos bits utiles
XCH A,BOPTOA ; Salvamos estado teclas
XRL A,BOPTOA ; Comparamos con estado anterior
JZ LEE_TECLA2
SETB O_VAR ; Señalamos tecla alterada
LEE_TECLA2:
SETB KL1
CLR KL2
MOV A,P3 ; Leemos fila de teclas
CPL A ; Logica positiva
ANL A,#0FCh ; Aislamos bits utiles
XCH A,BOPTOB ; Salvamos estado teclas
XRL A,BOPTOB ; Comparamos con estado anterior
JZ LEE_TECLA3
SETB O_VAR ; Señalamos tecla alterada
LEE_TECLA3:
POP ACC
MOV P0,A
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Contadores de tiempo
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TIEMPOS:
DEC R7 ; Contador de mS
DJNZ TapagadoL,FIN_IRQ
MOV TapagadoL,#250
TIEMPOS1:
DJNZ TapagadoH,FIN_IRQ ; Contador para el apagado.
SETB LCD_ILUM ; Cortamos la alimentacion
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Restauramos contexto y volvemos
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
FIN_IRQ:
POP ACC
POP PSW
RETI
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Constantes en memoria
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TXT_ABRIENDO:
DB 'Abriendo',0
TXT_CERRANDO:
DB 'Cerrando',0
TXT_ABIERTO:
DB 'Abierto',0
TXT_CERRADO:
DB 'Cerrado',0
TXT_OK:
DB 'OK',0
TXT_NO:
DB 'No',0
TXT_C_Auto:
DB 'Auto',0
TXT_C_Placa:
DB 'Placa',0
TXT_C_220:
DB '220V',0
TXT_C_ALT:
DB 'Alter.',0
TXT_TEST:
DB 'Test',0
TXT_TECLA:
DB 'Tecla',0
TXT_OPTO:
DB 'Opto',0
TXT_NOEEPROM:
DB 'EEPROM no responde',0

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Test (solo durante programacion
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TEST:
CALL LCD_BORRAR
TEST0:
CALL DECIMA
CALL LCD_BORRARTXT
MOV DPTR,#TXT_TEST
MOV R2,#12h
MOV R3,#00h
CALL LCD_TEXTO
JNB Tecla_1I,TEST_1
MOV DPTR,#TXT_TECLA
MOV R2,#00h
MOV R3,#02h
CALL LCD_TEXTO
MOV A,#' '
CALL LCD_CHAR
MOV A,#'1'
CALL LCD_CHAR
TEST_1:
JNB Tecla_2I,TEST_2
MOV DPTR,#TXT_TECLA
MOV R2,#00h
MOV R3,#03h
CALL LCD_TEXTO
MOV A,#' '
CALL LCD_CHAR
MOV A,#'2'
CALL LCD_CHAR
TEST_2:
JNB Tecla_3I,TEST_3
MOV DPTR,#TXT_TECLA
MOV R2,#00h
MOV R3,#04h
CALL LCD_TEXTO
MOV A,#' '
CALL LCD_CHAR
MOV A,#'3'
CALL LCD_CHAR
TEST_3:
JNB Tecla_1D,TEST_4
MOV DPTR,#TXT_TECLA
MOV R2,#00h
MOV R3,#05h
CALL LCD_TEXTO
MOV A,#' '
CALL LCD_CHAR
MOV A,#'4'
CALL LCD_CHAR
TEST_4:
JNB Tecla_2D,TEST_5
MOV DPTR,#TXT_TECLA
MOV R2,#00h
MOV R3,#06h
CALL LCD_TEXTO
MOV A,#' '
CALL LCD_CHAR
MOV A,#'5'
CALL LCD_CHAR
TEST_5:
JNB Tecla_3D,TEST_6
MOV DPTR,#TXT_TECLA
MOV R2,#00h
MOV R3,#07h
CALL LCD_TEXTO
MOV A,#' '
CALL LCD_CHAR
MOV A,#'6'
CALL LCD_CHAR
TEST_6:
JNB CHG_V,TEST_7
MOV DPTR,#TXT_OPTO
MOV R2,#10h
MOV R3,#02h
CALL LCD_TEXTO
MOV A,#' '
CALL LCD_CHAR
MOV A,#'1'
CALL LCD_CHAR
TEST_7:
JNB CHG_A,TEST_8
MOV DPTR,#TXT_OPTO
MOV R2,#10h
MOV R3,#03h
CALL LCD_TEXTO
MOV A,#' '
CALL LCD_CHAR
MOV A,#'2'
CALL LCD_CHAR
TEST_8:
JNB CNV_ERR,TEST_9
MOV DPTR,#TXT_OPTO
MOV R2,#10h
MOV R3,#04h
CALL LCD_TEXTO
MOV A,#' '
CALL LCD_CHAR
MOV A,#'3'
CALL LCD_CHAR
TEST_9:
JNB CNV_ON,TEST_10
MOV DPTR,#TXT_OPTO
MOV R2,#10h
MOV R3,#05h
CALL LCD_TEXTO
MOV A,#' '
CALL LCD_CHAR
MOV A,#'4'
CALL LCD_CHAR
TEST_10:
JNB Opto_5,TEST_11
MOV DPTR,#TXT_OPTO
MOV R2,#10h
MOV R3,#06h
CALL LCD_TEXTO
MOV A,#' '
CALL LCD_CHAR
MOV A,#'5'
CALL LCD_CHAR
TEST_11:
JNB Opto_6,TEST_12
MOV DPTR,#TXT_OPTO
MOV R2,#10h
MOV R3,#07h
CALL LCD_TEXTO
MOV A,#' '
CALL LCD_CHAR
MOV A,#'6'
CALL LCD_CHAR
TEST_12:
JNB Opto_7,TEST_13
MOV DPTR,#TXT_OPTO
MOV R2,#20h
MOV R3,#02h
CALL LCD_TEXTO
MOV A,#' '
CALL LCD_CHAR
MOV A,#'7'
CALL LCD_CHAR
TEST_13:
JNB Opto_8,TEST_14
MOV DPTR,#TXT_OPTO
MOV R2,#20h
MOV R3,#03h
CALL LCD_TEXTO
MOV A,#' '
CALL LCD_CHAR
MOV A,#'8'
CALL LCD_CHAR
TEST_14:
JNB Opto_9,TEST_15
MOV DPTR,#TXT_OPTO
MOV R2,#20h
MOV R3,#04h
CALL LCD_TEXTO
MOV A,#' '
CALL LCD_CHAR
MOV A,#'9'
CALL LCD_CHAR
TEST_15:
JNB Opto_A,TEST_16
MOV DPTR,#TXT_OPTO
MOV R2,#20h
MOV R3,#05h
CALL LCD_TEXTO
MOV A,#' '
CALL LCD_CHAR
MOV A,#'A'
CALL LCD_CHAR
TEST_16:
JNB Opto_B,TEST_17
MOV DPTR,#TXT_OPTO
MOV R2,#20h
MOV R3,#06h
CALL LCD_TEXTO
MOV A,#' '
CALL LCD_CHAR
MOV A,#'B'
CALL LCD_CHAR
TEST_17:
JNB Opto_C,TEST_18
MOV DPTR,#TXT_OPTO
MOV R2,#20h
MOV R3,#07h
CALL LCD_TEXTO
MOV A,#' '
CALL LCD_CHAR
MOV A,#'C'
CALL LCD_CHAR
TEST_18:


JMP TEST0
END

navegante 420
14/06/2010, 23:49
Joerrrrr pedazo código...... hasta la hora el más largo que he visto..... aunque creo que te lo superaré con lo de scalextric, jejejejejeje

Muchas gracias por la info, ahora me pongo a analizarlo y sacar conclusiones y ideas.