2ª Parte
----------
'--------------------------------------Main Programa-----------------------------------------------
main:
If s1 = 1 And s1_on = 1 And s2 = 1 And s2_on = 1 And flag_1 = 0 Then '________modo ajuste
flag_1 = 1 'activa la rutina de ajustes
dato = 0 'selecciono registro del RTC
pause = 200
Gosub pause_ms 'hace una pausa del valor que tenga pause en ms
s1_on = 0 'desbloquea la tecla S1
s2_on = 0 'desbloquea la tecla s2
Endif '___________________
If flag_1 = 1 Then Gosub ajuste_reloj '__________saltamos a la rutina de ajuste
If timer3_100ms >= timer3_100ms_tiempo Then 'actualiza datos en el lcd cada 100ms
Gosub lee_hora 'lee la fecha y hora del reloj
Gosub print_lcd 'actualiza los datos del reloj en el display
timer3_100ms = 0
Endif '__________________
If timer2_100ms >= timer2_100ms_tiempo Then
Gosub lee_adc 'salto con retorno, rutina de lectura de la entrada ADC
Gosub temp_calculo 'salto con retorno, hace el calculo de la temperatura y guarda el valor en temperatura
Gosub media_arit 'salto con retorno, calcula la media aritmetica
division = dvsion_dcmles(temperatura, factor_escala) 'llama a la funcion dvsion_dcmles, que retorna un long
Gosub print_rs232_temperatura
Gosub print_rs232_date
timer2_100ms = 0
Endif
Goto main
End
'--------------------------------------FIN DEL MAIN---------------------------------------------
'**************************************Subrrutinas**********************************************
inicaliza_rtc: '-------------------------inicializa el reloj----------------------------------------------------
PIE1.TMR1IE = 0 'deshabilita las interrupciones del timer1
I2CRead sda, scl, 0xd0, 0, reg(0) 'leo los segundos
reg(0) = reg(0) And %01111111 'habilito bit de control que activa el reloj
I2CWrite sda, scl, 0xd0, 0, reg(0) 'escribo el registro de los segundos
I2CRead sda, scl, 0xd0, 1, reg(0) 'leo el registro de los minutos
reg(0) = reg(0) And %10111111 'habilito bit de control que activa el formato de 24h
I2CWrite sda, scl, 0xd0, 0, reg(0) 'escribo el registro de los minutos
'-------------------------------inicializa la salida del RTC-------------------------------
If s1 = 0 Then I2CWrite sda, scl, 0xd0, 7, 0x10 'salida a 1hz, a on
If s2 = 0 Then I2CWrite sda, scl, 0xd0, 7, 0x80 'salida a off, led off
PIE1.TMR1IE = 1 'habilita las interrupciones del timer1
pause = 1000
Gosub pause_ms 'espera el tiempo indicado en pause
Return
ajuste_reloj: 'rutina de ajuste del reloj
'________________________Control posicion del dato a variar en el reloj
If s1 = 1 And s1_on = 1 And s2_on = 0 Then 'detecta tecla S1
dato = dato + 1 'seleciona el dato a ser modificado
If dato > 6 Then flag_1 = 0 'indica fin de rutina de ajuste
s1_on = 0 'la tecla queda desbloqueada
Endif '_____________________________
'____________Lectura de la hora para su modificacion y posterior grabacion, rutina BCD
If s2 = 1 And s2_on = 1 And s1_on = 0 Then 'deteca tecla S2
s2_on = 0 'la tecla queda desbloqueada
If dato < 7 Then 'limita la direcciones de trabajo del reloj
Gosub lee_hora 'lee los datos de los regis. RTC y los pasa a decimal, elimina los bit de control
aux_ajuste = reg(dato) 'hace una imagen del valor del registro a modificar
aux_ajuste = aux_ajuste + 1 'incrementa el dato a modificar que fue seleccionado
If dato = 2 And aux_ajuste > 23 Then aux_ajuste = 0 'acota horas
If dato = 0 Or dato = 1 Then 'acota segundos y minutos
If aux_ajuste > 59 Then aux_ajuste = 0
Endif
If dato = 3 And aux_ajuste > 7 Then aux_ajuste = 1 'acota el dia de la semana
If dato = 4 And aux_ajuste > 31 Then aux_ajuste = 1 'acota el dia del mes
If dato = 5 And aux_ajuste > 12 Then aux_ajuste = 1 'acota el mes
If dato = 6 And aux_ajuste > 30 Then aux_ajuste = 1 'acota el año, año maximo 2030
If aux_ajuste > 49 And aux_ajuste < 60 Then 'Decimal a BCD
aux_ajuste = aux_ajuste - 50
aux_ajuste.4 = 1
aux_ajuste.6 = 1
Endif
If aux_ajuste > 39 And aux_ajuste < 50 Then 'Decimal a BCD
aux_ajuste = aux_ajuste - 40
aux_ajuste.6 = 1
Endif
If aux_ajuste > 29 And aux_ajuste < 40 Then 'Decimal a BCD
aux_ajuste = aux_ajuste - 30
aux_ajuste.4 = 1
aux_ajuste.5 = 1
Endif
If aux_ajuste > 19 And aux_ajuste < 30 Then 'Decimal a BCD
aux_ajuste = aux_ajuste - 20
aux_ajuste.5 = 1
Endif
If aux_ajuste > 9 And aux_ajuste < 20 Then 'Decimal a BCD
aux_ajuste = aux_ajuste - 10
aux_ajuste.4 = 1
Endif
If aux_ajuste < 10 Then aux_ajuste = aux_ajuste 'Decimal a BCD
If dato = 0 Then aux_ajuste.7 = 0 'restaura el bit de configracion, activa el oscilador del reloj
If dato = 2 Then aux_ajuste.7 = 0 'restaura el bit, no lo utiliza el RTC
If dato = 2 Then aux_ajuste.6 = 0 'restaura el bit de configuracion, reloj 24h
PIE1.TMR1IE = 0 'deshabilita las interrupciones del timer1
I2CWrite sda, scl, 0xd0, dato, aux_ajuste 'actualiza el dato ya modificado
PIE1.TMR1IE = 1 'activa las interrupciones del timer1
Endif
Endif '____________
'__________Controla el parpadeo de los digitos cuando el modo selec es activo
If timer2_ms >= timer2_ms_tiempo Then 'tiempo del parpadeo
If flash_1 = 1 Then 'selecciona si el dato a modificar es visible o no
flash_1 = 0 'dato es visible
Else
flash_1 = 1 'dato no es visible
Endif
timer2_ms = 0 'recarga la base de tiempos
Endif '______________
Return
lee_hora: 'lee la hora del RTC en formato BCD y la pasa a decimal
i = 0 'variable indice, asigna los datos de forma ordenada, leidos del RTC
While i <= 6 'se repite el codigo comprendido entre while y wend, mientras i sea menor o igual a 6
PIE1.TMR1IE = 0 'deshabilita las interrupciones del timer1
I2CRead sda, scl, 0xd0, i, reg(i) 'lectura de la direccion de memoria indicada del RTC, formato BCD
PIE1.TMR1IE = 1 'activa las interrupciones del timer1
aux_4l = reg(i) And %00001111 'eliminamos los bit de configuracion del RTC y dejamos solo el nibble bajo
If i = 0 Then aux_4h = reg(i) And %01110000 'segundos, borrado de bit configuracion y almacena nibble alto
If i = 1 Then aux_4h = reg(i) And %01110000 'minutos, almacena nibble alto
If i = 2 Then aux_4h = reg(i) And %00110000 'horas, borrado de bit configuracion y almacena nibble alto
If i = 3 Then aux_4h = reg(i) And %00000000 'dia_semana, almacena nibble alto
If i = 4 Then aux_4h = reg(i) And %00110000 'dia_mes, almacena nibble alto
If i = 5 Then aux_4h = reg(i) And %00010000 'mes, almacena el nibble alto
If i = 6 Then aux_4h = reg(i) And %11110000 'año, almacena el nibble alto
aux_4h = ShiftRight(aux_4h, 4) 'convierte el nibble alto en bajo
reg(i) = (aux_4h * 10) + aux_4l 'fusiona los nibbles alto y bajo en una sola variable en formato decimal
i = i + 1 'incrementa la variable indice con cada repeticion del bucle While/Wend
Wend 'fin del bucle y salta a While
Return
print_lcd: 'rutina de escritura en el lcd
Lcdcmdout LcdLine1Home 'cursor del lcd a la izquierda en la linea 1
If dato = 2 And flash_1 = 1 Then 'control final del parpadeo de los digitos de la hora
Lcdout " " 'borra el dato determinado para dar la sencacion de parpadeo
Else
If reg(2) < 10 Then Lcdout "0" 'si horas es inferior a 10 escribe el cero delante
Lcdout #reg(2) 'escribe la hora
Endif
Lcdout ":" 'escribe el separador
If dato = 1 And flash_1 = 1 Then 'control final del parpadeo de los digitos de los minutos
Lcdout " " 'borra el dato determinado para dar la sencacion de parpadeo
Else
If reg(1) < 10 Then Lcdout "0" 'si minutos es inferior a 10 escribe el cero delante
Lcdout #reg(1) 'escribe los minutos
Endif
Lcdout ":" 'escribe el separador
If dato = 0 And flash_1 = 1 Then 'control final del parpadeo de los digitos de los segundos
Lcdout " " 'borra el dato determinado para dar la sencacion de parpadeo
Else
If reg(0) < 10 Then Lcdout "0" 'si segundos es inferior a 10 escribe el cero delante
Lcdout #reg(0) 'escribe los segundos
Endif
Gosub print_lcd_temp 'salto con retorno a la rutina de impresion de la temperatura
Lcdcmdout LcdLine2Home 'cursor del lcd a la izquierda en la linea 2
If dato = 3 And flash_1 = 1 Then 'control final del parpadeo de los digitos del dia semana
Lcdout " " 'borra el dato determinado para dar la sencacion de parpadeo
Else
If reg(3) = 1 Then Lcdout "Dom." 'asigna el literal al dia de la semana
If reg(3) = 2 Then Lcdout "Lun."
If reg(3) = 3 Then Lcdout "Mar."
If reg(3) = 4 Then Lcdout "Mie."
If reg(3) = 5 Then Lcdout "Jue."
If reg(3) = 6 Then Lcdout "Vie."
If reg(3) = 7 Then Lcdout "Sab."
Endif
Lcdout " " 'escribe separador
If dato = 4 And flash_1 = 1 Then 'control final del parpadeo de los digitos del dia del mes
Lcdout " " 'borra el dato determinado para dar la sencacion de parpadeo
Else
If reg(4) < 10 Then Lcdout "0" 'si dia del mes es inferior a 10 escribe cero
Lcdout #reg(4) 'escribe el dia del mes
Endif
Lcdout "/" 'escribe el separador
If dato = 5 And flash_1 = 1 Then 'control final del parpadeo de los digitos de los meses
Lcdout " " 'borra el dato determinado para dar la sencacion de parpadeo
Else
If reg(5) < 10 Then Lcdout "0" 'si mes es inferior a 10 escribe cero
Lcdout #reg(5) 'escribe el mes
Endif
Lcdout "/20" 'separador y los dos primeros digitos del año de 4 digitos
If dato = 6 And flash_1 = 1 Then 'control final del parpadeo de los digitos de los años
Lcdout " " 'borra el dato determinado para dar la sencacion de parpadeo
Else
If reg(6) < 10 Then Lcdout "0" 'si año es inferior a 10 escribe primero el cero
Lcdout #reg(6) 'escribe el año
Endif
Return
'--------------------------------------Subrrutina lectura ADC, division y LCD
lee_adc: '_______________________lee la entrada analogica
Adcin 4, adc_4 'lee el valor de la entrada analogica y lo guarda en adc_4
Return
print_lcd_temp: '____________________muestra los datos por el display
entero = division.HW 'sede el word alto a entero, parte entera
decimal = division.LW 'sede el byte alto del word bajo a decimal_1
Lcdout " " 'espacio en blanco
If signo = 0 Then Lcdout "+", #entero, "." 'muestra los datos en el lcd
If signo = 1 Then Lcdout "-", #entero, "." 'muestra los datos en el lcd
Lcdout #decimal, "C " 'muestra los datos en el lcd
Return
'________Argumentos de entrada dos variables tipo word, dividendo y divisor, argumento de salida una variable tipo long
Function dvsion_dcmles(dvdo As Word, dvsor As Word) As Long '________Rutina funcion division con decimales
Dim f_entera As Word 'variable local, contendra la parte entera
Dim f_resto As Word 'varable local, contendra el resto
Dim f_decimal As Word 'contendra la parte decimal
f_entera = dvdo / dvsor 'obtengo la division
f_resto = dvdo Mod dvsor 'obtengo el resto
f_decimal = (f_resto * 10) / dvsor 'calculo 1 decimal, para obtener 2 decimales multiplicar por 100
dvsion_dcmles.HW = f_entera 'almacena la parte entera en el word alto
dvsion_dcmles.LW = f_decimal 'almacena la parte decimal word bajo
'Recuerda que la parte decimal tiene que ser mostrada en el display con plantilla de dos digitos siempre
End Function
'___________Calculo de la media aritmetica de la temperatura, 20 muestras
media_arit:
media_temp(media_indice) = temperatura 'asigna el valor
temperatura = 0 'se inicaliza a cero
For aux_media = 0 To 19 'blucle for, se ejecuta 20 veces
temperatura = temperatura + media_temp(aux_media) 'se suman los valores
Next aux_media 'cierra for
temperatura = temperatura / 20 'termina el calculo de la media
media_indice = media_indice + 1 'controla la entrada de datos que corresponde a media_temp(x)
If media_indice > 19 Then media_indice = 0 'acota el ultimo valor del indice de media_temp
Return
'___________Calculo de la temperatura
temp_calculo: 'calculo de la temperatura y del signo de la misma
If adc_4 > 112 Then 'determina si la temperatura es superior a 0ºC
aux_adc_4 = adc_4 'asigna el valor del ra4 a la variable auxiliar
aux_adc_4 = aux_adc_4 - 112 'elimina de la temperatura la parte de la escala negativa
temp = (5000 * aux_adc_4) / 1023 'calcuala el valor de la temperatura sin coma decimal
signo = 0 'temperatura positiva
Endif
If adc_4 = 112 Then 'determina si la temperatura es 0ºC
temp = 0 'temperatura 0ºC
signo = 0 'asigna signo positivo
Endif
If adc_4 < 112 Then 'determina si la temperatura es inferior a 0ºC
aux_adc_4 = adc_4 'asigna el valor del RA4 a la variable auxiliar
aux_adc_4 = 112 - aux_adc_4 'elimina de la temperatura la parte de la escala negativa
temp = (5000 * aux_adc_4) / 1023 'calcuala el valor de la temperatura sin coma decimal
signo = 1 'asigna el simbolo menos a la temperatura
Endif
temperatura = temp 'se pasa de Long a Word
Return
inicializa_temp: '__________inicializa la media aritmetica de la temperatura en el arranque
Gosub lee_adc 'salto con retorno, rutina de lectura de la entrada ADC
Gosub temp_calculo 'salto con retorno, hace el calculo de la temperatura y guarda el valor en temperatura
For media_indice = 0 To 19 'indice para rocorrer todas las direcciones de memoria que forman la variable tipo array media_temp
media_temp(media_indice) = temperatura 'se de el valor a media_temp
Next media_indice 'terminacion del bucle For
media_indice = 0 'se inicializa a cero, para un uso posterior
Gosub media_arit 'salto con retorno, calcula la media aritmetica
division = dvsion_dcmles(temperatura, factor_escala) 'llama a la funcion dvsion_dcmles, que retorna un long
Return
print_rs232_temperatura: 'Envia la temperatura con decimales al puerto serie
PIE1.TMR1IE = 0 'OFF, interrupciones del timer1
Serout PORTB.5, 4800, "TEMPERATURA: " 'pagina en blanco y literal al purto serie
If signo = 0 Then Serout PORTB.5, 4800, "+" 'muestra el signo de la temperatura
If signo = 1 Then Serout PORTB.5, 4800, "-" 'muestra el signo de la temperatura
Serout PORTB.5, 4800, #entero, ".", #decimal, " " 'temperatura al rs232
PIE1.TMR1IE = 1 'ON, interrupciones del timer1
Return
print_rs232_date: 'rutina de escritura de la hora y fecha por el RS232
PIE1.TMR1IE = 0 'OFF, interrupciones del timer1
If reg(2) < 10 Then Serout PORTB.5, 4800, " 0" 'si horas es inferior a 10 escribe el cero delante
Serout PORTB.5, 4800, #reg(2), ":" 'escribe la hora
If reg(1) < 10 Then Serout PORTB.5, 4800, "0" 'si minutos es inferior a 10 escribe el cero delante
Serout PORTB.5, 4800, #reg(1), ":" 'escribe los minutos
If reg(0) < 10 Then Serout PORTB.5, 4800, "0" 'si segundos es inferior a 10 escribe el cero delante
Serout PORTB.5, 4800, #reg(0), " " 'escribe los segundos
If reg(3) = 1 Then Serout PORTB.5, 4800, "Dom." 'asigna el literal al dia de la semana
If reg(3) = 2 Then Serout PORTB.5, 4800, "Lun."
If reg(3) = 3 Then Serout PORTB.5, 4800, "Mar."
If reg(3) = 4 Then Serout PORTB.5, 4800, "Mie."
If reg(3) = 5 Then Serout PORTB.5, 4800, "Jue."
If reg(3) = 6 Then Serout PORTB.5, 4800, "Vie."
If reg(3) = 7 Then Serout PORTB.5, 4800, "Sab."
If reg(4) < 10 Then Serout PORTB.5, 4800, " 0" 'si dia del mes es inferior a 10 escribe cero
Serout PORTB.5, 4800, #reg(4), "/" 'escribe el dia del mes
If reg(5) < 10 Then Serout PORTB.5, 4800, "0" 'si mes es inferior a 10 escribe cero
Serout PORTB.5, 4800, #reg(5), "/20" 'escribe el mes
If reg(6) < 10 Then Serout PORTB.5, 4800, "0" 'si año es inferior a 10 escribe primero el cero
Serout PORTB.5, 4800, #reg(6), CrLf 'escribe el año
PIE1.TMR1IE = 1 'ON, interrupciones del timer1
Return
pause_ms: 'rutina de espera, rutina tipo Waitms, pause establese el tiempo total en mSeg
pause = 1 'ESTA LINEA SOLO SE ACTIVA CUANDO SE UTILIZA EL SIMULADOR
PIE1.TMR1IE = 0 'OFF, interrupciones del timer1
timer_1ms_tiempo = pause 'valor a temporizar por timer_1ms
PIE1.TMR1IE = 1 'ON, interrupciones del timer1
timer_1ms = 0 'al borrar el contador se activa y comienza la cuenta de 1mSeg
While timer_1ms < pause 'tiempo en mSeg maximos a contar
Wend
Return
'***********************************Interrupciones*****************************************************
On Interrupt 'Comienzan las rutinas de las interrupciones, desactiva las interrupciones
TMR1H = 0xf8 'recarga el contador del timer1 para que desborde pasado 1mSeg, byte alto
TMR1L = 0x30 'recarga el contador del timer1 para que desborde pasado 1mSeg, byte bajo
Save System 'Guarda los valores del sistema para poder reemprender el curso normal del programa
If PIR1.TMR1IF = 1 Then 'comprueba que la interrupcion del timer1 es activa
'_________________bases de tiempos
timer_base = timer_base + 1 'contador general
If timer_1ms < timer_1ms_tiempo Then timer_1ms = timer_1ms + 1 'contador para control de la rutina Pause
If timer1_ms < timer1_ms_tiempo Then timer1_ms = timer1_ms + 1 'contador
If timer2_ms < timer2_ms_tiempo Then timer2_ms = timer2_ms + 1 'contador
If timer3_ms < timer3_ms_tiempo Then timer3_ms = timer3_ms + 1 'contador
If timer_base >= timer_base_tiempo Then 'limita el timepo de ejecucion, cada timer_base_tiempo
If timer1_100ms < timer1_100ms_tiempo Then timer1_100ms = timer1_100ms + 1 'contador
If timer2_100ms < timer2_100ms_tiempo Then timer2_100ms = timer2_100ms + 1 'condtador
If timer3_100ms < timer3_100ms_tiempo Then timer3_100ms = timer3_100ms + 1 'contador
timer_base = 0 'reset a la base de tiempos
Endif '________________fin bases de tiempos
PIR1.TMR1IF = 0 'borra el flag de salto del tmr1
Endif
'_________________Detecta tecla pulsada
If s1 = 0 And s1_on = 0 And timer1_ms >= timer1_ms_tiempo Then 'tecla S1
s1_on = 1 'la tecla fue pulsada
s2_on = 0 'la tecla s2 a pff
If s1 = 0 And s2 = 0 Then s2_on = 1 'S2
timer1_ms = 0 'tiempo entre pulsacion y pulsacion
Endif
If s2 = 0 And s2_on = 0 And timer3_ms >= timer3_ms_tiempo Then 'tecla s2
s2_on = 1 'la tecla fue pulsada
s1_on = 0 'la tecla s1 a off
If s1 = 0 And s2 = 0 Then s1_on = 1 'S1
timer3_ms = 0 'tiempo entre pulsacion y pulsacion
Endif
If s1 = 0 Then led_verde = 0 'mestra el estado de S1
If s2 = 0 Then led_amarillo = 0 'muestra el estado de S2
If s1 = 1 Then led_verde = 1 'mestra el estado de S1
If s2 = 1 Then led_amarillo = 1 'muestra el estado de S2
'________Fin detecta tecla pulsada
Resume 'activa las interrupciones y retorna el curso normal del programa, antes del salto
PD: 03/06/08
%1101000x (direccion de seleccion del chip %1101000) siendo "x" el bit indicador de Write/Read. Modificado por I2CWrite y I2CRead.