'Voy a usar 4 pines para controlar el LCD
Define LCD_BITS = 4
'por medio del port B
Define LCD_DREG = PORTB
'Las lineas 4,5,6,y 7..
Define LCD_DBIT = 4
'El bit RS en port A bit 0
Define LCD_RSREG = PORTA
Define LCD_RSBIT = 0
'El bit E en port A bit 1
Define LCD_EREG = PORTA
Define LCD_EBIT = 1
'El bit RW en port A bit2
Define LCD_RWREG = PORTA
Define LCD_RWBIT = 2
'Demora despues de un LCDCMDOUT (10000)
Define LCD_COMMANDUS = 10000
'Demora despues de un LCDOUT (100)
Define LCD_DATAUS = 100
'Demora de arranque (LCDINIT) (1000)
Define LCD_INITMS = 1000
Dim s As Byte
Dim m As Byte
Dim h As Byte
Dim alarma As Word
alarma = 1 'Alarma activada.
s = 0 'Segundos
m = 0 'Minutos
h = 0 'Horas
Lcdinit 'Iinitializa LCD; sin cursor
'Defino caracter campanita
Lcddefchar 0, %00100, %01110, %01110, %01110, %11111, %11111, %00100, %00000
Lcdout "EL RELOCITO v3.0" 'linea 1
loop:
Lcdcmdout LcdLine2Clear 'Borra la linea 2
Lcdcmdout LcdLine2Home 'Comienzo linea 2
If h < 10 Then Lcdout "0"
Lcdout #h, ":"
If m < 10 Then Lcdout "0"
Lcdout #m, ":"
If s < 10 Then Lcdout "0"
Lcdout #s, " "
If alarma = 1 Then Lcdout 0
WaitMs 1000 '1 seg.
s = s + 1
If s > 59 Then
s = 0
m = m + 1
Endif
If m > 59 Then
m = 0
h = h + 1
Endif
If h > 23 Then
h = 0
Endif
Goto loop 'Repite eternamente
Hola aitopes, me quedo una duda con tu ultimo mensaje
Dijiste que pensabas utilizar el pic 16F818A u 16F819A, pero busque ese PIC y no lo encontre por ningún lado, ni en la pag de microchip aparece la dataste.
Saludos
'NOMBRE: 16F88_PicEBasic_LCD_01
'MICRO: PIC16F88, 8Mhz reloj interno, PSI v7.41, By COS
'Uso del LCD con bus de datos a 4Bit y sin pin de RW
'************************************************************************************************
Define CONF_WORD = 0x2f10 'Configuración de bits (fuses)
Define CONF_WORD_2 = 0x3ffc 'Configuración de bits (fuses)
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj a 8 Mhz
Define SIMULATION_WAITMS_VALUE = 1 'Suprime los tiempos de espera Waitms, solo activar esta linea en simulacion
'-------------------------------------Puertos del LCD---------------------------------------------
Define LCD_BITS = 4 'indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'el bus de datos sera el puerto A
Define LCD_DBIT = 0 'el bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'el bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'se usara el RB7 como RS
Define LCD_EREG = PORTB 'el bit de control E sera del puerto B
Define LCD_EBIT = 6 'se usara el RB6 como E
'Define LCD_RWREG = PORTA 'el bit de control RW sera del puerto A (si se suprime el compilador no protesta)
'Define LCD_RWBIT = 5 'se usara el RA5 como RW (si se suprime el compilador no protesta)
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comand del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 5 '(50) 'Tiempo de espera despues de inicializar el Display, solo se ejecuta una vez en mSeg., trucado para simulacion
'------------------------------------Definicion de puertos------------------------------------------
ANSEL = 0x00 'los pin I/O digitales (no analogicos)
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
CMCON = 0x07 'comparador a off
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
'------------------------------------Inicio------------------------------------------------------------
Lcdinit 'inicializa el lcd sin cursor
WaitMs 500 'pausa para estabilizar
main: 'comienza el programa principal
Lcdcmdout LcdClear 'borra el display
WaitMs 1000 'hace una pausa de 1Seg.
Lcdout "HOLA MUNDO" 'escribe en el display
WaitMs 1000 'hace una pausa de 1Seg.
Goto main 'impide que termine el programa principal
End
'***************** Placa Entrenadora ***************************************
'NOMBRE: 16F88_PicEBasic_02
'MICRO: PIC16F88, 8Mhz reloj interno, PSI v7.41, By COS
'Uso del LCD con bus de datos a 4Bit y sin pin de RW
'Activacion del Timer1 por rebose cada 1mSeg.
'implementacion de timer (bases de tiempos)por soft
'cambio de estado del RA7 de forma cíclica (led intermitente)
'***********************************************************************
Define CONFIG = 0x2f50 'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc 'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 8 'Clock en Mhz
Define SIMULATION_WAITMS_VALUE = 1 'Activar para simulación
'-------------------------------------Puertos del LCD---------------------------------------------
Define LCD_BITS = 4 'indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'el bus de datos sera el puerto A
Define LCD_DBIT = 0 'el bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'el bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'se usara el RB7 como RS
Define LCD_EREG = PORTB 'el bit de control E sera del puerto B
Define LCD_EBIT = 6 'se usara el RB6 como E
'Define LCD_RWREG = PORTA 'el bit de control RW sera del puerto A (si se suprime el compilador no protesta)
'Define LCD_RWBIT = 5 'se usara el RA5 como RW (si se suprime el compilador no protesta)
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comand del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera despues de inicializar el Display, solo se ejecuta una vez en mSeg.
'------------------------------------Definicion de puertos------------------------------------------
ANSEL = 0x00 'Los pin I/O digitales (no analogicos)
OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz
CMCON = 0x07 'Comparador a off
TRISA = 0x00 'Puerto A como salidas
TRISA.5 = 1 'Como entrada, no permite ser usada como salida digital
TRISB = 0x00 'Puerto B como salidas
PORTB.3 = 1 'luz lcd a on (RB3)
'------------------------------------Inicialización de Interrupciones-----------------------------
T1CON.TMR1CS = 0 'asigna el reloj interno al timer1, se incrementa cada ciclo de instruccion
T1CON.T1CKPS0 = 0 'factor del preescales del timer1, 0
T1CON.T1CKPS1 = 0 'factor del preescales del timer1, 0
TMR1H = 0xf8 'carga el registro del contador para que desborde cada 1mSeg, byte alto
TMR1L = 0x30 'carga el registro del contador para que desborde cada 1mSeg, byte bajo
T1CON.TMR1ON = 1 'habilitacion del TMR1, comienza a incrementarse
PIE1.TMR1IE = 1 'activa las interrupciones del timer1
INTCON.PEIE = 1 'bit de habilitacion de interrupciones de perifericos
'Inicializa el LCD ----------------------------------------------------------------------------------
Lcdinit 'inicializa el lcd sin cursor
'Variables de los timer****************************************
Dim timer_base As Byte 'tiempo referencia para los timer por soft del programa
Dim timer_base_tiempo As Byte 'contiene el valor del tiempo del timer_base
Dim timer1_ms As Word 'base de tiempos en ms
Dim timer2_ms As Word 'base de tiempos en ms
Dim timer3_ms As Word 'base de tiempos en ms
Dim timer1_100ms As Byte 'base de tiempos msx100
Dim timer2_100ms As Byte 'base de tiempos msx100
Dim timer3_100ms As Byte 'base de tiempos msx100
Dim timer1_ms_tiempo As Word 'contiene el valor del tiempo del timer1_ms
Dim timer2_ms_tiempo As Word 'contiene el valor del tiempo del timer2_ms
Dim timer3_ms_tiempo As Word 'contiene el valor del tiempo del timer3_ms
Dim timer1_100ms_tiempo As Byte 'contiene el valor del tiempo del timer1_100ms
Dim timer2_100ms_tiempo As Byte 'contiene el valor del tiempo del timer2_100ms
Dim timer3_100ms_tiempo As Byte 'contiene el valor del tiempo del timer3_100ms
'Asignacion de valores a las variables--------------------------
timer_base = 0
timer1_ms = 0
timer2_ms = 0
timer3_ms = 0
timer1_100ms = 0
timer2_100ms = 0
timer3_100ms = 0
timer_base_tiempo = 100 'cuenta 100mSeg
timer1_ms_tiempo = 500 'cuenta 500 mSeg.
timer2_ms_tiempo = 500
timer3_ms_tiempo = 5
timer1_100ms_tiempo = 1 'cuenta 0.1 Seg.
timer2_100ms_tiempo = 1
timer3_100ms_tiempo = 1
'------------------------------------------------------------------------------
Enable 'INTCON.GIE habilita todas las interrupciones globales
WaitMs 500 'pausa para estabilizar
timer1_ms_tiempo = 2 '500
timer2_ms_tiempo = 3 '250
Dim flag As Bit
'------------------------------------rutinas del Programa----------------------
main: 'comienza el programa principal
If timer1_ms >= timer1_ms_tiempo Then 'refresco el display cada timer1_ms_tiempo
Toggle flag
Lcdcmdout LcdClear 'borra el display
If flag = 0 Then Lcdout "HOLA MUNDO" 'escribe el caracter "A" en el display
timer1_ms = 0 'reinicio el timer1_ms
Endif
If timer2_ms >= timer2_ms_tiempo Then 'cambio de estado el pin RA7 cada timer2_ms_tiempo
Toggle RA7
timer2_ms = 0 'reinicio el timer2_ms
Endif
Goto main 'impide que termine el programa principal
End
'--------------------------------Interrupciones---------------------------------------------------
On Interrupt 'Comienzan las rutinas de las interrupciones, desactiva las interrupciones
Save System 'Guarda los valores del sistema para poder reemprender el curso normal del programa
If PIR1.TMR1IF = 1 Then 'Comprueba que la interrupción del timer1 es activa
'Bases de tiempos
timer_base = timer_base + 1
If timer1_ms < timer1_ms_tiempo Then timer1_ms = timer1_ms + 1
If timer2_ms < timer2_ms_tiempo Then timer2_ms = timer2_ms + 1
If timer3_ms < timer3_ms_tiempo Then timer3_ms = timer3_ms + 1
If timer_base >= timer_base_tiempo Then
If timer1_100ms < timer1_100ms_tiempo Then timer1_100ms = timer1_100ms + 1
If timer2_100ms < timer2_100ms_tiempo Then timer2_100ms = timer2_100ms + 1
If timer3_100ms < timer3_100ms_tiempo Then timer3_100ms = timer3_100ms + 1
timer_base = 0
Endif
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
PIR1.TMR1IF = 0 'Borra el flag de salto del tmr1
Endif
Resume 'Activa las interrupciones y retorna al curso normal del programa antes del salto
todo correcto a la primera... :-)
'********************************** PIC Entrenadora BASIC (PicEBasic)**************************
'NOMBRE: 16F88_LCD_ADC_Decimales_01
'VERSION: 1.0
'MICRO: PIC16f88A
'FECHA/AUTOR: 12/06 - By COS, PSI v7.41
'DESCRIPCION:
'Muestra en el display el valor de la entrada analogica con dos decimales y en voltios
'*****************************************************************************************
Define CONFIG = 0x2f50 'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc 'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 8 'Clock en Mhz
Define SIMULATION_WAITMS_VALUE = 1 'Activar para simulación
'-------------------------------------Puertos del LCD-----------------------------------------------
Define LCD_BITS = 4 'indicamos que el bus de datos del lcd será de 4bit
Define LCD_DREG = PORTA 'el bus de datos será el puerto A
Define LCD_DBIT = 0 'el bus de datos serán los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'el bit de control RS será del puerto B
Define LCD_RSBIT = 7 'se usara el RB7 como RS
Define LCD_EREG = PORTB 'el bit de control E será del puerto B
Define LCD_EBIT = 6 'se usara el RB6 como E
'Define LCD_RWREG = PORTx 'el bit de control RW será del puerto x(no se usa)
'Define LCD_RWBIT = n 'se usara el Rxn como RW (no se usa)
Define LCD_COMMANDUS = 2000 'Tiempo de espera después de ejecutar un comand del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera después de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera después de inicializar el Display, solo se ejecuta una vez en mSeg.
'**************************************DEFINICION DE PUERTOS*****************************
'----------------------ASIGNACION DE I/O y valores de inicio de las salidas---------------------
ANSEL = %00010000 'Los pin I/O digitales y RA4 analógico
Define ADC_SAMPLEUS = 10 'Configuración del ADC
Define ADC_CLOCK = 5 '16Tad a 8Mhz = 2uSeg, mínimo permitido por el micro 1.5uSeg, configuración ADC
'_______________registros afectados por Define ADC_CLOCK y ADCIN________________
'ANSEL = %00010000 'los pin I/O digitales y RA4 analógico
'ADCON0 = %01100000 'Fosc/16 a 8Mhz (ADCON1.ADCS2=1) =2uSeg (mínimo 1.uSeg), channel RA4
'ADCON1 = %01000000 'voltage reference (AVdd/AVss) y selección de escala división clock/2 ADCON1.ADCS2=1
'_______________________________________________________________________________
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
TRISA.4 = 1 'como entrada (RA4, adc)
TRISA.6 = 1 'como entrada (RA6, tecla S1)
TRISA.5 = 1 'como entrada (RA5, tecla S2)
PORTB.3 = 1 'luz lcd a on (RB3)
PORTA.7 = 1 'led amarillo a off
PORTB.0 = 1 'led verde a off
Lcdinit 'inicializa el lcd sin cursor
'Variables del ADC y Rutina división------------------------------
Dim num_1 As Word 'valor del adc y retorna la parte entera
Dim num_2 As Word 'factor de la escala y retorna el primer decimal
Dim num_3 As Word 'segundo decimal
Dim dvdo As Word 'dividendo operación
Dim dvsor As Word 'divisor operación
'-------------------------------------------------------------------
WaitMs 1000 'espera 1Seg
Lcdout "16f88_LCD_ADC" 'escribe en el lcd
Lcdcmdout LcdLine2Home 'selecciona la línea dos como próxima para escritura
Lcdout "Pruebas con ADC" 'escribe en el lcd
WaitMs 3000 'espera 3Seg
'--------------------------------------Main Programa-----------------------------------------------
main:
Gosub lee_adc 'salto con retorno, rutina de lectura de la entrada ADC
Gosub division_dos_decimales 'salto con retorno, rutina de conversión de valor adc a voltios
Gosub print_lcd 'salto con retorno, rutina que imprime los valores en el lcd
WaitMs 100 'hace una pausa de 100mSeg
Goto main
End
'--------------------------------------FIN DEL MAIN---------------------------------------------
'**************************************Subrutinas**********************************************
'--------------------------------------Subrutina lectura ADC, división y LCD
lee_adc: '_______________________lee la entrada analógica
Dim aux As Long
Adcin 4, num_1 'lee el valor de la entrada analógica y lo carga en num_1
aux = (500 * num_1) / 1023 'Pasa a formato de parte entera con dos decimales integrados
num_1 = aux
Return
division_dos_decimales: '________Rutina división con dos decimales
Dim resto As Word
dvdo = num_1 'asigna dividendo
dvsor = 100 'asigna divisor (dos decimales)
num_1 = dvdo / dvsor
resto = dvdo Mod dvsor
'Si resto es 0 se asignan valores
If resto = 0 Then
num_2 = 0
num_3 = 0
Endif
If resto = 0 Then Return 'Se sale de la subrutina
'Primer decimal
num_2 = resto * 10
num_2 = num_2 / dvsor
'Segundo decimal
num_3 = resto - (num_2 * 10)
Return
print_lcd: '____________________Muestra los datos por el display
Lcdcmdout LcdLine1Home 'Primera línea y cursor al principio
Lcdout "ENTR. ADC ", #num_1, ".", #num_2, #num_3, "V" 'Muestra los datos en el lcd
Lcdcmdout LcdLine2Home 'Segunda línea y cursor al principio
Lcdout "Lectura Pin RA4" 'muestra los datos en el lcd
Return
'********************************** PIC Entrenadora BASIC (PicEBasic)******************************
'NOMBRE: 16F88_LCD_I/O_01
'VERSION: 1.0
'MICRO: PIC16f88A
'FECHA/AUTOR: 12/06 - By COS, PSI v7.41
'DESCRIPCION: MUESTRA EN EL DISPLAY EL ESTADO DE LA TECLA ACTIVANDO EL LED ASOCIADO
'***************************************************************************************************
Define CONFIG = 0x2f50 'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc 'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 8 'Clock en Mhz
Define SIMULATION_WAITMS_VALUE = 1 'Activar para simulación
'-------------------------------------Puertos del LCD-----------------------------------------------
Define LCD_BITS = 4 'indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'el bus de datos sera el puerto A
Define LCD_DBIT = 0 'el bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'el bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'se usara el RB7 como RS
Define LCD_EREG = PORTB 'el bit de control E sera del puerto B
Define LCD_EBIT = 6 'se usara el RB6 como E
'Define LCD_RWREG = PORTx 'el bit de control RW sera del puerto x(no se usa)
'Define LCD_RWBIT = n 'se usara el Rxn como RW (no se usa)
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comand del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera despues de inicializar el Display, solo se ejecuta una vez en mSeg.
'**************************************DEFINICION DE PUERTOS*************************************
'----------------------ASIGNACION DE I/O y valores de inicio de las salidas---------------------
ANSEL = %00000000 'los pin I/O digitales
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
TRISA.4 = 1 'como entrada (RA4, adc)
TRISA.6 = 1 'como entrada (RA6, tecla S1)
TRISA.5 = 1 'como entrada (RA5, tecla S2)
PORTB.3 = 1 'luz lcd a on (RB3)
PORTA.7 = 1 'led amarillo a off
PORTB.0 = 1 'led verde a off
Lcdinit 'inicializa el lcd sin cursor
'***********************************DEFINICION DE VARIABLES**************************************
'--------------------------------------Variables Programa----------------------------------------
Dim tecla_s1 As Byte 'guarda el estado de la tecla hasta terminar la maniobra
Dim tecla_s2 As Byte 'guarda el estado de la tecla hasta terminar la maniobra
'------------------------------------------ASIGNACIONES------------------------------------------
tecla_s1 = 0
tecla_s2 = 0
WaitMs 1000 'espera 1Seg
Lcdout "16f88_LCD_I/O" 'escribe en el lcd
Lcdcmdout LcdLine2Home 'seleciona la linea dos como proxima para escritura
Lcdout "Pruebas con I/O" 'escribe en el lcd
WaitMs 3000 'espera 3Seg
'--------------------------------------Main Programa-----------------------------------------------
main:
If RA6 = 0 Then tecla_s1 = 1 'lee el estado de la tecla S1
If RA5 = 0 Then tecla_s2 = 1 'lee el estado de la tecla S2
Gosub print_lcd 'salto con retorno, rutina que imprime los valores en el lcd
WaitMs 100
If tecla_s1 = 1 Then 'si la tecla S1 fue pulsada
Toggle RA7 'invierte el estado de RA7, led amarillo
tecla_s1 = 0 'tecla queda en reposo
Endif
If tecla_s2 = 1 Then 'si la tecla S2 fue pulsada
Toggle RB0 'Invierte el estado de RB0, led verde
tecla_s2 = 0 'tecla queda en reposo
Endif
WaitMs 100 'hace una pausa de 100mSeg
Goto main
End
'--------------------------------------FIN DEL MAIN---------------------------------------------
'**************************************Subrrutinas**********************************************
print_lcd: '____________________Muestra los datos por el display
Lcdcmdout LcdLine1Home 'Primera linea y cursor al principio
Lcdout " S1 ", #tecla_s1, " -- S2 ", #tecla_s2 'imprime en el lcd
Lcdcmdout LcdLine2Home 'Segunda linea y cursor al principio
Lcdout "----------------" 'Muestra los datos en el lcd
Return
'************************* PIC Entrenadora BASIC (PicEBasic)******************************
'NOMBRE: 16F88_LCD_RTC
'VERSION: 1.0
'MICRO: PIC16f88A
'FECHA/AUTOR: 12/06 - By COS, PSI v7.41
'Descripcion: muestra en el display la fecha y la hora.
'Para transferir la hora al reloj dejar pulsada la tecla S1
'***************************************************************************************************
Define CONFIG = 0x2f50 'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc 'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 8 'Clock en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Activar para simulación
'-------------------------------------Puertos del LCD---------------------------------------------
Define LCD_BITS = 4 'indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'el bus de datos sera el puerto A
Define LCD_DBIT = 0 'el bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'el bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'se usara el RB7 como RS
Define LCD_EREG = PORTB 'el bit de control E sera del puerto B
Define LCD_EBIT = 6 'se usara el RB6 como E
'Define LCD_RWREG = PORTA 'el bit de control RW sera del puerto A
'Define LCD_RWBIT = 5 'se usara el RA5 como RW
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comand del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera despues de inicializar el Display, solo se ejecuta una vez en mSeg.
'Asignacion de I/O y valores de inicio de las salidas
ANSEL = %00000000 'Los pin I/O digitales
CMCON = 0x07 'Comparador a off
OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'Puerto B como salidas
TRISA.4 = 1 'Como entrada (RA4, adc)
TRISA.6 = 1 'Como entrada (RA6, tecla S1)
TRISA.5 = 1 'Como entrada (RA5, tecla S2)
PORTB.3 = 1 'Luz lcd a on (RB3)
PORTA.7 = 1 'Led amarillo a off
PORTB.0 = 1 'Led verde a off
'------------------------------------------------------------------------
Lcdinit 'Inicializa el lcd sin cursor
WaitMs 1000 'Espera 1Seg
Lcdout "16f88LCD_RTC/I2C" 'Escribe en el lcd
Lcdcmdout LcdLine2Home 'Selecciona la linea dos como proxima para escritura
Lcdout "Pruebas con I2C" 'Escribe en el lcd
WaitMs 3000 'Espera 3Seg
Lcdcmdout LcdClear
'Puerto I2C ---------------------------------------------------------
Symbol sda = PORTB.1 'Asignamos nombre al pin que hara de sda del puerto i2c
Symbol scl = PORTB.4 'Asignamos nombre al pin que hara de SCL del puerto I2C
'Variables Generales -------------------------------------------
Dim aux_4h As Byte 'Contendra el nibble alto del dato leido por el I2C
Dim aux_4l As Byte 'Contendra el nibble bajo del dato leido por el I2C
Dim i As Byte 'Variable indice
Dim reg(7) As Byte 'Contendra los valores finales de fecha y hora en el sistema decimal
'Inicializacion del reloj -------------------------------------------
'Aqui escribimos los valores para cargar al RTC ------
If RA6 = 0 Then 'Si la tecla S1 esta pulsada pasaremos los datos al reloj
I2CWrite sda, scl, 0xd0, 0, 0x00 'Segundos, escrito en hex, porque coincide en este caso con BCD del RTC
I2CWrite sda, scl, 0xd0, 1, 0x59 'Minutos
I2CWrite sda, scl, 0xd0, 2, 0x23 'Horas
I2CWrite sda, scl, 0xd0, 3, 0x01 'Dia de la semana
I2CWrite sda, scl, 0xd0, 4, 0x31 'Dia del mes
I2CWrite sda, scl, 0xd0, 5, 0x12 'Mes
I2CWrite sda, scl, 0xd0, 6, 0x06 'Año
I2CWrite sda, scl, 0xd0, 7, 0x10 'Salida a 1hz
Endif
'Bucle principal -----------------------------------------------------
main:
Gosub print_lcd 'Actualiza la hora
WaitMs 100 'Pausa de 100mSeg.
Goto main
End
'**************************************Subrutinas**********************************************
print_lcd: 'Lee la hora del RTC, la pasa a decimal y la envia al lcd
i = 0
While i <= 6 'Se repite el codigo comprendido entre while y wend, mientras i sea menor o igual a 6
I2CRead sda, scl, 0xd0, i, reg(i) 'Lectura de la direccion de memoria indicada del RTC, formato BCD
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 %11110000 'Minutos, almacena nibble alto
If i = 2 Then aux_4h = reg(i) And %10110000 'Horas, borrado de bit configuracion y almacena nibble alto
If i = 3 Then aux_4h = reg(i) And %11110000 'Dia_semana, almacena nibble alto
If i = 4 Then aux_4h = reg(i) And %11110000 'Dia_mes, almacena nibble alto
If i = 5 Then aux_4h = reg(i) And %11110000 '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
Lcdcmdout LcdLine1Home 'Cursor del lcd a la izquierda en la linea 1
If reg(2) < 10 Then Lcdout "0" 'Si horas es inferior a 10 escribe el cero delante
Lcdout #reg(2), ":" 'Escribe la hora y el separador
If reg(1) < 10 Then Lcdout "0" 'Si minutos es inferior a 10 escribe el cero delante
Lcdout #reg(1), ":" 'Escribe los minutos y el separador
If reg(0) < 10 Then Lcdout "0" 'Si segundos es inferior a 10 escribe el cerodelante
Lcdout #reg(0) 'Escribe los segundos
Lcdcmdout LcdLine2Home 'Cursor del lcd a la izquierda en la linea 2
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"
Lcdout "/" 'Escribe separador
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 y el separador
If reg(5) < 10 Then Lcdout "0" 'Si mes es inferior a 10 escribe cero
Lcdout #reg(5), "/20" 'Escribe el mes, separador y los dos primeros digitos del año de 4 digitos
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
Return
'********************************** PIC Entrenadora BASIC ***************************************
'NOMBRE: 16F88_LCD_RS232_01
'VERSION: 1.0
'MICRO: PIC16F88
'Fecha/Autor: 1/07, By COS, PSI v7.41
'DESCRIPCION: MUESTRA EN EL DISPLAY DE 16x2, LOS CARACTERES RECIBIDOS POR RS232 Y ENVIA OTRA CADENA FIJA
'tiempo de lectura entre byte y byte del puerto serie 10mseg maximo si no hay datos
'************************************************************************************************
Define CONFIG = 0x2f50 'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc 'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 8 'Clock en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Activar para simulación
'Puertos del LCD---------------------------------------------
Define LCD_BITS = 4 'indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'el bus de datos sera el puerto A
Define LCD_DBIT = 0 'el bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'el bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'se usara el RB7 como RS
Define LCD_EREG = PORTB 'el bit de control E sera del puerto B
Define LCD_EBIT = 6 'se usara el RB6 como E
'Define LCD_RWREG = PORTA 'el bit de control RW sera del puerto A (si se suprime el compilador no protesta)
'Define LCD_RWBIT = 5 'se usara el RA5 como RW (si se suprime el compilador no protesta)
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comand del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera despues de inicializar el Display, solo se ejecuta una vez en mSeg.
'**************************************DEFINICION DE PUERTOS*************************************
'Asignacion de I/O y valores de inicio de las salidas---------------------
ANSEL = 0x00 'los pin I/O digitales
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
TRISA.4 = 1 'como entrada (RA4, adc)
TRISA.6 = 1 'como entrada (RA6, tecla S1)
TRISA.5 = 1 'como entrada (RA5, tecla S2)
'TRISB.5 = 0 'RB5(Tx, RS232)
TRISB.2 = 1 'RB2 (Rx, RS232)
PORTB.3 = 1 'luz lcd a on (RB3)
PORTA.7 = 1 'led amarillo a off
PORTB.0 = 1 'led verde a off
'------------------------------------INICIO DEL PUERTO SERIE, TIMER E INTERRUPCIONES------------------
T1CON.TMR1CS = 0 'asigna el reloj interno al timer1, se incrementa cada ciclo de instruccion
T1CON.T1CKPS0 = 0 'factor del preescales del timer1, 0
T1CON.T1CKPS1 = 0 'factor del preescales del timer1, 0
TMR1H = 0xf8 'carga el registro del contador para que desborde cada 1mSeg, byte alto
TMR1L = 0x30 'carga el registro del contador para que desborde cada 1mSeg, byte bajo
T1CON.TMR1ON = 1 'habilitacion del TMR1, comienza a incrementarce
PIE1.TMR1IE = 1 'activa las interrupciones del timer1
PIE1.RCIE = 1 'Activa la interrupcion de la USART en modo rx
INTCON.PEIE = 1 'bit de habilitacion de interrupciones de perifericos
Lcdinit 'inicializa el LCD sin cursor
Hseropen 4800 'Velocidad del puerto serie e inicializa los comandos de bajo nivel que controlan la USART
'Reasignacion de nombres---------------------------------------
Symbol led_amarillo = PORTA.7 'led amarillo
Symbol led_verde = PORTB.0 'led verde
'--------------------------------------Declaracion DE VARIABLES-------------------------------------
'Variables subrutinas del puerto serie-----------------------------------
Dim assi As Byte 'Contiene el valor de lectura del puerto serie
Dim n_usart As Byte 'Numero de datos del USART y del bufer IMAGEN de control
Dim usart As Byte 'Variable indice que apunta al ultimo dato adquirido por la USART
Dim aux_usart As Byte 'Auxiliar de la variable indice usart del USART
Dim c_serial As Byte 'Como USART pero para la lectura de control del bufer IMAGEN
Dim bufer As Byte 'Indica si hay datos por leer en el bufer USART
Dim w_posrx As Byte 'Tiempo entre lectura y lectura del bufer
Dim n_aux As Byte 'contador para borrar el bufer_soft
'Variables de los timer---------------------------------------------------
Dim aux_pause As Word 'variable auxiiar el PAUSE
Dim pause As Word 'contiene el valor para simular el comando Waitms
Dim timer_1ms As Byte 'base de tiempos se incrementa cada 1mSeg, timer del PAUSE
Dim timer_base As Byte 'tiempo referencia para los timer por soft del programa
Dim timer_base_tiempo As Byte 'contiene el valor del tiempo del timer_base
Dim timer1_ms As Word 'base de tiempos en ms
Dim timer2_ms As Word 'base de tiempos en ms
Dim timer3_ms As Word 'base de tiempos en ms
Dim timer1_100ms As Byte 'base de tiempos msx100
Dim timer2_100ms As Byte 'base de tiempos msx100
Dim timer3_100ms As Byte 'base de tiempos msx100
Dim timer1_ms_tiempo As Word 'contiene el valor del tiempo del timer1_ms
Dim timer2_ms_tiempo As Word 'contiene el valor del tiempo del timer2_ms
Dim timer3_ms_tiempo As Word 'contiene el valor del tiempo del timer3_ms
Dim timer1_100ms_tiempo As Byte 'contiene el valor del tiempo del timer1_100ms
Dim timer2_100ms_tiempo As Byte 'contiene el valor del tiempo del timer2_100ms
Dim timer3_100ms_tiempo As Byte 'contiene el valor del tiempo del timer3_100ms
'Variables rutina muestra datos en el LCD
Dim n As Byte 'se utiliza para posicionar caracter en el lcd
Dim flag As Byte 'controla la alternancia para imprimir en el lcd el caracter "(" o el ")"
Dim flag_1 As Byte 'controla la alternacia entre secuencia 1 y 2, tramas tx
'Variables tipo array puerto serie----------------------------------
Dim usart_imagen(91) As Byte 'Componen el bufer IMAGEN para control del bufer USART
Dim usart_bufer(91) As Byte 'Componen el bufer de la USART de bajo nivel
'ASIGNACIONES-----------------------------------------------
'Variables del contador del TIMER1------------------------------
timer_base = 0
aux_pause = 0
pause = 0
timer_1ms = 0
timer1_ms = 0
timer2_ms = 0
timer3_ms = 0
timer1_100ms = 0
timer2_100ms = 0
timer3_100ms = 0
timer_base_tiempo = 100 'cuenta 100mSeg
timer1_ms_tiempo = 5 'cuenta 5mSeg.
timer2_ms_tiempo = 100 'cuenta 0.1Seg
timer3_ms_tiempo = 100 'cuenta 0.1Seg
timer1_100ms_tiempo = 10 'cuenta 1Seg.
timer2_100ms_tiempo = 5 'temporiza 0.5Seg
timer3_100ms_tiempo = 5 'temporiza 0.5seg
'-------------------------------------Asigna valores a las variables de la rutina del puerto serie--
usart = 0
aux_usart = 0
c_serial = 0
bufer = 0
n_usart = 90
assi = 0
w_posrx = 10 '10mSeg rf, se espera un maximo de tiempo antes de leer el bufer si no hay datos
n_aux = 0
'-------------------------------------AsignA valores a las variables del TIMER1---------------------
'--------------------------------------asignacion de valores generales-----------------------------
n = 0
flag = 0
flag_1 = 0
'----------------------------------------------------------------
'Enable 'INTCON.GIE habilita las interrupciones globales
Gosub clear_bufer 'Borra el BUFFER IMAGEN y por lo tanto tambien al USART, OBLIGATORIO POR LO MENOS UNA VEZ
Enable 'INTCON.GIE habilita todas las interrupciones globales
pause = 1000 'prepara una pausa de 1Seg
Gosub pause_ms 'espera el tiempo que indica pause
Lcdout "18F88_LCD_RS232" 'imprime en el LCD el literal
Lcdcmdout LcdLine2Home 'selecciona linea y cursor al principio
Lcdout "RS232-4800Baud." 'escribe la cadena de literales en el lcd
Hserout CrLf, CrLf, "VER. 1.0 - TX/RX", CrLf, "TX -> PRUEBAS RS232", CrLf, "By COS", CrLf, CrLf 'envia presentacion al RS232
Gosub clear_bufer 'Borra el BUFFER IMAGEN y por lo tanto tambien al USART, OBLIGATORIO POR LO MENOS UNA VEZ
pause = 3000 'prepara una pausa de 3Seg.
Gosub pause_ms 'hace una pausa de tiempo indicado por pause
Lcdcmdout LcdClear 'borra el display
'--------------------------------------Main Programa----------------------------------------------------
main:
If timer2_100ms >= timer2_100ms_tiempo And flag_1 = 0 Then 'determina cuando emitir la secuencia_1
Gosub secuencia_1
timer2_100ms = 0
flag_1 = 1 'activa la alternancia entre secuencia_1 y la 2
Endif
If timer2_100ms >= timer2_100ms_tiempo And flag_1 = 1 Then 'determina cuando emitir la secuencia_2
Gosub secuencia_2
timer2_100ms = 0
flag_1 = 0 'activa la alternancia entre secuencia_1 y la 2
Endif
Gosub lcd_control
Goto main
End
'--------------------------------------FIN DEL MAIN-------------------------------------------
'--------------------------------------Subrutinas Programa-----------------------------------------------
secuencia_1: 'envia la trama por el puerto serie
Hserout "@Hola Amigos de TODOPIC", CrLf
Return
secuencia_2: 'envia la trama por el puerto serie
Hserout "@Ejemplo de Trabajo con RS232", CrLf
Return
pause_ms: 'rutina de espera, rutina tipo Waitms, pause establese el tiempo total en mSeg
aux_pause = 0 'variable auxiliar lleva la cuenta de los ms
timer_1ms = 0 'al borrar el contador se activa y comienza la cuenta de 1mSeg
While aux_pause <= pause 'tiempo en mSeg maximos a contar
aux_pause = aux_pause + 1 'variable auxiliar lleva la cuenta de los ms
If timer_1ms > 0 Then timer_1ms = 0 'al borrar el contador se activa y cuenta 1mSeg
While timer_1ms < 1 'espera un miliesegundo
Wend
Wend
Return
pause_ms_rx: 'rutina de espera antes de leer el bufer, w_posrx establese el tiempo total en mSeg
If bufer < 1 Then
aux_pause = 0 'variable auxiliar lleva la cuenta de los ms
timer_1ms = 0 'al borrar el contador se activa y comienza la cuenta de 1mSeg
While aux_pause <= w_posrx 'tiempo en mSeg maximos a contar
If bufer > 0 Then aux_pause = w_posrx 'si entran datos en el bufer se termina el contaje
aux_pause = aux_pause + 1 'variable auxiliar lleva la cuenta de los ms
If timer_1ms > 0 Then timer_1ms = 0 'al borrar el contador se acitva y cuenta 1mSeg
While timer_1ms < 1 'espera un miliesegundo
Wend
Wend
Endif
Return
'------------------------------ rutinas para el control del bufer del puerto serie-------------
readserial:
'RUTINA DE LECTURA DEL BUFFER DEL PUERTO SERIE (ASSI)
Gosub pause_ms_rx 'valor de entrada en mSeg de espera definido por w_posrx
assi = 0 'se borra el valor de assi, no se debe de utilizar cero como un valor de control
If bufer = 1 Then 'si bufer tiene datos
assi = usart_bufer(c_serial) 'se lee el valor del bufer y se asigna assi
usart_imagen(c_serial) = 0 'se marca como leida para que pueda ser llenada de nuevo
c_serial = c_serial + 1 'se incrementa el indice del bufer
If c_serial >= n_usart Then c_serial = 0 'se verifica si se llego al final del bufer
If usart_imagen(c_serial) = 0 Then bufer = 0 'si no quedan mas datos en el bufer se marca como vacio
Endif
Return
clear_bufer: 'inicializa el bufer imagen y borra error del puerto fisico en modo Rx
'_________________________Borra el error del puerto serie en Rx
RCSTA.OERR = 0
RCSTA.CREN = 0
RCSTA.CREN = 1
'_________________________Borra e inicializa el bufer imagan del puerto serie
c_serial = 0
While c_serial <= n_usart 'se ejecuta tantas veces como variables tiene el bufer
usart_imagen(c_serial) = 0 'borra el indicador de variable del bufer con datos
c_serial = c_serial + 1
Wend
c_serial = 0 'variables de control del bufer
usart = 0
bufer = 0
assi = 0
Return
'--------------------------------------SIBRUTINAS ESPECIALES---------------------------------------------
On Interrupt 'desactiva las interrupciones
Save System 'Guarda los valores del sistema
'*****************************base de tiempos********************************************
If PIR1.TMR1IF = 1 Then 'comprueba que la interrupcion la proboco el timer1
timer_base = timer_base + 1 'base patron
If timer_1ms < 1 Then timer_1ms = timer_1ms + timer_1ms + 1 'contador para control del timer_1ms
If timer1_ms < timer1_ms_tiempo Then timer1_ms = timer1_ms + 1 'contador para control del timer1_ms
If timer2_ms < timer2_ms_tiempo Then timer2_ms = timer2_ms + 1 'contador para control del timer2_ms
If timer3_ms < timer3_ms_tiempo Then timer3_ms = timer3_ms + 1 'contador para control del timer3_ms
If timer_base >= timer_base_tiempo Then 'usa la base patron para retrazar la rutina 100mSeg.
If timer1_100ms < timer1_100ms_tiempo Then timer1_100ms = timer1_100ms + 1 'contador para control...
If timer2_100ms < timer2_100ms_tiempo Then timer2_100ms = timer2_100ms + 1 'contador para control...
If timer3_100ms < timer3_100ms_tiempo Then timer3_100ms = timer3_100ms + 1 'contador para control...
timer_base = 0 'reset a la base timer
Endif
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
Endif
'*****************************Fin base de tiempos****************************************
'*****************************BUFFER PUERTO SERIE****************************************
If PIR1.RCIF = 1 Then 'comprueba que es esta la interrupcion activa del modulo USAR
If usart < n_usart Then 'comprueba que el bufer de entrada no esta lleno
If usart_imagen(usart) = 0 Then 'comprueba que la posicion esta vacia
aux_usart = usart 'retiene la posicion antigua del bufer
usart = usart + 1 'indica cual sera la posicion siguiente del bufer
usart_imagen(aux_usart) = 1 'indica que hay dato en el bufer de entrada
bufer = 1 'indica que el bufer tine datos
Hserget usart_bufer(aux_usart) 'carga el dato en el bufer
Else
Hserget usart_bufer(n_usart) 'descarga la usart para que no se bloquee porque el bufer de entrada esta lleno
Endif
Else
If usart_imagen(0) = 0 Then 'comprueba que esta vacia la primera posicion del bufer
usart_imagen(0) = 1 'marca que hay dato en esa posicion del bufer
bufer = 1 'marca que el bufer tiene datos
usart = 1 'establece la proxima posicion del bufer
Hserget usart_bufer(0) 'lee la usart y guarda el dato en el bufer
Else
Hserget usart_bufer(n_usart) 'descarga la usart porque el bufer esta lleno
Endif
Endif
Endif
'_________________________Borra el error del puerto serie en Rx
If RCSTA.OERR = 1 Then
RCSTA.OERR = 0
RCSTA.CREN = 0
RCSTA.CREN = 1
'_________________________Borra e inicializa el bufer imagan del puerto serie
c_serial = 0
While c_serial <= n_usart 'se ejecuta tantas veces como variables tiene el bufer
usart_imagen(c_serial) = 0 'borra el indicador de variable del bufer con datos
c_serial = c_serial + 1
Wend
c_serial = 0 'variables de control del bufer
usart = 0
bufer = 0
assi = 0
Endif '____________________
If PIR1.TMR1IF = 1 Then PIR1.TMR1IF = 0 'borra el bit de salto del timer1
If PIR1.RCIF = 1 Then PIR1.RCIF = 0 'borra el bit de salto del Rx
Resume 'activa las interrupciones y retorna al curso normal del programa antes del salto
lcd_control: 'rutina que imprime los valores recibidos por el puerto serie en el display
'parte 1 de la rutina, sincroniza e imprime los caracteres recibidos por el puerto serie
If bufer = 1 Then 'la rutina se ejecuta si hay datos en el bufer
timer1_100ms = 0 'hay datos hace reset al timer1_100ms
Gosub readserial 'salta a la rutina de lectura del bufer serie
If assi = "@" Then 'caracter de sincronismo de la trama
n = 0 'possicion del display
Lcdcmdout LcdClear 'borra el display y posiciona el cursor superior izquierda
Endif
n = n + 1 'incrementa la posicion para escribir el siguiente caracter en le display
If assi > 31 And assi < 128 And assi <> "@" Then 'filtra los caracteres a imprimir
Lcdout assi 'escribe el caracter del bufer en el display
Endif
If n = 16 Then 'detecta fin de la linea primera
Lcdcmdout LcdLine2Home 'situa el cursor al principio de la siguiente linea
Endif
If n >= 32 Then 'detecta fin de la segunda linea
n = 0 'inicializa la posicion del proximo caracter a imprimir en el display
Lcdcmdout LcdHome 'a inicio de linea
Endif
Endif
'parte 2 de la rutina, cuando no se reciben datos imprime en el display "(" y ")" de forma alterna
If timer1_100ms >= timer1_100ms_tiempo Then 'produce un retrazo inicial a la ejecucion de la rutina
If bufer = 0 Then 'si no hay datos en el bufer
If timer1_ms >= timer1_ms_tiempo Then 'produce un retrazo cada vez que se intenta imprimir en el lcd
timer1_ms = 0 'resetea el timer1_ms para que cuente de nuevo
If flag = 0 Then 'produce la alternancia para escribir "("
n = n + 1
Lcdout "("
If n = 16 Then
Lcdcmdout LcdLine2Home
Endif
If n >= 32 Then
n = 0
flag = 1
Lcdcmdout LcdHome
Endif
Endif
If flag = 1 Then 'produce la alternancia para escribir ")"
n = n + 1
Lcdout ")"
If n = 16 Then
Lcdcmdout LcdLine2Home
Endif
If n >= 32 Then
n = 0
flag = 0
Lcdcmdout LcdHome
Endif
Endif
Endif
Endif
Endif
Return
'***************** Placa Entrenadora (PIC EBadic) ***************************************
'NOMBRE:16F88_LCD_Timer1_ADC_PWM_01
'MICRO: PIC16F88/8Mhz reloj interno
'Versión: 1.0
'Fecha/Autor: 1/07, By COS, PSI v7.41
'Uso del LCD con bus de datos a 4Bit y sin pin de RW
'Activación del Timer1 por rebose cada 1mSeg.
'implementación de bases de tiempos por soft, basadas en el Timer1
'lectura de entrada analógica y conversión a voltaje con dos decimales
'Implementacion de PWM con periodo de 20mseg. para el control de la luz del lcd por medio de la entrada adc
'***********************************************************************************
Define CONFIG = 0x2f50 'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc 'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 8 'Clock en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Activar para simulación
'-------------------------------------Puertos del LCD-------------------------------------
Define LCD_BITS = 4 'Indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'Bus de datos sera el puerto A
Define LCD_DBIT = 0 'Bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'Bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E sera del puerto B
Define LCD_EBIT = 6 'RB6 como E
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comando del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera despues de inicializar el Display.
'------------------------------------Definición de puertos------------------------------------------
ANSEL = %00010000 'Los pin I/O digitales y RA4 analogico
Define ADC_SAMPLEUS = 10 'Configuracion del ADC
Define ADC_CLOCK = 5 '16Tad a 8Mhz = 2uSeg, minimo permitido por el micro 1.5uSeg, configuracion ADC
'_______________Registros afectados por Define ADC_CLOCK y ADCIN________________
'ANSEL = %00010000 'Los pin I/O digitales y RA4 analogico
'ADCON0 = %01100000 'Fosc/16 a 8Mhz (ADCON1.ADCS2=1) =2uSeg (minimo 1.uSeg), channel RA4
'ADCON1 = %01000000 'Voltage reference (AVdd/AVss) y seleccion de escala division clock/2 ADCON1.ADCS2=1
'_______________________________________________________________________________
CMCON = 0x07 'Comparador a off
OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz
CMCON = 0x07 'Comparador a off
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'Puerto B como salidas
TRISA.4 = 1 'Como entrada (RA4, adc)
TRISA.6 = 1 'Como entrada (RA6, tecla S1)
TRISA.5 = 1 'Como entrada (RA5, tecla S2)
PORTB.3 = 1 'Luz lcd a on (RB3)
PORTA.7 = 1 'Led amarillo a off, negado
PORTB.0 = 1 'Led verde a off, negado
'Inicialización de Interrupciones-----------------------------
T1CON.TMR1CS = 0 'Asigna el reloj interno al timer1, se incrementa cada ciclo de instrucción
T1CON.T1CKPS0 = 0 'Factor del preescales del timer1, 0
T1CON.T1CKPS1 = 0 'Factor del preescales del timer1, 0
TMR1H = 0xf8 'Carga el registro del contador para que desborde cada 1mSeg, byte alto
TMR1L = 0x30 'Carga el registro del contador para que desborde cada 1mSeg, byte bajo
T1CON.TMR1ON = 1 'Habilitación del TMR1, comienza a incrementarse
PIE1.TMR1IE = 1 'Activa las interrupciones del timer1
INTCON.PEIE = 1 'Bit de habilitacion de interrupciones de perifericos
'Enable 'INTCON.GIE habilita todas las interrupciones globales
'Inicio-------------------------------------------------------
Lcdinit 'Inicializa el lcd sin cursor
WaitMs 500 'Pausa para estabilizar
'Reasignación de nombres---------------------------------------
Symbol led_amarillo = PORTA.7 'Led amarillo
Symbol led_verde = PORTB.0 'Led verde
Symbol luz_lcd = PORTB.3 'Retroiluminacion del lcd
'Declaracion de variables --------------------------------------
'Variables de los timer -----------------------------------------
Dim timer_base As Byte 'Tiempo referencia para los timer por soft del programa
Dim timer_base_tiempo As Byte 'Contiene el valor del tiempo del timer_base
Dim timer1_ms As Word 'Base de tiempos en ms
Dim timer2_ms As Word 'Base de tiempos en ms
Dim timer3_ms As Word 'Base de tiempos en ms
Dim timer1_100ms As Byte 'Base de tiempos msx100
Dim timer2_100ms As Byte 'Base de tiempos msx100
Dim timer3_100ms As Byte 'Base de tiempos msx100
Dim timer1_ms_tiempo As Word 'Contiene el valor del tiempo del timer1_ms
Dim timer2_ms_tiempo As Word 'Contiene el valor del tiempo del timer2_ms
Dim timer3_ms_tiempo As Word 'Contiene el valor del tiempo del timer3_ms
Dim timer1_100ms_tiempo As Byte 'Contiene el valor del tiempo del timer1_100ms
Dim timer2_100ms_tiempo As Byte 'Contiene el valor del tiempo del timer2_100ms
Dim timer3_100ms_tiempo As Byte 'Contiene el valor del tiempo del timer3_100ms
'Variables del ADC y Rutina division------------------------------
Dim num_1 As Word 'Valor del adc y retorna la parte entera
Dim num_2 As Word 'Factor de la escala y retorna el primer decimal
Dim num_3 As Word 'Segundo decimal
'Variables generales-----------------------------------------------
Dim flag_1 As Byte 'Determina si la luz del lcd estará a on o a off
Dim adc_4 As Word 'Contiene el valor de la entrada ADC
'Asignacion de valores a las variables--------------------------
timer_base = 0
timer1_ms = 0
timer2_ms = 0
timer3_ms = 0
timer1_100ms = 0
timer2_100ms = 0
timer3_100ms = 0
timer_base_tiempo = 100 'Cuenta 100mSeg
timer1_ms_tiempo = 1 'Cuenta 1mSeg.
timer2_ms_tiempo = 19 'Cuenta 19mSeg
timer3_ms_tiempo = 5 'Cuenta 5mSeg
timer1_100ms_tiempo = 10 'Cuenta 1 Seg.
timer2_100ms_tiempo = 20 'Temporiza 2Seg
timer3_100ms_tiempo = 1 'Temporiza 0.1seg
flag_1 = 0
adc_4 = 0
Enable 'INTCON.GIE habilita todas las interrupciones globales
'Rutinas Pricipal----------------------
main:
If timer1_100ms >= timer1_100ms_tiempo Then 'Cambio de estado el pin RA7 cada timer1_100ms_tiempo
Toggle led_amarillo
timer1_100ms = 0 'Reinicio el timer1_ms
Endif
If timer2_100ms >= timer2_100ms_tiempo Then 'Cambio de estado el pin RB0 cada timer2_100ms_tiempo
Toggle led_verde
timer2_100ms = 0 'Reinicio el timer2_100ms
Endif
If timer3_100ms >= timer3_100ms_tiempo Then
Gosub lee_adc 'Salto con retorno, rutina de lectura de la entrada ADC
Gosub division_dos_decimales 'Salto con retorno, rutina de conversion de valor adc a voltios
Gosub print_lcd 'Salto con retorno, rutina que imprime los valores en el lcd
timer3_100ms = 0
'__________Control de los tiempos del PWM con un periodo de 20mSeg segun el valor de adc_4
timer2_ms_tiempo = (adc_4 * 20) / 1023 'Controla el tiempo del PWM en estado alto, periodo 20mSeg
timer1_ms_tiempo = 20 - timer2_ms_tiempo 'Controla el tiempo del PWM en estado bajo, periodo 20mSeg
'___________________________________________________
Endif
Goto main 'Impide que termine el programa principal
End 'Especifica donde termina la rutina principal y comienzan las subrutinas y funciones
'Subrutina lectura ADC, division y LCD
lee_adc: '_______________________Lee la entrada analogica
Dim aux As Long
Adcin 4, adc_4 'Lee el valor de la entrada analogica y lo carga en adc_4
aux = (500 * adc_4) / 1023
num_1 = aux 'Sede el valor del adc para ser procesado
Return
division_dos_decimales: '________Rutina division con dos decimales y conversion a voltios
Dim resto As Word
Dim dvdo As Word
Dim dvsor As Word
dvdo = num_1 'Asigna dividendo
dvsor = 100 'Asigna divisor, dos decimales
num_1 = dvdo / dvsor 'Calcula parte entera
resto = dvdo Mod dvsor 'Calcula resto
If resto = 0 Then Return 'Se sale de la subrutina
num_2 = resto / 10 'Asigna primer decimal
num_3 = resto - (num_2 * 10) 'Asigna el segundo decimal
Return
print_lcd: '____________________Muestra los datos por el display
Lcdcmdout LcdLine1Clear 'Borra la primera linea y cursor al principio
Lcdout "ADC ", #adc_4, " ", #num_1, ".", #num_2, #num_3, "V", " " 'Muestra los datos en el lcd
Lcdcmdout LcdLine2Clear 'Borra la segunda linea y cursor al principio
Lcdout "LCD On ", #timer2_ms_tiempo, " Off ", #timer1_ms_tiempo, " " 'Muestra los datos en el lcd
Return
'--------------------------------Interrupciones---------------------------------------------------
On Interrupt 'Comienzan las rutinas de las interrupciones, desactiva las interrupciones
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
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
'__________________Base de tiempos
timer_base = timer_base + 1
If timer1_ms < timer1_ms_tiempo Then timer1_ms = timer1_ms + 1
If timer2_ms < timer2_ms_tiempo Then timer2_ms = timer2_ms + 1
If timer3_ms < timer3_ms_tiempo Then timer3_ms = timer3_ms + 1
If timer_base >= timer_base_tiempo Then
If timer1_100ms < timer1_100ms_tiempo Then timer1_100ms = timer1_100ms + 1
If timer2_100ms < timer2_100ms_tiempo Then timer2_100ms = timer2_100ms + 1
If timer3_100ms < timer3_100ms_tiempo Then timer3_100ms = timer3_100ms + 1
timer_base = 0
Endif
'_________________Control fisico de la retroiluminaicon del lcd
If timer1_ms >= timer1_ms_tiempo And flag_1 = 0 Then 'Tiempo en el que estara el lcd apagado
luz_lcd = 1 'Retroiluminacion a on
flag_1 = 1 'Controla la alternancia entre lcd iluminado o apagado
timer2_ms = 0 'Reinicio el timer2_ms
Endif
If timer2_ms >= timer2_ms_tiempo And flag_1 = 1 Then 'Tiempo en el que estara el lcd iluminado
luz_lcd = 0 'Retroiluminacion a off
flag_1 = 0 'Controla la alternancia entre lcd iluminado o apagado
timer1_ms = 0 'Reinicio el timer1_ms
Endif
'_____________________________________________________
PIR1.TMR1IF = 0 'Borra el flag de salto del tmr1
Endif
Resume 'Activa las interrupciones y retorna al curso normal del programa antes del salto
Nocturno:
jeje, yo entre en esto como de medio rebote, pero estoy disfrutando mucho.. :D :mrgreen:
Y para no perder la costumbre del foro de robotica un video del invento.. :D :D :D :D
http://www.mytempdir.com/1146434
'********************************** PIC Entrenadora BASIC (PicEBasic)**************************
'NOMBRE: 16F88_LCD_RTC_12
'MICRO: PIC16f88A
'FECHA/AUTOR: 12/06 - By COS, PSI v7.71
'Vercion 1.2, 18/02/07
'Correccion de fallo en la rutina de lectura de los registros del RTC
'correccion de fallo en la rutina de modificacion de los registros del RTC
'Modificacion de la rutina de configuracion del reloj
'Se trucan todas las posiciones que no usan los registro del RTC, rutina de lectura del RTC
'Se elimina la variable aux1_ajuste
'Version 1.1, 12/02/07
'Se cambia el formato del dia
'Se implementan bases de tiempos, para el control del flujo de las rutinas
'Se incorpora la rutina pause
'Se cambian la funcion de las teclas S1 y S2 pulsadas al mismo tiempo, ahora entramos en programacion
'Una vez en programacion con S1 seleccionamos el dato a cambiar, este queda en modo parpadeo
'Una vez en programacion con S2 incrementamos el dato seleccionado dentro de sus cotas
'Version 1.0
'Descripcion: muestra en el display la fecha y la hora en formato de 24 horas
'para transferir la hora al reloj dejar pulsada la tecla S1
'*******************************************************************************************************
Define CONF_WORD = 0x2f50 'Configuración de bits (fuses)
Define CONF_WORD_2 = 0x3ffc 'Configuración de bits (fuses)
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Solo para simulación, acelera los WaitMs
'-------------------------------------Puertos del LCD-------------------------------------
Define LCD_BITS = 4 'Indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'Bus de datos sera el puerto A
Define LCD_DBIT = 0 'Bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'Bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E sera del puerto B
Define LCD_EBIT = 6 'RB6 como E
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comando del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera despues de inicializar el Display.
'Asignacion de nombres
Symbol sda = PORTB.1 'Asignamos nombre al pin que hara de SDA del puerto I2C
Symbol scl = PORTB.4 'Asignamos nombre al pin que hara de SCL del puerto I2C
Symbol led_amarillo = PORTA.7 'Led amarillo
Symbol led_verde = PORTB.0 'Led verde
Symbol luz_lcd = PORTB.3 'Retroiluminacion del lcd
Symbol s1 = RA6 'Se asigna nombre a la tecla
Symbol s2 = RA5 'Se asigna nombre a la tecla
'Asignacion de I/O y valores de inicio de las salidas
ANSEL = %00000000 'Los pin I/O digitales
CMCON = 0x07 'Comparador a off
OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'Puerto B como salidas
TRISA.4 = 1 'Como entrada (RA4, adc)
TRISA.6 = 1 'Como entrada (RA6, tecla S1)
TRISA.5 = 1 'Como entrada (RA5, tecla S2)
PORTB.3 = 1 'Luz lcd a on (RB3)
PORTA.7 = 1 'Led amarillo a off
PORTB.0 = 1 'Led verde a off
'Inicializacion de Interrupciones
T1CON.TMR1CS = 0 'Asigna el reloj interno al timer1, se incrementa cada ciclo de instruccion
T1CON.T1CKPS0 = 0 'Factor del preescales del timer1, 0
T1CON.T1CKPS1 = 0 'Factor del preescales del timer1, 0
TMR1H = 0xf8 'Carga el registro del contador para que desborde cada 1mSeg, byte alto
TMR1L = 0x30 'Carga el registro del contador para que desborde cada 1mSeg, byte bajo
T1CON.TMR1ON = 1 'Habilitacion del TMR1, comienza a incrementarce
PIE1.TMR1IE = 1 'Activa las interrupciones del timer1
INTCON.PEIE = 1 'Bit de habilitacion de interrupciones de perifericos
'-------------------------------------------------------------------------------------------------------------------------
Lcdinit 'Inicializa el lcd sin cursor
'-------------------------------------------------------------------------------------------------------------------------
'Definicion de variables
'Variables de los timer
Dim aux_pause As Word 'Variable auxiiar el PAUSE
Dim pause As Word 'Contiene el valor para simular el comando Waitms
Dim timer_1ms As Byte 'Base de tiempos se incrementa cada 1mSeg, timer del PAUSE
Dim timer_base As Byte 'Tiempo referencia para los timer por soft del programa
Dim timer_base_tiempo As Byte 'contiene el valor del tiempo del timer_base
Dim timer1_ms As Word 'Base de tiempos en ms
Dim timer2_ms As Word 'Base de tiempos en ms
Dim timer3_ms As Word 'Base de tiempos ms
Dim timer1_100ms As Byte 'Base de tiempos msx100
Dim timer2_100ms As Byte 'Base de tiempos msx100
Dim timer3_100ms As Byte 'Base de tiempos msx100
Dim timer1_ms_tiempo As Word 'Contiene el valor del tiempo del timer1_ms
Dim timer2_ms_tiempo As Word 'Contiene el valor del tiempo del timer2_ms
Dim timer3_ms_tiempo As Word 'Contiene el valor del tiempo del timer3_ms
Dim timer1_100ms_tiempo As Byte 'Contiene el valor del tiempo del timer1_100ms
Dim timer2_100ms_tiempo As Byte 'Contiene el valor del tiempo del timer2_100ms
Dim timer3_100ms_tiempo As Byte 'Contiene el valor del tiempo del timer3_100ms
'Variables Programa
Dim aux_4h As Byte 'Contendra el nibble alto del dato leido por el I2C
Dim aux_4l As Byte 'Contendra el nibble bajo del dato leido por el I2C
Dim i As Byte 'Variable indice
Dim reg(7) As Byte 'Contendra los valores finales de fecha y hora en el sistema decimal
Dim flash_1 As Bit 'Controla el parpadeo de los digitos del lcd, activo a 1
Dim dato As Byte 'Indica la direccion del RTC a cambiar de valor
Dim flag_1 As Bit 'Activa la rutina de ajuste del reloj, activo a 1
Dim s1_on As Bit 'Tecla pulsada si s1_on=1
Dim s2_on As Bit 'Tecla pulsada si s2_on=1
Dim aux_ajuste As Byte 'Variable auxiliar para la rutina de ajuste
'Asignacion de valores a las variables
s1_on = 0
s2_on = 0
dato = 7 'Fuera de ajuste o modo normal de trabajo del reloj, de 0 a 6 modo ajuste
flash_1 = 0
flag_1 = 0
timer_base = 0
timer1_ms = 0
timer2_ms = 0
timer3_ms = 0
timer1_100ms = 0
timer2_100ms = 0
timer3_100ms = 0
timer_base_tiempo = 100 'Cuenta 100mSeg
timer1_ms_tiempo = 50 'Cuenta 50mSeg.
timer2_ms_tiempo = 500 'Cuenta 500mSeg
timer3_ms_tiempo = 5 'Cuenta 5mSeg
timer1_100ms_tiempo = 10 'Cuenta 1 Seg.
timer2_100ms_tiempo = 20 'Temporiza 2Seg
timer3_100ms_tiempo = 1 'Temporiza 0.1seg
'---------------------------------------------------------------------------------------
Enable 'INTCON.GIE habilita todas las interrupciones globales
pause = 1000
Gosub pause_ms 'Espera el tiempo indicado en pause
Lcdout "16f88LCD_RTC/I2C" 'Escribe en el lcd
Lcdcmdout LcdLine2Home 'Seleciona la linea dos como proxima para escritura
Lcdout "Pruebas con I2C" 'Sscribe en el lcd
pause = 3000
Gosub pause_ms 'Wspera el tiempo indicado en pause
Lcdcmdout LcdClear 'Borra el display y cursor a casa
'Bucle principal
main:
If s1 = 1 And s1_on = 1 Then s1_on = 0 'Libera el pulsador S1, control anti-rebotes tecla
If s2 = 1 And s2_on = 1 Then s2_on = 0 'Libera el pulsador S2, control anti-rebotes tecla
If s1 = 0 And s2 = 0 And s1_on = 0 And s2_on = 0 And flag_1 = 0 Then '________Modo ajuste
flag_1 = 1 'Activa la rutina de ajustes
dato = 0 'Activo cambio de la hora
timer1_ms = 0 'Resetea la base de tiempos de retraso entre pulsacion y pulsacion de S1
timer3_ms = 0 'Resetea la base de tiempos de retraso entre pulsacion y pulsacion de S2
s1_on = 1 'Bloquea la tecla S1, elimina rebotes
s2_on = 1 'Bloquea la tecla s2, elimina rebotes
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 '__________________
Goto main
End
'**************************************Subrutinas**********************************************
ajuste_reloj: 'Rutina de ajuste del reloj
If s1 = 1 And s1_on = 1 Then s1_on = 0 'Libera el pulsador S1, control anti-rebotes tecla
If s2 = 1 And s2_on = 1 Then s2_on = 0 'Libera el pulsador S2, control anti-rebotes tecla
'________________________Control posicion del dato a variar en el reloj
If s1 = 0 And s1_on = 0 And s2 = 1 Then 'Detecta tecla S1 y eliminacion de rebotes de la misma
If timer1_ms >= timer1_ms_tiempo Then 'Establece el retraso entre pulsaciones de S1
dato = dato + 1 'Seleciona el dato a ser modificado
s1_on = 1 'La tecla queda bloqueada
'If dato > 6 Then dato = 10 'Acota el valor de dato
If dato > 6 Then flag_1 = 0 'Indica fin de rutina de ajuste
timer1_ms = 0 'Resetea la base de tiempos de retraso entre pulsacion y pulsacion de S1
Endif
Endif '_____________________________
'____________Lectura de la hora para su modificacion y posterior grabacion, rutina BCD
If s2 = 0 And s2_on = 0 And s1 = 1 Then 'Deteca tecla S2 y eliminacion de rebotes de la misma
If timer3_ms >= timer3_ms_tiempo Then 'Establece el retraso entre pulsaciones de S2
s2_on = 1 'La tecla queda bloqueada
timer3_ms = 0 'Resetea la base de tiempos de retraso entre pulsacion y pulsacion de S2
If dato < 7 Then 'Limita la direcciones de trabajo del reloj
Gosub lee_hora 'Lee los datos de los registros del 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
I2CWrite sda, scl, 0xd0, dato, aux_ajuste 'Actualiza el dato ya modificado
Endif
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
I2CRead sda, scl, 0xd0, i, reg(i) 'Lectura de la direccion de memoria indicada del RTC, formato BCD
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
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
pause_ms: 'Rutina de espera, rutina tipo Waitms, pause establese el tiempo total en mSeg
aux_pause = 0 'Variable auxiliar lleva la cuenta de los ms
timer_1ms = 0 'Al borrar el contador se activa y comienza la cuenta de 1mSeg
While aux_pause <= pause 'Tiempo en mSeg maximos a contar
aux_pause = aux_pause + 1 'Variable auxiliar lleva la cuenta de los ms
If timer_1ms > 0 Then timer_1ms = 0 'Al borrar el contador se activa y cuenta 1mSeg
While timer_1ms < 1 'Espera un miliesegundo
Wend
Wend
Return
'***********************************Interrupciones*****************************************************
On Interrupt 'Comienzan las rutinas de las interrupciones, desactiva las interrupciones
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 < 1 Then timer_1ms = 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
Endif
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
PIR1.TMR1IF = 0 'Borra el flag de salto del tmr1
If s1 = 0 Then led_verde = 0 'Muestra el estado de la tecla, tecla S1 a on, led verde a on
If s1 = 1 Then led_verde = 1 'Muestra el estado de la tecla, tecla s1 a off, led verde a off
If s2 = 0 Then led_amarillo = 0 'Muestra el estado de la tecla, tecla S2 a on, led amarillo a on
If s2 = 1 Then led_amarillo = 1 'Muestra el estado de la tecla, tecla S2 a on, led amarillo a on
Resume 'Activa las interrupciones y retorna el curso normal del programa, antes del salto
'********************************** PIC Entrenadora BASIC (PicEBasic)******************************
'NOMBRE: 16F88_LCD_ADC_Funcion_12
'VERSION: 1.2
'MICRO: PIC16f88A
'FECHA/AUTOR: 24/02/07, 13/07, 12/06 - By COS, PSI v7.41
'version: 1.2
'Simplificado de la rutina de division
'Modificacion de la rutina print_lcd, para hacerla compatible con el nuevo formato salida de datos de la division
'Version: 1.1
'Se acelera la rutina del display
'Se implementa con funciones
'Version: 1.0
'Descripción: muestra en el display el valor de la entrada analogica con dos decimales y en voltios
'**********************************************************************************************
Define CONF_WORD = 0x2f50 'Configuración de bits (fuses)
Define CONF_WORD_2 = 0x3ffc 'Configuración de bits (fuses)
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Hace que se ignoren los tiempos de los WaitMs
'Puertos del LCD-------------------------------------
Define LCD_BITS = 4 'Indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'Bus de datos sera el puerto A
Define LCD_DBIT = 0 'Bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'Bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E sera del puerto B
Define LCD_EBIT = 6 'RB6 como E
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comando del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera despues de inicializar el Display.
'Definición de puertos y modulos
ANSEL = %00000000 'Los pin I/O digitales
Define ADC_SAMPLEUS = 10 'el minimo, configuracion del ADC
Define ADC_CLOCK = 5 '16Tad a 8Mhz = 2uSeg, minimo permitido por el micro 1.5uSeg, configuracion ADC
'_______________Registros afectados por Define ADC_CLOCK y ADCIN________________
ANSEL = %00010000 'Los pin I/O digitales y RA4 analogico
ADCON0 = %01100000 'Fosc/16 a 8Mhz (ADCON1.ADCS2=1) =2uSeg (minimo 1.uSeg), channel RA4
ADCON1 = %01000000 'Voltage reference (AVdd/AVss) y seleccion de escala division clock/2 ADCON1.ADCS2=1
'_______________________________________________________________________________
CMCON = 0x07 'Comparador a off
OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'Puerto B como salidas
TRISA.4 = 1 'Como entrada (RA4, adc)
TRISA.6 = 1 'Como entrada (RA6, tecla S1)
TRISA.5 = 1 'Como entrada (RA5, tecla S2)
PORTB.3 = 1 'Luz lcd a on (RB3)
PORTA.7 = 1 'Led amarillo a off
PORTB.0 = 1 'Led verde a off
'------------------------------------------------------------------
Lcdinit 'Inicializa el lcd sin cursor
'------------------------------------------------------------------
WaitMs 1000 'Espera 1Seg
Lcdout "16f88_LCD_ADC" 'Escribe en el lcd
Lcdcmdout LcdLine2Home 'Selecciona la linea dos como proxima para escritura
Lcdout "Pruebas con ADC" 'Escribe en el lcd
WaitMs 3000 'Espera 3Seg
Lcdcmdout LcdClear 'Borra el display, y cursor al principio de la primera linea
Lcdout "Lectura Pin RA4" 'Muestra los datos en el lcd
'Rutina principal
main:
Call _vadc4() 'Llama a la función de lectura de la entrada ADC, retorna un Word
Call _dvsion_2dcmles(_vadc4) 'Llama a la funcion dvsion_2dcmles, que retorna un long
Call _print_lcd(_dvsion_2dcmles) 'Llama a la función que muestra los datos por el LCD con dos decimales
WaitMs 100 'Hace una pausa de 100mSeg
Goto main
End
'Subrutinas y Funciones
'________Lee la entrada analogica y la pasa a voltios
'Devuelve un word con el voltaje con dos decimales, no tiene argumento de entrada.
Function _vadc4() As Word
Dim _aux As Long 'Variable auxiliar local
Adcin 4, _vadc4 'Lee el valor de la entrada analogica y lo guarda en _vadc4 con dos decimales
_aux = (500 * _vadc4) / 1023 'Pasa a voltios con dos decimales
_vadc4 = _aux 'Asigna valor de salida
End Function
'________Muestra los datos por el display
'Argumento de entrada una variable tipo Long, no devuelve datos.
Proc _print_lcd(_numero As Long)
Lcdcmdout LcdLine2Home 'Selecciona la primera linea y cursor al principio
Lcdout "ENTR. ADC ", #_numero.HW, "." 'Muestra los datos en el lcd
If _numero.LW < 10 Then Lcdout "0" 'Asegura que decimal siempre se escribira con dos digitos
Lcdout #_numero.LW, "V " 'Muestra los datos en el lcd
End Proc
'________Rutina funcion division con dos decimales
'Argumentos de entrada variable tipo word, argumento de salida una variable tipo long
Function _dvsion_2dcmles(_dvdo As Word) As Long
Dim _dvsor As Word 'Divisor
Dim _entera As Word 'Variable local, contendra la parte entera
Dim _resto As Word 'Varable local, contendra el resto
Dim _decimal As Word 'contendra la parte decimal
_dvsor = 100 'Dos decimales
_entera = _dvdo / _dvsor 'Obtengo la division
_resto = _dvdo Mod _dvsor 'Obtengo el resto
_dvsion_2dcmles.HW = _entera 'Almacena la parte entera en el word alto
_dvsion_2dcmles.LW = _resto '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
'********************************** PIC Entrenadora BASIC (PicEBasic)******************************
'NOMBRE: 16F88_LCD_ADC_Funcion_13
'MICRO: PIC16f88A
'FECHA/AUTOR: 24/02/07, 13/07, 12/06 - By COS, PSI v7.41
'Version: 1.3
'Se añade un sensor de temperatura en la entrada RA4, se conecta un LM35DZ por medio de la placa ETPA_LM35xZ, Ver. 1.2.
'Se toma una lectura cada 1000mSeg. y se calcula la media aritmetica con 20 muestras.
'Se ajusta la placa ETPA_LM35xZ, para maxima temperatura 60º = 3V (RA2).
'Como 5V=1023=100º, 3V=613.8=60º.
'Como el rango de temperatura del LM35DZ es de 0º a 100º, el RA1 se ajusta a cero voltios.
'Version: 1.2
'Simplificado de la rutina de division.
'Modificacion de la rutina print_lcd, para hacerla compatible con el nuevo formato salida de datos de la division.
'Version: 1.1
'Se acelera la rutina del display.
'Se implementa una rutina tipo funcion para la division.
'Version: 1.0
'Muestra en el display el valor de la entrada analogica con dos decimales y en voltios.
'***************************************************************************************************
'***********************************************************************************
Define CONFIG = 0x2f50 'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc 'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 8 'Clock en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Activar para simulación, acelera los comandos WaitMs
'-------------------------------------Puertos del LCD-------------------------------------
Define LCD_BITS = 4 'Indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'Bus de datos sera el puerto A
Define LCD_DBIT = 0 'Bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'Bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E sera del puerto B
Define LCD_EBIT = 6 'RB6 como E
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comando del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera despues de inicializar el Display.
'**************************************DEFINICION DE PUERTOS*************************************
'----------------------ASIGNACION DE I/O y valores de inicio de las salidas---------------------
ANSEL = %00000000 'los pin I/O digitales
Define ADC_SAMPLEUS = 10 'el minimo, configuracion del ADC
Define ADC_CLOCK = 5 '16Tad a 8Mhz = 2uSeg, minimo permitido por el micro 1.5uSeg, configuracion ADC
'_______________registros afectados por Define ADC_CLOCK y ADCIN________________
ANSEL = %00010000 'los pin I/O digitales y RA4 analogico
ADCON0 = %01100000 'Fosc/16 a 8Mhz (ADCON1.ADCS2=1) =2uSeg (minimo 1.uSeg), channel RA4
ADCON1 = %01000000 'voltage reference (AVdd/AVss) y seleccion de escala division clock/2 ADCON1.ADCS2=1
'_______________________________________________________________________________
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
TRISA.4 = 1 'como entrada (RA4, adc)
TRISA.6 = 1 'como entrada (RA6, tecla S1)
TRISA.5 = 1 'como entrada (RA5, tecla S2)
PORTB.3 = 1 'luz lcd a on (RB3)
PORTA.7 = 1 'led amarillo a off
PORTB.0 = 1 'led verde a off
'**************************************Inicio Programa*********************************************
Lcdinit 'inicializa el lcd sin cursor
'Definicion de variables -------------------------------------------
'Variables del ADC y Rutina division -----------------------------
Dim entero As Word 'parte entera
Dim decimal As Word 'los dos decimales
Dim division As Long 'almacenara el numero con los dos decimales
Dim adc_4 As Word 'contendra el valor de la entrada del ADC
'Variables temperatura -------------------------------------------
Dim factor_escala As Word 'contiene el factor de correcion para pasar el valor del ADC a voltios, max. 5V
Dim temperatura As Word
Dim temp As Long
'Variables calculo media aritmetica -------------------------------
Dim media_temp(20) As Word
Dim media_indice As Byte
Dim aux_media As Byte
'Asignaciones ----------------------------------------------------
entero = 0
decimal = 0
division = 0
adc_4 = 0
factor_escala = 10 'Factor de escala para un decimal
temperatura = 0
media_indice = 0
aux_media = 0
'------------------------------------------------------
WaitMs 1000 'Espera 1Seg
Lcdout "16f88_LCD_ADC_" 'Escribe en el lcd
Lcdcmdout LcdLine2Home 'Selecciona la linea dos como proxima para escritura
Lcdout "Funcion_1.3"
WaitMs 3000
Lcdcmdout LcdClear
Lcdout "Pruebas LM35DZ" 'EScribe en el lcd
WaitMs 3000 'Espera 3Seg
Lcdcmdout LcdClear 'Borra el display, y cursor al principio de la primera linea
Lcdout "Lectura Pin RA4" 'Muestra los datos en el lcd
'Inicializa variable media_temperatura---------------------------
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
'--------------------------------------Main Programa-----------------------------------------------
main:
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_lcd 'Salto con retorno, rutina muestra los datos por el LCD
WaitMs 1000 'Hace una pausa de 1000mSeg
Goto main
End
'**************************************Subrutinas**********************************************
'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: '____________________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
Lcdcmdout LcdLine2Home 'Selecciona la primera linea y cursor al principio
Lcdout "ADC ", #adc_4, " T ", #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, 10 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:
temp = ((adc_4 * 60) * 100) / 6138 'Temperatura sin decimales, variable tipo long
'temperatura = ((adc_4 * 60) / 613) * 10 'Temperatura sin decimales, variable tipo word
temperatura = temp 'Se pasa de Long a Word, si no se utiliza long se suprime esta linea
Return
Me gustaria que me dijeran, como hago para leer algun dato (letra - numero - lo que sea...) en el LCD Module...
'************************* PIC Entrenadora BASIC (PicEBasic)******************************
'NOMBRE: 16F88_LCD_ADC_Funcion_14
'VERSION: 1.3
'MICRO: PIC16f88A
'FECHA/AUTOR: 04/07, 02/07, 13/07, 12/06 - By COS, PSI v7.41
'Version 1.4
'Para la version 1.3 de hard, 04/07, etpa_lm35xz, LM35: -55 a +150C.
'Se hacen modificaciones para que muestre valores negativos de temperatura con la nueva version del hard.
'Se corrige la rutina de calculo de temperatura para el nuevo circuito acondicionador
'Se corrige la rutina de muestra de datos para mostrar la temperatura con signo.
'Version: 1.3
'Se añade un sensor de temperatura en la entrada RA4, se conecta un LM35DZ por medio de la placa ETPA_LM35xZ, Ver. 1.2
'Se toma una lectura cada 1000mSeg. y se calcula la media aritmetica con 20 muestras
'Se ajusta la placa ETPA_LM35xZ, para maxima temperatura 60º = 3V (RA2)
'Como 5V=1023=100º, 3V=613.8=60º
'Como el rango de temperatura del LM35DZ es de 0º a 100º, el RA1 se ajusta a cero voltios
'Version: 1.2
'Simplificado de la rutina de division
'Modificacion de la rutina print_lcd, para hacerla compatible con el nuevo formato salida de datos de la division
'Version: 1.1
'Se acelera la rutina del display
'Se implementa una rutina tipo funcion para la division
'Version: 1.0
'Descripcion: muestra en el display el valor de la entrada analogica con dos decimales y en voltios
'***********************************************************************************
Define CONFIG = 0x2f50 'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc 'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 8 'Clock en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Activar para simulación, acelera los comandos WaitMs
'-------------------------------------Puertos del LCD-------------------------------------
Define LCD_BITS = 4 'Indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'Bus de datos sera el puerto A
Define LCD_DBIT = 0 'Bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'Bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E sera del puerto B
Define LCD_EBIT = 6 'RB6 como E
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comando del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera despues de inicializar el Display.
'************************DEFINICION DE PUERTOS*************************************
'Asignacion de I/O y valores de inicio de las salidas---------------------
ANSEL = %00000000 'Los pin I/O digitales
Define ADC_SAMPLEUS = 10 'El minimo, configuracion del ADC
Define ADC_CLOCK = 5 '16Tad a 8Mhz = 2uSeg, minimo permitido por el micro 1.5uSeg, configuracion ADC
'_______________Registros afectados por Define ADC_CLOCK y ADCIN________________
ANSEL = %00010000 'Los pin I/O digitales y RA4 analogico
ADCON0 = %01100000 'Fosc/16 a 8Mhz (ADCON1.ADCS2=1) =2uSeg (minimo 1.uSeg), channel RA4
ADCON1 = %01000000 'Voltage reference (AVdd/AVss) y seleccion de escala division clock/2 ADCON1.ADCS2=1
'_______________________________________________________________________________
CMCON = 0x07 'Comparador a off
OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'Puerto B como salidas
TRISA.4 = 1 'Como entrada (RA4, adc)
TRISA.6 = 1 'Como entrada (RA6, tecla S1)
TRISA.5 = 1 'Como entrada (RA5, tecla S2)
PORTB.3 = 1 'Luz lcd a on (RB3)
PORTA.7 = 1 'Led amarillo a off
PORTB.0 = 1 'Led verde a off
'------------------------------------------------------------------
Lcdinit 'Inicializa el lcd sin cursor
'Variables globales
'Variables del ADC y Rutina division------------------------------
Dim entero As Word 'Parte entera
Dim decimal As Word 'Los dos decimales
Dim division As Long 'Almacenara el numero con los dos decimales
Dim adc_4 As Word 'Contendra el valor de la entrada del ADC
Dim aux_adc_4 As Word 'Auxiliar
'Variables temperatura-------------------------------------------
Dim factor_escala As Word 'Contiene el factor de correcion para pasar el valor del ADC a voltios, max. 5V
Dim temperatura As Word 'Almacena la temperatura final
Dim temp As Long 'Contendra la temperatura completa sin coma
Dim signo As Bit 'Indica el signo de la temperatura
'Variables calculo media aritmetica-------------------------------
Dim media_temp(20) As Word 'Numero de muestras para calcular la media aritmetica
Dim media_indice As Byte 'Se utiliza como indice
Dim aux_media As Byte 'Variable auxiliar
'Asignaciones ---------------------------------------------------
entero = 0
decimal = 0
division = 0
adc_4 = 0
factor_escala = 10 'Factor de escala para un decimal
temperatura = 0
media_indice = 0
aux_media = 0
'----------------------------------------------------------------
WaitMs 1000 'Espera 1Seg
Lcdout "16f88_LCD_ADC_" 'Escribe en el lcd
Lcdcmdout LcdLine2Home 'Seleciona la linea dos como proxima para escritura
Lcdout "Funcion_1.4"
WaitMs 3000
Lcdcmdout LcdClear
Lcdout "Pruebas LM35xZ" 'Escribe en el lcd
WaitMs 3000 'Espera 3Seg
Lcdcmdout LcdClear 'Borra el display, y cursor al principio de la primera linea
Lcdout "Lectura Pin RA4" 'Muestra los datos en el lcd
'--------------------------------Inicializa variable media_temperatura---------------------------
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
'--------------------------------------Main Programa-----------------------------------------------
main:
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_lcd 'Salto con retorno, rutina muestra los datos por el LCD
WaitMs 1000 'Hace una pausa de 100mSeg
Goto main
End
'**************************************Subrutinas**********************************************
'Subrutina 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: '____________________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
Lcdcmdout LcdLine2Home 'Selecciona la primera linea y cursor al principio
Lcdout "ADC ", #adc_4, " T " 'Muestra los datos en el lcd
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
'***********************************
'Ejemplo 1
'Solo para simulación, Basic PSI, v7.41
'Cambia de estado un PIN de forma cíclica
'Permite especificar el tiempo del Pin a nivel 1
'y el tiempo a nivel 0.
'***********************************
Define SIMULATION_WAITMS_VALUE = 1 'Activar para simulación
AllDigital 'Todos los pin digitales
TRISB.0 = 0 'Puerto B como salidas
Symbol led = PORTB.0 'Asigna nombre al pin 0 del puerto B
inicio: 'Rutina principal del programa
High led 'Enciende led
Gosub tiempo_on 'Hace una pausa, salto con retorno
Low led 'Apaga led
Gosub tiempo_off 'Hace una pausa, salto con retorno
Goto inicio 'Crea un bucle infinito, sata a la etiqueta inicio
End 'Separa la rutina principal de las subrutinas y funciones.
'Subrutinas *******************
'Tiempo que el led estara encendido
tiempo_on:
WaitMs 500 'Espera 0.5Seg.
Return 'Retorna al programa
'Tiempo que el led estara apagado
tiempo_off:
WaitMs 500 'Espera 0.5Seg.
Return 'Retorna al programa
'Ejemplo 1_1 *********************************************
'Cambia de estado un pin ***********************************
'Solo para simulación, Basic PSI, v7.41 ************************
'-------------------------------------------------------------------------
Define SIMULATION_WAITMS_VALUE = 1 'Activar para simulación
'-----------inicializacion de los modulos internos del micro----------------
AllDigital 'deshabilita el ADC que esta por defecto, todas los pin I/O
TRISB.0 = 0 'PORTB.0 como salida
'Asignacion de nombres-------------------------------------------------
Symbol led = PORTB.0 'asigna nombre a un pin fisico
'Cuerpo del programa (rutina principal)----------------------------------
inicio:
High led 'Pin a nivel 1
WaitMs 500 'Pausa 0.5Seg.
Low led 'Pin a nivel 0
WaitMs 500 'Pausa 0.5Seg.
Goto inicio
End
'*****************************************
'Ejemplo 2
'Pic16F88, PSI v7.41
'Programa juego de lueces
'Usará el oscilador interno del pic por defecto a 4Mhz
'------------------------------------------------------
Define CONFIG = 0x2f50 'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc 'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 4 'Clock en Mhz
Define SIMULATION_WAITMS_VALUE = 1 'Solo se usa cuando se simula, hace que se ignoren los tiempos de los WaitMs
'---------------------------------------
AllDigital 'todas los pin como digitales, deshabilita el ADC que esta siempre por defecto
TRISA = 0 'Salidas excepto RA5
TRISB = 0 'Purto B como salida
Symbol led0 = PORTB.0 'Asignacion de nombres a Pin fisicos del micro
Symbol led1 = PORTB.1
Symbol led2 = PORTB.2
Symbol led3 = PORTB.3
Symbol led4 = PORTB.4
Symbol led5 = PORTB.5
'--------------------------Cuerpo del programa-----------------------
inicio:
High led0 'Pone a alto un pin
Low led1 'Pone a estado bajo un pin
Low led2
Low led3
Low led4
High led5
WaitMs 1000 'Hace una pausa de 1 Seg.
High led0
High led1
Low led2
Low led3
Low led4
High led5
WaitMs 1000
Low led0
Low led1
High led2
High led3
Low led4
Low led5
WaitMs 1000
Low led0
Low led1
High led2
High led3
High led4
Low led5
WaitMs 1000
Goto inicio 'Genera un bucle infinito, salta a la etiqueta inicio.
End 'Indica al compilador donde termina la rutina principal
'Ejemplo 3
'Pic16F88, PSI v7.41
'Cambia el estado de un pin
'Version: 2
'Oscilador interno y por defecto 4Mhz
'------------------------------------------------------
Define CONFIG = 0x2f50 'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc 'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 4 'Clock en Mhz
Define SIMULATION_WAITMS_VALUE = 1 'Solo se usa cuando se simula, hace que se ignoren los tiempos de los WaitMs
'------------------------------------------------------------------------
'Inicializacion de los modulos internos del micro
AllDigital 'Deshabilita el ADC que esta por defecto, todas los pin I/O
TRISA = 0 'Pins PORTA como salidas excepto el RA5
TRISB = 0 'Pins PORTB como salidas
'----------------Asignacion de nombres-----------------------------------
Symbol led = PORTB.0 'asigna nombre a un pin fisico
'-----------------cuerpo del programa------------------------------------
inicio:
Toggle led 'invierte el estado de un pin output
WaitMs 1000 'espera 1Seg.
Goto inicio 'Impide que se termine el programa
End
'*********************************************************
'Ejemplo 4
'Pic16F88 o equivalente, PSI v7.41
'Cambia el estado de un pin
'Version: 3
'While/Wend
'Usará el oscilador interno del pic por defecto a 4Mhz
'------------------------------------------------------
Define CONFIG = 0x2f50 'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc 'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 4 'Clock en Mhz
Define SIMULATION_WAITMS_VALUE = 1 'Solo se usa cuando se simula, hace que se ignoren los tiempos de los WaitMs
'------------------------------------------------------------------------
'Inicializacion de los modulos internos del micro
AllDigital 'Pines como I/O que esta por defecto como analogicos
TRISA = 0 'Pines como salidas excepto RA5
TRISB = 0 'Pines como salidas
'----------------Asignacion de nombres-----------------------------------
Symbol led = PORTB.0 'asigna nombre a un pin fisico
'----------------Declaracion de variables-------------------------------
Dim buclemain As Byte
'-----------------Asignacion de valores a las variables
buclemain = 1
'-----------------Cuerpo del programa------------------------------------
'main:
While buclemain = 1 'Bucle While/Wend, se ejecuta mientas la igualdad sea cierta (bucle infinito)
Toggle led 'Invierte el estado de un pin output
WaitMs 1000 'Espera 1Seg.
Wend
'Goto main 'Impide que se termine el programa (bucle infinito)
End
'*******************************************************
'Ejemplo 5
'Pic16F88 y compatibles, PSI v7.41
'Cambia el estado de un pin
'Version: 4
'While/Wend, If/Then
'Oscilador interno y por defecto 4Mhz
'------------------------------------------------------
Define CONFIG = 0x2f50 'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc 'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 4 'Clock en Mhz
Define SIMULATION_WAITMS_VALUE = 1 'Solo se usa cuando se simula, hace que se ignoren los tiempos de los WaitMs
'------------------------------------------------------------------------
'Inicializacion de los modulos internos del micro-------------
AllDigital 'deshabilita el ADC que esta por defecto, todas los pin I/O
TRISA = 0 'Puerto A como salidas menos RA5
TRISB = 0 'Puerto B como salidas
TRISB.1 = 1 'RB1 como entrada
'Asignacion de nombres-----------------------------------
Symbol led = PORTB.0 'asigna nombre a un pin fisico
Symbol tecla = RB1 'RB1 es la forma abreviada de PORTB.1
'Declaracion de variables-------------------------------
Dim buclemain As Byte
'Asignacion de valores a las variables
buclemain = 1
'Cuerpo del programa------------------------------------
'main:
While buclemain = 1 'bucle While/Wend, se ejecuta mientas la igualdad sea cierta
Toggle led 'invierte el estado de un pin output
WaitMs 1000 'espera 1Seg.
If tecla = 1 Then buclemain = 0 'Proboca que termine el bucle
Wend
'Goto main 'Impide que se termine el programa
End
'*******************************************************
'Ejemplo 6
'Pic16F88 y compatibles, PSI v7.41
'Cambia el estado de un pin
'Version: 4
'While/Wend, If/Then
'Oscilador interno y por defecto 4Mhz
'------------------------------------------------------
Define CONFIG = 0x2f50 'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc 'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 4 'Clock en Mhz
Define SIMULATION_WAITMS_VALUE = 1 'Solo se usa cuando se simula, hace que se ignoren los tiempos de los WaitMs
'------------------------------------------------------------------------
'Inicializacion de los modulos internos del micro-------------
AllDigital 'deshabilita el ADC que esta por defecto, todas los pin I/O
TRISA = 0 'Puerto A como salidas menos RA5
TRISB = 0 'Puerto B como salidas
TRISB.1 = 1 'RB1 como entrada
'Asignacion de nombres-----------------------------------
Symbol led = PORTB.0 'asigna nombre a un pin fisico
Symbol tecla = RB1 'RB1 es la forma abreviada de PORTB.1
'Cuerpo del programa------------------------------------
'main:
While tecla = 0 'bucle While/Wend, se ejecuta mientas la igualdad sea cierta
Toggle led 'invierte el estado de un pin output
WaitMs 1000 'espera 1Seg.
Wend
'Goto main 'Impide que se termine el programa
End
'************************************************************
'Ejemplo 7
'Pic16F88 o similar, PSI v7.41
'Cambia el estado del puerto B (Contador en Binario)
'Version: 1
'While/Wend, If/Then, incremento de variables, salida datos por pueto
'Oscilador interno y por defecto 4Mhz
'------------------------------------------------------
Define CONFIG = 0x2f50 'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc 'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 4 'Clock en Mhz
Define SIMULATION_WAITMS_VALUE = 1 'Solo se usa cuando se simula, hace que se ignoren los tiempos de los WaitMs
'------------------------------------------------------------------------
'Inicializacion de los modulos internos del micro-------------
AllDigital 'Pin com I/O, deshabilita los pin como analogicos
TRISA = 0 'Puerto A como salidas excepto RA5
TRISB = 0 'Puerto B como salidas
TRISA.0 = 1 'RA0 como entrada
PORTB = 0 'El puerto B tendra todos los pin en estado bajo
'----------------Asignacion de nombres-----------------------------------
Symbol led = PORTB.0 'asigna nombre a un pin fisico
Symbol tecla = PORTA.0
'-----------------Declaracion de variables-------------------------------
Dim a As Word 'Declaracin de la variable a como de 16bit
'-----------------Asignacion de valores a las variables
a = 0
'-----------------Cuerpo del programa------------------------------------
'main:
'________Si el valor de la variable "a" es mayor que 255 termina el programa
While a <= 255 'Bucle While/Wend, se ejecuta mientas la igualdad sea cierta
PORTB = a 'Sale el valor de "a" por el puerto B, en binario
WaitMs 1000 'Espera 1Seg.
a = a + 1 'Incrementa el valor de a
If tecla = 1 Then a = 256 'RA0=1 termina el programa
Wend
'Goto main 'Impide que se termine el programa
End
'******************************************************
'Ejemplo 8
'Pic16F88 o similar, PSI v7.41
'Cambia el estado del puerto B
'Versión: 2
'Bucle For/Next, ShiftRight, ShiftLeft, salida datos por puerto B
'Efecto coche fantástico.
'Oscilador interno y por defecto 4Mhz
'------------------------------------------------------
Define CONFIG = 0x2f50 'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc 'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 4 'Clock en Mhz
Define SIMULATION_WAITMS_VALUE = 1 'Solo se usa cuando se simula, hace que se ignoren los tiempos de los WaitMs
'------------------------------------------------------------------------
'Inicializacion de los modulos internos del micro-------------
AllDigital 'Pin como I/O, deshabilita pin analogicos
TRISA = 0 'Puerto A como salida excepto RA5
TRISB = 0 'Puerto B como salida
PORTB = 0 'B tendra todos los pin en estado bajo
'----------------Asignacion de nombres-----------------------------------
Symbol led = PORTB.0 'asigna nombre a un pin fisico
'-----------------Declaracion de variables-------------------------------
Dim a As Word 'Declaración de la variable a como de 16bit
Dim i As Byte 'Variable indice para el bucle For/Next, esta variable no
'importa el valor que tenga cuando llegue al bucle For este la inicializa
'----------------Asignacion de valores a las variables
a = %10000000 'Se da el valor de entrada en forma binaria, no importa en que formato
'se asigne el valor a una variable o registro, el compilador internamente siempre
'lo transforma a binario.
'----------------Cuerpo del programa------------------------------------
inicio:
For i = 1 To 7 'La variable i tomara los valores comprendidos entre 1 to 7
PORTB = a 'Saca el valor de la variable por el puerto B
a = ShiftRight(a, 1) 'Desplaza la variable a un bit a la derecha
WaitMs 1000 'Espera 1Seg.
Next i 'i = 7 termina el bucle y se incrementa i en uno (i=8)
For i = 1 To 7 'La variable i tomara los valores comprendidos entre 1 to 7
PORTB = a 'Saca el valor de la variable por el puerto B
a = ShiftLeft(a, 1) 'Desplaza la variable a un bit a la izquierda
WaitMs 1000 'Espera 1Seg.
Next i 'Si i = 7 termina el bucle y se incrementa i en uno (i=8)
Goto inicio 'Impide que se termine el programa
End
Aqui dejo un ejemplito:
-Ya se puede cambiar la hora del reloj
-Los datos a cambiar quedan en modo parpadeo
-Se modifican solo con dos teclas
-Las teclas responden muy bien, sin fallos, si pulsas rapido respondes rapidas y si pulsas lento van lentas.
Código:
'********************************** PIC Entrenadora BASIC (PicEBasic)******************************
'NOMBRE: 16F88_LCD_RTC_12
'MICRO: PIC16f88A
'********************************** PIC Entrenadora BASIC (PicEBasic)******************************
'NOMBRE: 16F88_Pic_EBasic_LCD_RTC_ADC_10
'MICRO: PIC16F88A
'FECHA/AUTOR: 04/07 - By COS, PSI v7.41
'Version 1.0
'DESCRIPCION: Muestra en el display la fecha, hora (24h)mediante el DS1307 y temperatura (LM35)
'S1 y S2 pulsadas al mismo tiempo, entramos en programacion del reloj
'Una vez en programacion con S1 seleccionamos el dato a cambiar, este queda en modo parpadeo
'Una vez en programacion con S2 incrementamos el dato seleccionado dentro de sus cotas
'S1, pulsado al principio salida del RTC a on, 1Hz, y S2 salida a off, led off
'Se muestra la temperatura en el LCD mediante un LM35, temperatura positiva y negativa
'************************************************************************************************************
Define CONF_WORD = 0x2f50 'Configuración de bits (fuses)
Define CONF_WORD_2 = 0x3ffc 'Configuración de bits (fuses)
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Solo para simulación, acelera los WaitMs
'-------------------------------------Puertos del LCD-------------------------------------
Define LCD_BITS = 4 'Indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'Bus de datos sera el puerto A
Define LCD_DBIT = 0 'Bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'Bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E sera del puerto B
Define LCD_EBIT = 6 'RB6 como E
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comando del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera despues de inicializar el Display.
'Asignacion de nombres ----------------------------------------------
Symbol sda = PORTB.1 'Asignamos nombre al pin que hara de SDA del puerto I2C
Symbol scl = PORTB.4 'Asignamos nombre al pin que hara de SCL del puerto I2C
Symbol led_amarillo = PORTA.7 'Led amarillo
Symbol led_verde = PORTB.0 'Led verde
Symbol luz_lcd = PORTB.3 'Retroiluminacion del lcd
Symbol s1 = RA6 'Se asigna nombre a la tecla
Symbol s2 = RA5 'Se asigna nombre a la tecla
'Definicion de variables ----------------------------------------------
'Variables de los timer -----------------------------------------------
Dim aux_pause As Word 'Variable auxiiar el PAUSE
Dim pause As Word 'Contiene el valor para simular el comando Waitms
Dim timer_1ms As Byte 'Base de tiempos se incrementa cada 1mSeg, timer del PAUSE
Dim timer_base As Byte 'Tiempo referencia para los timer por soft del programa
Dim timer_base_tiempo As Byte 'Contiene el valor del tiempo del timer_base
Dim timer1_ms As Word 'Base de tiempos en ms
Dim timer2_ms As Word 'Base de tiempos en ms
Dim timer3_ms As Word 'Base de tiempos ms
Dim timer1_100ms As Byte 'Base de tiempos msx100
Dim timer2_100ms As Byte 'Base de tiempos msx100
Dim timer3_100ms As Byte 'Base de tiempos msx100
Dim timer1_ms_tiempo As Word 'Contiene el valor del tiempo del timer1_ms
Dim timer2_ms_tiempo As Word 'Contiene el valor del tiempo del timer2_ms
Dim timer3_ms_tiempo As Word 'Contiene el valor del tiempo del timer3_ms
Dim timer1_100ms_tiempo As Byte 'Contiene el valor del tiempo del timer1_100ms
Dim timer2_100ms_tiempo As Byte 'Contiene el valor del tiempo del timer2_100ms
Dim timer3_100ms_tiempo As Byte 'Contiene el valor del tiempo del timer3_100ms
'Variables Programa RTC ------------------------------------------
Dim aux_4h As Byte 'Contendra el nibble alto del dato leido por el I2C
Dim aux_4l As Byte 'Contendra el nibble bajo del dato leido por el I2C
Dim i As Byte 'Variable indice
Dim reg(7) As Byte 'Contendra los valores finales de fecha y hora en el sistema decimal
Dim flash_1 As Bit 'Controla el parpadeo de los digitos del lcd, activo a 1
Dim dato As Byte 'Indica la direccion del RTC a cambiar de valor
Dim flag_1 As Bit 'Activa la rutina de ajuste del reloj, activo a 1
Dim s1_on As Bit 'Tecla pulsada si s1_on=1
Dim s2_on As Bit 'Tecla pulsada si s2_on=1
Dim aux_ajuste As Byte 'Variable auxiliar para la rutina de ajuste
'Variables del ADC y Rutina division (temperatura) ---------
Dim entero As Word 'Parte entera
Dim decimal As Word 'Los dos decimales
Dim division As Long 'Almacenara el numero con los dos decimales
Dim adc_4 As Word 'Contendra el valor de la entrada del ADC
Dim aux_adc_4 As Word 'Auxiliar
'Variables temperatura -----------------------------------------------
Dim factor_escala As Word 'Contiene el factor de correcion para pasar el valor del ADC a voltios, max. 5V
Dim temperatura As Word 'Almacena la temperatura final
Dim temp As Long 'Contendra la temperatura completa sin coma
Dim signo As Bit 'Indica el signo de la temperatura
'Variables calculo media aritmetica (temperatura) ----------
Dim media_temp(20) As Word 'Numero de muestras para calcular la media aritmetica
Dim media_indice As Byte 'Se utiliza como indice
Dim aux_media As Byte 'Variable auxiliar
'Asignaciones ----------------------------------------------------------
Dim error As Byte
error = 0
'Asignacion de valores a las variables (RTC) ---------------
s1_on = 0
s2_on = 0
dato = 7 'Tuera de ajuste o modo normal de trabajo del reloj, de 0 a 6 modo ajuste
flash_1 = 0
flag_1 = 0
timer_base = 0
timer1_ms = 0
timer2_ms = 0
timer3_ms = 0
timer1_100ms = 0
timer2_100ms = 0
timer3_100ms = 0
timer_base_tiempo = 100 'Temporiza 100 mSeg
timer1_ms_tiempo = 50 'Temporiza 50m Seg.
timer2_ms_tiempo = 500 'Temporiza 500 mSeg.
timer3_ms_tiempo = 5 'Temporiza 5 mSeg.
timer1_100ms_tiempo = 10 'Temporiza 1 Seg.
timer2_100ms_tiempo = 255 'Temporiza 25.5 Seg.
timer3_100ms_tiempo = 1 'Temporiza 0.1seg.
'Asiganacion de valores a las variables (temperatura) -----
entero = 0
decimal = 0
division = 0
adc_4 = 0
factor_escala = 10 'Factor de escala para un decimal
temperatura = 0
temp = 0
media_indice = 0
aux_media = 0
'Asignacion de I/O y valores de inicio de las salidas ------
Define ADC_SAMPLEUS = 10 'El minimo, configuracion del ADC
Define ADC_CLOCK = 5 '16Tad a 8Mhz = 2uSeg, minimo permitido por el micro 1.5uSeg, configuracion ADC
'_______________Registros afectados por Define ADC_CLOCK y ADCIN________________
ANSEL = %00010000 'Los pin I/O digitales y RA4 analogico
ADCON0 = %01100000 'Fosc/16 a 8Mhz (ADCON1.ADCS2=1) =2uSeg (minimo 1.uSeg), channel RA4
ADCON1 = %01000000 'Voltage reference (AVdd/AVss) y seleccion de escala division clock/2 ADCON1.ADCS2=1
'ANSEL = %00000000 'Los pin I/O digitales
CMCON = 0x07 'Comparador a off
OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'Puerto B como salidas
TRISA.4 = 1 'Como entrada (RA4, adc)
TRISA.6 = 1 'Como entrada (RA6, tecla S1)
TRISA.5 = 1 'Como entrada (RA5, tecla S2)
PORTB.3 = 1 'Luz lcd a on (RB3)
PORTA.7 = 1 'Led amarillo a off
PORTB.0 = 1 'Led verde a off
'Inicializacion de TMR1 e Interrupciones ------------------
T1CON.TMR1CS = 0 'Asigna el reloj interno al timer1, se incrementa cada ciclo de instruccion
T1CON.T1CKPS0 = 0 'Factor del preescales del timer1, 0
T1CON.T1CKPS1 = 0 'Factor del preescales del timer1, 0
TMR1H = 0xf8 'Carga el registro del contador para que desborde cada 1mSeg, byte alto
TMR1L = 0x30 'Carga el registro del contador para que desborde cada 1mSeg, byte bajo
T1CON.TMR1ON = 1 'Habilitacion del TMR1, comienza a incrementarce
'PIE1.TMR1IE = 1 'Activa las interrupciones del timer1
INTCON.PEIE = 1 'Bit de habilitacion de interrupciones de perifericos
Enable 'INTCON.GIE habilita todas las interrupciones globales
'-----------------------------------------------------------------------
Lcdinit 'Inicializa el lcd sin cursor
PIE1.TMR1IE = 1 'Habilita interrupcion del timer1
pause = 1000
Gosub pause_ms 'Espera el tiempo indicado en pause
Lcdout "16F88LCD_RTC/I2C" 'Escribe en el lcd
Lcdcmdout LcdLine2Home 'Seleciona la linea dos como proxima para escritura
Lcdout "ADC_Temperatura" 'Escribe en el lcd
pause = 3000
Gosub pause_ms 'Espera el tiempo indicado en pause
Lcdcmdout LcdClear 'Borra el display y cursor a casa
'Inicializa media_temperatura -----------------------------
Gosub inicializa_temp
'Inicializa los registros del RTC ---------------------------
Gosub inicaliza_rtc
'Inicializa la salida del RTC --------------------------------
PIE1.TMR1IE = 0 'Deshabilita las interrupciones del timer1
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
'Bucle principal
main:
error = 0
If s1 = 1 And s1_on = 1 Then s1_on = 0 'Libera el pulsador S1, control anti-rebotes tecla
If s2 = 1 And s2_on = 1 Then s2_on = 0 'Libera el pulsador S2, control anti-rebotes tecla
If s1 = 0 And s2 = 0 And s1_on = 0 And s2_on = 0 And flag_1 = 0 Then '________Modo ajuste
flag_1 = 1 'Activa la rutina de ajustes
dato = 0 'Activo cambio de la hora
timer1_ms = 0 'Resetea la base de tiempos de retraso entre pulsacion y pulsacion de S1
timer3_ms = 0 'Resetea la base de tiempos de retraso entre pulsacion y pulsacion de S2
s1_on = 1 'Bloquea la tecla S1, elimina rebotes
s2_on = 1 'Bloquea la tecla s2, elimina rebotes
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
timer2_100ms = 0
Endif
Goto main
End
'********************************* Subrutinas **********************************************
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
ajuste_reloj: 'Rutina de ajuste del reloj
If s1 = 1 And s1_on = 1 Then s1_on = 0 'Libera el pulsador S1, control anti-rebotes tecla
If s2 = 1 And s2_on = 1 Then s2_on = 0 'Libera el pulsador S2, control anti-rebotes tecla
'________________________Control posicion del dato a variar en el reloj
If s1 = 0 And s1_on = 0 And s2 = 1 Then 'Detecta tecla S1 y eliminacion de rebotes de la misma
If timer1_ms >= timer1_ms_tiempo Then 'Establece el retraso entre pulsaciones de S1
dato = dato + 1 'Seleciona el dato a ser modificado
s1_on = 1 'La tecla queda bloqueada
If dato > 6 Then flag_1 = 0 'Indica fin de rutina de ajuste
timer1_ms = 0 'Resetea la base de tiempos de retraso entre pulsacion y pulsacion de S1
Endif
Endif '_____________________________
'____________Lectura de la hora para su modificacion y posterior grabacion, rutina BCD
If s2 = 0 And s2_on = 0 And s1 = 1 Then 'Deteca tecla S2 y eliminacion de rebotes de la misma
If timer3_ms >= timer3_ms_tiempo Then 'Establece el retraso entre pulsaciones de S2
s2_on = 1 'La tecla queda bloqueada
timer3_ms = 0 'Resetea la base de tiempos de retraso entre pulsacion y pulsacion de S2
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
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
'--------------------------------------Subrutina 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 " "
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 'Variable 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
pause_ms: 'Rutina de espera, rutina tipo Waitms, pause establese el tiempo total en mSeg
aux_pause = 0 'Variable auxiliar lleva la cuenta de los ms
timer_1ms = 0 'Al borrar el contador se activa y comienza la cuenta de 1mSeg
While aux_pause <= pause 'Tiempo en mSeg maximos a contar
aux_pause = aux_pause + 1 'Variable auxiliar lleva la cuenta de los ms
If timer_1ms > 0 Then timer_1ms = 0 'Al borrar el contador se activa y cuenta 1mSeg
While timer_1ms < 1 'Espera un miliesegundo
Wend
Wend
Return
'***********************************Interrupciones*****************************************************
On Interrupt 'Comienzan las rutinas de las interrupciones, desactiva las interrupciones
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 < 1 Then timer_1ms = 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
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
PIR1.TMR1IF = 0 'Borra el flag de salto del tmr1
Endif
If s1 = 0 Then led_verde = 0 'Muestra el estado de la tecla, tecla S1 a on, led verde a on
If s1 = 1 Then led_verde = 1 'Muestra el estado de la tecla, tecla S1 a off, led verde a off
If s2 = 0 Then led_amarillo = 0 'Muestra el estado de la tecla, tecla S2 a on, led amarillo a on
If s2 = 1 Then led_amarillo = 1 'Muestra el estado de la tecla, tecla S2 a on, led amarillo a on
Resume 'Activa las interrupciones y retorna el curso normal del programa, antes del salto
'---------------
'***************** Placa Entrenadora (PIC EBadic) ***************************************
'NOMBRE:16F88_Pic_EBasic_LCD_Timer1_ADC_PWM_RB4
'Descripcion: Control de un servomotor (Futaba S3003) usando el ADC, Timer1, Interrupciones
'Micro: pic16f88 / 8mhz reloj interno
'Version: 1.0
'Fecha/Autor: 4/07, By COS
'Uso del LCD con bus de datos a 4Bit y sin pin de RW
'uso del timer1 para controlar el PWM
'lectura de entrada analogica y conversion a tiempo
'conversion de tiempo a valores a cargar en el timer1
'************************************************************************************************
'-------------------------------------Puertos del LCD---------------------------------------------
Define LCD_BITS = 4 'indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'el bus de datos sera el puerto A
Define LCD_DBIT = 0 'el bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'el bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'se usara el RB7 como RS
Define LCD_EREG = PORTB 'el bit de control E sera del puerto B
Define LCD_EBIT = 6 'se usara el RB6 como E
'Define LCD_RWREG = PORTA 'el bit de control RW sera del puerto A (si se suprime el compilador no protesta)
'Define LCD_RWBIT = 5 'se usara el RA5 como RW (si se suprime el compilador no protesta)
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comando del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 5 '50 'Tiempo de espera despues de inicializar el Display, solo se ejecuta una vez en mSeg.
'****************************************************************************************************
Define SIMULATION_WAITMS_VALUE = 1 'Ignora los valores de Waitms
'--------------------------------------Reasignacion de nombres---------------------------------------
Symbol led_amarillo = PORTA.7 'led amarillo
Symbol led_verde = PORTB.0 'led verde
Symbol luz_lcd = PORTB.3 'retroiluminacion del lcd
'------------------------------------declaracion de variables---------------------------------------
'************************************variables de los timer****************************************
'-------------------------------Variables del ADC y Rutina division------------------------------
Dim adc_4 As Word 'contiene el valor de la entrada ADC
'-------------------------------------------------------------------------------------------------
Dim pwm As Word 'variable de paso
Dim pwm_nop As Word 'variable de paso
Dim aux_pwm As Long 'calculo del tiempo a ON, de la señal de control
Dim aux_pwm_nop As Long 'calculo del tiempo a OFF, de la señal de cotrol
Dim timer_pwm As Word 'valor del tiempo a on, para ser interpretado
Dim timer_pwm_nop As Word 'valor del tiempo a off, para ser interpretado
Dim flag1_pwm As Byte 'variable que determina si ON o a OFF de la señal de control
Dim flag2_pwm As Byte 'controla la actualizacion de una nueva posicion del servo
'--------------------------------Variables generales-----------------------------------------------
'------------------------------------asignacion de valores a las variables--------------------------
pwm = 62535
pwm_nop = 28535
aux_pwm = 62535
flag1_pwm = 1
flag2_pwm = 0
adc_4 = 0
'------------------------------------Definicion de puertos------------------------------------------
Define ADC_SAMPLEUS = 0 'el minimo, configuracion del ADC
Define ADC_CLOCK = 5 '16Tad a 8Mhz = 2uSeg, minimo permitido por el micro 1.5uSeg, configuracion ADC
'_______________registros afectados por Define ADC_CLOCK y ADCIN________________
ANSEL = %00010000 'los pin I/O digitales y RA4 analogico
ADCON0 = %01100000 'Fosc/16 a 8Mhz (ADCON1.ADCS2=1) =2uSeg (minimo 1.uSeg), channel RA4
ADCON1 = %01000000 'voltage reference (AVdd/AVss) y seleccion de escala division clock/2 ADCON1.ADCS2=1
'_______________________________________________________________________________
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
TRISA.4 = 1 'como entrada (RA4, adc)
TRISA.6 = 1 'como entrada (RA6, tecla S1)
TRISA.5 = 1 'como entrada (RA5, tecla S2)
PORTB.3 = 1 'luz lcd a on (RB3)
PORTA.7 = 1 'led amarillo a off, negado
PORTB.0 = 1 'led verde a off, negado
'------------------------------------Inicializacion de Interrupciones-----------------------------
T1CON.TMR1CS = 0 'asigna el reloj interno al timer1, se incrementa cada ciclo de instruccion
T1CON.T1CKPS0 = 0 'factor del preescales del timer1, 0
T1CON.T1CKPS1 = 0 'factor del preescales del timer1, 0
TMR1H = 0xf8 'carga el registro del contador para que desborde cada 1mSeg, byte alto
TMR1L = 0x30 'carga el registro del contador para que desborde cada 1mSeg, byte bajo
T1CON.TMR1ON = 1 'habilitacion del TMR1, comienza a incrementarce
'PIE1.TMR1IE = 1 'activa las interrupciones del timer1
INTCON.PEIE = 1 'bit de habilitacion de interrupciones de perifericos
Enable 'INTCON.GIE habilita todas las interrupciones globales
'------------------------------------Inicio-------------------------------------------------------
Lcdinit 'inicializa el lcd sin cursor
WaitMs 1000 'espera 1Seg
Lcdout "LCD_Tmr1_ADC_PWM" 'escribe en el lcd
Lcdcmdout LcdLine2Home 'seleciona la linea dos como proxima para escritura
Lcdout "Servo S3003" 'escribe en el lcd
WaitMs 3000 'espera 3Seg
Lcdcmdout LcdClear 'borra el display
PIE1.TMR1IE = 1 'activa las interrupciones del timer1
'------------------------------------rutinas del Programa----------------------
main: 'comienza el programa principal
If flag2_pwm = 1 Then 'permite una nueva posicion del servo
Gosub lee_adc 'salto con retorno a la rutina de lectura del ADC
aux_pwm = ((adc_4 + 213) * 223) / (1023 + 213) 'tiempo a ON de la señal de control del servo
'213, es el valor que se le asigna por defecto al ADC cuando el potenciometro esta a cero
If aux_pwm < 45 Then aux_pwm = 45 'tiempo minimo a ON, de la señal de control del servo
aux_pwm_nop = 2000 - aux_pwm 'calculo del tiempo de la señal de control a OFF
aux_pwm_nop = 65535 - ((aux_pwm_nop * 100) / 5) 'valor a cargar en el timer1, OFF
aux_pwm = 65535 - ((aux_pwm * 100) / 5) 'valor a cargar en el timer1, ON
pwm = aux_pwm 'se cambia de long a word, para acelerar la rutina de interrupciones
pwm_nop = aux_pwm_nop 'se cambia de long a word, apra acelerar la rutina de interrupciones
Gosub print_lcd 'salto con retorno a la rutina que muestra los dato por el display
flag2_pwm = 0 'bloquea la rutina hasta que se procese la nueva posicion
Endif
Goto main 'impide que termine el programa principal
End 'es conveniente ponerlo siempre segun el manual
'--------------------------------------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 carga en adc_4
Return
print_lcd: '____________________muestra los datos por el display
Lcdcmdout LcdLine1Home 'cursor al principio
Lcdout "ADC ", #adc_4, " ", #pwm, " " 'muestra los datos en el lcd
Return
'--------------------------------Interrupciones---------------------------------------------------
On Interrupt 'Comienzan las rutinas de las interrupciones, desactiva las interrupciones
Save System 'Guarda los valores del sistema para poder reemprender el curso normal del programa
'___________Rutina generadora del PWM, para la entrada de control del servomotor
If flag1_pwm = 1 Then 'controla el tiempo de la señal del servo a OFF
RB4 = 0 'salida del servo a OFF
TMR1H = timer_pwm_nop.HB 'recarga el contador del timer1 para que desborde, tiempo a off
TMR1L = timer_pwm_nop.LB 'recarga el contador del timer1 para que desborde, tiempo a off
flag1_pwm = 0 'permite la alternancia entre señal del servo a ON o a OFF
flag2_pwm = 1 'permiten que entren nuevos valoles del ADC, nueva posicion del servomotor
timer_pwm = pwm 'recarga la rutina con los nuevos valores del potenciometro
timer_pwm_nop = pwm_nop 'recara la rutina con los nuevos valores del potenciometro
Else
RB4 = 1 'salida de la señal de contol del servo a ON
TMR1H = timer_pwm.HB 'recarga el contador del timer1 para que desborde, tiempo a on
TMR1L = timer_pwm.LB 'recarga el contador del timer1 para que desborde, tiempo a on
flag1_pwm = 1 'permite la alternancia entre señal del servo a ON o a OFF
Endif
PIR1.TMR1IF = 0 'borra el flag de salto del tmr1
Resume 'activa las interrupciones y retorna al curso normal del programa antes del salto
End
'***************** Placa Entrenadora (PIC EBadic) ***************************************
'NOMBRE:16F88_Pic_EBasic_Timer0
'Descripcion: Base de tiempos programable empleando el Timer0
'Micro: pic16f88 / 8mhz reloj interno
'Version: 1.0
'Fecha/Autor: 4/07, By COS
'Las bases de tiempos no interrumpen el flujo normal del programa
'************************************************************************************************
'Define SIMULATION_WAITMS_VALUE = 1 'Ignora los valores de Waitms
'--------------------------------------Reasignacion de nombres---------------------------------------
Symbol led_amarillo = PORTA.7 'led amarillo
Symbol led_verde = PORTB.0 'led verde
Symbol luz_lcd = PORTB.3 'retroiluminacion del lcd
'--------------------------------Variables generales-----------------------------------------------
Dim timer0_1ms As Word 'declaracion de la base de tiempos
Dim timer0_1ms_tiempo As Word 'determina el tiempo en que la base de tiempos estara incrementandose
'------------------------------------asignacion de valores a las variables--------------------------
timer0_1ms = 0 'inicializa la base de tiempos
timer0_1ms_tiempo = 1 'mSeg., tiempo en que el led verde estara cambiando de estado
'------------------------------------Definicion de puertos------------------------------------------
ANSEL = %00010000 'los pin I/O digitales y RA4 analogico
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
TRISA.4 = 1 'como entrada (RA4, adc)
TRISA.6 = 1 'como entrada (RA6, tecla S1)
TRISA.5 = 1 'como entrada (RA5, tecla S2)
PORTB.3 = 1 'luz lcd a on (RB3)
PORTA.7 = 1 'led amarillo a off, negado
PORTB.0 = 1 'led verde a off, negado
'------------------------------------Inicializacion de Interrupciones por TIMER0-----------------------------
OPTION_REG.T0CS = 0 'selecciona reloj interno
OPTION_REG.PSA = 0 'asigna el prescales al timer0
OPTION_REG.PS0 = 1 'bits de la seleccion del factor de division,prescaler 16
OPTION_REG.PS1 = 1 'bits de la seleccion del factor de division,prescaler 16
OPTION_REG.PS2 = 0 'bits de la seleccion del factor de division,prescaler 16
INTCON.PEIE = 1 'bit de habilitacion de interrupciones de perifericos
Enable 'INTCON.GIE habilita todas las interrupciones globales
INTCON.TMR0IF = 0 'borra el flag de desbordamiento del timer0
TMR0 = 130 'cargo el registro del tmr0 para que desborde cada 1mS
INTCON.TMR0IE = 1 'habilita las interrupciones del timer0
'------------------------------------rutinas del Programa----------------------
main: 'comienza el programa principal
'_________________Cambia de estado el led verde segun el valor de timer0_1ms_tiempo, en mSeg
If timer0_1ms >= timer0_1ms_tiempo Then 'control
Toggle led_verde 'invierte el estado del pin
timer0_1ms = 0 'inicializa la base de tiempos timer0_1ms
Endif
'_________________
Goto main 'impide que termine el programa principal
End 'es conveniente ponerlo siempre segun el manual
'--------------------------------Interrupciones---------------------------------------------------
On Interrupt 'Comienzan las rutinas de las interrupciones, desactiva las interrupciones
Save System 'Guarda los valores del sistema para poder reemprender el curso normal del programa
If timer0_1ms <= timer0_1ms_tiempo Then timer0_1ms = timer0_1ms + 1 'base de tiempos
TMR0 = 130 'recarga el registro del tiemr0 para que desborde cada 1mSeg.
INTCON.TMR0IF = 0 'borra el flag de desbordamiento del timer0
Resume 'activa las interrupciones y retorna al curso normal del programa antes del salto
'End
'***************** Placa Entrenadora (PIC EBadic) ***************************************
'NOMBRE:16F88_Pic_EBasic_LCD_Timer1_ADC_PWM_Servo_11
'Descripcion: Control de un servomotor (Futaba S3003) usando el ADC, Timer1, Interrupciones
'Micro: pic16f88 / 8mhz reloj interno
'Version: 1.0
'Fecha/Autor: 4/07, By COS
'Uso del LCD con bus de datos a 4Bit y sin pin de RW
'uso del timer1 para controlar el PWM, de periodo 20mSeg.
'lectura de entrada analogica y conversion a tiempo
'conversion de tiempo a valores a cargar en el timer1
'Version 1.1
'se fusiona la rutina de divicion con decimales
'para mostrar el tiempo del ducty cycle en pantalla, minimo 0.43mSeg. y maximo 2.26mSeg.
'modificacion del formato de salida de la informacion por el lcd
'************************************************************************************************
'-------------------------------------Puertos del LCD---------------------------------------------
Define LCD_BITS = 4 'indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'el bus de datos sera el puerto A
Define LCD_DBIT = 0 'el bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'el bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'se usara el RB7 como RS
Define LCD_EREG = PORTB 'el bit de control E sera del puerto B
Define LCD_EBIT = 6 'se usara el RB6 como E
'Define LCD_RWREG = PORTA 'el bit de control RW sera del puerto A (si se suprime el compilador no protesta)
'Define LCD_RWBIT = 5 'se usara el RA5 como RW (si se suprime el compilador no protesta)
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comando del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 5 '50 'Tiempo de espera despues de inicializar el Display, solo se ejecuta una vez en mSeg.
'****************************************************************************************************
Define SIMULATION_WAITMS_VALUE = 1 'Ignora los valores de Waitms
'--------------------------------------Reasignacion de nombres---------------------------------------
Symbol led_amarillo = PORTA.7 'led amarillo
Symbol led_verde = PORTB.0 'led verde
Symbol luz_lcd = PORTB.3 'retroiluminacion del lcd
'------------------------------------declaracion de variables---------------------------------------
'-------------------------------Variables del ADC y Rutina division------------------------------
Dim entero As Word 'parte entera
Dim decimal As Word 'los dos decimales
Dim division As Long 'almacenara el numero con los dos decimales
Dim factor_escala As Word 'situa la parte entera del numero
Dim reg_timer1 As Word 'valor maximo que puede contener el registro del TMR1
Dim tiempo_ms As Word 'tiempo a on de la señal de control del servo en mSeg.
Dim aux_adc_4 As Word 'auxiliar
Dim adc_4 As Word 'contiene el valor de la entrada ADC
'----------------------------------------variables calculo y control PWM-----------------------------
Dim pwm As Word 'variable de paso
Dim pwm_nop As Word 'variable de paso
Dim aux_pwm As Long 'calculo del tiempo a ON, de la señal de control
Dim aux_pwm_nop As Long 'calculo del tiempo a OFF, de la señal de cotrol
Dim timer_pwm As Word 'valor del tiempo a on, para ser interpretado
Dim timer_pwm_nop As Word 'valor del tiempo a off, para ser interpretado
Dim flag1_pwm As Byte 'variable que determina si ON o a OFF de la señal de control
Dim flag2_pwm As Byte 'controla la actualizacion de una nueva posicion del servo
'------------------------------------asignacion de valores a las variables--------------------------
pwm = 62535
pwm_nop = 28535
aux_pwm = 62535
flag1_pwm = 1
flag2_pwm = 0
entero = 0
decimal = 0
division = 0
adc_4 = 0
reg_timer1 = 65535 'maximo valor registro de 16 bit del TMR1
factor_escala = 100 'factor de escala para dos decimal
'------------------------------------Definicion de puertos------------------------------------------
Define ADC_SAMPLEUS = 0 'el minimo, configuracion del ADC
Define ADC_CLOCK = 5 '16Tad a 8Mhz = 2uSeg, minimo permitido por el micro 1.5uSeg, configuracion ADC
'_______________registros afectados por Define ADC_CLOCK y ADCIN________________
ANSEL = %00010000 'los pin I/O digitales y RA4 analogico
ADCON0 = %01100000 'Fosc/16 a 8Mhz (ADCON1.ADCS2=1) =2uSeg (minimo 1.uSeg), channel RA4
ADCON1 = %01000000 'voltage reference (AVdd/AVss) y seleccion de escala division clock/2 ADCON1.ADCS2=1
'_______________________________________________________________________________
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
TRISA.4 = 1 'como entrada (RA4, adc)
TRISA.6 = 1 'como entrada (RA6, tecla S1)
TRISA.5 = 1 'como entrada (RA5, tecla S2)
PORTB.3 = 1 'luz lcd a on (RB3)
PORTA.7 = 1 'led amarillo a off, negado
PORTB.0 = 1 'led verde a off, negado
'------------------------------------Inicializacion de Interrupciones-----------------------------
T1CON.TMR1CS = 0 'asigna el reloj interno al timer1, se incrementa cada ciclo de instruccion
T1CON.T1CKPS0 = 0 'factor del preescales del timer1, 0
T1CON.T1CKPS1 = 0 'factor del preescales del timer1, 0
TMR1H = 0xf8 'carga el registro del contador para que desborde cada 1mSeg, byte alto
TMR1L = 0x30 'carga el registro del contador para que desborde cada 1mSeg, byte bajo
T1CON.TMR1ON = 1 'habilitacion del TMR1, comienza a incrementarce
'PIE1.TMR1IE = 1 'activa las interrupciones del timer1
INTCON.PEIE = 1 'bit de habilitacion de interrupciones de perifericos
Enable 'INTCON.GIE habilita todas las interrupciones globales
'------------------------------------Inicio-------------------------------------------------------
Lcdinit 'inicializa el lcd sin cursor
WaitMs 1000 'espera 1Seg
Lcdout "LCD_Tmr1_ADC_PWM" 'escribe en el lcd
Lcdcmdout LcdLine2Home 'seleciona la linea dos como proxima para escritura
Lcdout "Servo S3003" 'escribe en el lcd
WaitMs 3000 'espera 3Seg
Lcdcmdout LcdClear 'borra el display
PIE1.TMR1IE = 1 'activa las interrupciones del timer1
'------------------------------------rutinas del Programa----------------------
main: 'comienza el programa principal
If flag2_pwm = 1 Then 'permite una nueva posicion del servo
Gosub lee_adc 'salto con retorno a la rutina de lectura del ADC
aux_pwm = ((adc_4 + 240) * 250) / (1023 + 370) 'tiempo a ON de la señal de control del servo
'240 y 370 fijan los mavolores minimo y valores maximos del ducty cycle
aux_pwm_nop = 2000 - aux_pwm 'calculo del tiempo de la señal de control a OFF
aux_pwm_nop = 65535 - ((aux_pwm_nop * 100) / 5) 'valor a cargar en el timer1, OFF
aux_pwm = 65535 - ((aux_pwm * 100) / 5) 'valor a cargar en el timer1, ON
pwm = aux_pwm 'se cambia de long a word, para acelerar la rutina de interrupciones
pwm_nop = aux_pwm_nop 'se cambia de long a word, apra acelerar la rutina de interrupciones
Gosub print_lcd 'salto con retorno a la rutina que muestra los dato por el display
flag2_pwm = 0 'bloquea la rutina hasta que se procese la nueva posicion
tiempo_ms = ((reg_timer1 - pwm) * 5) / 100 'calculo en mSeg.
division = dvsion_dcmles(tiempo_ms, factor_escala) 'llama a la funcion dvsion_dcmles, que retorna un long
Gosub formato_decimales 'extrae e imprime con formato decimal
Endif
Goto main 'impide que termine el programa principal
End 'es conveniente ponerlo siempre segun el manual
formato_decimales: '____________________da formato a los decimales y los saca por el lcd
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 #entero, "." 'muestra los datos en el lcd
If decimal < 10 Then Lcdout "0"
Lcdout #decimal, " " 'muestra los datos en el lcd
Return
'--------------------------------------Subrrutina lectura ADC
lee_adc: '_______________________lee la entrada analogica
Adcin 4, adc_4 'lee el valor de la entrada analogica y lo carga en adc_4
Return
print_lcd: '____________________muestra los datos por el display
Lcdcmdout LcdLine1Home 'cursor al principio
Lcdout "ADC--TMR1--mSeg." 'magnitudes
Lcdcmdout LcdLine2Home 'selecciona la linea dos del lcd y cursor a inicio
If adc_4 < 1000 Then Lcdout "0" 'para mantener la plantilla
If adc_4 < 100 Then Lcdout "0" 'para mantener la plantilla
If adc_4 < 10 Then Lcdout "0" 'para mantener la plantilla de salida
Lcdout #adc_4, " ", #pwm, " " '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 * 100) / 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 1 o mas digitos siempre
End Function
'--------------------------------Interrupciones---------------------------------------------------
On Interrupt 'Comienzan las rutinas de las interrupciones, desactiva las interrupciones
Save System 'Guarda los valores del sistema para poder reemprender el curso normal del programa
'___________Rutina generadora del PWM, para la entrada de control del servomotor
If flag1_pwm = 1 Then 'controla el tiempo de la señal del servo a OFF
RB4 = 0 'salida del servo a OFF
TMR1H = timer_pwm_nop.HB 'recarga el contador del timer1 para que desborde, tiempo a off
TMR1L = timer_pwm_nop.LB 'recarga el contador del timer1 para que desborde, tiempo a off
flag1_pwm = 0 'permite la alternancia entre señal del servo a ON o a OFF
flag2_pwm = 1 'permiten que entren nuevos valoles del ADC, nueva posicion del servomotor
timer_pwm = pwm 'recarga la rutina con los nuevos valores del potenciometro
timer_pwm_nop = pwm_nop 'recara la rutina con los nuevos valores del potenciometro
Else
RB4 = 1 'salida de la señal de contol del servo a ON
TMR1H = timer_pwm.HB 'recarga el contador del timer1 para que desborde, tiempo a on
TMR1L = timer_pwm.LB 'recarga el contador del timer1 para que desborde, tiempo a on
flag1_pwm = 1 'permite la alternancia entre señal del servo a ON o a OFF
Endif
PIR1.TMR1IF = 0 'borra el flag de salto del tmr1
Resume 'activa las interrupciones y retorna al curso normal del programa antes del salto
End
'********************************** PIC Entrenadora BASIC ***************************************
'NOMBRE: 16F88_Pic_EBasic_LCD_RS232_Menu_10
'VERSION: 1.0
'MICRO: PIC16F88
'Fecha/Autor: 4/07 By COS
'DESCRIPCION: Control de los led de la EBasic por medio de un menu en el Hyperterminal
'programar el hyperterminal del Windows:
'Bits por segundo: 4800
'Bits de datos: 8
'Paridad: Ninguno
'Control de flujo: Ninguno
'LCD a 4 bit, sin bit de RW
'************************************************************************************************
'-------------------------------------PUERTOS DEFINIDOS POR EL SISTEMA----------------------------
'-------------------------------------Puertos del LCD---------------------------------------------
Define LCD_BITS = 4 'indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'el bus de datos sera el puerto A
Define LCD_DBIT = 0 'el bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'el bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'se usara el RB7 como RS
Define LCD_EREG = PORTB 'el bit de control E sera del puerto B
Define LCD_EBIT = 6 'se usara el RB6 como E
'Define LCD_RWREG = PORTA 'el bit de control RW sera del puerto A (si se suprime el compilador no protesta)
'Define LCD_RWBIT = 5 'se usara el RA5 como RW (si se suprime el compilador no protesta)
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comand del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 5 '50 'Tiempo de espera despues de inicializar el Display, solo se ejecuta una vez en mSeg.
'--------------------------------Reasignacion de nombres---------------------------------------
Symbol led_amarillo = PORTA.7 'led amarillo
Symbol led_verde = PORTB.0 'led verde
'--------------------------------Definicion de caracteres de control del Hyperterminal--------
Const ff = 0x0c 'FF, Avance de pagina
Const bell = 0x07 'BELL, Señal sonora
Const sp = 0x20 'SP, Espacio
Const bksp = 0x08 'BKSP, Retroceso
'--------------------------------------Declaracion DE VARIABLES-------------------------------------
'-------------------------------------Variables sub_rutinas del puerto serie---------------------
Dim assi As Byte 'Contiene el valor de lectura del puerto serie
Dim n_usart As Byte 'Numero de datos del USART y del bufer IMAGEN de control
Dim usart As Byte 'Variable indice que apunta al ultimo dato adquirido por la USART
Dim aux_usart As Byte 'Auxiliar de la variable indice usart del USART
Dim c_serial As Byte 'Como USART pero para la lectura de control del bufer IMAGEN
Dim bufer As Byte 'Indica si hay datos por leer en el bufer USART
Dim n_aux As Byte 'contador para borrar el bufer_soft
'************************************variables de los timer****************************************
Dim pause As Word 'contiene el valor para simular el comando Waitms
Dim timer_1ms As Word 'base de tiempos se incrementa cada 1mSeg, timer del PAUSE
'------------------------------------Variables tipo array puerto serie----------------------------------
Dim usart_imagen(91) As Byte 'Componen el bufer IMAGEN para control del bufer USART
Dim usart_bufer(91) As Byte 'Componen el bufer de la USART de bajo nivel
'-----------------------------------------------ASIGNACIONES----------------------------------------
'-------------------------------------Asignacion de valores del TIMER1----------------------------
pause = 0 'genera una pausa en MSeg
timer_1ms = 0 'en mSeg
'-------------------------------------Asigna valores a las variables de la rutina del puerto serie--
usart = 0
aux_usart = 0
c_serial = 0
bufer = 0
n_usart = 90
assi = 0
n_aux = 0
'**************************************DEFINICION DE PUERTOS*************************************
'----------------------ASIGNACION DE I/O y valores de inicio de las salidas---------------------
ANSEL = 0x00 'los pin I/O digitales
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
TRISA.4 = 1 'como entrada (RA4, adc)
TRISA.6 = 1 'como entrada (RA6, tecla S1)
TRISA.5 = 1 'como entrada (RA5, tecla S2)
'TRISB.5 = 0 'RB5(Tx, RS232)
TRISB.2 = 1 'RB2 (Rx, RS232)
PORTB.3 = 1 'luz lcd a on (RB3)
PORTA.7 = 1 'led amarillo a off
PORTB.0 = 1 'led verde a off
'------------------------------------INICIO DEL PUERTO SERIE, TIMER E INTERRUPCIONES------------------
Hseropen 4800 'Velocidad del puerto serie e inicializa los comandos de bajo nivel que controlan la USART
Gosub clear_bufer 'Borra el BUFFER IMAGEN y por lo tanto tambien al USART, OBLIGATORIO POR LO MENOS UNA VEZ
T1CON.TMR1CS = 0 'asigna el reloj interno al timer1, se incrementa cada ciclo de instruccion
T1CON.T1CKPS0 = 0 'factor del preescales del timer1, 0
T1CON.T1CKPS1 = 0 'factor del preescales del timer1, 0
TMR1H = 0xf8 'carga el registro del contador para que desborde cada 1mSeg, byte alto
TMR1L = 0x2f 'carga el registro del contador para que desborde cada 1mSeg, byte bajo
T1CON.TMR1ON = 1 'habilitacion del TMR1, comienza a incrementarce
'PIE1.TMR1IE = 1 'activa las interrupciones del timer1
'PIE1.RCIE = 1 'Activa la interrupcion de la USART en modo rx
INTCON.PEIE = 1 'bit de habilitacion de interrupciones de perifericos
Enable 'INTCON.GIE habilita todas las interrupciones globales
'--------------------------------------Inicio Programa--------------------------------------------------
Lcdinit 'inicializa el LCD sin cursor
PIE1.TMR1IE = 1 'activa las interrupciones del timer1
PIE1.RCIE = 1 'Activa la interrupcion de la USART en modo rx
pause = 0 '1000 'prepara una pausa de 1Seg
Gosub pause_ms 'espera el tiempo que indica pause
Lcdout "16F88_RS232_MENU" 'imprime en el LCD el literal
Lcdcmdout LcdLine2Home 'selecciona linea y cursor al principio
Lcdout "4800 Baud.--1.0" 'escribe la cadena de literales en el lcd
Hserout ff, CrLf, CrLf, "VER. 1.0 - TX/RX", CrLf, "TX -> MENU POR RS232", CrLf, "By COS", CrLf, CrLf 'envia presentacion al RS232
Gosub clear_bufer 'Borra el BUFFER IMAGEN y por lo tanto tambien al USART, OBLIGATORIO POR LO MENOS UNA VEZ
pause = 0 '3000 'prepara una pausa de 3Seg
Gosub pause_ms 'hace una pausa de tiempo indicado por pause
'Lcdcmdout LcdClear 'borra el display
'--------------------------------------Main Programa----------------------------------------------------
Gosub print_menu 'envia el menu principal al hyperterminal
main:
Gosub readserial 'lee un caracter del puerto serie, salto con retorno
If assi >= 0x30 And assi <= 0x31 Then 'filtro de caracteres, "0" y el "1"
Hserout bell 'señal sonora
Hserout assi 'envia al hyperterminal
pause = 0 '1000 'carga la base de tiempos
Gosub pause_ms 'espera el tiempo indicado por pause
If assi = "0" Then Gosub control_led_amarillo 'salta a la rutina de control del led amarillo
If assi = "1" Then Gosub control_led_verde 'salta a la rutina de control del led verde
Endif
Goto main
End
'--------------------------------------FIN DEL MAIN-------------------------------------------
'--------------------------------------Rutinas Programa-----------------------------------------------
print_menu:
Hserout ff 'Paguina en blanco
Hserout " Menu de Control de los Led de la Pic EBasic ", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "------------------------------------------------", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "0 - Para menu Led amarillo", CrLf 'implime la cadena literal y salta a la siguiente linea
Hserout "1 - Para menu Led verde", CrLf 'implime la cadena literal y salta siguiente linea
Hserout "------------------------------------------------", CrLf 'implime la cadena literal y salta siguiente linea
Hserout "->" 'cursor
Hserout bell 'señal sonora
Return
control_led_verde:
Hserout ff 'pagina en blanco
Hserout " Menu control del Led Verde ", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "---------------------------------", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "0 - Led verde a Off", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "1 - Led verde a On", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "2 - Para Salir", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "---------------------------------", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "->" 'cursor
assi = 0 'borra el ultimo caracter leido del bufer serie
While assi <> "2" 'controla el menu
Gosub readserial 'lee caracter del bufer serial (retorna en assi)
If assi >= 0x30 And assi <= 0x32 Then 'filtro de opciones o teclas
Hserout bell 'señal sonora
Hserout assi 'caracter leido del bufer serie
pause = 0 '1000 'prepara una pausa de 1Seg.
Gosub pause_ms 'pausa indicada por pause
Hserout bell 'señal sonora
Gosub retrocede_caracter 'salto a la rutina de borra caracter
If assi = "0" Then led_verde = 1 'led verde a off
If assi = "1" Then led_verde = 0 'led verde a on
If assi = "2" Then Gosub print_menu 'reimprime el menu principal
Endif
Wend
Return
control_led_amarillo:
Hserout ff 'pantalla en blanco
Hserout " Menu control del Led Amarillo ", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "------------------------------------", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "0 - Led Amarillo a Off", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "1 - Led Amarillo a On", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "2 - Para Salir", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "------------------------------------", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "->" 'cursor
assi = 0 'borra el ultimo caracter leido del bufer serie
While assi <> "2" 'controla el menu
Gosub readserial 'lee caracter del bufer serial (retorna en assi)
If assi >= 0x30 And assi <= 0x32 Then 'filtro de opciones o teclas
Hserout bell 'señal sonora
Hserout assi 'caracter leido del bufer serie
pause = 0 '1000 'prepara una pausa de 1Seg.
Gosub pause_ms 'pausa indicada por pause
Hserout bell 'señal sonora
Gosub retrocede_caracter 'salto a la rutina de borra caracter
If assi = "0" Then led_amarillo = 1 'led amarillo a off
If assi = "1" Then led_amarillo = 0 'led amarillo a on
If assi = "2" Then Gosub print_menu 'reimprime el menu principal
Endif
Wend
Return
retrocede_caracter: 'borra caracter
Hserout bksp, sp, bksp
Return
pause_ms: 'rutina de espera, rutina tipo Waitms, pause establese el tiempo total en mSeg
timer_1ms = 0 'al borrar el contador se activa y comienza la cuenta de mSeg
While timer_1ms < pause 'tiempo en mSeg maximos a contar
Wend
Return
'------------------------------ rutinas para el control del bufer del puerto serie-------------
readserial:
'RUTINA DE LECTURA DEL BUFFER DEL PUERTO SERIE (ASSI)
If bufer = 1 Then 'si bufer tiene datos
assi = usart_bufer(c_serial) 'se lee el valor del bufer y se asigna assi
usart_imagen(c_serial) = 0 'se marca como leida para que pueda ser llenada de nuevo
c_serial = c_serial + 1 'se incrementa el indice del bufer
If c_serial >= n_usart Then c_serial = 0 'se verifica si se llego al final del bufer
If usart_imagen(c_serial) = 0 Then bufer = 0 'si no quedan mas datos en el bufer se marca como vacio
Else
assi = 0
Endif
Return
clear_bufer: 'inicializa el bufer imagen y borra error del puerto fisico en modo Rx
'_________________________Borra e inicializa el bufer imagan del puerto serie
c_serial = 0
While c_serial <= n_usart 'se ejecuta tantas veces como variables tiene el bufer
usart_imagen(c_serial) = 0 'borra el indicador de variable del bufer con datos
c_serial = c_serial + 1
Wend
c_serial = 0 'variables de control del bufer
usart = 0
bufer = 0
assi = 0
'_________________________Borra el error del puerto serie en Rx
RCSTA.OERR = 0
RCSTA.CREN = 0
RCSTA.CREN = 1
Return
'--------------------------------------SIBRUTINAS ESPECIALES---------------------------------------------
On Interrupt 'desactiva las interrupciones
Save System 'Guarda los valores del sistema
'*****************************base de tiempos********************************************
If PIR1.TMR1IF = 1 Then 'comprueba que la interrupcion la proboco el timer1
If timer_1ms < pause Then timer_1ms = timer_1ms + 1 'contador para control del timer_1ms
TMR1H = 0xf8 'recarga el contador del timer1 para que desborde pasado 1mSeg, byte alto
TMR1L = 0x2f 'recarga el contador del timer1 para que desborde pasado 1mSeg, byte bajo
PIR1.TMR1IF = 0 'borra el bit de salto del timer1
Endif
'*****************************BUFFER PUERTO SERIE****************************************
If PIR1.RCIF = 1 Then 'comprueba que es esta la interrupcion activa del modulo USAR
If usart < n_usart Then 'comprueba que el bufer de entrada no esta lleno
If usart_imagen(usart) = 0 Then 'comprueba que la posicion esta vacia
aux_usart = usart 'retiene la posicion antigua del bufer
usart = usart + 1 'indica cual sera la posicion siguiente del bufer
usart_imagen(aux_usart) = 1 'indica que hay dato en el bufer de entrada
bufer = 1 'indica que el bufer tine datos
Hserget usart_bufer(aux_usart) 'carga el dato en el bufer
Else
Hserget usart_bufer(n_usart) 'descarga la usart para que no se bloquee porque el bufer de entrada esta lleno
Endif
Else
If usart_imagen(0) = 0 Then 'comprueba que esta vacia la primera posicion del bufer
usart_imagen(0) = 1 'marca que hay dato en esa posicion del bufer
bufer = 1 'marca que el bufer tiene datos
usart = 1 'establece la proxima posicion del bufer
Hserget usart_bufer(0) 'lee la usart y guarda el dato en el bufer
Else
Hserget usart_bufer(n_usart) 'descarga la usart porque el bufer esta lleno
Endif
Endif
PIR1.RCIF = 0 'borra el bit de salto del Rx
Endif
'_________________________Borra el error del puerto serie en Rx
If RCSTA.OERR = 1 Then
RCSTA.OERR = 0
RCSTA.CREN = 0
RCSTA.CREN = 1
Endif
Resume 'activa las interrupciones y retorna al curso normal del programa antes del salto
End
'***************** Placa Entrenadora (PIC EBadic) ***************************************
'NOMBRE: 16F88_Pic_EBasic_Adcin_ServoOut_01
'Descripcion: Control de un servomotor (Futaba S3003) usando las declaraciones Adcin y ServoOut
'Micro: pic16f88 / 8mhz reloj interno
'Version: 1.0
'Fecha/Autor: 4/07, By COS, PSI v7.41
'periodo de la señal de control 20mSeg, duty cycle comprendido entre 0.5 y 2.3 mSeg.
'_________________________Ajuste de la declaracion ADCIN________________________
Define ADC_SAMPLEUS = 10 'el minimo, configuracion del ADC
Define ADC_CLOCK = 5 '16Tad a 8Mhz = 2uSeg, minimo permitido por el micro 1.5uSeg, configuracion ADC
'_______________________________________________________________________________
'_______________registros afectados por Define ADC_CLOCK y ADCIN________________
ANSEL = %00010000 'los pin I/O digitales y RA4 analogico
ADCON0 = %01100000 'Fosc/16 a 8Mhz (ADCON1.ADCS2=1) =2uSeg (minimo 1.uSeg), channel RA4
ADCON1 = %01000000 'voltage reference (AVdd/AVss) y seleccion de escala division clock/2 ADCON1.ADCS2=1
'_______________________________________________________________________________
'------------------------Definicion del funcionamiento de los modulos internos del micro--------------------
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
TRISA.4 = 1 'como entrada (RA4, adc)
TRISA.6 = 1 'como entrada (RA6, tecla S1)
TRISA.5 = 1 'como entrada (RA5, tecla S2)
PORTB.3 = 1 'luz lcd a on (RB3)
PORTA.7 = 1 'led amarillo a off, negado
PORTB.0 = 1 'led verde a off, negado
'Configura el puerto serie RS232 ---------------------
Hseropen 4800
'--------------------Asignacion de nombres a los pins----------------------------------------------------
Symbol led_amarillo = PORTA.7 'led amarillo
Symbol led_verde = PORTB.0 'led verde
Symbol luz_lcd = PORTB.3 'retroiluminacion del lcd
'-----------------------declaracion de variables----------------------------------------------------------
Dim servo_1 As Byte 'valor del ADC y tiempo del duty cycle
Dim tiemp_resta As Word 'tiempo en que la señal de control estara a OFF
'-----------------------Programa principal-------------------------------------
main:
PORTB.4 = 0 'salida de control del servo a estado bajo, pin RB4
Adcin 4, servo_1 'lectura del puerto analogico, pin RA4
Hserout #servo_1, CrLf 'Envia el valor del AN4 al puerto serie
If servo_1 < 50 Then servo_1 = 50 'acota el minimo para que el mecanismo del servo no sufra
If servo_1 > 230 Then servo_1 = 230 'acota el desplazamiento máximo para que el servo no sufra
ServoOut PORTB.4, servo_1 'declaracion para el control de servo motores, resolución de 10uSeg.
'se ajusta de forma automatica a la frecuencia de reloj de trabajo del micro.
tiemp_resta = 20000 - (servo_1 * 10) 'calculo de la señal de control a off en uSeg., periodo - duty = tiempo pendiente
'hasta completar el periodo seleccionado, en este caso 20mSeg.
WaitUs tiemp_resta 'pausa en uSeg. hasta completar el periodo de la señal de control
Goto main
'PROGRAMA PARA PRACTICAR CON INTERRUPCIONES EXTERIORES DEL PIN RB0
'On Interrupt - Interrupts in BASIC
'Turn LED on. Interrupt on PORTB.0 (INTE) turns LED off.
'Program waits .5 seconds and turns LED back on.
'-------------------------------------------------------------------
Define SIMULATION_WAITMS_VALUE = 1 'ignora los Waitms
'-------------------------------------------------------------------
Symbol led = PORTB.7 'reasigno nombre al portb.7
ANSEL = %00000000 'los pin I/O digitales
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISB.7 = 0 'declaro portb.7 como salida
TRISB.0 = 1 'declaro portb.0 como entrada
OPTION_REG = 0x7f 'Enable PORTB pullups
INTCON = 0x90 'Enable INTE interrupt
'-------------------------------------------------------------------
main:
High led 'Turn LED on
Goto main 'Do it forever
End
'Interrupt handler
On Interrupt 'Define interrupt handler, disable interrupt
Low led 'If we get here, turn LED off
WaitMs 500 'Wait 0.5 Seconds
INTCON.1 = 0 'Clear interrupt flag
Resume 'Return to main program, enable interrupt
'********************************** PIC Entrenadora BASIC ***************************************
'NOMBRE: 16F88_Pic_EBasic_LCD_RS232_Menu_11
'VERSION: 1.1
'MICRO: PIC16F88
'Fecha/Autor: 4/07, 5/07 By COS, PSI v7.41
'DESCRIPCION: Control de clave de acceso
'Programar el hyperterminal del Windows:
'Bits por segundo: 4800
'Bits de datos: 8
'Paridad: Ninguno
'Control de flujo: Ninguno
'LCD a 4 bit, sin bit de RW
'VERSION: 1.1
'Implementacion de una rutina que lee digitos numericos del teclado del ordenador y los pasa
'a un unico numero, se muestra en el lcd y lo compara con otro de 4 digitos compilado en el
'programa (1234), indicando tanto por el hyperterminal como por el lcd si es correcto, clave.
'Implementacion de poder corregir los digitos tecleados en el PC
'Lectura del puerto serie mediante un buffer en anillo
'************************************************************************************************
Define CONFIG = 0x2f50 'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc 'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 8 'Clock en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Activar para simulación
'-------------------------------------Puertos del LCD---------------------------------------------
Define LCD_BITS = 4 'indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'el bus de datos sera el puerto A
Define LCD_DBIT = 0 'el bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'el bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'se usara el RB7 como RS
Define LCD_EREG = PORTB 'el bit de control E sera del puerto B
Define LCD_EBIT = 6 'se usara el RB6 como E
'Define LCD_RWREG = PORTA 'el bit de control RW sera del puerto A (si se suprime el compilador no protesta)
'Define LCD_RWBIT = 5 'se usara el RA5 como RW (si se suprime el compilador no protesta)
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comand del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 5 '50 'Tiempo de espera despues de inicializar el Display, solo se ejecuta una vez en mSeg.
'--------------------------------Reasignacion de nombres---------------------------------------
Symbol led_amarillo = PORTA.7 'led amarillo
Symbol led_verde = PORTB.0 'led verde
'--------------------------------Definicion de caracteres de control del Hyperterminal--------
Const ff = 0x0c 'FF, Avance de pagina
Const bell = 0x07 'BELL, Señal sonora
Const sp = 0x20 'SP, Espacio
Const bksp = 0x08 'BKSP, Retroceso
Const cr = 0x0d 'CR, retorno de carro
'**************************************DEFINICION DE PUERTOS*************************************
'----------------------ASIGNACION DE I/O y valores de inicio de las salidas---------------------
ANSEL = 0x00 'los pin I/O digitales
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
TRISA.4 = 1 'como entrada (RA4, adc)
TRISA.6 = 1 'como entrada (RA6, tecla S1)
TRISA.5 = 1 'como entrada (RA5, tecla S2)
'TRISB.5 = 0 'RB5(Tx, RS232)
TRISB.2 = 1 'RB2 (Rx, RS232)
PORTB.3 = 1 'luz lcd a on (RB3)
PORTA.7 = 1 'led amarillo a off
PORTB.0 = 1 'led verde a off
'------------------------------------INICIO DEL PUERTO SERIE, TIMER E INTERRUPCIONES------------------
T1CON.TMR1CS = 0 'asigna el reloj interno al timer1, se incrementa cada ciclo de instruccion
T1CON.T1CKPS0 = 0 'factor del preescales del timer1, 0
T1CON.T1CKPS1 = 0 'factor del preescales del timer1, 0
TMR1H = 0xf8 'carga el registro del contador para que desborde cada 1mSeg, byte alto
TMR1L = 0x2f 'carga el registro del contador para que desborde cada 1mSeg, byte bajo
T1CON.TMR1ON = 1 'habilitacion del TMR1, comienza a incrementarse
'PIE1.TMR1IE = 1 'activa las interrupciones del timer1
'PIE1.RCIE = 1 'Activa la interrupción de la USART en modo rx
INTCON.PEIE = 1 'bit de habilitación de interrupciones de periféricos
'-------------------------------------Variables rutinas del buffer puerto serie----------------------
Dim assi As Byte 'Contiene el valor de lectura del puerto serie
Dim buffer As Byte 'Indica si hay datos por leer en el buffer USART
Dim n_usart As Byte 'Numero de datos del USART y del buffer IMAGEN de control
Dim usart As Byte 'Variable indice que apunta al ultimo dato adquirido por la USART
Dim aux_usart As Byte 'Auxiliar de la variable indice usart del USART
Dim c_serial As Byte 'Como USART pero para la lectura de control del buffer IMAGEN
Dim n_aux As Byte 'contador para borrar el buffer_soft
Dim usart_imagen(10) As Byte '91 'Componen el buffer IMAGEN para control del buffer USAR
Dim usart_buffer(10) As Byte '91'Componen el buffer de la USAR de bajo nivel
'-------------------------------------Asigna valores a las variables de la rutina del puerto serie--
usart = 0
aux_usart = 0
c_serial = 0
buffer = 0
n_usart = 9 '90
assi = 0
n_aux = 0
'************************************variables de los timer****************************************
Dim pause As Word 'contiene el valor para simular el comando Waitms
Dim timer_1ms As Word 'base de tiempos se incrementa cada 1mSeg, timer del PAUSE
'-------------------------------------Asignacion de valores del TIMER1----------------------------
pause = 0 'genera una pausa en MSeg
timer_1ms = 0 'en mSeg
'-----------------------------------Asigna valores a las variables de la rutina lectura teclado--
Dim d_teclas As Byte 'Numero de digitos + 1 de la clave
Dim _digclave(4) As Byte 'Clave
_digclave(0) = "1"
_digclave(1) = "2"
_digclave(2) = "3"
_digclave(3) = "4"
Dim aux_digclave(5) As Byte 'Clave entrada por el teclado
d_teclas = 3 'numero de digitos +1, max. a introducir por el teclado del PC
'-----------------------------------------------
Lcdinit 'inicializa el LCD sin cursor
Hseropen 4800 'Velocidad del puerto serie e inicializa los comandos de bajo nivel que controlan la USART
Gosub clear_buffer 'Borra el BUFFER IMAGEN y por lo tanto tambien al USART, OBLIGATORIO POR LO MENOS UNA VEZ
PIE1.TMR1IE = 1 'activa las interrupciones del timer1
PIE1.RCIE = 1 'Activa la interrupcion de la USART en modo rx
Enable 'INTCON.GIE habilita todas las interrupciones globales
pause = 1000 'prepara una pausa de 1Seg
Gosub pause_ms 'espera el tiempo que indica pause
Lcdout "16F88_RS232_MENU" 'imprime en el LCD el literal
Lcdcmdout LcdLine2Home 'selecciona linea y cursor al principio
Lcdout "4800 Baud.--1.1" 'escribe la cadena de literales en el lcd
Hserout ff, CrLf, CrLf, "VER. 1.1 - TX/RX", CrLf, "TX -> MENU POR RS232", CrLf, "By COS", CrLf, CrLf 'envía presentación al RS232
Gosub clear_buffer 'Borra el BUFFER IMAGEN y por lo tanto también al USART, OBLIGATORIO POR LO MENOS UNA VEZ
pause = 3000 'prepara una pausa de 3Seg
Gosub pause_ms 'hace una pausa de tiempo indicado por pause
'--------------------------------------Main Programa----------------------------------------------------
main:
Gosub print_menu 'envia el menu principal al hyperterminal
Gosub d_read 'rutina de lectura del teclado del pc
Gosub verifica_clave 'verifica la clave y lo indica por el lcd
pause = 1000 'carga la base de tiempos
Gosub pause_ms 'espera el tiempo indicado por pause
Goto main
End
'--------------------------------------Rutinas Programa-----------------------------------------------
d_read: '___________________Rutina de lectura del teclado del pc, a través del hyperterminal
Dim d_aux As Byte
Dim d_control As Byte
aux_digclave(0) = "-"
aux_digclave(1) = "-"
aux_digclave(2) = "-"
aux_digclave(3) = "-"
d_control = 0 'valor inicial
d_aux = 0 'valor inicial
Gosub hserout_cursor 'salto con retorno escribe cursor en el hyperterminal
While d_control = 0 'lee el teclado del pc, hasta que se valida el numero, enter
If buffer > 0 Then 'controla que hay datos en el buffer serie
Gosub readserial 'lee un dato del buffer serie
Gosub hserout_bell 'señal sonora
Endif
If assi >= 0x30 And assi <= 0x39 And d_aux <= d_teclas Then 'filtro de teclas validas y numero de digitos max.
Gosub hserout_assi 'envia el valor de assi al hyperterminal, tecla numerica pulsada
aux_digclave(d_aux) = assi 'Asigna la tecla a la clave auxiliar
d_aux = d_aux + 1 'incrementa la siguiente posicion del digito a recibir
assi = 0 'se borra el digito recibido
Endif
If assi = bksp Then '___________borra el ultimo caracter
If d_aux > 0 Then 'Si se introdujo algun digito
d_aux = d_aux - 1 'Selecciona el digito a borrar
aux_digclave(d_aux) = "-" 'Borra el digito
Gosub borra_caracter 'Retrocede y borra una posicion en el hyperterminal
Endif
assi = 0 'se borra el digito recibido
Endif '________________________
If assi = cr Then '_______detecta el retorno de carro, o fin de entrada de datos
Gosub hserout_crlf 'envia un avance de linea y principio de linea
assi = 0 'se borra el digito recibido por el puerto serie
Return
Endif '_____________________
Wend
Return
hserout_cursor: 'cursor en el hyperterminal
Hserout "->"
Return
hserout_ff: 'Pagina en blanco
Hserout ff
Return
hserout_crlf: 'salta una linea y principio de linea
Hserout CrLf
Return
hserout_assi: 'envia el valor al puerto serie
Hserout assi
Return
hserout_bell: 'señal sonora
Hserout bell
Return
borra_caracter: 'borra caracter
Hserout bksp, sp, bksp
Return
print_menu:
'Gosub hserout_ff 'Pagina en blanco
Hserout "-------------------------------", CrLf 'imprime la cadena literal y salta a una nueva linea
Hserout " Entre la Clave, 4 Digitos ", CrLf 'imprime la cadena literal y salta a una nueva linea
Hserout "-------------------------------", CrLf 'imprime la cadena literal y salta a una nueva linea
Gosub hserout_bell 'señal sonora
Return
verifica_clave: '___________________VERIFICA LA CLAVE Y SACA DATOS POR EL LCD Y PUERTO SERIE
Lcdcmdout LcdLine1Home
Lcdout "Numero: ", aux_digclave(0), aux_digclave(1), aux_digclave(2), aux_digclave(3), " " 'escribe en el lcd y numero reconocido por la EBasic
Lcdcmdout LcdLine2Home 'principio de linea 2 del lcd
If aux_digclave(0) = _digclave(0) And aux_digclave(1) = _digclave(1) And aux_digclave(2) = _digclave(2) And aux_digclave(3) = _digclave(3) Then 'comprueba la clave
Lcdout "Clave Correcta " 'manada datos al lcd
Hserout CrLf, CrLf, "Clave Correcta", CrLf, CrLf 'manda datos al puerto serie
Gosub hserout_bell 'manda datos la puerto serie, señal sonora
Gosub hserout_bell 'manda datos la puerto serie, señal sonora
pause = 200 'indica la duracion de la pausa
Gosub pause_ms 'hace una pausa
Gosub hserout_bell 'manda datos la puerto serie, señal sonora
Gosub pause_ms 'hace una pausa
Gosub hserout_bell 'manda datos la puerto serie, señal sonora
Else
Lcdout "Clave Incorrecta" 'manda datos al lcd
Hserout CrLf, CrLf, "Clave Incorrecta", CrLf, CrLf 'manda datos al puerto serie
Endif
Return
pause_ms: 'rutina de espera, rutina tipo Waitms, pause establece el tiempo total en mSeg
pause = 0 'deshabilita la rutina pause 0, solo simulación
timer_1ms = 0 'al borrar el contador se activa y comienza la cuenta de mSeg
While timer_1ms < pause 'tiempo en mSeg máximos a contar
Wend
Return
'------------------------------ rutinas para el control del buffer del puerto serie-------------
readserial:
'RUTINA DE LECTURA DEL BUFFER DEL PUERTO SERIE (ASSI)
If buffer = 1 Then 'si buffer tiene datos
assi = usart_buffer(c_serial) 'se lee el valor del buffer y se asigna assi
usart_imagen(c_serial) = 0 'se marca como leida para que pueda ser llenada de nuevo
c_serial = c_serial + 1 'se incrementa el indice del buffer
If c_serial >= n_usart Then c_serial = 0 'se verifica si se llego al final del buffer
If usart_imagen(c_serial) = 0 Then buffer = 0 'si no quedan mas datos en el buffer se marca como vacio
Else
assi = 0
Endif
Return
clear_buffer: 'inicializa el buffer imagen y borra error del puerto físico en modo Rx
'_________________________Borra e inicializa el buffer imagen del puerto serie
c_serial = 0
While c_serial <= n_usart 'se ejecuta tantas veces como variables tiene el buffer
usart_imagen(c_serial) = 0 'borra el indicador indice, informa que esa posicion del buffer tiene o no tiene datos
c_serial = c_serial + 1
Wend
c_serial = 0 'variables de control del buffer
usart = 0
buffer = 0
assi = 0
'_________________________Borra el error del puerto serie en Rx
RCSTA.OERR = 0
RCSTA.CREN = 0
RCSTA.CREN = 1
Return
'--------------------------------------SIBRUTINAS ESPECIALES---------------------------------------------
On Interrupt 'desactiva las interrupciones
Save System 'Guarda los valores del sistema
'*****************************base de tiempos********************************************
If PIR1.TMR1IF = 1 Then 'comprueba que la interrupcion la provoco el timer1
If timer_1ms < pause Then timer_1ms = timer_1ms + 1 'contador para control del timer_1ms
TMR1H = 0xf8 'recarga el contador del timer1 para que desborde pasado 1mSeg, byte alto
TMR1L = 0x2f 'recarga el contador del timer1 para que desborde pasado 1mSeg, byte bajo
PIR1.TMR1IF = 0 'borra el bit de salto del timer1
Endif
'*****************************BUFFER PUERTO SERIE****************************************
If PIR1.RCIF = 1 Then 'comprueba que es esta la interrupcion activa del modulo USAR
If usart < n_usart Then 'comprueba que el buffer de entrada no esta lleno
If usart_imagen(usart) = 0 Then 'comprueba que la posicion esta vacia
aux_usart = usart 'retiene la posicion antigua del buffer
usart = usart + 1 'indica cual sera la posicion siguiente del buffer
usart_imagen(aux_usart) = 1 'indica que hay dato en el buffer de entrada
buffer = 1 'indica que el buffer tiene datos
Hserget usart_buffer(aux_usart) 'carga el dato en el buffer
Else
Hserget usart_buffer(n_usart) 'descarga la usart para que no se bloquee porque el buffer de entrada esta lleno
Endif
Else
If usart_imagen(0) = 0 Then 'comprueba que esta vacía la primera posicion del buffer
usart_imagen(0) = 1 'marca que hay dato en esa posicion del buffer
buffer = 1 'marca que el buffer tiene datos
usart = 1 'establece la próxima posición del buffer
Hserget usart_buffer(0) 'lee la usart y guarda el dato en el buffer
Else
Hserget usart_buffer(n_usart) 'descarga la usart porque el buffer esta lleno
Endif
Endif
PIR1.RCIF = 0 'borra el bit de salto del Rx
Endif
'_________________________Borra el error del puerto serie en Rx
If RCSTA.OERR = 1 Then
RCSTA.OERR = 0
RCSTA.CREN = 0
RCSTA.CREN = 1
Endif
Resume 'activa las interrupciones y retorna al curso normal del programa antes del salto
'********************************** PIC Entrenadora BASIC ***************************************
'NOMBRE: 16F88_Pic_EBasic_LCD_Timer1_MidiendoTiempo_10
'VERSION: 1.0
'MICRO: PIC16F88
'Fecha/Autor: 5/07 By COS, PSI v7.41
'DESCRIPCION: Midiendo el tiempo que tardan ciertas rutinas en ejecutarse
'Programar el hyperterminal del Windows:
'Bits por segundo: 4800
'Bits de datos: 8
'Paridad: Ninguno
'Control de flujo: Ninguno
'LCD a 4 bit, sin bit de RW
'valor por el display y por el hyperterminal
'************************************************************************************************
Define CONFIG = 0x2f50 'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc 'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 8 'Clock en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Activar para simulación
'-------------------------------------Puertos del LCD---------------------------------------------
Define LCD_BITS = 4 'indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'el bus de datos sera el puerto A
Define LCD_DBIT = 0 'el bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'el bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'se usara el RB7 como RS
Define LCD_EREG = PORTB 'el bit de control E sera del puerto B
Define LCD_EBIT = 6 'se usara el RB6 como E
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comand del lcd en uSeg., depende del lcd (este 500)
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg., depende de la respuesta del lcd
Define LCD_INITMS = 5 '50 'Tiempo de espera despues de inicializar el Display, solo se ejecuta una vez en mSeg.
'----------------------ASIGNACION DE I/O y valores de inicio de las salidas---------------------
ANSEL = 0x00 'los pin I/O digitales
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
TRISA.4 = 1 'como entrada (RA4, adc)
TRISA.6 = 1 'como entrada (RA6, tecla S1)
TRISA.5 = 1 'como entrada (RA5, tecla S2)
'TRISB.5 = 0 'RB5(Tx, RS232)
TRISB.2 = 1 'RB2 (Rx, RS232)
PORTB.3 = 1 'luz lcd a on (RB3)
PORTA.7 = 1 'led amarillo a off
PORTB.0 = 1 'led verde a off
'------------------------------------PROGRAMACION TIMER1---------------------------------------
T1CON.TMR1CS = 0 'asigna el reloj interno al timer1, se incrementa cada ciclo de instruccion
T1CON.T1CKPS0 = 0 'factor del preescales del timer1, 0
T1CON.T1CKPS1 = 0 'factor del preescales del timer1, 0
'TMR1H = 0x00 'carga el registro del contador para que desborde cada 32.76 mSeg, byte alto
'TMR1L = 0x00 'carga el registro del contador para que desborde cada 32.76 mSeg, byte bajo
T1CON.TMR1ON = 0 'parado el contador del TMR1
PIE1.TMR1IE = 0 'desactiva las interrupciones del timer1
'INTCON.PEIE = 1 'bit de habilitacion de interrupciones de perifericos
'Enable 'INTCON.GIE habilita todas las interrupciones globales
'--------------------------------------Inicio Programa--------------------------------------------------
Lcdinit 'inicializa el LCD sin cursor
'-------------------------------Reasignacion de nombres---------------------------------------
Symbol led_amarillo = PORTA.7 'led amarillo
Symbol led_verde = PORTB.0 'led verde
'**********************DECLARACION DE VARIABLES****************************************
Dim timer1 As Long 'contendra el valor de los registros del timer1 y posterior valor a uSeg.
Dim aux As Byte
aux = 0
'WaitMs 1000 'prepara una pausa de 1Seg
Lcdout "16F88_LCD_TIMER1" 'imprime en el LCD el literal
Lcdcmdout LcdLine2Home 'selecciona linea y cursor al principio
Lcdout "MidiendoTiempo10" 'escribe la cadena de literales en el lcd
'WaitMs 3000 'prepara una pausa de 3Seg
'--------------------------------------Main Programa----------------------------------------------------
main:
TMR1H = 0x00 'borro el registro alto del timer1
TMR1L = 0x00 'borro el registro bajo del timer1
T1CON.TMR1ON = 1 'activa el contador del TMR1
'****************************************************************************
'-------------------Rutina a medir en uSeg-----------------------------------
'WaitMs 15 'Tarda 14998 uS
Lcdcmdout LcdClear 'Tarda 2024uS
'Lcdout "Hola TodoPic" 'Tarda 906uS
'aux = 100 '__________Tarda 3 uSeg
'If aux = 100 Then
'Endif '______________
'----------------------------------------------------------------------------
'****************************************************************************
T1CON.TMR1ON = 0 'Para el contador del TMR1
timer1 = 0
timer1.HB = TMR1H 'asigna registro de mas peso
timer1.LB = TMR1L 'asigna registro de menos peso
'timer1_aux = timer1 'pasa de long a word
Lcdcmdout LcdClear 'borra el lcd y cursor linea 1
Lcdout "Timer1:", #timer1 'datos por el lcd
Serout PORTB.5, 4800, CrLf, "Timer1: ", #timer1, CrLf 'puerto serie Tx, por soft
timer1 = (timer1 * 5) / 10 'en microsegundos
'timer1_aux = timer1 'paso de long a word, la rutina del display no permite variables tipo Long
Lcdcmdout LcdLine2Home 'cursor al principio de la linea 2 del lcd
Lcdout "Tiemp.:", #timer1, "uS." 'datos por el lcd
Serout PORTB.5, 4800, CrLf, "Tiempo: ", #timer1, " uSeg.", CrLf 'puerto serie Tx, por soft
End
'********************************** PIC Entrenadora BASIC (PicEBasic)******************************
'NOMBRE: 16F88_Pic_EBasic_LCD_RTC_ADC_11
'MICRO: PIC16F88
'FECHA/AUTOR: 04/07, 05/07 - By COS
'VERSION 1.1
'modificacion de la rutina "pause_ms"
'modificacion de rutina de teclas, porque se veian afectadas al crecer la longitud del programa main
'Se añade salida de la temperatura, hora y fecha por el puerto serie (Soft)
'Pendiente de grafica de temperatura por el hyperterminal
'VERSION 1.0
'DESCRIPCION: Muestra en el display la fecha, hora (24h)mediante el DS1307 y temperatura (LM35)
'S1 y S2 pulsadas al mismo tiempo, entramos en programacion del reloj
'Una vez en programacion con S1 seleccionamos el dato a cambiar, este queda en modo parpadeo
'Una vez en programacion con S2 incrementamos el dato seleccionado dentro de sus cotas
'S1, pulsado al principio salida del RTC a on, 1Hz, y S2 salida a off, led off
'Se muestra la temperatura en el LCD mediante un LM35, temperatura positiva y negativa
'***************************************************************************************************
'-------------------------------------Puertos del LCD-----------------------------------------------
Define LCD_BITS = 4 'indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'el bus de datos sera el puerto A
Define LCD_DBIT = 0 'el bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'el bit de nrol RS sera del puerto B
Define LCD_RSBIT = 7 'se usara el RB7 como RS
Define LCD_EREG = PORTB 'el bit de nrol E sera del puerto B
Define LCD_EBIT = 6 'se usara el RB6 como E
Define LCD_COMMANDUS = 500 '2000 'Tiempo de espera despues de ejecutar un comand del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 5 '50 'Tiempo de espera despues de inicializar el Display, solo se ejecuta una vez en mSeg.
'-------------------------------------------------------------------------------------------------------------
Define SEROUT_DELAYUS = 0 'no hay delay entre caracter y caracter enviado al puerto serie
'-----------------------------------asignacion de nombres-----------------------------------------------------
Symbol sda = PORTB.1 'asignamos nombre al pin que hara de SDA del puerto I2C
Symbol scl = PORTB.4 'asignamos nombre al pin que hara de SCL del puerto I2C
Symbol led_amarillo = PORTA.7 'led amarillo
Symbol led_verde = PORTB.0 'led verde
Symbol luz_lcd = PORTB.3 'retroiluminacion del lcd
Symbol s1 = RA6 'se asigna nombre a la tecla
Symbol s2 = RA5 'se asigna nombre a la tecla
'***********************************DEFINICION DE VARIABLES**************************************
'-----------------------------------variables de los timer---------------------------------------
Dim aux_pause As Word 'variable auxiiar el PAUSE
Dim pause As Word 'contiene el valor para simular el comando Waitms
Dim timer_1ms As Word 'base de tiempos se incrementa cada 1mSeg, timer del PAUSE
Dim timer_base As Byte 'tiempo referencia para los timer por soft del programa
Dim timer_base_tiempo As Byte 'contiene el valor del tiempo del timer_base
Dim timer1_ms As Word 'base de tiempos en ms
Dim timer2_ms As Word 'base de tiempos en ms
Dim timer3_ms As Word 'base de tiempos ms
Dim timer1_100ms As Byte 'base de tiempos msx100
Dim timer2_100ms As Byte 'base de tiempos msx100
Dim timer3_100ms As Byte 'base de tiempos msx100
Dim timer_1ms_tiempo As Word 'contiene el valor del tiempo de timer_1ms
Dim timer1_ms_tiempo As Word 'contiene el valor del tiempo del timer1_ms
Dim timer2_ms_tiempo As Word 'contiene el valor del tiempo del timer2_ms
Dim timer3_ms_tiempo As Word 'contiene el valor del tiempo del timer3_ms
Dim timer1_100ms_tiempo As Byte 'contiene el valor del tiempo del timer1_100ms
Dim timer2_100ms_tiempo As Byte 'contiene el valor del tiempo del timer2_100ms
Dim timer3_100ms_tiempo As Byte 'contiene el valor del tiempo del timer3_100ms
'--------------------------------------Variables Programa RTC----------------------------------------
Dim aux_4h As Byte 'contendra el nibble alto del dato leido por el I2C
Dim aux_4l As Byte 'contendra el nibble bajo del dato leido por el I2C
Dim i As Byte 'variable indice
Dim reg(7) As Byte 'contendra los valores finales de fecha y hora en el sistema decimal
Dim flash_1 As Bit 'controla el parpadeo de los digitos del lcd, activo a 1
Dim dato As Byte 'indica la direccion del RTC a cambiar de valor
Dim flag_1 As Bit 'activa la rutina de ajuste del reloj, activo a 1
Dim s1_on As Bit 'tecla pulsada si s1_on=1
Dim s2_on As Bit 'tecla pulsada si s2_on=1
Dim aux_ajuste As Byte 'variable auxiliar para la rutina de ajuste
'-----------------------------------------------------------------------------------------------
'-------------------------------Variables del ADC y Rutina division (temperatura)------------------------------
Dim entero As Word 'parte entera
Dim decimal As Word 'los dos decimales
Dim division As Long 'almacenara el numero con los dos decimales
Dim adc_4 As Word 'contendra el valor de la entrada del ADC
Dim aux_adc_4 As Word 'auxiliar
'--------------------------------Variables temperatura-------------------------------------------
Dim factor_escala As Word 'contiene el factor de correcion para pasar el valor del ADC a voltios, max. 5V
Dim temperatura As Word 'almacena la temperatura final
Dim temp As Long 'contendra la temperatura completa sin coma
Dim signo As Bit 'indica el signo de la temperatura
'--------------------------------Variables calculo media aritmetica (temperatura)----------------------------
Dim media_temp(20) As Word 'numero de muestras para calcular la media aritmetica
Dim media_indice As Byte 'se utiliza como indice
Dim aux_media As Byte 'variable auxiliar
'------------------------------------------ASIGNACIONES------------------------------------------
'------------------------------------asignacion de valores a las variables (RTC)--------------------------
s1_on = 0
s2_on = 0
dato = 7 'fuera de ajuste o modo normal de trabajo del reloj, de 0 a 6 modo ajuste
flash_1 = 0
flag_1 = 0
timer_base = 0
timer1_ms = 0
timer2_ms = 0
timer3_ms = 0
timer1_100ms = 0
timer2_100ms = 0
timer3_100ms = 0
timer_base_tiempo = 1 '100 'temporiza 100 mSeg
timer_1ms_tiempo = 1 'temporiza 1mseg
timer1_ms_tiempo = 1 '100 'temporiza 100 mSeg., asignado a la tecla S1
timer2_ms_tiempo = 1 '500 'temporiza 500 mSeg.
timer3_ms_tiempo = 1 '100 'temporiza 100 mSeg., asignado a la tecla S2
timer1_100ms_tiempo = 1 '10 'temporiza 1 Seg.
timer2_100ms_tiempo = 1 '255 'temporiza 25.5 Seg.
timer3_100ms_tiempo = 1 'temporiza 0.1seg.
'-------------------------------------asiganacion de valores a las variables (temperatura)------
entero = 0
decimal = 0
division = 0
adc_4 = 0
factor_escala = 10 'factor de escala para un decimal
temperatura = 0
temp = 0
media_indice = 0
aux_media = 0
'**************************************DEFINICION DE PUERTOS*************************************
'----------------------ASIGNACION DE I/O y valores de inicio de las salidas---------------------
Define ADC_SAMPLEUS = 0 'el minimo, configuracion del ADC
Define ADC_CLOCK = 5 '16Tad a 8Mhz = 2uSeg, minimo permitido por el micro 1.5uSeg, configuracion ADC
'_______________registros afectados por Define ADC_CLOCK y ADCIN________________
ANSEL = %00010000 'los pin I/O digitales y RA4 analogico
ADCON0 = %01100000 'Fosc/16 a 8Mhz (ADCON1.ADCS2=1) =2uSeg (minimo 1.uSeg), channel RA4
ADCON1 = %01000000 'voltage reference (AVdd/AVss) y seleccion de escala division clock/2 ADCON1.ADCS2=1
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
TRISA.4 = 1 'como entrada (RA4, adc)
TRISA.6 = 1 'como entrada (RA6, tecla S1)
TRISA.5 = 1 'como entrada (RA5, tecla S2)
PORTB.3 = 1 'luz lcd a on (RB3)
PORTA.7 = 1 'led amarillo a off
PORTB.0 = 1 'led verde a off
'------------------------------------Inicializacion de Interrupciones-----------------------------
T1CON.TMR1CS = 0 'asigna el reloj interno al timer1, se incrementa cada ciclo de instruccion
T1CON.T1CKPS0 = 0 'factor del preescales del timer1, 0
T1CON.T1CKPS1 = 0 'factor del preescales del timer1, 0
TMR1H = 0xf8 'carga el registro del contador para que desborde cada 1mSeg, byte alto
TMR1L = 0x30 'carga el registro del contador para que desborde cada 1mSeg, byte bajo
T1CON.TMR1ON = 1 'habilitacion del TMR1, comienza a incrementarce
INTCON.PEIE = 1 'bit de habilitacion de interrupciones de perifericos
Enable 'INTCON.GIE habilita todas las interrupciones globales
'**************************************Inicio Programa*********************************************
Lcdinit 'inicializa el lcd sin cursor
Serout PORTB.5, 4800, 0x0c, "MUESTRA LA TEMPERATURA MEDIA CADA 25.5 Seg.", CrLf 'alpuerto serie
Serout PORTB.5, 4800, "-------------------------------------------", CrLf, CrLf 'alpuerto serie
PIE1.TMR1IE = 1 'activa las interrupciones del timer1
pause = 1000
Gosub pause_ms 'espera el tiempo indicado en pause
Lcdout "16F88LCD_RTC/I2C" 'escribe en el lcd
Lcdcmdout LcdLine2Home 'seleciona la linea dos como proxima para escritura
Lcdout "ADC_LM35_RS232" 'escribe en el lcd
pause = 3000
Gosub pause_ms 'espera el tiempo indicado en pause
Lcdcmdout LcdClear 'borra el display y cursor a casa
'--------------------------------inicializa variable media_temperatura---------------------------
Gosub inicializa_temp
'--------------------------------inicializa los registros del RTC---------------------------------
Gosub inicaliza_rtc
'--------------------------------------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
'********************************** PIC Entrenadora BASIC (PicEBasic)******************************
'NOMBRE: 16F88_Pic_EBasic_LCD_RTC_ADC_12
'MICRO: PIC16F88
'FECHA/AUTOR: 04/07, 05/07 - By COS
'VERSION 1.2
'Se habilita el modulo usar como salida de datos serie
'se cambian todos los "Serout PORTB.5, 4800, " por Hserout
'se observa un ahorro de memoria considerable y una aceleracion del programa increible.
'VERSION 1.1
'modificacion de la rutina "pause_ms"
'modificacion de rutina de teclas, porque se veian afectadas al crecer la longitud del programa main
'Se añade salida de la temperatura, hora y fecha por el puerto serie (Soft)
'Pendiente de grafica de temperatura por el hyperterminal
'VERSION 1.0
'DESCRIPCION: Muestra en el display la fecha, hora (24h)mediante el DS1307 y temperatura (LM35)
'S1 y S2 pulsadas al mismo tiempo, entramos en programacion del reloj
'Una vez en programacion con S1 seleccionamos el dato a cambiar, este queda en modo parpadeo
'Una vez en programacion con S2 incrementamos el dato seleccionado dentro de sus cotas
'S1, pulsado al principio salida del RTC a on, 1Hz, y S2 salida a off, led off
'Se muestra la temperatura en el LCD mediante un LM35, temperatura positiva y negativa
'***************************************************************************************************
'-------------------------------------Puertos del LCD-----------------------------------------------
Define LCD_BITS = 4 'indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'el bus de datos sera el puerto A
Define LCD_DBIT = 0 'el bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'el bit de nrol RS sera del puerto B
Define LCD_RSBIT = 7 'se usara el RB7 como RS
Define LCD_EREG = PORTB 'el bit de nrol E sera del puerto B
Define LCD_EBIT = 6 'se usara el RB6 como E
Define LCD_COMMANDUS = 500 '2000 'Tiempo de espera despues de ejecutar un comand del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 5 '50 'Tiempo de espera despues de inicializar el Display, solo se ejecuta una vez en mSeg.
'-----------------------------------asignacion de nombres-----------------------------------------------------
Symbol sda = PORTB.1 'asignamos nombre al pin que hara de SDA del puerto I2C
Symbol scl = PORTB.4 'asignamos nombre al pin que hara de SCL del puerto I2C
Symbol led_amarillo = PORTA.7 'led amarillo
Symbol led_verde = PORTB.0 'led verde
Symbol luz_lcd = PORTB.3 'retroiluminacion del lcd
Symbol s1 = RA6 'se asigna nombre a la tecla
Symbol s2 = RA5 'se asigna nombre a la tecla
'***********************************DEFINICION DE VARIABLES**************************************
'-----------------------------------variables de los timer---------------------------------------
Dim aux_pause As Word 'variable auxiiar el PAUSE
Dim pause As Word 'contiene el valor para simular el comando Waitms
Dim timer_1ms As Word 'base de tiempos se incrementa cada 1mSeg, timer del PAUSE
Dim timer_base As Byte 'tiempo referencia para los timer por soft del programa
Dim timer_base_tiempo As Byte 'contiene el valor del tiempo del timer_base
Dim timer1_ms As Word 'base de tiempos en ms
Dim timer2_ms As Word 'base de tiempos en ms
Dim timer3_ms As Word 'base de tiempos ms
Dim timer1_100ms As Byte 'base de tiempos msx100
Dim timer2_100ms As Byte 'base de tiempos msx100
Dim timer3_100ms As Byte 'base de tiempos msx100
Dim timer_1ms_tiempo As Word 'contiene el valor del tiempo de timer_1ms
Dim timer1_ms_tiempo As Word 'contiene el valor del tiempo del timer1_ms
Dim timer2_ms_tiempo As Word 'contiene el valor del tiempo del timer2_ms
Dim timer3_ms_tiempo As Word 'contiene el valor del tiempo del timer3_ms
Dim timer1_100ms_tiempo As Byte 'contiene el valor del tiempo del timer1_100ms
Dim timer2_100ms_tiempo As Byte 'contiene el valor del tiempo del timer2_100ms
Dim timer3_100ms_tiempo As Byte 'contiene el valor del tiempo del timer3_100ms
'--------------------------------------Variables Programa RTC----------------------------------------
Dim aux_4h As Byte 'contendra el nibble alto del dato leido por el I2C
Dim aux_4l As Byte 'contendra el nibble bajo del dato leido por el I2C
Dim i As Byte 'variable indice
Dim reg(7) As Byte 'contendra los valores finales de fecha y hora en el sistema decimal
Dim flash_1 As Bit 'controla el parpadeo de los digitos del lcd, activo a 1
Dim dato As Byte 'indica la direccion del RTC a cambiar de valor
Dim flag_1 As Bit 'activa la rutina de ajuste del reloj, activo a 1
Dim s1_on As Bit 'tecla pulsada si s1_on=1
Dim s2_on As Bit 'tecla pulsada si s2_on=1
Dim aux_ajuste As Byte 'variable auxiliar para la rutina de ajuste
'-----------------------------------------------------------------------------------------------
'-------------------------------Variables del ADC y Rutina division (temperatura)------------------------------
Dim entero As Word 'parte entera
Dim decimal As Word 'los dos decimales
Dim division As Long 'almacenara el numero con los dos decimales
Dim adc_4 As Word 'contendra el valor de la entrada del ADC
Dim aux_adc_4 As Word 'auxiliar
'--------------------------------Variables temperatura-------------------------------------------
Dim factor_escala As Word 'contiene el factor de correcion para pasar el valor del ADC a voltios, max. 5V
Dim temperatura As Word 'almacena la temperatura final
Dim temp As Long 'contendra la temperatura completa sin coma
Dim signo As Bit 'indica el signo de la temperatura
'--------------------------------Variables calculo media aritmetica (temperatura)----------------------------
Dim media_temp(20) As Word 'numero de muestras para calcular la media aritmetica
Dim media_indice As Byte 'se utiliza como indice
Dim aux_media As Byte 'variable auxiliar
'------------------------------------------ASIGNACIONES------------------------------------------
'------------------------------------asignacion de valores a las variables (RTC)--------------------------
s1_on = 0
s2_on = 0
dato = 7 'fuera de ajuste o modo normal de trabajo del reloj, de 0 a 6 modo ajuste
flash_1 = 0
flag_1 = 0
timer_base = 0
timer1_ms = 0
timer2_ms = 0
timer3_ms = 0
timer1_100ms = 0
timer2_100ms = 0
timer3_100ms = 0
timer_base_tiempo = 1 '100 'temporiza 100 mSeg
timer_1ms_tiempo = 1 'temporiza 1mseg
timer1_ms_tiempo = 1 '100 'temporiza 100 mSeg., asignado a la tecla S1
timer2_ms_tiempo = 1 '500 'temporiza 500 mSeg.
timer3_ms_tiempo = 1 '100 'temporiza 100 mSeg., asignado a la tecla S2
timer1_100ms_tiempo = 1 '10 'temporiza 1 Seg.
timer2_100ms_tiempo = 1 '255 'temporiza 25.5 Seg.
timer3_100ms_tiempo = 1 'temporiza 0.1seg.
'-------------------------------------asiganacion de valores a las variables (temperatura)------
entero = 0
decimal = 0
division = 0
adc_4 = 0
factor_escala = 10 'factor de escala para un decimal
temperatura = 0
temp = 0
media_indice = 0
aux_media = 0
'**************************************DEFINICION DE PUERTOS*************************************
'----------------------ASIGNACION DE I/O y valores de inicio de las salidas---------------------
Define ADC_SAMPLEUS = 0 'el minimo, configuracion del ADC
Define ADC_CLOCK = 5 '16Tad a 8Mhz = 2uSeg, minimo permitido por el micro 1.5uSeg, configuracion ADC
'_______________registros afectados por Define ADC_CLOCK y ADCIN________________
ANSEL = %00010000 'los pin I/O digitales y RA4 analogico
ADCON0 = %01100000 'Fosc/16 a 8Mhz (ADCON1.ADCS2=1) =2uSeg (minimo 1.uSeg), channel RA4
ADCON1 = %01000000 'voltage reference (AVdd/AVss) y seleccion de escala division clock/2 ADCON1.ADCS2=1
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
TRISA.4 = 1 'como entrada (RA4, adc)
TRISA.6 = 1 'como entrada (RA6, tecla S1)
TRISA.5 = 1 'como entrada (RA5, tecla S2)
PORTB.3 = 1 'luz lcd a on (RB3)
PORTA.7 = 1 'led amarillo a off
PORTB.0 = 1 'led verde a off
'------------------------------------Velocidad de la UART-----------------------------------------
Hseropen 4800 'velocidad de trabajo del modulo UART del PIC, RB5 tiene que ser declarado como salida
'------------------------------------Inicializacion de Interrupciones-----------------------------
T1CON.TMR1CS = 0 'asigna el reloj interno al timer1, se incrementa cada ciclo de instruccion
T1CON.T1CKPS0 = 0 'factor del preescales del timer1, 0
T1CON.T1CKPS1 = 0 'factor del preescales del timer1, 0
TMR1H = 0xf8 'carga el registro del contador para que desborde cada 1mSeg, byte alto
TMR1L = 0x30 'carga el registro del contador para que desborde cada 1mSeg, byte bajo
T1CON.TMR1ON = 1 'habilitacion del TMR1, comienza a incrementarce
INTCON.PEIE = 1 'bit de habilitacion de interrupciones de perifericos
Enable 'INTCON.GIE habilita todas las interrupciones globales
'**************************************Inicio Programa*********************************************
Lcdinit 'inicializa el lcd sin cursor
Hserout 0x0c, "MUESTRA LA TEMPERATURA MEDIA CADA 25.5 Seg.", CrLf 'alpuerto serie
Hserout "-------------------------------------------", CrLf, CrLf 'alpuerto serie
PIE1.TMR1IE = 1 'activa las interrupciones del timer1
pause = 1000
Gosub pause_ms 'espera el tiempo indicado en pause
Lcdout "16F88LCD_RTC/I2C" 'escribe en el lcd
Lcdcmdout LcdLine2Home 'seleciona la linea dos como proxima para escritura
Lcdout "ADC_LM35_RS232" 'escribe en el lcd
pause = 3000
Gosub pause_ms 'espera el tiempo indicado en pause
Lcdcmdout LcdClear 'borra el display y cursor a casa
'--------------------------------inicializa variable media_temperatura---------------------------
Gosub inicializa_temp
'--------------------------------inicializa los registros del RTC---------------------------------
Gosub inicaliza_rtc
'--------------------------------------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
Hserout "TEMPERATURA: " 'pagina en blanco y literal al purto serie
If signo = 0 Then Hserout "+" 'muestra el signo de la temperatura
If signo = 1 Then Hserout "-" 'muestra el signo de la temperatura
Hserout #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 Hserout " 0" 'si horas es inferior a 10 escribe el cero delante
Hserout #reg(2), ":" 'escribe la hora
If reg(1) < 10 Then Hserout "0" 'si minutos es inferior a 10 escribe el cero delante
Hserout #reg(1), ":" 'escribe los minutos
If reg(0) < 10 Then Hserout "0" 'si segundos es inferior a 10 escribe el cero delante
Hserout #reg(0), " " 'escribe los segundos
If reg(3) = 1 Then Hserout "Dom." 'asigna el literal al dia de la semana
If reg(3) = 2 Then Hserout "Lun."
If reg(3) = 3 Then Hserout "Mar."
If reg(3) = 4 Then Hserout "Mie."
If reg(3) = 5 Then Hserout "Jue."
If reg(3) = 6 Then Hserout "Vie."
If reg(3) = 7 Then Hserout "Sab."
If reg(4) < 10 Then Hserout " 0" 'si dia del mes es inferior a 10 escribe cero
Hserout #reg(4), "/" 'escribe el dia del mes
If reg(5) < 10 Then Hserout "0" 'si mes es inferior a 10 escribe cero
Hserout #reg(5), "/20" 'escribe el mes
If reg(6) < 10 Then Hserout "0" 'si año es inferior a 10 escribe primero el cero
Hserout #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
End
'***************** PIC Entrenadora BASIC (PicEBasic)**********************
'NOMBRE: 16F88_Pic_EBasic_Ejemplo_14
'MICRO: PIC16F88
'FECHA/AUTOR: 05/07 - By COS, PSI v7.41
'Pprograma para practicar con servos y la declaracion WaitUs
'Periodo para la señal de control del servo 20mSeg. (50Hz)
'Duty Cycle max. 2300uSeg. (extremo derecha) y minimo 450uSeg. (extr. izquierda)
'Control de la posicion del servo mediante RA0 y RA1
'-----------------------------------------------------------------------------------------------
Define CONFIG = 0x2f50 'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc 'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 8 'Clock en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Activar para simulación
'-------------------------------------------------------------------------------
AllDigital 'Todos los puertos como I/O
CMCON = 0x07 'Comparador a off
OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0xff 'Puerto A como Entradas
TRISB = 0xff 'Puerto B como Entradas
TRISA.4 = 1 'Como entrada (RA4, adc)
TRISA.6 = 1 'Como entrada (RA6, tecla S1)
TRISA.5 = 1 'Como entrada (RA5, tecla S2)
TRISB.3 = 0 'Como salida
TRISB.7 = 0 'Como salida
TRISB.0 = 0 'Como salida
TRISB.4 = 0 'Como salida, control servo
PORTB.3 = 1 'Luz lcd a on (RB3)
PORTA.7 = 1 'Led amarillo a off, negado
PORTB.0 = 1 'Led verde a off, negado
'-------------------------------------------------------------------------------
Dim posicion As Word 'duty cycle, señal de control servo a on
Dim periodo As Word 'frecuencia de trabajo de la señal del servo
Dim resto As Word 'señal de control del servo que tiene que estar a OFF
'-------------------------------------------------------------------------------
periodo = 20000 'Periodo (50Hz) de la señal del servo, en uSeg.
posicion = 1350 'Posicion central, duty cycle, señal de control a ON, uSeg.
'-------------------------------------------------------------------------------
main:
If RA5 = 0 Then '__________Nueva posicion (izquierda) y sus limites y tecla
If posicion > 450 Then posicion = posicion - 1
Endif '__________________________________________
If RA6 = 0 Then '___________Nueva posicion (derecha) y sus limites y tecla
If posicion < 2300 Then posicion = posicion + 1
Endif '___________________________________________
Gosub pwm_servo 'Salto con retorno a la rutina generadora del PWM
Goto main
End
pwm_servo: '_____________Genera la señal PWM, para controlar el servo
High RB4 'Control del servo, parte a on
WaitUs posicion 'Duty cycle, señal del servo a ON, pausa absoluta y perdida de tiempo
Low RB4 'Control del servo, parte a off
resto = (periodo - posicion) / 1000 'Tiempo que la señal del servo tiene que estar a OFF
WaitMs resto 'Pausa absoluta y una perdida de tiempo total
Return
Que grandes avances haces amigo dogflu66 :-/ :-/ :-/
veré si puedo hacer arrancar la lcd con este simulador.
una de las bondades, es que puedes ver las instrucciones línea por línea en asm y cambiar la velocidad de simulación.
'********************************** PIC Entrenadora BASIC *********************************
'NOMBRE: 16F88_Pic_EBasic_LCD_RS232_13
'VERSION: 1.3
'MICRO: PIC16F88
'Fecha/Autor: 1/07, 4/07, 5/7, 6/7 By COS, PSI v7.41
'VERSION 1.3
'Se simplifica la rutina bufer de lectura del puerto serie fisico
'mejora en la precision en las bases de tiempos
'VERSION: 1.2
'modificacion de la rutina Pause_ms
'se baja el bufer del puerto serie a 80 caracteres, porque se aprecia un fallo esporadico de lectura
'se filtran solo los caracteres de control < 31 y "@", se igualan a "_"
'no se aprecia ninguna perdida esporadica de caracteres (ok)
'Version: 1.1
'Simplificacion y mejora de las rutinas
'eliminacion del tiempo de lectura entre byte y byte, ahora solo se lee si hay datos en el bufer
'VERSION: 1.0
'Descripcion: muestra en el display de 16x2, los caracteres recibidos por rs232 y envia otra cadena fija
'tiempo de lectura entre byte y byte del puerto serie 10mseg maximo si no hay datos
'Baudios 4800, 8n1
'************************************************************************************************
Define CONF_WORD = 0x2f50 'Configuración de bits (fuses)
Define CONF_WORD_2 = 0x3ffc 'Configuración de bits (fuses)
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Hace que se ignoren los tiempos de los WaitMs
'Puertos del LCD -------------------------------------------------------------------------------------------
Define LCD_BITS = 4 'Indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'Bus de datos sera el puerto A
Define LCD_DBIT = 0 'Bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'Bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E sera del puerto B
Define LCD_EBIT = 6 'RB6 como E
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comando del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera despues de inicializar el Display.
'Asignacion de I/O y valores de inicio de las salidas---------------------------------------------------
ANSEL = 0x00 'los pin I/O digitales
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
TRISA.4 = 1 'como entrada (RA4, adc)
TRISA.6 = 1 'como entrada (RA6, tecla S1)
TRISA.5 = 1 'como entrada (RA5, tecla S2)
'TRISB.5 = 0 'RB5(Tx, RS232)
TRISB.2 = 1 'RB2 (Rx, RS232)
PORTB.3 = 1 'luz lcd a on (RB3)
PORTA.7 = 1 'led amarillo a off
PORTB.0 = 1 'led verde a off
'Inicio TMER1 -------------------------------------------------------------------------------------------------
T1CON.TMR1CS = 0 'asigna el reloj interno al timer1, se incrementa cada ciclo de instruccion
T1CON.T1CKPS0 = 0 'factor del preescales del timer1, 0
T1CON.T1CKPS1 = 0 'factor del preescales del timer1, 0
TMR1H = 0xf8 'carga el registro del contador para que desborde cada 1mSeg, byte alto
TMR1L = 0x2f 'carga el registro del contador para que desborde cada 1mSeg, byte bajo
T1CON.TMR1ON = 1 'habilitacion del TMR1, comienza a incrementarce
'Bit interrupciones
PIE1.TMR1IE = 1 'Permete las interrupciones del timer1
PIE1.RCIE = 1 'Permte la interrupcion de la uart en modo rx
INTCON.PEIE = 1 'Bit de habilitacion de interrupciones de perifericos
'--------------------------------------------------------------------------------------------------------------------
Lcdinit 'inicializa el LCD sin cursor
Hseropen 4800 'Configura puerto serie
'--------------------------------------Reasignacion de nombres-----------------------------------------
Symbol led_amarillo = PORTA.7 'led amarillo
Symbol led_verde = PORTB.0 'led verde
'--------------------------------------Declaracion DE VARIABLES-------------------------------------
'Variables subrutinas del puerto serie ----------------------------------------------------------------
Dim assi As Byte 'Contiene el valor de lectura del puerto serie
Dim n_uart As Byte 'Numero de datos del uart y del bufer IMAGEN de control
Dim uart As Byte 'Variable indice que apunta al ultimo dato adquirido por la uart
Dim c_serial As Byte 'Como uart pero para la lectura de control del bufer IMAGEN
Dim bufer As Byte 'Indica si hay datos por leer en el bufer uart
'Variables de los timer-------------------------------------------------------------------------------------
Dim aux_pause As Word 'variable auxiiar el PAUSE
Dim pause As Word 'contiene el valor para simular el comando Waitms
Dim timer_1ms As Word 'base de tiempos se incrementa cada 1mSeg, timer del PAUSE
Dim timer_1ms_tiempo As Word 'contiene el valor del tiempo del timer_1ms
Dim timer_base As Byte 'tiempo referencia para los timer por soft del programa
Dim timer_base_tiempo As Byte 'contiene el valor del tiempo del timer_base
Dim timer1_ms As Word 'base de tiempos en ms
Dim timer2_ms As Word 'base de tiempos en ms
Dim timer3_ms As Word 'base de tiempos en ms
Dim timer1_100ms As Byte 'base de tiempos msx100
Dim timer2_100ms As Byte 'base de tiempos msx100
Dim timer3_100ms As Byte 'base de tiempos msx100
Dim timer1_ms_tiempo As Word 'contiene el valor del tiempo del timer1_ms
Dim timer2_ms_tiempo As Word 'contiene el valor del tiempo del timer2_ms
Dim timer3_ms_tiempo As Word 'contiene el valor del tiempo del timer3_ms
Dim timer1_100ms_tiempo As Byte 'contiene el valor del tiempo del timer1_100ms
Dim timer2_100ms_tiempo As Byte 'contiene el valor del tiempo del timer2_100ms
Dim timer3_100ms_tiempo As Byte 'contiene el valor del tiempo del timer3_100ms
'--------------------------------------Variables Programa--------------------------------------------------
'Variables rutina muestra datos en el LCD
Dim n As Byte 'se utiliza para posicionar caracter en el lcd
Dim flag As Byte 'controla la alternancia para imprimir en el lcd el caracter "(" o el ")"
Dim flag_1 As Byte 'controla la alternacia entre secuencia 1 y 2, tramas tx
'Variables tipo array puerto serie ------------------------------------------------------------------------
Dim uart_imagen(80) As Byte 'Componen el bufer IMAGEN para control del bufer UART
Dim uart_bufer(80) As Byte 'Componen el bufer de la UART de bajo nivel
'Asigna valores a las bases de tiempos del TIMER1-----------------------------------------------
timer_base = 0
aux_pause = 0
pause = 0
timer_1ms = 0
timer1_ms = 0
timer2_ms = 0
timer3_ms = 0
timer1_100ms = 0
timer2_100ms = 0
timer3_100ms = 0
timer_base_tiempo = 100 'cuenta 100mSeg
timer1_ms_tiempo = 5 'cuenta 5mSeg.
timer2_ms_tiempo = 100 'cuenta 0.1Seg
timer3_ms_tiempo = 100 'cuenta 0.1Seg
timer1_100ms_tiempo = 10 'cuenta 1Seg.
timer2_100ms_tiempo = 5 'temporiza 0.5Seg
timer3_100ms_tiempo = 5 'temporiza 0.5seg
'Asigna valores a las variables de la rutina del puerto serie----------------
uart = 0
c_serial = 0
bufer = 0
n_uart = 79
assi = 0
'Asignacion de valores generales ------------------------------------------------
n = 0
flag = 0
flag_1 = 0
'----------------------------------------------------------------------------------------------
Enable 'INTCON.GIE habilita todas las interrupciones globales
Gosub clear_bufer 'Inicializa el Buffer RS232, OBLIGATORIO POR LO MENOS UNA VEZ
pause = 1000 'prepara una pausa de 1Seg
Gosub pause_ms 'espera el tiempo que indica pause
Lcdout "18F88_LCD_RS232" 'imprime en el LCD el literal
Lcdcmdout LcdLine2Home 'selecciona linea y cursor al principio
Lcdout "RS232-4800Baud." 'escribe la cadena de literales en el lcd
Hserout CrLf, CrLf, "VER. 1.0 - TX/RX", CrLf, "TX -> PRUEBAS RS232", CrLf, "By COS", CrLf, CrLf 'envia presentacion al RS232
pause = 3000 'prepara una pausa de 3Seg
Gosub pause_ms 'hace una pausa de tiempo indicado por pause
Lcdcmdout LcdClear 'borra el display
'--------------------------------------Bucle Main ------------------------------------------
main:
If timer2_100ms >= timer2_100ms_tiempo And flag_1 = 0 Then 'determina cuando emitir la secuencia_1
Gosub secuencia_1
timer2_100ms = 0
flag_1 = 1 'activa la alternancia entre secuencia_1 y la 2
Endif
If timer2_100ms >= timer2_100ms_tiempo And flag_1 = 1 Then 'determina cuando emitir la secuencia_2
Gosub secuencia_2
timer2_100ms = 0
flag_1 = 0 'activa la alternancia entre secuencia_1 y la 2
Endif
Gosub lcd_control
Goto main
End
'--------------------------------------Subrutinas Programa-----------------------------------------------
secuencia_1: 'envia la trama por el puerto serie
Hserout "@Hola Amigos de TODOPIC", CrLf
Return
secuencia_2: 'envia la trama por el puerto serie
Hserout "@Ejemplo de Trabajo con RS232", CrLf
Return
pause_ms: 'rutina de espera, rutina tipo Waitms, pause establese el tiempo total en mSeg
timer_1ms = 0 'al borrar el contador se activa y comienza la cuenta de mSeg
While timer_1ms < pause 'tiempo en mSeg maximos a contar
Wend
Return
'------------------------------ rutinas para el control del bufer del puerto serie-------------
readserial:
'Rutina de lectura del bufer del puerto serie (assi)
If bufer > 0 Then 'si bufer tiene datos
assi = uart_bufer(c_serial) 'se lee el valor del bufer y se asigna assi
uart_imagen(c_serial) = 0 'se marca como leida para que pueda ser llenada de nuevo
c_serial = c_serial + 1 'se incrementa el indice del bufer
If c_serial >= n_uart Then c_serial = 0 'se verifica si se llego al final del bufer
If uart_imagen(c_serial) = 0 Then bufer = 0 'si no quedan mas datos en el bufer se marca como vacio
Else
assi = 0
Endif
Return
clear_bufer: 'inicializa el bufer imagen y borra error del puerto fisico en modo Rx
'_________________________Borra e inicializa el bufer imagan del puerto serie
c_serial = 0
While c_serial <= n_uart 'se ejecuta tantas veces como variables tiene el bufer
uart_imagen(c_serial) = 0 'borra el indicador de variable del bufer con datos
c_serial = c_serial + 1
Wend
c_serial = 0 'variables de control del bufer
uart = 0
bufer = 0
assi = 0
'_________________________Borra el error del puerto serie fisico en Rx
RCSTA.OERR = 0
RCSTA.CREN = 0
RCSTA.CREN = 1
Return
'Subrutina gestión interrupciones -----------------------------------------------------------------
On Interrupt 'desactiva las interrupciones
Save System 'Guarda los valores del sistema
'__Bases de tiempos
If PIR1.TMR1IF = 1 Then 'comprueba que la interrupcion la proboco el timer1
TMR1H = 0xf8 'recarga el contador del timer1 para que desborde pasado 1mSeg, byte alto
TMR1L = 0x2f 'recarga el contador del timer1 para que desborde pasado 1mSeg, byte bajo
timer_base = timer_base + 1 'base patron
timer_1ms = timer_1ms + 1 'contador para control del timer_1ms
If timer1_ms < timer1_ms_tiempo Then timer1_ms = timer1_ms + 1 'contador para control del timer1_ms
If timer2_ms < timer2_ms_tiempo Then timer2_ms = timer2_ms + 1 'contador para control del timer2_ms
If timer3_ms < timer3_ms_tiempo Then timer3_ms = timer3_ms + 1 'contador para control del timer3_ms
If timer_base >= timer_base_tiempo Then 'usa la base patron para retrazar la rutina 100mSeg.
If timer1_100ms < timer1_100ms_tiempo Then timer1_100ms = timer1_100ms + 1 'contador para control...
If timer2_100ms < timer2_100ms_tiempo Then timer2_100ms = timer2_100ms + 1 'contador para control...
If timer3_100ms < timer3_100ms_tiempo Then timer3_100ms = timer3_100ms + 1 'contador para control...
timer_base = 0 'reset a la base timer
Endif
PIR1.TMR1IF = 0 'borra el bit de salto del timer1
Endif
'__Bufffer puerto serie
If PIR1.RCIF = 1 Then 'comprueba que es esta la interrupcion activa del modulo USART
If uart_imagen(uart) = 0 Then 'comprueba que la posicion esta vacia
uart_imagen(uart) = 1 'indica que hay dato en el bufer de entrada
bufer = 1 'indica que el bufer tine datos
Hserget uart_bufer(uart) 'carga el dato en el bufer
uart = uart + 1 'indica cual sera la posicion siguiente del bufer
If uart >= n_uart Then uart = 0 'comprueba el final del bufer y lo inicializa
Else
Hserget uart_bufer(n_uart) 'descarga la uart para que no se bloquee porque el bufer de entrada esta lleno
Endif
PIR1.RCIF = 0 'borra el bit de salto del Rx, esto ya lo hace de forma automatica Hserget
Endif
Resume 'activa las interrupciones y retorna al curso normal del programa antes del salto
lcd_control: 'rutina que imprime los valores recibidos por el puerto serie en el display
'parte 1 de la rutina, sincroniza e imprime los caracteres recibidos por el puerto serie
If bufer = 1 Then 'la rutina se ejecuta si hay datos en el bufer
timer1_100ms = 0 'hay datos hace reset al timer1_100ms
Gosub readserial 'salta a la rutina de lectura del bufer serie
If assi = "@" Then 'caracter de sincronismo de la trama
n = 0 'possicion del display
Lcdcmdout LcdClear 'borra el display y posiciona el cursor superior izquierda
Endif
n = n + 1 'incrementa la posicion para escribir el siguiente caracter en el display
If assi < 21 Or assi = "@" Then assi = 95 'filtra los caracteres a imprimir
Lcdout assi 'escribe el caracter del bufer en el display
If n = 16 Then 'detecta fin de la linea primera
Lcdcmdout LcdLine2Home 'situa el cursor al principio de la siguiente linea
Endif
If n >= 32 Then 'detecta fin de la segunda linea
n = 0 'inicializa la posicion del proximo caracter a imprimir en el display
Lcdcmdout LcdLine1Home 'a inicio de linea
Endif
Endif
'parte 2 de la rutina, cuando no se reciben datos imprime en el display "(" y ")" de forma alterna
If timer1_100ms >= timer1_100ms_tiempo Then 'produce un retrazo inicial a la ejecucion de la rutina
If bufer = 0 Then 'si no hay datos en el bufer
If timer1_ms >= timer1_ms_tiempo Then 'produce un retrazo cada vez que se intenta imprimir en el lcd
timer1_ms = 0 'resetea el timer1_ms para que cuente de nuevo
If flag = 0 Then 'produce la alternancia para escribir "("
n = n + 1
Lcdout "("
If n = 16 Then
Lcdcmdout LcdLine2Home
Endif
If n >= 32 Then
n = 0
flag = 1
Lcdcmdout LcdLine1Home
Endif
Endif
If flag = 1 Then 'produce la alternancia para escribir ")"
n = n + 1
Lcdout ")"
If n = 16 Then
Lcdcmdout LcdLine2Home
Endif
If n >= 32 Then
n = 0
flag = 0
Lcdcmdout LcdLine1Home
Endif
Endif
Endif
Endif
Endif
Return
Tú te lo guisas y tú te lo comes. ¡Cualquiera se atreve a preguntarte! :D
'***************** Placa Entrenadora (PIC EBadic) ***************************************
'NOMBRE: 16F88_Pic_EBasic_LCD_Timer1_ADC_PWM_12
'MICRO: PIC16F88/8Mhz reloj interno
'Fecha/Autor: 1/07, 6/07 By COS, PSI v7.41
'Version: 1.2
'se elimina el control del PWM por bases de tiempos y se controla mediante el modulo CCP1
'Version: 1.1
'Se cambian los Lcdcmdout LcdClear por Lcdcmdout LcdLinexHome en la subrutina del display, print_lcd
'este cambio acelera la escritura en el display
'Se convierte en subrutina el calculo del PWM segun el valor leido del ADC, calculo_pwm
'Se cambian el orden de los saltos en las lineas acotadas por el timer3_100ms, en el main, esto hace que el valor
'leido de la entrada analogica se actualice con los valores del PWM en el mismo ciclo
'Version: 1.0
'Uso del LCD con bus de datos a 4Bit y sin pin de RW
'Activacion del Timer1 por rebose cada 1mSeg.
'implementacion de timer (bases de tiempos) por soft
'lectura de entrada analogica y conversion a voltaje con dos decimales
'Implementacion de PWM con periodo de 20mseg. para el control de la luz del lcd por medio de la entrada adc
'*********************************************************************************************
Define CONF_WORD = 0x2f50 'Configuración de bits (fuses)
Define CONF_WORD_2 = 0x3ffc 'Configuración de bits (fuses)
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Hace que se ignoren los tiempos de los WaitMs
'Puertos del LCD-------------------------------------
Define LCD_BITS = 4 'Indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'Bus de datos sera el puerto A
Define LCD_DBIT = 0 'Bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'Bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E sera del puerto B
Define LCD_EBIT = 6 'RB6 como E
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comando del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera despues de inicializar el Display.
'------------------------------------Definicion de puertos------------------------------------------
ANSEL = 0x00 'los pin I/O digitales
Define ADC_SAMPLEUS = 10 'el minimo, configuracion del ADC
Define ADC_CLOCK = 5 '16Tad a 8Mhz = 2uSeg, minimo permitido por el micro 1.5uSeg, configuracion ADC
'_______________registros afectados por Define ADC_CLOCK y ADCIN________________
ANSEL = %00010000 'los pin I/O digitales y RA4 analogico
ADCON0 = %01100000 'Fosc/16 a 8Mhz (ADCON1.ADCS2=1) =2uSeg (minimo 1.uSeg), channel RA4
ADCON1 = %01000000 'voltage reference (AVdd/AVss) y seleccion de escala division clock/2 ADCON1.ADCS2=1
'_______________________________________________________________________________
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
TRISA.4 = 1 'como entrada (RA4, adc)
TRISA.6 = 1 'como entrada (RA6, tecla S1)
TRISA.5 = 1 'como entrada (RA5, tecla S2)
PORTB.3 = 1 'luz lcd a on (RB3)
PORTA.7 = 1 'led amarillo a off (RA7), negado
PORTB.0 = 1 'led verde a off (RB0), negado
'------------------------------------Inicializacion del TMR1 ---------------------------------
T1CON.TMR1CS = 0 'asigna el reloj interno al timer1, se incrementa cada ciclo de instruccion
T1CON.T1CKPS0 = 0 'factor del preescales del timer1, 0
T1CON.T1CKPS1 = 0 'factor del preescales del timer1, 0
TMR1H = 0xf8 'carga el registro del contador para que desborde cada 1mSeg, byte alto
TMR1L = 0x30 'carga el registro del contador para que desborde cada 1mSeg, byte bajo
T1CON.TMR1ON = 1 'habilitacion del TMR1, comienza a incrementarce
PIE1.TMR1IE = 1 'activa las interrupciones del timer1
INTCON.PEIE = 1 'bit de habilitacion de interrupciones de perifericos
'------------------------------------------------------------------------------------------------------
Lcdinit 'inicializa el lcd sin cursor
'Asignación de nombres --------------------------------------------------------------------
Symbol led_amarillo = PORTA.7 'led amarillo
Symbol led_verde = PORTB.0 'led verde
Symbol luz_lcd = PORTB.3 'iluminacion del lcd
'Declaracion de variables-------------------------------------------------------------------
'************************************variables de los timer************************
Dim timer_base As Byte 'tiempo referencia para los timer por soft del programa
Dim timer_base_tiempo As Byte 'contiene el valor del tiempo del timer_base
Dim timer1_ms As Word 'base de tiempos en ms
Dim timer2_ms As Word 'base de tiempos en ms
Dim timer3_ms As Word 'base de tiempos en ms
Dim timer1_100ms As Byte 'base de tiempos msx100
Dim timer2_100ms As Byte 'base de tiempos msx100
Dim timer3_100ms As Byte 'base de tiempos msx100
Dim timer1_ms_tiempo As Word 'contiene el valor del tiempo del timer1_ms
Dim timer2_ms_tiempo As Word 'contiene el valor del tiempo del timer2_ms
Dim timer3_ms_tiempo As Word 'contiene el valor del tiempo del timer3_ms
Dim timer1_100ms_tiempo As Byte 'contiene el valor del tiempo del timer1_100ms
Dim timer2_100ms_tiempo As Byte 'contiene el valor del tiempo del timer2_100ms
Dim timer3_100ms_tiempo As Byte 'contiene el valor del tiempo del timer3_100ms
'-------------------------------Variables del ADC y Rutina division-------------------
Dim adc_4 As Word 'contiene el valor de la entrada ADC
Dim num_1 As Word 'valor del adc y retorna la parte entera
Dim num_2 As Word 'factor de la escala y retorna el primer decimal
Dim num_3 As Word 'segundo decimal
Dim dvdo As Word 'dividendo operacion
Dim dvsor As Word 'divisor operacion
'-------------------------------Variables generales-----------------------------------------
Dim flag_1 As Byte 'determina si la luz del lcd estara a on o a off
Dim duty As Word 'contiene el tiempo a on de la iluminacion del lcd a 10bit
Dim resto_periodo As Word 'contine el tiempo a off de la iluminacion del lcd
'-------------------------------Asignacion de valores a las variables------------------
timer_base = 0
timer1_ms = 0
timer2_ms = 0
timer3_ms = 0
timer1_100ms = 0
timer2_100ms = 0
timer3_100ms = 0
timer_base_tiempo = 1 '100 'cuenta 100mSeg
timer1_ms_tiempo = 1 'cuenta 1mSeg.
timer2_ms_tiempo = 19 'cuenta 19mSeg
timer3_ms_tiempo = 5 'cuenta 5mSeg
timer1_100ms_tiempo = 10 'cuenta 1 Seg.
timer2_100ms_tiempo = 20 'temporiza 2Seg
timer3_100ms_tiempo = 1 'temporiza 0.1seg
flag_1 = 0
adc_4 = 0
resto_periodo = 0
duty = 0
'-------------------------------------------------------------------------------------------------------------
Enable 'INTCON.GIE habilita todas las interrupciones globales
WaitMs 1000 'espera 1Seg, las interrupciones alargan este tiempo
Lcdout "LCD_Tmr1_ADC_PWM" 'escribe en el lcd
Lcdcmdout LcdLine2Home 'seleciona la linea dos como proxima para escritura
Lcdout "Pruebas con CCP" 'escribe en el lcd
WaitMs 3000 'espera 3Seg, las iterrupciones hacen este tiempo mas largo
Lcdcmdout LcdClear 'borra el display
PWMon 1, 1 'activa el modulo CCP1, a 10bit, 488Hz y duty cycle 0
'------------------------------------Rutinas Principal----------------------
main: 'comienza el programa principal
If timer1_100ms >= timer1_100ms_tiempo Then 'cambio de estado el pin RA7 cada timer1_100ms_tiempo
Toggle led_amarillo 'invierte el valor del pin
timer1_100ms = 0 'reinicio el timer1_100ms
Endif
If timer2_100ms >= timer2_100ms_tiempo Then 'cambio de estado el pin RB0 cada timer2_100ms_tiempo
Toggle led_verde 'invierte el valor del pin
timer2_100ms = 0 'reinicio el timer2_100ms
Endif
If timer3_100ms >= timer3_100ms_tiempo Then 'permite que se ejecute las rutinas solo una vez cada timer3_100ms_tiempo
Gosub lee_adc 'salto con retorno, rutina de lectura de la entrada ADC
Gosub division_dos_decimales 'salto con retorno, rutina de conversion de valor adc a voltios
Gosub calculo_pwm 'salto con retorno, rutina de calculo de tiempos del PWM
Gosub print_lcd 'salto con retorno, rutina que imprime los valores en el lcd
timer3_100ms = 0 'reset a la base de tiempos
Endif
PWMduty 1, duty 'mantiene el duty cycle del modulo ccp
Goto main 'impide que termine el programa principal
End 'Fin main
'--------------------------------------Subrutina lectura ADC, division y LCD
lee_adc: '_______________________lee la entrada analogica
Adcin 4, adc_4 'lee el valor de la entrada analogica y lo carga en adc_4
num_1 = adc_4 'sede el valor del adc para ser procesado
num_2 = 205 'asigna factor de correccion, para 5V
Return
division_dos_decimales: '________Rutina division con dos decimales y conversion a voltios
dvdo = num_1 'asigna dividendo
dvsor = num_2 'asigna divisor
If dvdo > dvsor Then 'calcula la parte entera
num_1 = dvdo / dvsor
dvdo = dvdo Mod dvsor
Else
num_1 = 0
Endif
dvdo = dvdo * 10
If dvdo > dvsor Then 'extrae el primer decimal
num_2 = dvdo / dvsor
dvdo = dvdo Mod dvsor
Else
num_2 = 0
Endif
dvdo = dvdo * 10
If dvdo > dvsor Then 'extrae el segundo decimal
num_3 = dvdo / dvsor
Else
num_3 = 0
Endif
Return
print_lcd: '____________________muestra los datos por el display
Lcdcmdout LcdLine1Home 'cursor al principio, de la primera linea
Lcdout "ADC ", #adc_4, " ", #num_1, ".", #num_2, #num_3, "V", " " 'muestra los datos en el lcd
Lcdcmdout LcdLine2Home 'cursor al principio de la segunda linea
Lcdout "On ", #duty, " Off ", #resto_periodo, " " 'muestra los datos en el lcd
Return
calculo_pwm: '__________control de los tiempos del PWM segun el valor de adc_4
duty = adc_4 'controla el tiempo del PWM en estado alto
resto_periodo = 1023 - duty 'nos indica el tiempo del PWM en estado bajo
'___________________________________________________
Return
'--------------------------------Interrupciones---------------------------------------------------
On Interrupt 'Comienzan las rutinas de las interrupciones, desactiva las interrupciones
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
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
'___base de tiempos
timer_base = timer_base + 1 'contador general
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 tiempo 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 'contador
If timer3_100ms < timer3_100ms_tiempo Then timer3_100ms = timer3_100ms + 1 'contador
timer_base = 0 'reset a la base de tiempos
Endif
'__fin base de tiempos
PIR1.TMR1IF = 0 'borra el flag de salto del tmr1
Endif
Resume 'activa las interrupciones y retorna al curso normal del programa antes del salto
''******************** PIC Entrenadora BASIC (PicEBasic)********************
'NOMBRE: 16F88_Pic_EBasic_Ejemplo_16
'MICRO: PIC16F88
'FECHA/AUTOR: 06/07 - By COS, PSI v7.41
'Practicando con el WatchDog (WDT)
'Si se pulsa S1 o S2 se anula la línea que hace reset al WatchDog.
'Activacion del reset generado por el WatchDog sobre los 2mSeg.
'Led con secuencia de parpadeo establecida, para observar el reset.
'Se crea un tipo de pause (delay) que permite hacer reset al WDT.
'Este modulo WDT tiene un único reloj que es interno a 31250Hz.
'Tiene un Prescaler y se le puede añadir un poscaler, este poscaler
'puede ser asignado al WDT o al TMR0, no a los dos a la vez.
'***********************************************************************************
Define CONFIG = 0x2f14 'Configuración de bits (fuses)
Define CONF_WORD_2 = 0x3ffc 'Configuración de bits (fuses)
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Hace que se ignoren los tiempos de los WaitMs
'---------------------------- Configuración del Clock, Puertos I/O -------------------
AllDigital 'todos los puertos como I/O
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0xff 'Puerto A como Entradas
TRISB = 0xff 'puerto B como Entradas
'TRISA.4 = 1 'como entrada (RA4, adc)
'TRISA.6 = 1 'como entrada (RA6, tecla S1)
'TRISA.5 = 1 'como entrada (RA5, tecla S2)
TRISB.3 = 0 'como salida, iluminación lcd
TRISA.7 = 0 'como salida, led amarillo
TRISB.0 = 0 'como salida, led verde
TRISB.4 = 0 'como salida, control servo
PORTB.3 = 1 'luz lcd a on (RB3)
PORTA.7 = 1 'led amarillo a off (RA7), negado
PORTB.0 = 1 'led verde a off (RB0), negado
'--------------------------- Configuración del WatchDog ------------------------------
'Prescaler del Wdt 31250Hz/64
WDTCON.WDTPS0 = 1 'Prescaler Rate Select bits 64 (2048uSeg)
WDTCON.WDTPS1 = 0
WDTCON.WDTPS2 = 0
WDTCON.WDTPS3 = 0
OPTION_REG.PSA = 0 'No asigna poscaler al WDT
'Declaración y Asignación de valores -----------------------------------------------
Dim watchdog_on As Bit 'permite que se haga el reset al contador del watchdog
Dim pause As Word 'asigna el valor de espera en mSeg.
watchdog_on = 1 'inicializa la variable, borrado del registro del watchdog a on
'--------------------------------------------------------------------------------------------------
Gosub clear_watchdog 'borra el contador del watchdog antes que rebose
RA7 = 0 'salida led amarillo
RB0 = 0 'salida led verde
pause = 5000 'carga la rutina de espera con 5 Seg.
Gosub wait_ms 'salto con retorno a la rutina de espera
'Bucle main
main:
RA7 = 1 'salida led amarillo
RB0 = 1 'salida led verde
pause = 500 'carga la rutina de espera con 0,5 Seg.
Gosub wait_ms 'salto con retorno a la rutina de espera
RB0 = 0 'salida led verde
pause = 500 'carga la rutina de espera con 0,5 Seg.
Gosub wait_ms 'salto con retorno a la rutina de espera
RA7 = 0 'salida led amarillo
pause = 500 'carga la rutina de espera con 0,5 Seg.
Gosub wait_ms 'salto con retorno a la rutina de espera
Goto main 'impide que termine la rutina main
End
clear_watchdog: 'borra el contador del WatchDog
If watchdog_on = 0 Then Return 'determina si se hace el reset al WatchDog
ASM: clrwdt 'reinicializa el WDT, assembler
Return
wait_ms: 'rutina de espera, reset al WatchDog y lectura de las teclas
While pause > 0 'bucle que se repite mientras la condición sea cierta
If RA6 = 0 Or RA5 = 0 Then watchdog_on = 0 'lee las teclas
WaitMs 1 'espera 1 mSeg.
pause = pause - 1 'decrementa el tiempo de espera
Gosub clear_watchdog 'salto con retorno a la rutina
Wend 'acota el bucle While
Return
'*----------------------------*
'Display LCD 2x20 LM032L
'PIC 16F628A
'*----------------------------*
Define LCD_BITS = 4 'numeros de bits de datos
Define LCD_DREG = PORTB 'puerto de datos
Define LCD_DBIT = 0 'pines del puertos de datos (0,1,2,3)
Define LCD_RSREG = PORTA 'puerto del RS
Define LCD_RSBIT = 0 'pin del puerto RS
Define LCD_EREG = PORTA 'puerto del E
Define LCD_EBIT = 2 'pin del puerto E
Define LCD_RWREG = PORTA 'puerto del R/W
Define LCD_RWBIT = 1 'pin del puerto R/W
Define LCD_COMMANDUS = 5000 'demora de la escritura de un comando
Define LCD_DATAUS = 100 'demora de la escritura de un dato
Define LCD_INITMS = 100 'demora de la inicializacion del LCD
AllDigital
Lcdinit 3 'inicializo el LCD con cursor subrayado y parpadeando
loop:
Lcdcmdout LcdHome 'Lleva el cursor a la primera posición del primer renglón del LCD
Lcdout "www.todopic.com.ar"
WaitMs 1000 'Espero un segundo
Lcdcmdout LcdClear 'Borro el display
WaitMs 1000 'Espero un segundo
Goto loop
'***************** Placa Entrenadora (PIC EBadic) ***************************************
'NOMBRE: 16F88_Pic_EBasic_Ejemplo_19
'Descripcion: Usando Funciones
'Micro: PIC16F88 a 8mhz reloj interno, By COS, PSI v7.41
'Rutina de division hasta 4 decimales (Funcion) ________________
'Argumentos de entrada 2 variables tipo Word: dividendo, divisor,
'Numero decimales (1 Byte), una tipo Bit que permite que la funcion muestre (ON/OFF) el valor por display
'y como argumento de salida una variable tipo Long
'Muestra datos en el LCD hasta 4 decimales _________
'Uso del LCD con bus de datos a 4Bit y sin pin de RW
'*****************************************************************************************
Define CONF_WORD = 0x2f50 'Configuración de bits (fuses)
Define CONF_WORD_2 = 0x3ffc 'Configuración de bits (fuses)
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Hace que se ignoren los tiempos de los WaitMs
'-------------------------------------Puertos del LCD-------------------------------------
Define LCD_BITS = 4 'Indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'Bus de datos sera el puerto A
Define LCD_DBIT = 0 'Bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'Bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E sera del puerto B
Define LCD_EBIT = 6 'RB6 como E
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comando del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera despues de inicializar el Display.
'------------------------------Definicion de puertos--------------------------------------
ANSEL = 0x00 'los pin I/O digitales
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0xff 'Puerto A como Entradas
TRISB = 0xff 'puerto B como Entradas
TRISA.4 = 1 'como entrada (RA4, adc)
TRISA.6 = 1 'como entrada (RA6, tecla S1)
TRISA.5 = 1 'como entrada (RA5, tecla S2)
PORTB.3 = 1 'luz lcd a on (RB3)
PORTA.7 = 1 'led amarillo a off, negado
PORTB.0 = 1 'led verde a off, negado
'------------------------------------------------------
Lcdinit 'Inicializa el lcd sin cursor
WaitMs 1000 'Espera 1Seg
'Reasignacion de nombres----------------------------
Symbol led_amarillo = PORTA.7 'led amarillo
Symbol led_verde = PORTB.0 'led verde
Symbol luz_lcd = PORTB.3 'retroiluminacion del lcd
'Variables---------------------------------------------
Dim division As Long 'Almacenara el numero con los dos decimales
Dim numero_1 As Word 'Dividendo
Dim numero_2 As Word 'Divisor
'Asignacion de valores a las variables-----------------
numero_1 = 255
'Rutina principal--------------------------------------
main:
'Bucle que se repite hasta que numero_2 tome todos los valores comprendidos entre 1 y 5000 inclusive
For numero_2 = 1 To 5000
Lcdcmdout LcdLine1Home 'Cursor principio de linea 1
Lcdout #numero_1, "/", #numero_2, "= " 'Muestra los datos en el lcd
Lcdcmdout LcdLine2Home 'Cursor principio de linea 2
division = dvsion_dcmles(numero_1, numero_2, 3, 1) 'Llama a la funcion
Lcdout " " 'Borra caracteres sobrantes
WaitMs 1000 'Hace una pausa de 1 Seg.
Next numero_2 'Limita el bucle for
'Goto main 'Genera un bucle infinito
End
'______Rutina funcion division con decimales
'______Argumentos de entrada: 2 variables tipo word, dividendo, divisor,
'______numero de decimales (1 Byte) y display ON/OFF (1 Bit), argumento de salida una variable tipo Long
Function dvsion_dcmles(dvd As Word, dvsor As Word, n_dec As Byte, lcd_on As Bit) As Long
dvsion_dcmles.HW = 0 'inicializo el word alto
dvsion_dcmles.LW = dvd Mod dvsor 'obtengo el resto
'Multiplicar 1xx seguido de tantos ceros como decimales
dvsion_dcmles = (dvsion_dcmles * 10000) / dvsor
dvsion_dcmles.HW = dvd / dvsor 'obtengo la parte entera
'la parte decimal tiene que ser mostrada con plantilla si se usa mas de 1 decimal
'ahorro memoria al utilizar el menor numero de veces operaciones con Long
'___________________________________________________________________________________
'____________da formato a los decimales y los saca por el lcd
If n_dec < 1 Then n_dec = 1 'acota el numero de decimales
If n_dec > 4 Then n_dec = 4 'acota el numero de decimales
If n_dec = 1 Then dvsion_dcmles.LW = dvsion_dcmles.LW / 1000 'elimina decimales
If n_dec = 2 Then dvsion_dcmles.LW = dvsion_dcmles.LW / 100 'elimina decimales
If n_dec = 3 Then dvsion_dcmles.LW = dvsion_dcmles.LW / 10 'elimina decimales
If lcd_on = 1 Then 'habilita la opcion imprimir en el display
Lcdout #dvsion_dcmles.HW, "." 'muestra los datos en el lcd, parte entera
'mantiene la plantilla de los decimales, eliminar para 1 decimal
If dvsion_dcmles.LW < 10 And n_dec > 1 Then Lcdout "0"
'mantiene la plantilla de los decimales, eliminar para 1 y 2 decimales
If dvsion_dcmles.LW < 100 And n_dec > 2 Then Lcdout "0"
'mantiene la plantilla de los decimales, eliminar para 2 y 3 decimales
If dvsion_dcmles.LW < 1000 And n_dec > 3 Then Lcdout "0"
Lcdout #dvsion_dcmles.LW, 'muestra los datos en el lcd, decimales
Endif
End Function
'***************** Placa Entrenadora (PIC EBadic) *************************************
'NOMBRE: 16F88_Ejemplo 20
'MICRO: PIC16F88/8Mhz reloj interno
'Fecha/Autor: 06/07, By COS, PSI v7.41
'Parpadeo de un caracter en la pantalla del lcd
'Uso del LCD con bus de datos a 4Bit y sin pin de RW
'********************************************************************************
'********************************************************************************
Define CONF_WORD = 0x2f50 'Configuración de bits (fuses)
Define CONF_WORD_2 = 0x3ffc 'Configuración de bits (fuses)
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Hace que se ignoren los tiempos de los WaitMs
'-------------------------------------Puertos del LCD-------------------------------------
Define LCD_BITS = 4 'Indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'Bus de datos sera el puerto A
Define LCD_DBIT = 0 'Bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'Bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E sera del puerto B
Define LCD_EBIT = 6 'RB6 como E
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comando del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera despues de inicializar el Display.
'*************************************************************************************
'Definicion de puertos------------------------------------------
AllDigital 'Los pin de los puertos como I/O
CMCON = 0x07 'Comparador a off
OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0xff 'Puerto A como entradas
TRISB = 0xff 'Puerto B como entradas
'Inicializacion de Interrupciones-----------------------------
T1CON.TMR1CS = 0 'asigna el reloj interno al timer1, se incrementa cada ciclo de instruccion
T1CON.T1CKPS0 = 0 'factor del preescales del timer1, 0
T1CON.T1CKPS1 = 0 'factor del preescales del timer1, 0
TMR1H = 0xf8 'carga el registro del contador para que desborde cada 1mSeg, byte alto
TMR1L = 0x2f 'carga el registro del contador para que desborde cada 1mSeg, byte bajo
T1CON.TMR1ON = 1 'habilitacion del TMR1, comienza a incrementarce
PIE1.TMR1IE = 1 'activa las interrupciones del timer1
INTCON.PEIE = 1 'bit de habilitacion de interrupciones de perifericos
Lcdinit 'Inicializa el display
'Declaracion de variables---------------------------------------
Dim n As Byte 'Variable auxiliar
Dim flash As Bit 'Control parpadeo
Dim timer1_ms As Word 'Base de tiempos en ms
Dim timer1_ms_tiempo As Word 'Contiene el valor del tiempo del timer1_ms
'Asignacion de valores a las variables--------------------------
n = 0
timer1_ms = 0
timer1_ms_tiempo = 500 'Tiempo del parpadeo del caracter en mSeg.
WaitMs 500 'Pausa de medio segundo
PIE1.TMR1IE = 1 'Activa las interrupciones del timer1, despues del inicio del LCD
Enable 'INTCON.GIE habilita todas las interrupciones globales
'de este modo no tenemos que esperar tanto en el Simulador (PSI)
'Rutina Principal----------------------
main: 'Comienza el programa principal
Lcdcmdout LcdLine1Home 'Cursor del lcd al principio
If timer1_ms >= timer1_ms_tiempo Then 'Control base tiempos
Toggle flash 'Control parpadeo
timer1_ms = 0 'Reinicia la base de tiempos
Endif
If flash = 0 Then 'Rutina lcd y parpadeo
Lcdout "N" 'Muestra en el lcd
Else
Lcdout " " 'Muestra en el lcd, borra
Endif
Lcdout "=", #n, " " 'Muestra en el lcd
n = n + 1 'Contador
Goto main 'Impide que termine el programa principal
End
'--------------------------------Interrupciones---------------------------------------------------
On Interrupt 'Comienzan las rutinas de las interrupciones, desactiva las interrupciones
Save System 'Guarda los valores del sistema
If PIR1.TMR1IF = 1 Then 'Comprueba que la interrupcion del timer1 es activa
TMR1H = 0xf8 'Carga el registro del contador para que desborde cada 1mSeg, byte alto
TMR1L = 0x2f 'Carga el registro del contador para que desborde cada 1mSeg, byte bajo
If timer1_ms < timer1_ms_tiempo Then timer1_ms = timer1_ms + 1 'Base tiempos
PIR1.TMR1IF = 0 'Borra el flag de salto del tmr1
Endif
Resume 'Activa las interrupciones y retorna al curso normal del programa antes del salto
'*******************PIC Entrenadora BASIC (PicEBasic)************************
'NOMBRE: 16F88_Pic_EBasic_Ejemplo_18
'MICRO: PIC16F88
'FECHA/AUTOR: 06/07 - By COS, PSI v7.41
'Practicando con la funcion Read/Write (EEPROM interna del micro) y WatchDog
'Hereda todas las funciones del ejemplo 17______
'Practicando con la funcion Read/Write (EEPROM interna del micro)
'Se envia por el puerto serie las cinco primeras posiciones de memoria EEPROM
'las tres primeras como control para saber si es la primera vez que se ejecuta el programa
'y la 4 y 5 son dos contadores que indican el numero de veces que se ejecuto el programa
'ya sea por reset o por puesta en marcha de la alimentacion
'la posicion cinco indica las veces que la posicion 4 desbordo (255).
'puerto serie a 1200 baudios, por emulacion.
'Hereda todas las funciones del ejemplo 16_______
'Practicando con el WatchDog
'Si se pulsa S1 o S2 se anula la linea que hace reset al WatchDog
'Activacion del reset generado por el WatchDog sobre los 262,144mSeg.
'**********************************************************************
Define CONFIG = 0x2f54 'Configuración de bits (fuses)
Define CONF_WORD_2 = 0x3ffc 'Configuración de bits (fuses)
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Hace que se ignoren los tiempos de los WaitMs
'-----------------------------Configuracion del Clock, Puertos I/O--------------
AllDigital 'todos los puertos como I/O
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0xff 'Puerto A como Entradas
TRISB = 0xff 'puerto B como Entradas
'TRISA.4 = 1 'como entrada (RA4, adc)
'TRISA.6 = 1 'como entrada (RA6, tecla S1)
'TRISA.5 = 1 'como entrada (RA5, tecla S2)
TRISB.3 = 0 'como salida, iluminacion lcd
TRISA.7 = 0 'como salida, led amarillo
TRISB.0 = 0 'como salida, led verde
TRISB.4 = 0 'como salida, control servo
PORTB.3 = 1 'luz lcd a on (RB3)
PORTA.7 = 1 'led amarillo a off (RA7), negado
PORTB.0 = 1 'led verde a off (RB0), negado
'---------------------------Configuracion del WatchDog--------------------------
OPTION_REG.T0CS = 0 'selecciona reloj interno para el WDT
'Prescaler del Wdt
'_wdt_div8192 = 8 '262,144mSeg.
WDTCON.WDTPS0 = 0 'Prescaler Rate Select bits
WDTCON.WDTPS1 = 0
WDTCON.WDTPS2 = 0
WDTCON.WDTPS3 = 1
OPTION_REG.PSA = 0 'No prescales2
'-----------------------------Declaracion y Asignacion de valores---------------
Dim n As Byte 'variable auxiliar
Dim dato_eeprom(5) As Byte 'variables por los que pasaran los valores de la eeprom
Dim watchdog_on As Bit 'permite que se haga el reset al contador del watchdog
Dim pause As Word 'asigna el valor de espera en mSeg.
watchdog_on = 1 'inicializa la variable, borrado del registro del watchdog a on
'---------------------------------------------------------------------------------
Gosub clear_watchdog 'borra el contador del watchdog antes que rebose
Gosub actualiza_eeprom
RA7 = 0 'salida led amarillo
RB0 = 0 'salida led verde
pause = 5000 'carga la rutina de espera con 5 Seg.
Gosub wait_ms 'salto con retorno a la rutina de espera
main: 'comienza la rutina principal
Gosub clear_watchdog 'salto con retorno a la rutina
RA7 = 1 'salida led amarillo
RB0 = 1 'salida led verde
pause = 500 'carga la rutina de espera con 0,5 Seg.
Gosub wait_ms 'salto con retorno a la rutina de espera
RB0 = 0 'salida led verde
pause = 500 'carga la rutina de espera con 0,5 Seg.
Gosub wait_ms 'salto con retorno a la rutina de espera
RA7 = 0 'salida led amarillo
pause = 500 'carga la rutina de espera con 0,5 Seg.
Gosub wait_ms 'Borra pone a cero el registro contador del WDT
Goto main 'impide que termine la rutina main
End
clear_watchdog: 'borra el contador del WatchDog
If watchdog_on = 0 Then Return 'determina si se hace el reset al WatchDog
ASM: clrwdt 'reinicializa el WDT, assembler
Return
wait_ms: 'rutina de espera, reset al WatchDog y lectura de las teclas
While pause > 0 'bucle que se repite mientras la condiccion sea cierta
If RA6 = 0 Or RA5 = 0 Then watchdog_on = 0 'lee las teclas
WaitMs 1 'espera 1 mSeg.
pause = pause - 1 'decrementa el tiempo de espera
Gosub clear_watchdog 'salto con retorno a la rutina
Wend 'acota el bucle While
Return
actualiza_eeprom: 'comprueba si la eeprom fue escrita, si no la inicializa y comienza el contaje
For n = 0 To 4 'bucle para recorrer las primeras posiciones de memoria
Read n, dato_eeprom(n) 'se asigna el contenido de la direc. "n" el dato a la varia. dato_eeprom(n)
Next n 'acota el bucle For
If dato_eeprom(0) <> 0 Or dato_eeprom(1) <> 1 Or dato_eeprom(2) <> 2 Then 'verifica eeprom inicializada
For n = 0 To 2 '____Escribe los tres primeros caracteres de control
Write n, n 'escribe en la eeprom
Next n '_____________
Write 3, 1 'inicializa el primer contador
Write 4, 0 'inicializa el segundo contador que nos indica las veces que reboso el primer contador
Else 'si lo anterior no es cierto entonces esto otro
If dato_eeprom(3) = 255 Then
dato_eeprom(4) = dato_eeprom(4) + 1 'se incrementa el segundo contador
Write 4, dato_eeprom(4) 'se escribe el valor del segundo contador
Endif
dato_eeprom(3) = dato_eeprom(3) + 1 'incrementa el primer contador
Write 3, dato_eeprom(3) 'escribe el nuevo valor para el primer contador
Endif
Serout PORTB.5, 1200, #dato_eeprom(0), #dato_eeprom(1), #dato_eeprom(2) 'envia las tres
'primeras posiciones al puerto serie
Serout PORTB.5, 1200, " ", #dato_eeprom(3), "-", #dato_eeprom(4), CrLf 'envia las 2 ultimas
'posiciones al puerto serie
Return
El efecto es que coexiste el parpadeo junto con el incremento constante del contador.
La sensación del que ve el display es que se trabaja en multitarea.
Cuando pueda pondré un video del lcd de la EBasic para poder apreciar bien el efecto.
'***************** Placa Entrenadora (PIC EBadic) *****************
'NOMBRE: 16F88_Ejemplo 22
'MICRO: PIC16F88, 8Mhz reloj interno
'Fecha/Autor: 07/07, By COS, PSI v7.41
'Metodo para el calibrado del reloj interno del pic
'******************************************************************
'******************************************************************
Define CONF_WORD = 0x2f50 'Configuración de bits (fuses)
Define CONF_WORD_2 = 0x3ffc 'Configuración de bits (fuses)
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Hace que se ignoren los tiempos de los WaitMs
'Definicion de puertos y modulos ---------
AllDigital 'Los pin de los puertos como I/O
CMCON = 0x07 'Comparador a off
OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz
'OSCTUNE = 63 'Factor de correcion del reloj
TRISA = 0xff 'Puerto A como entradas
TRISB = 0xff 'puerto B como entradas
TRISB.4 = 0 'RB4 como salida
'Rutina Principal ----------------------
main: 'Bucle infinito
RB4 = 1 '_______Genera una frecuencia de 1Khz
WaitUs 500
RB4 = 0
WaitUs 500 '____
Goto main 'Impide que termine la subrutina principal
End
'***************** Placa Entrenadora (PIC EBadic) ***************************************
'NOMBRE: 16F88_Pic_EBasic_EJEMPLO_23
'Descripcion: Generando numeros aleatorios con el Timer0, Dado Electronico
'Micro: pic16f88 / 8mhz reloj interno
'Version: 1.0
'Fecha/Autor: 22/7/07, By COS, PSI v7.41
'**********************************************************************************
Define CONF_WORD = 0x2f50 'Configuración de bits (fuses)
Define CONF_WORD_2 = 0x3ffc 'Configuración de bits (fuses)
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Hace que se ignoren los tiempos de los WaitMs
'Puertos del LCD-------------------------------------
Define LCD_BITS = 4 'Indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'Bus de datos sera el puerto A
Define LCD_DBIT = 0 'Bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'Bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E sera del puerto B
Define LCD_EBIT = 6 'RB6 como E
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comando del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera despues de inicializar el Display.
'Definicion de puertos------------------------------------------
ANSEL = %00010000 'Los pin I/O digitales y RA4 analogico
CMCON = 0x07 'Comparador a off
OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0xff 'Puerto A como entradas
TRISB = 0xff 'Puerto B como entradas
'TRISA.4 = 1 'Como entrada (RA4, adc)
'TRISA.6 = 1 'Como entrada (RA6, tecla S1)
'TRISA.5 = 1 'Como entrada (RA5, tecla S2)
TRISB.3 = 0 'Como salida RB3
TRISA.7 = 0 'Como salida RA7
TRISB.0 = 0 'Como salida RB0
PORTB.3 = 1 'Luz lcd a on (RB3)
PORTA.7 = 1 'Led amarillo a off (RA7), negado
PORTB.0 = 1 'Led verde a off (RB0), negado
'Inicialización TIMER0-----------------------------
OPTION_REG.T0CS = 0 'Selecciona reloj interno
OPTION_REG.PSA = 0 'Asigna el prescaler al timer0
'---------------------------------------------------
Lcdinit 'Inicializa el LCD sin cursor.
'Reasignacion de nombres-------------------------
Symbol led_amarillo = PORTA.7 'Led amarillo
Symbol led_verde = PORTB.0 'Led verde
Symbol luz_lcd = PORTB.3 'Iluminacion del lcd
Symbol s1 = RA6 'Tecla S1
Symbol s2 = RA5 'Tecla S2
'Variables generales--------------------------------
Dim random As Byte 'Contendra el numero deseado
'---------------------------------------------------
WaitMs 500 'Espera medio segundo
Lcdout "Pulse una Tecla" 'Imprime en el lcd
'Rutinas Principal ---------------------------------
main: 'Comienza el programa principal
If s1 = 0 Or s2 = 0 Then 'Detecta las teclas
While s1 = 0 Or s2 = 0 'Espera que se suelte la tecla
Wend
random = (TMR0 Mod 6) + 1 'Siendo 6 el numero maximo y +1 porque no queremos que salga el cero.
Lcdcmdout LcdLine2Home 'Cursor del lcd al principio linea 2
Lcdout "El Numero: ", #random, " " 'Imprime la plantilla y el resultado en el lcd
WaitMs 300 'Espera 0.3 segundo
Endif
Goto main 'Impide que termine el programa principal
End
'***************** Placa Entrenadora (PIC EBadic) ***************************************
'NOMBRE: 16F88_Pic_EBasic_EJEMPLO_23_1
'Descripcion: Generando numeros aleatorios con el Timer0, Dado Electronico
'Micro: PIC16F88 / 8mhz reloj interno
'Fecha/Autor: 22-25/7/07, By COS, PSI v7.41
'Version: 1.1
'Usando Function y Proc
'Se calcula el numero mediante una Funcion.
'El primer numero de entrada de la funcion es el numero maximo y
'el segundo numero de la funcion es el numero minimo.
'nueva rutina para el control de los led mediante Proc.
'Version: 1.0
'Calcula numero aleatorio
'**************************************************************************************
Define CONFIG = 0x2f50 'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc 'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 8 'Clock en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Activar para simulación
'Puertos del LCD---------------------------------------------
Define LCD_BITS = 4 'indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'el bus de datos sera el puerto A
Define LCD_DBIT = 0 'el bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'el bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'se usara el RB7 como RS
Define LCD_EREG = PORTB 'el bit de control E sera del puerto B
Define LCD_EBIT = 6 'se usara el RB6 como E
'Define LCD_RWREG = PORTA 'el bit de control RW sera del puerto A (si se suprime el compilador no protesta)
'Define LCD_RWBIT = 5 'se usara el RA5 como RW (si se suprime el compilador no protesta)
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comand del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera despues de inicializar el Display, solo se ejecuta una vez en mSeg.
'Definicion de puertos------------------------------------------
ANSEL = %00010000 'Los pin I/O digitales y RA4 analogico
CMCON = 0x07 'Comparador a off
OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0xff 'Puerto A como entradas
TRISB = 0xff 'Puerto B como entradas
'TRISA.4 = 1 'Como entrada (RA4, adc)
'TRISA.6 = 1 'Como entrada (RA6, tecla S1)
'TRISA.5 = 1 'Como entrada (RA5, tecla S2)
TRISB.3 = 0 'Como salida RB3
TRISA.7 = 0 'Como salida RA7
TRISB.0 = 0 'Como salida RB0
PORTB.3 = 1 'Luz lcd a on (RB3)
PORTA.7 = 1 'Led amarillo a off (RA7), negado
PORTB.0 = 1 'Led verde a off (RB0), negado
'-----------------------------------------------------------------
Lcdinit 'Inicializa el LCD sin cursor.
'Reasignacion de nombres---------------------------------------
Symbol led_amarillo = PORTA.7 'led amarillo
Symbol led_verde = PORTB.0 'led verde
Symbol luz_lcd = PORTB.3 'retroiluminacion del lcd
Symbol s1 = RA6 'tecla S1
Symbol s2 = RA5 'tecla S2
'Variables generales-----------------------------------------------
Dim n_random As Byte 'contendra el numero deseado
'------------------------------------------------------------------
WaitMs 500 'Espera medio segundo
Lcdout "Pulse una Tecla" 'Imprime en el lcd
Call led(_off, _off) 'Inicializa los led a off
n_random = random(0, 0) 'Inicializa random (timer0)
'Rutinas principal ------------------------------------------------
main: 'Comienza el programa principal
If s1 = 0 Then 'Si la tecla es pulsada
While s1 = 0 'Espera mientras esta pulsada la tecla
Wend
Call led(_on, _nc) 'Ilumina led_amarillo, no modifica led verde
n_random = random(6, 1) 'Funcion que genera numero aleatorio
Lcdcmdout LcdLine2Home 'Cursor del lcd al principio linea 2
Lcdout "El Numero: ", #n_random, " " 'Imprime la plantilla y el resultado en el lcd
WaitMs 300 'Espera 0.3 segundos
Call led(_off, _nc) 'Apaga led_amarillo, no modifica led verde
Endif
Goto main 'Impide que termine la rutina principal
End
'Calcula numeros aleatoriios, n_max = numero maximo y n_min = numero minimo
Const _on = 0 'Led encendido
Const _off = 1 'Led apagado
Const _nc = 2 'No cambia
Function random(n_max As Byte, n_min As Byte) As Byte
OPTION_REG.T0CS = 0 'Selecciona reloj interno
n_max = (n_max + 1) - n_min 'Arregla el numero maximo
random = (TMR0 Mod n_max) + n_min 'Siendo n_max el numero maximo y + n_min valor minimo
End Function
'Controla el estado de los led, call (x,x)
Proc led(amarillo As Byte, verde As Byte)
If amarillo = 0 Then RA7 = 0 'Led amarillo a on
If amarillo = 1 Then RA7 = 1 'Led amarillo a off
If verde = 0 Then RB0 = 0 'Led verde a on
If verde = 1 Then RB0 = 1 'Led verde a off
End Proc
'***********************************************
'Asignación de variables
'***********************************************
Dim a As Byte
Dim b As Byte
'Dim C As Byte --- Error: Incorrect variable name
'Dim D As Byte --- Error: Incorrect variable name
Dim e As Byte
'Dim F As Byte --- Error: Incorrect variable name
Dim g As Byte
Dim h As Byte
Dim i As Byte
Dim j As Byte
Dim k As Byte
Dim l As Byte
Dim m As Byte
Dim n As Byte
Dim o As Byte
'Dim P As Byte --- Error: Incorrect variable name
Dim q As Byte
'Dim R As Byte --- Error: Incorrect variable name
'Dim S As Byte --- Error: Incorrect variable name
Dim t As Byte
Dim u As Byte
Dim v As Byte
'Dim W As Byte --- Error: Incorrect variable name
Dim x As Byte
Dim y As Byte
'Dim Z As Byte --- Error: Incorrect variable name
'***********************************************
'Aparentan ser palabras reservadas pero no
'encuentro la documentación que me lo confirme
'***********************************************
'***************** Placa Entrenadora (PIC EBasic) **************************************
'NOMBRE: 16F88_Pic_EBasic_EJEMPLO_24
'Descripción: TEST DE LA PLACA EBasic_I2C (Led y 24LC04B)
'Micro: PIC16F88 / 8mhz reloj interno
'Fecha/Autor: 29/7/07, By COS, PSI v7.41
'Versión: 1.0
'Programa de Test para el Led y la E2Prom
'Muestra en pantalla tanto la dirección de escritura
'Como el dato a escribir. En el caso de error lo
'indica tanto luminosamente como en pantalla.
'*********************************************************************************
Define CONF_WORD = 0x2f50 'Configuración de bits (fuses)
Define CONF_WORD_2 = 0x3ffc 'Configuración de bits (fuses)
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Hace que se ignoren los tiempos de los WaitMs
'-------------------------------------Puertos del LCD-------------------------------------
Define LCD_BITS = 4 'Indicamos que el bus de datos del lcd será de 4bit
Define LCD_DREG = PORTA 'Bus de datos será el puerto A
Define LCD_DBIT = 0 'Bus de datos serán los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'Bit de control RS será del puerto B
Define LCD_RSBIT = 7 'RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E será del puerto B
Define LCD_EBIT = 6 'RB6 como E
Define LCD_COMMANDUS = 2000 'Tiempo de espera después de ejecutar un comando del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera después de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera después de inicializar el Display.
'*********************************************************************************
'------------------------------------Definición de puertos--------------------------------------------------
AllDigital 'los pin I/O digitales
'ANSEL = %00010000 'los pin I/O digitales y RA4 analógico
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0xff 'Puerto A como entradas
TRISB = 0xff 'puerto B como entradas
'TRISA.4 = 1 'como entrada (RA4, adc)
'TRISA.6 = 1 'como entrada (RA6, tecla S1)
'TRISA.5 = 1 'como entrada (RA5, tecla S2)
TRISB.3 = 0 'como salida RB3
TRISA.7 = 0 'como salida RA7
TRISB.0 = 0 'como salida RB0
TRISA.4 = 0 'como salida RA4
PORTB.3 = 1 'luz lcd a on (RB3)
PORTA.7 = 1 'led amarillo a off (RA7), negado
PORTB.0 = 1 'led verde a off (RB0), negado
PORTA.4 = 0 'led EB_I2C a off (RA4)
'------------------------------------Inicio-----------------------------------------------
'--------------------------------variables generales--------------------------------------
Dim addr As Byte 'dirección i2c
Dim data As Byte 'dato i2c
Dim n_random As Byte 'contendrá el numero deseado
'------------------------------------asignación de valores a las variables------------------
'--------------------------------------Reasignación de nombres--------------------------
Symbol sda = RB1 'asignamos nombre al pin que hará de SDA del puerto I2C
Symbol scl = RB4 'asignamos nombre al pin que hará de SCL del puerto I2C
Symbol led_amarillo = RA7 'led amarillo
Symbol led_verde = RB0 'led verde
Symbol luz_lcd = RB3 'iluminación del lcd
Symbol s1 = RA6 'tecla S1
Symbol s2 = RA5 'tecla S2
Const p_off = 0 'apaga el led
Const p_on = 1 'enciende el led
Const p_st = 2 'no cambia estado el led
Const w_on = 1 'se escribe y lee en la E2Prom
Const w_off = 0 'Solo se lee la E2Prom
'---------------------------------------------------------------------------------------
Lcdinit 'inicializa el LCD sin cursor
WaitMs 100 'pausa de 100 mSeg.
Lcdout "Test P. EB_I2C" 'Imprime el texto en el LCD
WaitMs 3000 'pausa de 3Seg.
Call led(p_off, p_off, p_off) 'led a off
n_random = random(0, 0) 'inicializa random (timer0)
'--------------------------------Rutina Programa---------------------------------------
main:
Lcdcmdout LcdClear 'borra lcd
For addr = 0 To 255 'addr tomara los valores desde 0 hasta 255,bucle
Lcdcmdout LcdLine1Home 'cursor línea 1 y principio
Lcdout "Escribiendo: ", #addr 'se escribe en el lcd
data = d_e2prom(addr, addr, 1) 'se llama a la función RW del I2C
Lcdcmdout LcdLine2Home 'cursor línea 2 y principio
Lcdout "leyendo: ", #data, " " 'se escribe en el lcd
WaitMs 100 'se espera 100mSeg.
If _error = 1 Then 'bit de error si esta a 1
Lcdcmdout LcdClear 'borra el lcd
Lcdout "Error: " 'imprime en el display
Lcdcmdout LcdLine2Home 'cursor al principio de la línea 2
Lcdout #addr, " ", #data, " " 'imprime en el display
WaitMs 5000 'se hace una pausa de 5Seg.
Endif 'cierra el if
Next addr 'cierra el bule for
End
'------------------------------Rutinas-----------------------------------------------
'Escribe y lee en la E2Prom, dirección, dato, E2P_RW = 1 escribe y lee
Dim _error As Bit 'Flag indicador de error
Function d_e2prom(e2p_addr As Byte, e2p_data As Byte, e2p_rw As Byte) As Byte
RA4 = 1 'activa el led de la placa EB_E2Prom
_error = 1 'Marca error
If e2p_rw = 1 Then I2CWrite RB1, RB4, 0xa0, e2p_addr, e2p_data 'escribe en el I2C
WaitMs 5 'pausa para que el chip termine la escritura
I2CRead RB1, RB4, 0xa1, e2p_addr, d_e2prom 'lee en el puerto I2C
If d_e2prom = e2p_data Then
_error = 0 'Borra error
RA4 = 0 'Apaga el led placa EBasic_I2C
Endif
End Function
'calcula números aleatorios, n_max = numero máximo y n_ini = numero mínimo
Function random(n_max As Byte, n_ini As Byte) As Byte
OPTION_REG.T0CS = 0 'selecciona reloj interno
n_max = (n_max + 1) - n_ini 'arregla el numero máximo
random = (TMR0 Mod n_max) + n_ini 'siendo n_max el numero máximo y +n_ini valor mínimo
End Function
'controla el estado de los led, call (x,x)
Proc led(amarillo As Byte, verde As Byte, eb_i2c As Byte)
If amarillo = 1 Then RA7 = 0 'led amarillo a on
If amarillo = 0 Then RA7 = 1 'led amarillo a off
If verde = 1 Then RB0 = 0 'led verde a on
If verde = 0 Then RB0 = 1 'led verde a off
If eb_i2c = 1 Then RA4 = 1 'led EB_I2C a on
If eb_i2c = 0 Then RA4 = 0 'led EB_I2C a off
End Proc
'***************** Placa Entrenadora (PIC EBadic) ***************************************
'NOMBRE: 16F88_Pic_EBasic_EJEMPLO_25
'Descripcion: TEST DE LA PLACA EBasic_I2C (Led y DS1624), Temperatura positiva)
'Micro: PIC16F88 / 8mhz reloj interno
'Fecha/Autor: 29/7/07, 2/08/07, By COS, PSI v7.41
'Version: 1.1
'Se añade TEST para el DS1624 (temperatura)
'*****************************************************************************************
Define CONF_WORD = 0x2f50 'Configuración de bits (fuses)
Define CONF_WORD_2 = 0x3ffc 'Configuración de bits (fuses)
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Hace que se ignoren los tiempos de los WaitMs
'-------------------------------------Puertos del LCD-------------------------------------
Define LCD_BITS = 4 'Indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'Bus de datos sera el puerto A
Define LCD_DBIT = 0 'Bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'Bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E sera del puerto B
Define LCD_EBIT = 6 'RB6 como E
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comando del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera despues de inicializar el Display.
'------------------------------------Definicion de puertos-----------------------------------
AllDigital 'los pin I/O digitales
'ANSEL = %00010000 'los pin I/O digitales y RA4 analogico
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0xff 'Puerto A como salidas
TRISB = 0xff 'puerto B como salidas
'TRISA.4 = 1 'como entrada (RA4, adc)
'TRISA.6 = 1 'como entrada (RA6, tecla S1)
'TRISA.5 = 1 'como entrada (RA5, tecla S2)
TRISB.3 = 0 'como salida RB3
TRISA.7 = 0 'como salida RA7
TRISB.0 = 0 'como salida RB0
TRISA.4 = 0 'como salida RA4
PORTB.3 = 1 'luz lcd a on (RB3)
PORTA.7 = 1 'led amarillo a off (RA7), negado
PORTB.0 = 1 'led verde a off (RB0), negado
PORTA.4 = 0 'led EBbasic_I2C a off (RA4)
'------------------------------------Inicio--------------------------------------------
'Reasignacion de nombres------------------------------
Symbol sda = RB1 'asignamos nombre al pin que hara de SDA del puerto I2C
Symbol scl = RB4 'asignamos nombre al pin que hara de SCL del puerto I2C
Symbol led_amarillo = RA7 'led amarillo
Symbol led_verde = RB0 'led verde
Symbol luz_lcd = RB3 'iluminacion del lcd
Symbol s1 = RA6 'tecla S1
Symbol s2 = RA5 'tecla S2
'Variables generales---------------------------------------
Dim temperatura As Word 'temperatura entero .HB, decimales .LB
Dim temperatura_aux As Long 'calculo de los decimales
'--------------------------------------------------------------------------------------
Lcdinit 'inicializa el LCD sin cursor
WaitMs 100 'pausa de 100 mSeg.
Lcdout "Test P. EB_I2C" 'Imprime el texto en el LCD
WaitMs 3000 'pausa de 3Seg.
'--------------------------------Rutina Principal---------------------------------------
main:
temperatura = 0
temperatura_aux = 0
temperatura = d_ds1624(0, 0, 0) 'genera una lectura en el chip ds
WaitMs 1000 'pausa de 1Seg, tiempo maximo de conversion del chip ds
temperatura = d_ds1624(0, 0, 1) 'lee la lectura en dos bytes (13bit)
temperatura.LB = ShiftRight(temperatura.LB, 3) 'elimina bit que no se usan (decimales)
temperatura_aux = (temperatura.LB * 3125) / 1000 'calcula la parte decimal
temperatura.LB = temperatura_aux.LB 'Inserta los decimales
Lcdcmdout LcdLine2Home 'cursor al principio de la linea 2
Lcdout "Temp. +", #temperatura.HB, "." 'imprime en el lcd
If temperatura.LB < 10 Then Lcdout "0" 'mantiene el formato dos decimales
Lcdout #temperatura.LB, " " 'imprime en el lcd
WaitMs 1000 '0 'hace una pausa de 10Seg.
Goto main
End
'------------------------------ Subrutinas y Funciones ----------------------------------
'Funcion de lectura/escritura del DS1624
'ds1624_rw=0 el chip prepara un lectura, ds1624_rw=1 el chip entrega una lectura
'ds1624_rw=2 se hace una lectura del registro de control.
Function d_ds1624(ds1624_h As Byte, ds1624_l As Byte, ds1624_rw As Byte) As Word
'I2CPrepare sda, scl
RA4 = 1 'led placa I2c a On
If ds1624_rw = 0 Then 'solicita una lectura de temperatura
I2CWrite sda, scl, %10010010, 0xac, 0x00 'incializa el registro de control
WaitMs 10 'pausa para que termine la escritura
I2CWrite1 sda, scl, %10010010, 0xee 'comienza una conversion
Endif
If ds1624_rw = 1 Then 'hace la lectura de la temperatura
I2CWrite1 sda, scl, %10010010, 0xaa 'prepara el chip para lectura de temperatura
I2CRead1 sda, scl, %10010011, ds1624_h, ds1624_l 'lee la temperatura
Endif
If ds1624_rw = 2 Then 'hace una lectura del registro de control
I2CRead sda, scl, %10010011, 0xac, ds1624_l 'lee registro de control
ds1624_h = 0 'borra byte alto de antiguos valores
Endif
d_ds1624.HB = ds1624_h 'actualiza la temperatura
d_ds1624.LB = ds1624_l 'actualiza decimales temperatura o indica datos registro control
RA4 = 0 'led placa i2c a Off
End Function
'**************************************DEFINICION DE PUERTOS*************************************
'----------------------ASIGNACION DE I/O y valores de inicion de las salidas---------------------
ANSEL = %00000000 'los pin I/O digitales
Define ADC_SAMPLEUS = 0 'el minimo, configuracion del ADC
Define ADC_CLOCK = 5 '16Tad a 8Mhz = 2uSeg, minimo permitido por el micro 1.5uSeg, configuracion ADC
'_______________registros afectados por Define ADC_CLOCK y ADCIN________________
'ANSEL = %00010000 'los pin I/O digitales y RA4 analogico
'ADCON0 = %01100000 'Fosc/16 a 8Mhz (ADCON1.ADCS2=1) =2uSeg (minimo 1.uSeg), channel RA4
'ADCON1 = %01000000 'voltage reference (AVdd/AVss) y seleccion de escala division clock/2 ADCON1.ADCS2=1
Define ADC_CLOCK = 5 '16Tad a 8Mhz = 2uSeg, minimo permitido por el micro 1.5uSeg, configuracion ADC
el manual dice que ADC_CLOCK puede tomar valores de 0..3 o 0..7 según el pic. en la página 118 del datasheet debe estar la solución pero no consigo verla y ese valor ADC_CLOCK = 5 me tiene completamente desorientado.
DEFINE OSCCAL_1K 1
define OSC 4
@ DEVICE pic12F675, 0x1fc4 ' palabra de configuración: oscilador interno IO. PWRT y BOREN enables
DEFINE ADC_BITS 8 ' numero de bits
DEFINE ADC_SAMPLEUS 50 ' tiempo de muestreo en microsegundos
TRISIO = %001101 ' GP0 y GP2 son entradas; GP1 y GP4 son salidas
CMCON = %00000111 ' deshabilita comparadores
ADCON0 = %10000001 ' GP0 es la entrada del conversor A/D
ANSEL = %00110001 ' oscilador interno(FRC). GP0 analógica,
' las demás son digitales
...
...
ADCIN 0, variable
¿conocerás por acaso algún documento o web del tipo spi (o i2c) para torpes?.
Mario el bit ADFM del registro ADCON1 está a 0 lo cual nos indica que trabajaremos con 10 bits y justificado a la izquierda.
'********************************** PIC Entrenadora BASIC (PicEBasic)***************************
'NOMBRE: 16F88_Pic_EBasic_Ejemplo_26
'MICRO: PIC16f88
'FECHA/AUTOR: 08/07 - By COS, PSI v7.41
'Version: 1.0
'Estudio del modulo ADC y relacion con ADCIN
'Envia al puerto serie por emulación un registro predeterminado de 8bit en formato binario.
'**********************************************************************************************************
Define CONF_WORD = 0x2f50 'Configuración de bits (fuses)
Define CONF_WORD_2 = 0x3ffc 'Configuración de bits (fuses)
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Hace que se ignoren los tiempos de los WaitMs
'***********************************************************************************************************
'_____Asignacion de I/O y valores de inicio de las salidas
ANSEL = %00000000 'Los pin I/O digitales
Define ADC_SAMPLEUS = 10 'El minimo posible, configuracion del ADC
Define ADC_CLOCK = 5 '16Tad a 8Mhz = 2uSeg, minimo permitido por el micro 1.5uSeg, configuracion ADC
'_____Registros afectados por Define ADC_CLOCK y ADCIN________________________
ANSEL = %00010000 'Los pin I/O digitales y RA4 analogico
ADCON0 = %01100000 'Fosc/16 a 8Mhz (ADCON1.ADCS2=1) =2uSeg (minimo 1.uSeg), channel RA4
ADCON1 = %01000000 'Voltage reference (AVdd/AVss) y seleccion de escala division clock/2 ADCON1.ADCS2=1
'________________________________________________________________________
CMCON = 0x07 'Comparador a off
OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'Puerto B como salidas
TRISA.4 = 1 'Como entrada (RA4, adc)
TRISA.6 = 1 'Como entrada (RA6, tecla S1)
TRISA.5 = 1 'Como entrada (RA5, tecla S2)
PORTB.3 = 1 'Luz lcd a on (RB3)
PORTA.7 = 1 'Led amarillo a off
PORTB.0 = 1 'Led verde a off
'_____Main Programa
Dim adc_4 As Word 'Contendra el valor de la entrada del ADC
main:
While RA6 = 0 'Pausa, mientras este pulsada la tecla S1
Wend
ADCON1 = %11000000
Adcin 4, adc_4 'Lee el valor de la entrada analogica y lo guarda en adc_4
Serout PORTB.5, 2400, "adc_4 ", #adc_4, " adc_4.HB ", #adc_4.HB, " adc_4.LB ", #adc_4.LB, CrLf 'escribe la lectura del ADC
Serout RB.5, 2400, "ADCON0 "
Call lcd_bit(ADCON0)
Serout RB.5, 2400, " ADCON1 "
Call lcd_bit(ADCON1)
Serout RB.5, 2400, " ANSEL "
Call lcd_bit(ANSEL)
Serout RB.5, 2400, CrLf
'Añadir los registro que querais....
WaitMs 500
Goto main
End
'Envia por el puerto serie el valor de "registro" en formato binario
Proc lcd_bit(registro As Byte)
Dim n As Byte
Dim var As Byte
var = 0
For n = 7 To 0 Step -1 'Numero de bit de la variable
var.0 = registro.n
Serout RB5, 2400, #var 'Envia el bit al puerto serie
Next n
End Proc
en el ejemplo del programa, ADCIN le asigna el valor obtenido a la variable num_1 que es una variable del tipo Word y por tanto (entiendo yo) está haciendo uso de los 10 bits de la lectura. si quisiera quedarme solamente con los 8 bits más significativos despreciando los demás crearía una variable del tipo Byte que tomase el valor de la parte alta de num_1 :
Dim num_1 As Word
Dim mivar As Byte
mivar = num_1.HB
'********************************** PIC Entrenadora BASIC (PicEBasic)******************************
'NOMBRE: 16F88_Pic_EBasic_Ejemplo_27
'MICRO: PIC16f88A
'FECHA/AUTOR: 08/07 - By COS, PSI v7.41
'Version: 1.0
'Estudio del modulo ADC
'Usando el modulo ADC directamente.
'*********************************************************************************************
Define CONF_WORD = 0x2f50 'Configuración de bits (fuses)
Define CONF_WORD_2 = 0x3ffc 'Configuración de bits (fuses)
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Suprime los tiempos de espera Waitms, solo para el simulador
'*********************************************************************************************
'_____Asignacion de I/O y valores de inicio de las salidas, configracion adc
ANSEL = %00010000 'Los pin I/O digitales y RA4 analogico
ADCON0 = %01100001 'Fosc/16 a 8Mhz (ADCON1.ADCS2=1) =2uSeg (minimo 1.5uSeg), channel RA4, Power on ADC (ADON)
ADCON1 = %01000000 'V. Ref. (AVdd/AVss) y seleccion escala division clock/2 (ADCS2) y 8Bit ADC (ADFM)
'---------------------------------------
CMCON = 0x07 'Comparador a off
OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'Puerto B como salidas
TRISA.4 = 1 'Como entrada (RA4, adc)
TRISA.6 = 1 'Como entrada (RA6, tecla S1)
TRISA.5 = 1 'Como entrada (RA5, tecla S2)
PORTB.3 = 1 'Luz lcd a on (RB3)
PORTA.7 = 1 'Led amarillo a off
PORTB.0 = 1 'Led verde a off
WaitMs 25
'_____Variables
Dim adc_4 As Word 'Contendra el valor de la entrada del ADC
main:
ADCON0.GO = 1 'A/D conversion en progreso
While ADCON0.GO = 1 'Pausa hasta terminar la conversion
Wend
adc_4.HB = ADRESH 'Asignacion de valores, tiene la conversion a 8Bit
adc_4.LB = ADRESL 'Asignacion de valores
'Adc_4 y adc_4.LB no tendran valores utilies, solo el byte alto de adc_4
Serout PORTB.5, 2400, "adc_4 ", #adc_4, " adc_4.HB ", #adc_4.HB, " adc_4.LB ", #adc_4.LB, CrLf 'Escribe la lectura del ADC
Goto main
End
JA... efectivamente tenía una versión anterior... ahora ya estoy actualizado y todo bien!.
Gracias... vamos a ver como sigue.
Saludos :)
Aclaracion:
Aqui la resolucion esta a 8Bit -> ADCON1 = %01000000 'voltage reference (AVdd/AVss) y seleccion de escala division clock/2 ADCON1.ADCS2=1
pero al terminar ADCIN, queda cambiado a 10BIT -> ADCON1 = %11000000
Espero que con esto quede completo el estudio del ADC relativo al ADCIN...Claro que si, completísimo.
Aclaracion:
Aqui la resolucion esta a 8Bit -> ADCON1 = %01000000 'voltage reference (AVdd/AVss) y seleccion de escala division clock/2 ADCON1.ADCS2=1
pero al terminar ADCIN, queda cambiado a 10BIT -> ADCON1 = %11000000
Eso es lo que quería saber.
Raro que no te deje trabajar con 8 bits, PBP si te permite. A eso me refería cuando en PBP colocas ADC_BITS=8, solo toma el ADRESH justificado a la izquierda (para tener los 8 bits de mayor peso).
e si, completísimo.
y para entender un poco mas el por que diré que el autor
de este entorno tiene una relación especial con nosotros sus usuarios registrados, es un entorno que tiene muchos ojo
vigilándolo de una forma que yo definiria casi paternal....
Felicitaciones dogflu66!!
Te a quedado muy bien y la explicación esta muy completa!
Yo al final hace tiempo que estoy dando vuelta para armar un entrenador, había dicho que iba a armar este, y al final nunca arme nada, a ver cuando me hago un poco de tiempo y me lo armo jejeje
Saludos
Hola Dogflu66
Queria agradecerte por estos super tutoriales para PCI, me ha servido de gran ayuda,... muchas gracias :-/ :-/ :-/
En el caso que nos atañe he utilizado un valor de la R relativamente alto 120 oh.
Un poco de funcionamiento:
La comunicación es Half-Duplex multipunto diferencial sobre dos hilos preferentemente de par entrelazado (trenzado y ninguna de las dos líneas es masa).
Permite transmitir datos a grandes distancias, hasta 1200mtrs de 300 a 19200 bps.
Y se pueden utilizar hasta 32 driver en esta configuración, puestos en paralelo con la línea RS485.
De todo esto deducimos que podremos tener comunicación bi-direccional a tiempos separados, cuando un equipo transmite (TX) todos los de mas reciben (RX) y en esta configuración todos los equipos podrán ser RX o TX, esta claro que si colocamos mas de dos en la línea esta la llamaremos bus y tendremos que crear un protocolo que ponga orden en las transmisiones de los datos, y sobretodo para evitar las colisiones, no puede haber nunca mas de un driver configurado como TX al mismo tiempo.
La línea necesita una resistencia que llamaremos de carga o fin de línea, como en este caso usaremos muy pocos driver y una distancia muy corta solo usaremos una la cual incorporaremos en paralelo con los dos hilos mediante el puente del esquema anterior.
En el caso que nos atañe he utilizado un valor de la R relativamente alto 120 oh.
De todas formas solo me he encontrado en muy cortas distancia la ausencia de la resistencia y por
lo tanto mi siguiente pregunta es: con esas distancias tan grandes (hasta 100mtrs como indicas) en
entornos industriales sin la R, ¿puede haber una mayor sensibilidad a las interferencias?.
Código: [Seleccionar]Define CONF_WORD = 0x2f10
Define CONF_WORD_2 = 0x3ffc
Define CLOCK_FREQUENCY = 8
'NOMBRE:16F88_PicEBasic_LCD
'MICRO: PIC16F88/8Mhz reloj interno
'Uso del LCD con bus de datos a 4Bit y sin pin de RW
'************************************************************************************************
'-------------------------------------Puertos del LCD---------------------------------------------
Define LCD_BITS = 4 'indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'el bus de datos sera el puerto A
Define LCD_DBIT = 0 'el bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'el bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'se usara el RB7 como RS
Define LCD_EREG = PORTB 'el bit de control E sera del puerto B
Define LCD_EBIT = 6 'se usara el RB6 como E
'Define LCD_RWREG = PORTA 'el bit de control RW sera del puerto A (si se suprime el compilador no protesta)
'Define LCD_RWBIT = 5 'se usara el RA5 como RW (si se suprime el compilador no protesta)
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comand del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 5 '(50) 'Tiempo de espera despues de inicializar el Display, solo se ejecuta una vez en mSeg., trucado para simulacion
'------------------------------------------------------------------------------------------------------
Define SIMULATION_WAITMS_VALUE = 1 'suprime los tiempos de espera Waitms, solo activar esta linea en simulacion
'------------------------------------Definicion de puertos------------------------------------------
ANSEL = 0x00 'los pin I/O digitales (no analogicos)
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
CMCON = 0x07 'comparador a off
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
'------------------------------------Inicio------------------------------------------------------------
Lcdinit 'inicializa el lcd sin cursor
WaitMs 500 'pausa para estabilizar
main: 'comienza el programa principal
Lcdcmdout LcdClear 'borra el display
WaitMs 1000 'hace una pausa de 1Seg.
Lcdout "A" 'escribe el caracter "A" en el display
WaitMs 1000 'hace una pausa de 1Seg.
Goto main 'impide que termine el programa principal
End 'es conveniente ponerlo siempre segun el manual
Ahi dejo el programita para simular el LCD, a mi me funciona correctamente
a la hora de activar el modulo LCD del simulador indicarle que coja la configuracion
de pin segun le indicamos en el programa.
Lo proximo seria simular el LCD y la entrada analogica a ver si da alguna incompatibilidad.
PD. Los tiempos estan trucados para no tener que esperar tanto en el Simulador, los tiempos
reales son los que estan indicados entre parentesis.
PD. Corregido ya que este ejemplo se realizo antes de tener la Placa EBasic construida, asi que lo modifique para que funcione sobre ella.
PD. 22/07/07, solo correccion en la descripcion de los pin del LCD.
PD. 15/11/07, añado la configuracion de bit (fuses) del micro y la velocidad del clock en el programa, las 3 primeras lineas.
Ya le di un empujoncito al Índice del hilo.... A ver si lo puedo terminar antes de que llegue el año nuevo.
Cuando termine de hacer mención a los ejemplos principales del foro, iré ordenándolo, simplificando y
comentando de una forma más adecuada... :mrgreen:
No recordaba que el hilo fuera tan extenso... :8}
Excelente trabajo dogflu66!!!
A quedado muy bueno, y sobre todo Cómodo!
'***************** Placa Entrenadora (PIC EBadic) ***************************************
'NOMBRE: 16F88_Pic_EBasic_EJEMPLO_28
'Descripción: TEST DE LA PLACA EBasic_I2C (Led y 24LC04B)
'Micro: PIC16F88 / 8mhz reloj interno
'Fecha/Autor: 30/12/07, 29/7/07, By COS, PSI v7.41
'Versión: 1.1
'Se completa la función para que lea o escriba en todos los bloques de la memoria I2C
'Esta memoria solo tiene dos bloques y cada uno de ellos tiene 256 posiciones de 1 byte
'La funcion los maneja como si de un único bloque de 512 bytes se tratara.
'Multiplicando la longuitud de 1 bloque por el numero de bloques es igual
'a la capasidad maxima de la memoria, contemplada como si de su estructura interna
'estuviera compuesta de un unico bloque (256x2)=512 y direccion maxima 511 bytes
'ya que la direccion primera comienza en 0.
'Version: 1.0
'Solo escribe o lee en el bloque "0" de la memoria
'*****************************************************************************************
Define CONF_WORD = 0x2f50 'Configuración de bits (fuses)
Define CONF_WORD_2 = 0x3ffc 'Configuración de bits (fuses)
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Hace que se ignoren los tiempos de los WaitMs
'-------------------------------------Puertos del LCD-------------------------------------
Define LCD_BITS = 4 'Indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'Bus de datos sera el puerto A
Define LCD_DBIT = 0 'Bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'Bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E sera del puerto B
Define LCD_EBIT = 6 'RB6 como E
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comando del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera despues de inicializar el Display.
'*********************************************************************************
'------------------------------------Definicion de puertos------------------------------------------
AllDigital 'los pin I/O digitales
'ANSEL = %00010000 'los pin I/O digitales y RA4 analogico
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0xff 'Puerto A como entradas
TRISB = 0xff 'puerto B como entradas
'TRISA.4 = 1 'como entrada (RA4, adc)
'TRISA.6 = 1 'como entrada (RA6, tecla S1)
'TRISA.5 = 1 'como entrada (RA5, tecla S2)
TRISB.3 = 0 'como salida RB3
TRISA.7 = 0 'como salida RA7
TRISB.0 = 0 'como salida RB0
TRISA.4 = 0 'como salida RA4
PORTB.3 = 1 'luz lcd a on (RB3)
PORTA.7 = 1 'led amarillo a off (RA7), negado
PORTB.0 = 1 'led verde a off (RB0), negado
PORTA.4 = 0 'led EBbasic_I2C a off (RA4)
'------------------------------------Inicio--------------------------------------------
'------------------------------Reasignacion de nombres----------------------
Symbol sda = RB1 'asignamos nombre al pin que hara de SDA del puerto I2C
Symbol scl = RB4 'asignamos nombre al pin que hara de SCL del puerto I2C
Symbol led_amarillo = RA7 'led amarillo
Symbol led_verde = RB0 'led verde
Symbol luz_lcd = RB3 'iluminacion del lcd
Symbol s1 = RA6 'tecla S1
Symbol s2 = RA5 'tecla S2
'--------------------------------variables generales-----------------------------------------------
Dim addr As Word 'direccion I2C
Dim dato As Byte 'valor a escribir en el I2C
Dim data As Word 'lectura dato I2C, data.HB = 1 = error de escritura, data.LB = dato i2c
'------------------------------------asignacion de valores a las variables--------------------------
dato = 0 'inicializa dato
'--------------------------------------------------------------------------------------
Lcdinit 'inicializa el LCD sin cursor
WaitMs 100 'pausa de 0.1Seg.
Lcdout "Test P. EB_I2C" 'Imprime el texto en el LCD
Lcdcmdout LcdLine2Home
Lcdout "Version 1.1"
WaitMs 5000 'pausa de 5Seg.
'--------------------------------Rutina Programa---------------------------------------
main:
Lcdcmdout LcdClear 'borra lcd
For addr = 0 To 511 'addr tomara los valores desde 0 hasta 511, bucle
Lcdcmdout LcdLine1Home 'cursor linea 1 y principio
Lcdout "Wr: ad.", #addr, " d.", #dato, " " '#addr 'se escribe en el lcd
data = d_e2prom(addr, dato, 0) 'llama a la funcion R/W del I2C en modo escritura
Lcdcmdout LcdLine2Home 'cursor linea 2 y principio
Lcdout "Read: ", #data.LB, " " 'se escribe en el lcd
WaitMs 100 'se espera 100mSeg.
If data.HB = 1 Then 'bit de error si esta a 1
Lcdcmdout LcdClear 'borra el lcd
Lcdout "Error: " 'imprime en el display
Lcdcmdout LcdLine2Home 'cursor al principio de la linea 2
Lcdout "Wr: ", #dato, " Rd:", #data.LB, " " 'imprime en el display
WaitMs 500 'se hace una pausa de 500mSeg.
Endif 'cierra el if
dato = dato + 1 'incrementa dato, se tiene en cuenta que cuando desborda comienza en 0.
Next addr 'cierra el bucle for
End
'------------------------------Subrutinas y funciones ----------------------------------------
'Funcion para el manejo de la E2Prom y Led indicador R/W
'La funcion devuelve un numero tipo Word, en el que el byte menos significativo es
'el dato leido y el byte mas significativo indica si hubo error en la escritura, error=1
'e2p_addr.15...12, selecciona el dispositivo en el bus I2C
'e2p_addr.11...09, selecciona la pagina o bloque de la memoria
'e2p_addr.8, selecciona si la operacion sera de lectura o escritura
'e2p_addr.LB, selecciona la posicion a escribir dentro del bloque de momoria seleccionado
'e2p_data, dato a escribir en la posicion indicada por e2p_addr
'e2p_rw, indica a la funcion si la operacion sera de lectura (=1) o escritura (=0)
Function d_e2prom(e2p_addr As Word, e2p_data As Byte, e2p_rw As Byte) As Word
'0xa0 (1010b) direccion de la memoria I2C, todos los pin de configuracion a cero
e2p_addr.15 = 1 'direccion o nombre del dispositivo en el bus I2C, bit mas significativo
e2p_addr.14 = 0 '...
e2p_addr.13 = 1 '...
e2p_addr.12 = 0 '..., bit menos significativo
e2p_addr.11 = e2p_addr.10 'selecciona la pagina de la memoria I2C, bit mas significativo
e2p_addr.10 = e2p_addr.9 '...
e2p_addr.9 = e2p_addr.8 '..., bit menos significativo
e2p_addr.8 = 0 'modo escritura, indiferente ya que lo controla directamente I2CWrite
RA4 = 1 'activa el led de la placa EBasic_I2C, actividad
If e2p_rw = 0 Then 'permite el modo escritura
I2CWrite RB1, RB4, e2p_addr.HB, e2p_addr.LB, e2p_data 'escribe en el I2C
d_e2prom.HB = 1 'registra posible error si no se borra posteriormente
WaitMs 5 'pausa para que el chip termine la escritura, tiempo indicado en el datasheet
Endif
e2p_addr.8 = 1 'modo lectura, indiferente ya que lo controla directamente I2CRead
I2CRead RB1, RB4, e2p_addr.HB, e2p_addr.LB, d_e2prom.LB 'lee en el puerto I2C
If d_e2prom.LB = e2p_data And e2p_rw = 0 Then 'solo se ejecuta si hubo ciclo de escritura
d_e2prom.HB = 0 'borra el flag de error
Endif
RA4 = 0 'apaga led placa EB_I2C, actividad
End Function
'****************************************************************
'** RUTINAS PARA LEER **
'** UNA **
'** MEMORIA RAM **
'** HM 62256 o Compatible **
'****************************************************************
'PIC 16f877
'xtal = 20mhz
'--------------
'RA0 LED ESCRITURA
'RA1 - LED LECTURA
'RA2 - LED ESCRITURA EEPROM
'RA3 - LED ENCENDIDO CIRCUITO
'RA4 - LED STAND-BY
'- -- -- -- -- -- --
'- -- -- -- -- -- --
'RB0-7 -> i/o0-7 hm62256alp-10
'RC0-7 -> a0-7
'RD0-6 -> a8-14
'RE0 -> #cs
'RE1 -> #we
'RE2 - > #oe
'-------------------------------------------------------------
AllDigital 'Todo digital
'Pongo los puertos B, C, y D en salida
TRISB = 0
TRISC = 0
TRISD = 0
'Asigno las Variables
Dim direccion_h As Byte
Dim direccion_l As Byte
Dim dato_ram As Byte
Dim respuesta_ram As Byte
Dim b0 As Byte
'Rutina Principal
main:
High PORTA.3
Gosub escritura 'voy a turina de escritura
Gosub lectura 'voy a rutina de lectura
Gosub escritura_pic 'escribo en la eeprom interna del pic
Low PORTA.3
Goto led_standby
End
'Rutina de escritura
escritura:
High PORTA.0 'enciendo led para ver que se empieza la rutina
direccion_h = 0 'asigno posicion
direccion_l = 5 'asigno posicon
dato_ram = 24 'asigno el dato que voy a grabar
High PORTE.2 'TIMMING
Low PORTE.0 'TIMMING
Low PORTE.1 'Preparado para grabar
PORTC = direccion_l 'pongo al puerto C en la posicion L
PORTD = direccion_h 'Pongo al puerto D en la posicion H
PORTB = dato_ram 'dato a grabar
High PORTE.0 'Cierro el TIMMIMG
High PORTE.1 'Cierro el timming
Low PORTE.2 'Cierro el timming
Low PORTA.0 'Apago el LED para ver que termino de escribir la RAM.
Return
'Rutina para leer la posicion que yo desee en la ram
lectura:
High PORTA.1 'enciendo led que indica lectura
direccion_h = 0 'direccion que voy a leer
direccion_l = 5 'direccion l que voy a leer
PORTC = direccion_l 'PASO LA DIRECCION A PUERTO C
PORTD = direccion_h 'PASO LA DIRECCION A PUERTO D
High PORTE.1 'RUTINA PARA LEER (ABRE TIMMING)
Low PORTE.0 'abro el timming para leer
Low PORTE.2 'timming
TRISB = 1 'PONGO EL BUS DE DATOS EN ENTRADA PORQUE LA RAM ME VA A ENVIAR EL DATO
PORTB = respuesta_ram 'lo que la ram me entrega por el puerto B lo grabo en la variable respuesta ram
TRISB = 0 'Pongo en salida el puerto b
High PORTE.1 'Cierro el timming el WE lo dejo alto para que no halla una escritura inesperada
High PORTE.0 'cierro timming
High PORTE.2 'cierro timming
Low PORTA.1 'apago led que indica lectura
Return
'RUTINA PARA ESCRIBIR EL DATO OBTENIDO EN LA MEMORIA EEPROM DEL PIC
'PARA LUEGO SER LEIDO CON WINPIC 800 Y UTRO PROGRAMADOR
'Listo ya tengo almacenado el dato de la ram en la variable RESPUESTA_RAM
escritura_pic:
High PORTA.2 'Enciendo led de escritura de eeprom
b0 = 0
Write b0, respuesta_ram 'escribo el dato obtenido de la ram en la posicion 0 de la eeprom interna del pic
WaitMs 100 'le doy una pausa de 100 ms
Low PORTA.2 'Apago led de lectura
Return
led_standby:
High PORTA.4
WaitMs 100
Low PORTA.4
WaitMs 100
Goto led_standby
End
'***************** Placa Entrenadora (PIC EBadic) ***************************************
'NOMBRE: 16F88_Pic_EBasic_LCD_CCP1_Timer1_ADC_01
'MICRO: PIC16F88/8Mhz reloj interno
'Fecha/Autor: 3/08, By COS, PSI v7.41
'Version: 1.0
'Uso del modulo CCP1 configurado en especial mode.
'Se crean bases de tiempos usando el modulo CCP1 configurado en modo comparador
'y generando el mismo modulo una lectura del ADC cada 1mSeg.
'*********************************************************************************
Define CONF_WORD = 0x2f50 'Configuración de bits (fuses)
Define CONF_WORD_2 = 0x3ffc 'Configuración de bits (fuses)
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Hace que se ignoren los tiempos de los WaitMs
'-------------------------------------Puertos del LCD-------------------------------------
Define LCD_BITS = 4 'Indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'Bus de datos sera el puerto A
Define LCD_DBIT = 0 'Bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'Bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E sera del puerto B
Define LCD_EBIT = 6 'RB6 como E
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comando del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera despues de inicializar el Display.
'------------------------------------Definicion de puertos y modulos--------------------------------------
ANSEL = %00010000 'Los pin I/O digitales y RA4 analogico
ADCON0 = %01100000 'Fosc/16 a 8Mhz (ADCON1.ADCS2=1) =2uSeg (minimo 1.uSeg), channel RA4
ADCON1 = %01000000 '8Bit, voltage reference (AVdd/AVss) y seleccion de escala division clock/2 ADCON1.ADCS2=1
'ADCON1.ADFM = 1 'ADC con 10Bit de resolucion.
ADCON0.ADON = 1 'Modulo ADC a ON
'_______________________________________________________________________________
CMCON = 0x07 'Comparador a off
OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'Puerto B como salidas
TRISA.4 = 1 'Como entrada (RA4, adc)
TRISA.6 = 1 'Como entrada (RA6, tecla S1)
TRISA.5 = 1 'Como entrada (RA5, tecla S2)
PORTB.3 = 1 'Luz lcd a on (RB3)
PORTA.7 = 1 'Led amarillo a off (RA7), negado
PORTB.0 = 1 'Led verde a off (RB0), negado
'--------------Inicializacion de Interrupciones y configuracion del CCP1 en modo comparador----------
T1CON.TMR1CS = 0 'Asigna el reloj interno al timer1, se incrementa cada ciclo de instruccion
T1CON.T1CKPS0 = 0 'Factor del preescaler del timer1, 0
T1CON.T1CKPS1 = 0 'Factor del preescaler del timer1, 0
T1CON.TMR1ON = 1 'Habilitación del TMR1, comienza a incrementarse
CCPR1H = 0x07 'Registro mas significativo del comparador CCP1, 1mSeg.
CCPR1L = 0xd0 'Registro menos significativo del comparador CCP1, 1mSeg.
CCP1CON.CCP1M3 = 1 'Compare mode, trigger special event (CCP1M3...0).
CCP1CON.CCP1M2 = 0
CCP1CON.CCP1M1 = 1
CCP1CON.CCP1M0 = 1
PIE1.CCP1IE = 1 'Habilita las interrupciones del modulo ccp1
INTCON.PEIE = 1 'Bit de habilitacion de interrupciones de perifericos
'Reasignacion de nombres--------------------------------
Symbol led_amarillo = PORTA.7 'Led amarillo
Symbol led_verde = PORTB.0 'Led verde
Symbol luz_lcd = PORTB.3 'Iluminacion del lcd
'Declaracion de variables---------------------------------
'Variables de los timer -----------------------------------
Dim timer_base As Byte 'Tiempo referencia para los timer_100ms por soft del programa
Dim timer_base_tiempo As Byte 'Contiene el valor del tiempo del timer_base
Dim timer1_ms As Byte 'Base de tiempos en ms
Dim timer1_10ms As Byte 'Base de tiempos msx10
Dim timer2_10ms As Byte 'Base de tiempos msx10
Dim timer3_10ms As Byte 'Base de tiempos en msx10
Dim timer4_10ms As Byte 'Base de tiempos en msx10
Dim timer1_ms_tiempo As Byte 'Contiene el valor del tiempo del timer1_ms
Dim timer1_10ms_tiempo As Byte 'Contiene el valor del tiempo del timer1_10ms
Dim timer2_10ms_tiempo As Byte 'Contiene el valor del tiempo del timer2_10ms
Dim timer3_10ms_tiempo As Byte 'Contiene el valor del tiempo del timer3_10ms
Dim timer4_10ms_tiempo As Byte 'Contiene el valor del tiempo del timer4_10ms
'Variables generales------------------------------------
Dim adc_4 As Byte 'Contendra el valor de la entrada ADC trabajando a 8bit
Dim flag As Bit 'Controla parpadeo display
Dim flag_1 As Bit 'Controla parpadeo display
'Asignacion de valores a las variables------------------
timer_base = 0
timer1_ms = 0
timer1_10ms = 0
timer2_10ms = 0
timer3_10ms = 0
timer4_10ms = 0
timer_base_tiempo = 10 'Divide entre 10, solo afecta a los timerX_10ms.
timer1_ms_tiempo = 100 'Temporiza 100mSeg.
timer1_10ms_tiempo = 100 'Temporiza 1 Seg.
timer2_10ms_tiempo = 200 'Temporiza 2Seg
timer3_10ms_tiempo = 60 'Temporiza 0.6Seg
timer4_10ms_tiempo = 200 'Temporiza 2Seg
adc_4 = 0
flag = 1
flag_1 = 1
'-------------------------------------------------------
Lcdinit 'Inicializa el lcd sin cursor
WaitMs 1000 'Espera 1Seg, las interrupciones alargan este tiempo
Lcdout "COMPARE MODE" 'Escribe en el lcd
Lcdcmdout LcdLine2Home 'Seleciona la linea dos como proxima para escritura
Lcdout "Pruebas con CCP1" 'Escribe en el lcd
WaitMs 3000 'Espera 3Seg, las iterrupciones hacen este tiempo mas largo
Lcdcmdout LcdLine1Clear 'Borra el display,linea 1
Enable 'INTCON.GIE habilita todas las interrupciones globales
'------------------------------------rutinas del Programa----------------------------------------
main: 'comienza el programa principal
If timer1_10ms >= timer1_10ms_tiempo Then 'cambio de estado el pin RA7 cada timer1_100ms_tiempo
Toggle led_amarillo 'invierte el valor del pin
timer1_10ms = 0 'reinicio el timer1_100ms
Endif
If timer2_10ms >= timer2_10ms_tiempo Then 'cambio de estado el pin RB0 cada timer2_100ms_tiempo
Toggle led_verde 'invierte el valor del pin
timer2_10ms = 0 'reinicio el timer2_100ms
Endif
If timer1_ms >= timer1_ms_tiempo Then 'permite que se ejecute las rutinas solo una vez cada timer1_ms_tiempo
Gosub print_lcd 'salto con retorno, rutina que imprime los valores en el lcd
timer1_ms = 0 'reset a la base de tiempos
Endif
Goto main 'impide que termine el programa principal
End
'--------------------------------------Subrutinas------------------------------------------------
print_lcd: '_______________________Imprime la entrada analogica
Lcdcmdout LcdLine1Home 'Cursor al principio de linea
If timer3_10ms >= timer3_10ms_tiempo Then 'Control parpadeo, condicionado por timer3_10ms
timer3_10ms = 0 'Reinicializa el timer3_10ms
Toggle flag 'Invierte el valor contenido en flag
Endif
If timer4_10ms >= timer4_10ms_tiempo Then 'Control parpadeo, condicionado por timer4_10ms
timer4_10ms = 0 'Reinicializa el timer4_10ms
Toggle flag_1 'Invierte el valor contenido en flag_1
Endif
If flag = 1 Then Lcdout " ADC: " 'Imprime en el LCD, condicionado por el valor de flag
If flag = 0 Then Lcdout " " 'Imprime en el LCD, condicionado por el valor de flag
Lcdout #adc_4, " " 'Imprime en el LCD
Lcdcmdout LcdLine2Home 'Cursor al principio de linea
If flag_1 = 1 Then Lcdout "Pruebas con CCP1" 'Imprime en el LCD, condicionado por el valor de flag_1
If flag_1 = 0 Then Lcdout "en Especial Modo" 'Imprime en el LCD, condicionado por el valor de flag_1
Return
'--------------------------------Interrupciones---------------------------------------------------
On Interrupt 'Comienzan las rutinas de las interrupciones, desactiva las interrupciones
'Save System 'Guarda valores del sistema y valores intermedios.
adc_4 = ADRESH 'Valor mas significativo de la lectura del ADC
'___Base de tiempos
timer_base = timer_base + 1 'Contador general
If timer1_ms < timer1_ms_tiempo Then timer1_ms = timer1_ms + 1 'Contador
If timer_base >= timer_base_tiempo Then 'Limita el tiempo de ejecucion, cada timer_base_tiempo
If timer1_10ms < timer1_10ms_tiempo Then timer1_10ms = timer1_10ms + 1 'Contador
If timer2_10ms < timer2_10ms_tiempo Then timer2_10ms = timer2_10ms + 1 'Contador
If timer3_10ms < timer3_10ms_tiempo Then timer3_10ms = timer3_10ms + 1 'Contador
If timer4_10ms < timer4_10ms_tiempo Then timer4_10ms = timer4_10ms + 1 'Contador
timer_base = 0 'Reset a la base de tiempos
Endif
'__Fin base de tiempos
PIR1.CCP1IF = 0 'borra el flag de salto del CCP1
Resume 'Activa las interrupciones y retorna al curso normal del programa antes del salto
Hola:
Me puede la curiosidad y la ignorancia, que es el LSP1 y LSP2 en la antena?
Que tal amigos!
dogflu66 por lo que veo en el programa que posteaste a esos modulos rf no les colocaste decoder y encoder y por lo que se ve son faciles de sincronizar :shock:
Me recuerdan mis pruebas con los laipac toda una odisea para sincronizarlos :D
El unico detalle a tomar en cuenta, muy pequeño por cierto, es que si los modulos estan cerca de algun equipo que genere mucha interferencia se podrian perder los datos, esto lo observe en mi imnumerables pruebas que hice con los modulos de laipac me funcionban bien en mi casa, pero, cuando los probaba en la casa de un amigo que tiene un router y varios switch para internet se volvia loco :D
Saludos
Tengo esos mismos modulos!! ;)
Los usaba con unos....HT12, creo. Los voy a buscar.
Que caracteristicas tiene ese pila??? 12V? 23....Amper!?!?!?! :lol: (obviamente, es imposible....pero ..)
Que tal amigos!
Si eson son los modulos que te vendieron, en ese entonces a mi por error me enviaron unos que supuestamente son y que la version mejorada :mrgreen:
Pero los veo iguales a los tuyos con excepcion de la velocidad de transmision que creo es mayor y el alcance.
Pero habia algo que no me gustaba creo que era que la entrada del receptor oscilaba cuando el transmisor se apagaba o no transmitia o algo asi en los tuyos sino mal recuerdo no hacia eso :mrgreen:
Aitopes los modulos HT12 son los que hacia referencia mas arriba eso es lo que recomienda el fabricante :D
Saludos
Con otro modelo de modulo de Rx de Laipac:
(http://img146.imageshack.us/img146/6162/laipactxrx2do8.jpg)
Experimento 2:
Tx = Aurel
Rx = Laipac
Mismo programa
Resultado:
Se observa que el modulo capta ruido.
16 tramas recibidas suele fallar 1 o 2 a un nivel de ruido indeterminado.
o aquí más rápido:
http://www.4shared.com/file/1694958/a5c96550/bot_miguelito_robot_siguelineas.html
Respecto a la memoria, tu la pondrias por I2C tambien.
Hola dogflu66,
Revisando el programa en la parte del rtc cuando llegas a la parte de leer y escribir dato creo que esta erroneo se escribe con 0xD0 y se lee con 0xD1
i2cwrite sda, scl, 0xD0, Addr, Data
i2clead sda, scl, 0xD1, Addr, Data
estan cambiados.
Pues lo miro, seria un error grave. El programa lo tengo funcionando ahora mismo y no observo fallos.
Hola dogflu66.
tengo una pregunta, de la rutina del programa 2.
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
------------------------------
PIE1.TMR1IE = 1 para que lo volvemos a encender?para que lo apagamos antes? no comprendo, perdona mi ignorancia.
otra cosita:
aux_4l = reg(i) And %00001111
la variable que guarda el nible bajo es igual al resultado de hacer una and logica del registro numero "i" es decir "reg(i)" y el numero binario 0111 0000,
¿por que ese numero binario? en algunos otros tambien? cambia, tiene que ver con el registro del DS1307
si la variable "i" toma valores desde 0 hasta 6, la parte baja del nible lo comprendo, pero la baja
la parte alta nos va ha dar siempre 0. Tomamos por ejemplo i=1 seria:
0000 0001 --> reg(1)
0111 0000 -->%01110000
------------
000000000 --> aux_4h=0000
aux_4h = ShiftRight(aux_4h, 4)
con esto lo desplamos el nible alto a derecha, 4 posiciones a la derecha, si fuera 0111 0000 seria 0000 0111, pero como da todo ceros seguira siendo cero.
La conversion del nible alto a bajo no se deberia de hacer antes?
antes de la and logica asi se evitaria que fuera cero
otra cosilla
reg(i) = (aux_4h * 10) + aux_4l
con esto haces: el registro numero "i" le igualamos el valor del nible alto multiplicado por 10 y le sumamos el nible bajo.
yo creo que el nible alto estaba en binario, salio como resultado de una and logica del registro numero "i" con el numero
binario 0000 1111.
no entiendo como multiplicas un numero binario por un numero decimal, a no ser que el aux_4h sea decimal.
ejemplo i=1
aux_4h = reg(i) And %01110000 parte del nible alto
aux_4H= 0000 0001 and 0111 0000 se queda con la parte alta
0000 0001
0111 0000
--------------
0000 0000 --> aux_4h si se queda con la parte alta simpre sera cero ya que
"i" toma valores de 0 a 6 situandose simpre en el nible bajo
aux_4l = reg(i) And %00001111
aux_4l= 0000 0001 and 0000 1111 = 0000 0001 solo almacena los 4 primeros seria 0001 aux_4l =0001
aplicamos:
reg(i) = (aux_4h * 10) + aux_4l siendo aux_4l simpre binario
reg (i)=(0*10)+dato binario
reg (i)= aux_4l en binario
para poner un dato BCD "0101" a binario seria (0*23)+(1*22)+(0*21)+(1*20)
esto sera (0*8 )+(1*4)+(0*2)+1*1) => 0+4+0+1 => 4+1 => 5 en decimal
I2CRead sda, scl, 0xd0, i, reg(i) yo prefiero poner para "I2CRead" 0xD1 pero bueno
estamos leyendo las direciones correlativas del 0 al 6 con el valor de"i" ademas estamos leyendo correlativamente los registros del 0 al 6 del nible bajo.
amigo dogflus66 podrias corregirme, y aclarme esta dudas.
gracias
hola dogflu,
El programa adaptado del 16f88 al 16f877A, se deberian de cambiar los pines: el porta.7 y el porta.6 correspondientes del led amarillo, y el pulsador S1, a mi no me da ningun error ni nigun warnig, pero lo debemos cambiar para poder pulsar boton y ver el led amarillo.
hola, dogflu66
Crees que seria posible simular el programa 2, el adaptado al 16f87A, en proteus 7?
La simulación por software no le sera impedimento verdad, para proteus?
un cordial saludo
'***********Solo para simulación ********************************
'Nombre: Ejemplo 30
'VERSION: 1.0
'MICRO: PIC16f88
'FECHA/AUTOR: 08/08 - By COS, PSI v7.41
'Encender un led distinto por cada pulsación de tecla que ingrese en un mismo pin.
'Programación tradicional (subrutinas).
'Uso de bases de tiempos sin uso de interrupciones.
'***********************************************************
Define CONFIG = 0x2f50 'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc 'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 8 'Clock en Mhz
Define SIMULATION_WAITMS_VALUE = 1 'Modo simulación, acelera los WaitMs
'Definicion de puertos
'Asignacion de I/O y valores de inicio de las salidas
ANSEL = 0x00 'Los pin I/O digitales
CMCON = 0x07 'Comparador a off
OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'Puerto B como salidas
TRISA.0 = 1 'Como entrada tecla_1 = 0 pulsada
PORTB.0 = 0 'Luz lcd Rojo a off
PORTB.1 = 0 'Led amarillo a off
PORTB.2 = 0 'Led verde a off
PORTB.3 = 0 'Led azul estado tecla, led off tecla abierta y led on tecla cerrada
PORTB.4 = 0 'Led rojo_2 a off
'Asignacion de nombres a pin
Symbol tecla_1 = PORTA.0
Symbol led_rojo = PORTB.0
Symbol led_amarillo = PORTB.1
Symbol led_verde = PORTB.2
Symbol sw = PORTB.3
Symbol led_rojo_2 = PORTB.4
'Variables generales (globales)
Dim t_1 As Byte 'Guarda el estado de la tecla, 0 libre, 1 pulsada
Dim contador_1 As Byte 'Contador para control de pulsaciones
Dim contador_2 As Byte 'Controla la repetición de la tecla
Dim contador_3 As Word 'Contador para el control del tiempo
Dim contador_4 As Word 'Contador para el control del tiempo
Dim contador_5 As Word 'Contador para control del tiempo
Dim tiempo_contador_2 As Byte 'Limite del contador
Dim tiempo_contador_3 As Word 'Limite del contador
Dim tiempo_contador_4 As Word 'Limite del contador
Dim tiempo_contador_5 As Word 'Limite del contador
Dim n_led_rojo As Byte 'Numero de pulsaciones para led rojo
Dim n_led_amarillo As Byte 'Numero de pulsaciones para led amarillo
Dim n_led_verde As Byte 'Numero de pulsaciones para activar led verde
Dim on_contador_2 As Bit 'Activa contador =1
Dim on_contador_3 As Bit 'Activa contador =1
Dim on_contador_4 As Bit 'Activa contador =1
Dim flag_t_1 As Bit 'Se utiliza para saber que la tecla no sigue pulsada
'Asignaciones
t_1 = 0
contador_1 = 0
contador_2 = 0
contador_3 = 0
tiempo_contador_2 = 200 '(20 valor real = 200mSeg.), pasos de 10mSeg.
tiempo_contador_3 = 500 '(500 valor real = 5 Seg.), pasos de 10mSeg.
tiempo_contador_4 = 50 '(50 valor real = 0.5 Seg.), pasos de 10mSeg.
tiempo_contador_5 = 50 '(50 valor real = 0.5 Seg.), pasos de 10mSeg.
n_led_rojo = 1
n_led_amarillo = 2
n_led_verde = 3
on_contador_2 = 0
on_contador_3 = 0
on_contador_4 = 0
flag_t_1 = 0
WaitMs 1000 'Espera 1Seg
'------Main Programa----------------------------------------
main:
WaitMs 10 'Parada absoluta de 10mSeg., base de tiempos del sistema
Gosub estado_led_tecla 'Control led tecla
Gosub bases_tiempos 'Control de los temporizadores y contadores
'*********Aqui podemos insertarle otra tarea al micro *******************
'____Control de un led rojo intermitente, 0.5Seg. a On y 0.5 a Off
If contador_5 >= tiempo_contador_5 Then 'Control led intermitente
Toggle led_rojo_2 'Invierte el estado del pin
contador_5 = 0 'Inicializa la base de tiempos
Endif
'____
'***********************************************************************
Gosub control_tecla 'Conjunto de rutinas de control de pulsacion
Gosub control_led 'Conjunto de rutinas que activan el led seleccionado durante un tiempo
Goto main 'Impide que termine el main
End
'*********************** SUBRRUTINAS **********************************
control_tecla:
If on_contador_4 = 0 Then 'Si se cumple queda bloqueado hasta la nueva secuencia
Gosub lee_tecla 'Estado de la tecla
If t_1 = 1 Then Gosub evento_tecla 'Validación de la pulsación y activa evento tecla
Endif
Return
lee_tecla: 'Detecta tecla pulsada
If tecla_1 = 0 And t_1 = 0 And flag_t_1 = 0 Then 'Si se pulsa la tecla:
t_1 = 1 'Activa evento tecla
on_contador_2 = 1 'Inicializa el contador anti-rebotes de la tecla
on_contador_3 = 1 'Inicializa el contador del tiempo general de la rutina
Endif
Return
evento_tecla: 'Reaccion al pulsar la tecla
If t_1 = 1 And contador_2 >= tiempo_contador_2 Then '_Si se solto la tecla
'_______________________________________ y si se pulso la tecla anteriormente
'_______________________________________ y pulsacion valida a los 200mseg
contador_1 = contador_1 + 1 'Incrementa el numero de pulsaciones validas
t_1 = 0 'Termino el evento pulsar tecla
flag_t_1 = 1 'Indica si la tecla se mantiene pulsada
contador_2 = 0 'Inicializa contador anti-rebotes
on_contador_2 = 0 'Stop contador
Endif
Return
control_led: 'Controla el tiempo en el que el led seleccionado estara activo
If on_contador_4 = 0 Then Gosub control_leds_on 'Control led a on
If on_contador_4 = 1 Then Gosub control_leds_off 'Control led a off
Return
control_leds_on: 'Control led a on
If on_contador_3 = 1 And contador_3 >= tiempo_contador_3 Then
If contador_1 = n_led_rojo Then led_rojo = 1 'Si se cumple activa led rojo
If contador_1 = n_led_amarillo Then led_amarillo = 1 'Si se cumple activa led amarillo
If contador_1 = n_led_verde Then led_verde = 1 'Si se cumple activa led verde
on_contador_4 = 1 'Activa contador
contador_4 = 0 'Inicializa contador
on_contador_2 = 0 'Stop contador
contador_2 = 0 'Inicializa contador
on_contador_3 = 0 'Stop contador
contador_3 = 0 'Inicializa contador
Endif
Return
control_leds_off: 'Control led a off
If on_contador_4 = 1 And contador_4 >= tiempo_contador_4 Then
led_rojo = 0 'Apaga led rojo
led_amarillo = 0 'Apaga led amarillo
led_verde = 0 'Apaga led verde
on_contador_4 = 0 'Stop contador
contador_1 = 0 'Reset contador
contador_2 = 0 'Reset contador
on_contador_2 = 0 'Stop contador
t_1 = 0 'Se liveraliza, desactiva evento_tecla
flag_t_1 = 0 'Se permite repetir tecla si sigue pulsada
Endif
Return
estado_led_tecla: 'Indicacion luminosa del estado de la tecla
If tecla_1 = 1 Then 'Si la tecla no esta pulsada
sw = 0 'Tecla no pulsada, led azul a off
flag_t_1 = 0 'Se dejo de pulsar la tecla
Endif
If tecla_1 = 0 Then sw = 1 'Tecla pulsada, led azul a on
Return
bases_tiempos: 'Contadores y bases de tiempos
If on_contador_2 = 1 Then contador_2 = contador_2 + 1 'Contador del retardo de la tecla, pasos de 10mSeg.
If on_contador_3 = 1 Then contador_3 = contador_3 + 1 'Contador que se puede repetir la tecla, pasos de 10mSeg.
If on_contador_4 = 1 Then contador_4 = contador_4 + 1 'Contador que controla los leds, pasos de 10mSEg.
If contador_5 < tiempo_contador_5 Then contador_5 = contador_5 + 1 'Contador que controla led intermitente
Return
'********************************** *********************
'NOMBRE: 16F88_MandoJEVO_01
'MICRO: PIC16f88
'Version: 1.0
''*****************************************************************************************************
Define CONF_WORD = 0x2f50
Define CONF_WORD_2 = 0x3ffc
Define CLOCK_FREQUENCY = 8
Define ADC_SAMPLEUS = 10
Define ADC_CLOCK = 5
Dim duty(16) As Byte 'Duty Cicle
Dim curva(15) As Byte 'Curva grabada
Dim vg As Byte 'Valor gatillo
Dim ca As Byte 'Curva actual
Dim cn As Byte 'Curva nueva
Dim mca As Byte 'Modificacion curva actual P5
Dim mcn As Byte 'Modificacion curva nueva P5
Dim asa As Byte 'Antispin Actual P4
Dim asn As Byte 'Antispin nuevo P4
Dim ai As Byte 'Contador inicio
Dim af As Byte 'Contador fin
Dim a As Byte 'contador
Dim b As Byte
Dim va(4) As Byte
Dim mc(3) As Byte
ANSEL = %00100011
TRISB = %11110111
TRISA = %11111111
'Ver curva actual
Gosub vercurva
Gosub leermemoria
Gosub modificarcurva
Gosub modificararranque
PWMon 1, 12
PWMduty 1, 0
'****************************************************************************
'Rutina principal
loop:
Gosub vercurva 'Comprueba que no se haya cambiado la curva
If cn <> ca Then Gosub leermemoria
'* Leer gatillo
Gosub salidapwm
Adcin 0, mcn 'lee el valor de p5
If mcn <> mca Then Gosub modificarcurva
'* Leer gatillo
Gosub salidapwm
Adcin 5, asn 'lee el valor de p4
If asn <> asa Then Gosub modificararranque
'* Leer gatillo
Gosub salidapwm
Goto loop
End
'********************************************************
'Deteccion de la curva a leer
vercurva:
'Ver curva nueva
cn = 0
If PORTA.2 = 1 Then cn = cn + 4
If PORTA.3 = 1 Then cn = cn + 2
If PORTA.4 = 1 Then cn = cn + 1
If PORTA.5 = 1 Then cn = cn + 8
ai = cn * 16 'Posicion inicial de memoria donde leer
af = ai + 14 'Posicion final de memoria donde leer
Return
leermemoria:
'Leer valores Guardados segun la curva a leer
For a = ai To af
b = a - ai
Read a, duty(b)
curva(b) = duty(b)
Next a
'Genera los valores para las modificaciones de curvas
va(0) = (curva(10) - curva(4)) / 5 'Calculo maxima modificacion
va(1) = va(0) * 2 '(va(0) * 10) / 5 es el valor de correccion del 100 % multiplicado por 10
va(2) = va(0) '(va(0) * 10) / (2 * 5) es el valor de correccion del 50 % multiplicado por 10
va(3) = (va(0) * 10) / 15 '(va(0) * 10) / (3 * 5) es el valor de correccion del 30 % multiplicado por 10
ca = cn
Return
'********************************************************************************************
'Rutina deteccion posicion del gatillo y entrega de potencia
salidapwm:
For a = 1 To 8
Adcin 1, vg 'lee el valor del gatillo
Select Case vg
Case < 16
PWMduty 1, 0 'Freno
Case < 32
PWMduty 1, duty(0)
Case < 48
PWMduty 1, duty(1)
Case < 64
PWMduty 1, duty(2)
Case < 80
PWMduty 1, duty(3)
Case < 96
PWMduty 1, duty(4)
Case < 112
PWMduty 1, duty(5)
Case < 128
PWMduty 1, duty(6)
Case < 144
PWMduty 1, duty(7)
Case < 160
PWMduty 1, duty(8)
Case < 176
PWMduty 1, duty(9)
Case < 192
PWMduty 1, duty(10)
Case < 208
PWMduty 1, duty(11)
Case < 224
PWMduty 1, duty(12)
Case < 240
PWMduty 1, duty(13)
Case <= 255
PWMduty 1, duty(14)
EndSelect
Next a
Return
'*************************************************************
'Ajuste fino de la curva grabada
'Rutina para modificar el centro de la curva
modificarcurva:
Select Case mcn
Case < 22 'P -5
mc(0) = ((va(3) * 5) / 10)
mc(1) = ((va(1) * 5) / 10)
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
Return
Case < 44 'P -4
mc(0) = ((va(3) * 4) / 10)
mc(1) = ((va(1) * 4) / 10)
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
Return
Case < 66 'P -3
mc(0) = ((va(3) * 3) / 10)
mc(1) = ((va(1) * 3) / 10)
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
Return
Case < 88 'P -2
mc(0) = ((va(3) * 2) / 10)
mc(1) = ((va(1) * 2) / 10)
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
Return
Case < 110 'P -1
mc(0) = va(3) / 10
mc(1) = va(1) / 10
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
Return
Case < 145 'P 0
duty(5) = curva(5)
duty(6) = curva(6)
duty(7) = curva(7)
duty(8) = curva(8)
duty(9) = curva(9)
mca = mcn
Return
Case < 165 'P +1
mc(0) = va(3) / 10
mc(1) = va(2) / 10
mc(2) = va(1) / 10
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
Return
Case < 185 'P +2
mc(0) = ((va(3) * 2) / 10)
mc(1) = ((va(2) * 2) / 10)
mc(2) = ((va(1) * 2) / 10)
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
Return
Case < 205 'P +3
mc(0) = ((va(3) * 3) / 10)
mc(1) = ((va(2) * 3) / 10)
mc(2) = ((va(1) * 3) / 10)
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
Return
Case < 230 'P +4
mc(0) = ((va(3) * 4) / 10)
mc(1) = ((va(2) * 4) / 10)
mc(2) = ((va(1) * 4) / 10)
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
Return
Case <= 255 'P +5
mc(0) = ((va(3) * 5) / 10)
mc(1) = ((va(2) * 5) / 10)
mc(2) = ((va(1) * 5) / 10)
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
Return
EndSelect
Return
'*****************************************************************
'Ajuste del control de arrancada
modificararranque:
Select Case asn
Case < 25 'P 1
duty(0) = curva(0)
duty(1) = curva(1)
duty(2) = curva(2)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 50 'P 2
duty(0) = curva(0) + (((curva(1) - curva(0)) * 50) / 100)
duty(1) = curva(1)
duty(2) = curva(2)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 75 'P 3
duty(0) = curva(1)
duty(1) = curva(1) + (((curva(2) - curva(1)) * 40) / 100)
duty(2) = curva(2)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 100 'P 4
duty(0) = curva(1) + (((curva(2) - curva(1)) * 40) / 100)
duty(1) = curva(1) + (((curva(2) - curva(1)) * 80) / 100)
duty(2) = curva(2)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 125 'P 5
duty(0) = curva(1) + (((curva(2) - curva(1)) * 80) / 100)
duty(1) = curva(2)
duty(2) = curva(2) + (((curva(3) - curva(2)) * 40) / 100)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 150 'P 6
duty(0) = curva(2)
duty(1) = curva(2) + (((curva(3) - curva(2)) * 40) / 100)
duty(2) = curva(2) + (((curva(3) - curva(2)) * 80) / 100)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 175 'P 7
duty(0) = curva(2) + (((curva(3) - curva(2)) * 40) / 100)
duty(1) = curva(2) + (((curva(3) - curva(2)) * 80) / 100)
duty(2) = curva(3)
duty(3) = curva(3) + (((curva(4) - curva(3)) * 40) / 100)
duty(4) = curva(4)
asa = asn
Return
Case < 200 'p 8
duty(0) = curva(2) + (((curva(3) - curva(2)) * 80) / 100)
duty(1) = curva(3)
duty(2) = curva(3) + (((curva(4) - curva(3)) * 40) / 100)
duty(3) = curva(3) + (((curva(4) - curva(3)) * 80) / 100)
duty(4) = curva(4)
asa = asn
Return
Case < 225 'P 9
duty(0) = curva(3)
duty(1) = curva(3) + (((curva(4) - curva(3)) * 40) / 100)
duty(2) = curva(3) + (((curva(4) - curva(3)) * 80) / 100)
duty(3) = curva(4)
duty(4) = curva(4) + (((curva(5) - curva(4)) * 40) / 100)
asa = asn
Return
Case <= 255 'P 10
duty(0) = curva(3) + (((curva(4) - curva(3)) * 40) / 100)
duty(1) = curva(3) + (((curva(4) - curva(3)) * 80) / 100)
duty(2) = curva(4)
duty(3) = curva(4) + (((curva(5) - curva(4)) * 40) / 100)
duty(4) = curva(4) + (((curva(5) - curva(4)) * 80) / 100)
asa = asn
Return
EndSelect
Return
Define CONF_WORD = 0x3f72
AllDigital
TRISA = 0x00 'PORTA Outputs
INTCON.GIE = 1 'Int General
INTCON.PEIE = 1 'Int Perifericos
PIE1.TMR2IE = 1 'Int TMR2
T2CON.T2CKPS0 = 0 'TMR2 Prescale
T2CON.T2CKPS1 = 0 'TMR2 Prescale
T2CON.TOUTPS0 = 0 'TMR2 Postcale
T2CON.TOUTPS1 = 0 'TMR2 Postcale
T2CON.TOUTPS2 = 1 'TMR2 Postcale
T2CON.TOUTPS3 = 0 'TMR2 Postcale
PR2 = 244 'Overload TMR2
T2CON.TMR2ON = 1 'TMR2 ON
End
On Interrupt
PORTA.0 = Not PORTA.0
PIE1.TMR2IF = 0
Resume
Usando el ADC del gatillo como word se me reduce el tiempo de ejecucion, durante un proceso de 13 ciclos (pongo un bucle dentro de la rutina loop: para realizar trece ciclos), se reduce en 600 us.
¿Es que funciona mejor usando los 10 bits ?
Hola tengo el siguiete problema:
quiero generar un cambio de estado en un pin cada 244µs por lo que configuré el TMR2 con el prescale en 1:1 y el postcale en 1:5. Tengo un PIC16F877A con un cristal de 20Mhz por lo que el calculo me dio
Periodo = (1/20Mhz)x4x244x1x5 =244µs
pero al implementarlo o simularlo en el Pic Simulator IDE la interrupción ocurre solo una vez
¿alguna idea?
Saludos cordiales y agradecimientos a dogflu66 por contestar todas mis dudas...Código: [Seleccionar]Define CONF_WORD = 0x3f72
AllDigital
TRISA = 0x00 'PORTA Outputs
INTCON.GIE = 1 'Int General
INTCON.PEIE = 1 'Int Perifericos
PIE1.TMR2IE = 1 'Int TMR2
T2CON.T2CKPS0 = 0 'TMR2 Prescale
T2CON.T2CKPS1 = 0 'TMR2 Prescale
T2CON.TOUTPS0 = 0 'TMR2 Postcale
T2CON.TOUTPS1 = 0 'TMR2 Postcale
T2CON.TOUTPS2 = 1 'TMR2 Postcale
T2CON.TOUTPS3 = 0 'TMR2 Postcale
PR2 = 244 'Overload TMR2
T2CON.TMR2ON = 1 'TMR2 ON
End
On Interrupt
PORTA.0 = Not PORTA.0
PIE1.TMR2IF = 0
Resume
'**********************************************************************************
Define CONFIG = 0x2f50 'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc 'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 8 'Clock en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Activar para simulación, acelera los comandos WaitMs
'Definicion de puertos-----------------
ANSEL = 0x00 'Los pin I/O digitales (no analogicos)
OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz
CMCON = 0x07 'Comparador a off
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'Puerto B como salidas
PORTA.7 = 1 'Led amarillo a off
PORTB.0 = 1 'Led verde a off
'Config TMR2
'No prescaler :1
T2CON.T2CKPS0 = 0 'TMR2 Prescaler
T2CON.T2CKPS1 = 0 'TMR2 Prescaler
'Postscaler :16
T2CON.TOUTPS0 = 1 'TMR2 Postcaler
T2CON.TOUTPS1 = 1 'TMR2 Postcaler
T2CON.TOUTPS2 = 1 'TMR2 Postcaler
T2CON.TOUTPS3 = 1 'TMR2 Postcaler
PIE1.TMR2IE = 1 'Int TMR2
INTCON.PEIE = 1 'Int Perifericos
'PR2 = ((1000uSeg. / (4/8Mhz)) / (1 x 16) -1 = 124
PR2 = 124 'Overload TMR2, 1mSeg.
T2CON.TMR2ON = 1 'TMR2 ON
Enable 'INTCON.GIE = 1 'Interrupción General
'-----------------------------------------------
'Bucle rutina principal
main:
'Cambia de estado el led cada 500mSeg.
Toggle RA7
WaitMs 500
Goto main
End
'------------------------------------------------
'Subrutina de control Interrupciones
On Interrupt
Save System
'Cambia de estado el led cada 500mSeg.
Dim _contador As Word
_contador = _contador + 1
If _contador >= 500 Then
Toggle RB0
_contador = 0
Endif
PIR1.TMR2IF = 0
Resume
Hola tengo el siguiete problema:
quiero generar un cambio de estado en un pin cada 244µs por lo que configuré el TMR2 con el prescale en 1:1 y el postcale en 1:5. Tengo un PIC16F877A con un cristal de 20Mhz por lo que el calculo me dio
Periodo = (1/20Mhz)x4x244x1x5 =244µs
pero al implementarlo o simularlo en el Pic Simulator IDE la interrupción ocurre solo una vez
¿alguna idea?
Saludos cordiales y agradecimientos a dogflu66 por contestar todas mis dudas...Código: [Seleccionar]Define CONF_WORD = 0x3f72
AllDigital
TRISA = 0x00 'PORTA Outputs
INTCON.GIE = 1 'Int General
INTCON.PEIE = 1 'Int Perifericos
PIE1.TMR2IE = 1 'Int TMR2
T2CON.T2CKPS0 = 0 'TMR2 Prescale
T2CON.T2CKPS1 = 0 'TMR2 Prescale
T2CON.TOUTPS0 = 0 'TMR2 Postcale
T2CON.TOUTPS1 = 0 'TMR2 Postcale
T2CON.TOUTPS2 = 1 'TMR2 Postcale
T2CON.TOUTPS3 = 0 'TMR2 Postcale
PR2 = 244 'Overload TMR2
T2CON.TMR2ON = 1 'TMR2 ON
End
On Interrupt
PORTA.0 = Not PORTA.0
PIE1.TMR2IF = 0
Resume
Cambia "PIE1.TMR2IF = 0" por "PIR1.TMR2IF = 0", y nos cuentas.
PD. Recuerda añadir el MAIN al programa.
Gracias por tu tiempo y comentarios. Como ya te he dico soy novato en el tema y cualquier aportacion es de agradecer.
Decirte que tal como esta el programa el mando me funciona "creo que bastante bien", no obstante queria reducir el tiempo de ejecucion para que fuera mas fiable.
Por tanto tomo nota del ejemplo que me has enviado y de los comentarios que me has pasado
Gracias
'********************************** Para Simular *********************************************
'NOMBRE: 16F88_ADC 8 y 10 Bit
'VERSION: 1.0
'MICRO: PIC16F88
'Fecha/Autor: 10/08 By COS, PSI v7.41
'Descripción: usando el modulo adc directamente.
'************************************************************************************************
Define CONFIG = 0x2f50 'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc 'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 8 'Clock en Mhz
Define SIMULATION_WAITMS_VALUE = 1 'Activar para simulación, acelera los comandos WaitMs
'Asignacion de I/O y valores de inicio de las salidas --------------------------------------------
ANSEL = %00010000 'Los pin I/O digitales y RA4 analogico
CMCON = 0x07 'Comparador a off
OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz
ADCON0 = %01100001 'Fosc/16 a 8Mhz (ADCON1.ADCS2=1) =2uSeg (minimo 1.6uSeg), channel RA4
ADCON1 = %11000000 'Volt. ref.(avdd/avss), selec. de escala division clock/16 ADCON1.ADCS2=1, adc a On
'ADCON1.ADFM = 0 'Activa lectura 8bit del ADC
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'Puerto B como salidas
TRISA.4 = 1 'Como entrada (RA4, adc)
'Declaracion de variables --------------------------------------------------------------------------------
Dim adc_4 As Word
adc_4 = 0
'Bucle principal ------------------------------------------------------------------------------------------
WaitMs 500 'Pausa 500mSeg.
main:
ADCON0.GO = 1 'Activa una conversión ADC
While ADCON0.GO = 1 'Espera hasta terminar la conversión ADC
Wend
'Pasa la lectura con formato de 10Bits a una variable tipo Word
adc_4.HB = ADRESH
adc_4.LB = ADRESL
'adc_4.LB = ADRESH 'ADC a 8 bit, se puede utilizar una variable tipo Byte
Goto main
End
'********************************** *********************
'NOMBRE: 16F88_MandoJEVO_01
'MICRO: PIC16f88
'Version: 1.0
''*****************************************************************************************************
Define CONF_WORD = 0x2f50
Define CONF_WORD_2 = 0x3ffc
Define CLOCK_FREQUENCY = 8
Define ADC_SAMPLEUS = 10
Define ADC_CLOCK = 5
CMCON = 0x07
ADCON0 = %01001001
ADCON1 = %11000000
Dim duty(16) As Byte 'Duty Cicle
Dim curva(15) As Byte 'Curva grabada
Dim vg As Word 'Valor gatillo
Dim ca As Byte 'Curva actual
Dim cn As Byte 'Curva nueva
Dim mca As Byte 'Modificacion curva actual P5
Dim mcn As Byte 'Modificacion curva nueva P5
Dim asa As Byte 'Antispin Actual P4
Dim asn As Byte 'Antispin nuevo P4
Dim ai As Byte 'Contador inicio
Dim af As Byte 'Contador fin
Dim a As Byte 'contador
Dim b As Byte
Dim va(4) As Byte
Dim mc(3) As Byte
Dim i As Byte
ANSEL = %00100011
TRISB = %11110111
TRISA = %11111111
'Ver curva actual
Gosub vercurva
Gosub leermemoria
Gosub modificarcurva
Gosub modificararranque
PWMon 1, 12
PWMduty 1, 0
'****************************************************************************
'Rutina principal
loop:
For i = 1 To 13
Gosub vercurva 'Comprueba que no se haya cambiado la curva
If cn <> ca Then Gosub leermemoria
'* Leer gatillo
Gosub salidapwm
Adcin 0, mcn 'lee el valor de p5
If mcn <> mca Then Gosub modificarcurva
'* Leer gatillo
Gosub salidapwm
Adcin 5, asn 'lee el valor de p4
If asn <> asa Then Gosub modificararranque
'* Leer gatillo
Gosub salidapwm
Next i
Goto loop
End
'********************************************************
'Deteccion de la curva a leer
vercurva:
'Ver curva nueva
cn = 0
If PORTA.2 = 1 Then cn = cn + 4
If PORTA.3 = 1 Then cn = cn + 2
If PORTA.4 = 1 Then cn = cn + 1
If PORTA.5 = 1 Then cn = cn + 8
ai = cn * 16 'Posicion inicial de memoria donde leer
af = ai + 14 'Posicion final de memoria donde leer
Return
leermemoria:
'Leer valores Guardados segun la curva a leer
For a = ai To af
b = a - ai
Read a, duty(b)
curva(b) = duty(b)
Next a
'Genera los valores para las modificaciones de curvas
va(0) = (curva(10) - curva(4)) / 5 'Calculo maxima modificacion
va(1) = va(0) * 2 '(va(0) * 10) / 5 es el valor de correccion del 100 % multiplicado por 10
va(2) = va(0) '(va(0) * 10) / (2 * 5) es el valor de correccion del 50 % multiplicado por 10
va(3) = (va(0) * 10) / 15 '(va(0) * 10) / (3 * 5) es el valor de correccion del 30 % multiplicado por 10
ca = cn
Return
'********************************************************************************************
'Rutina deteccion posicion del gatillo y entrega de potencia
salidapwm:
For a = 1 To 8
'Adcin 1, vg 'lee el valor del gatillo
ADCON0.GO = 1
While ADCON0.GO = 1 'Espera hasta terminar la conversion ADC
Wend
vg.HB = ADRESH 'ADC a 10bit
vg.LB = ADRESL 'ADC a 10bit
Select Case vg
Case < 64
PWMduty 1, 0 'Freno
Case < 128
PWMduty 1, duty(0)
Case < 192
PWMduty 1, duty(1)
Case < 256
PWMduty 1, duty(2)
Case < 320
PWMduty 1, duty(3)
Case < 384
PWMduty 1, duty(4)
Case < 448
PWMduty 1, duty(5)
Case < 512
PWMduty 1, duty(6)
Case < 576
PWMduty 1, duty(7)
Case < 640
PWMduty 1, duty(8)
Case < 704
PWMduty 1, duty(9)
Case < 768
PWMduty 1, duty(10)
Case < 832
PWMduty 1, duty(11)
Case < 896
PWMduty 1, duty(12)
Case < 960
PWMduty 1, duty(13)
Case <= 1023
PWMduty 1, duty(14)
EndSelect
Next a
Return
'*************************************************************
'Ajuste fino de la curva grabada
'Rutina para modificar el centro de la curva
modificarcurva:
Select Case mcn
Case < 22 'P -5
mc(0) = ((va(3) * 5) / 10)
mc(1) = ((va(1) * 5) / 10)
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
Return
Case < 44 'P -4
mc(0) = ((va(3) * 4) / 10)
mc(1) = ((va(1) * 4) / 10)
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
Return
Case < 66 'P -3
mc(0) = ((va(3) * 3) / 10)
mc(1) = ((va(1) * 3) / 10)
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
Return
Case < 88 'P -2
mc(0) = ((va(3) * 2) / 10)
mc(1) = ((va(1) * 2) / 10)
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
Return
Case < 110 'P -1
mc(0) = va(3) / 10
mc(1) = va(1) / 10
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
Return
Case < 145 'P 0
duty(5) = curva(5)
duty(6) = curva(6)
duty(7) = curva(7)
duty(8) = curva(8)
duty(9) = curva(9)
mca = mcn
Return
Case < 165 'P +1
mc(0) = va(3) / 10
mc(1) = va(2) / 10
mc(2) = va(1) / 10
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
Return
Case < 185 'P +2
mc(0) = ((va(3) * 2) / 10)
mc(1) = ((va(2) * 2) / 10)
mc(2) = ((va(1) * 2) / 10)
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
Return
Case < 205 'P +3
mc(0) = ((va(3) * 3) / 10)
mc(1) = ((va(2) * 3) / 10)
mc(2) = ((va(1) * 3) / 10)
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
Return
Case < 230 'P +4
mc(0) = ((va(3) * 4) / 10)
mc(1) = ((va(2) * 4) / 10)
mc(2) = ((va(1) * 4) / 10)
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
Return
Case <= 255 'P +5
mc(0) = ((va(3) * 5) / 10)
mc(1) = ((va(2) * 5) / 10)
mc(2) = ((va(1) * 5) / 10)
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
Return
EndSelect
Return
'*****************************************************************
'Ajuste del control de arrancada
modificararranque:
Select Case asn
Case < 25 'P 1
duty(0) = curva(0)
duty(1) = curva(1)
duty(2) = curva(2)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 50 'P 2
duty(0) = curva(0) + (((curva(1) - curva(0)) * 50) / 100)
duty(1) = curva(1)
duty(2) = curva(2)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 75 'P 3
duty(0) = curva(1)
duty(1) = curva(1) + (((curva(2) - curva(1)) * 40) / 100)
duty(2) = curva(2)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 100 'P 4
duty(0) = curva(1) + (((curva(2) - curva(1)) * 40) / 100)
duty(1) = curva(1) + (((curva(2) - curva(1)) * 80) / 100)
duty(2) = curva(2)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 125 'P 5
duty(0) = curva(1) + (((curva(2) - curva(1)) * 80) / 100)
duty(1) = curva(2)
duty(2) = curva(2) + (((curva(3) - curva(2)) * 40) / 100)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 150 'P 6
duty(0) = curva(2)
duty(1) = curva(2) + (((curva(3) - curva(2)) * 40) / 100)
duty(2) = curva(2) + (((curva(3) - curva(2)) * 80) / 100)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 175 'P 7
duty(0) = curva(2) + (((curva(3) - curva(2)) * 40) / 100)
duty(1) = curva(2) + (((curva(3) - curva(2)) * 80) / 100)
duty(2) = curva(3)
duty(3) = curva(3) + (((curva(4) - curva(3)) * 40) / 100)
duty(4) = curva(4)
asa = asn
Return
Case < 200 'p 8
duty(0) = curva(2) + (((curva(3) - curva(2)) * 80) / 100)
duty(1) = curva(3)
duty(2) = curva(3) + (((curva(4) - curva(3)) * 40) / 100)
duty(3) = curva(3) + (((curva(4) - curva(3)) * 80) / 100)
duty(4) = curva(4)
asa = asn
Return
Case < 225 'P 9
duty(0) = curva(3)
duty(1) = curva(3) + (((curva(4) - curva(3)) * 40) / 100)
duty(2) = curva(3) + (((curva(4) - curva(3)) * 80) / 100)
duty(3) = curva(4)
duty(4) = curva(4) + (((curva(5) - curva(4)) * 40) / 100)
asa = asn
Return
Case <= 255 'P 10
duty(0) = curva(3) + (((curva(4) - curva(3)) * 40) / 100)
duty(1) = curva(3) + (((curva(4) - curva(3)) * 80) / 100)
duty(2) = curva(4)
duty(3) = curva(4) + (((curva(5) - curva(4)) * 40) / 100)
duty(4) = curva(4) + (((curva(5) - curva(4)) * 80) / 100)
asa = asn
Return
EndSelect
Return
'Este software servirá como base para um sistema de checagem de senha tipo (Hardlock) via se-
'rial .
'MCU utilizada (10F200) rodando a 4MHZ em operação normal(RC interno).
'Autor: _Lince_
'Data: 21/10/2008
'Nome do aplicativo (Checa senha r0.1)
'*********************************Configuração dos fusiveis**********************************
Define CONF_WORD = 0x000
Define SEROUT_REG = GPIO
Define SEROUT_BIT = 0
Define SERIN_BIT = 3
Define SEROUT_BAUD = 9600
'Define SIMULATION_WAITMS_VALUE = 1 'Retirar esta linha para gravação em hardware.
'*********************************Definição dos I/Os*****************************************
'GPIO.GP0 saída led de validação.
'GPIO.GP1 entrada RX RS232 a 9600 bps..
'*********************************Variaveis do sistema***************************************
Dim buffer_rx_0 As Byte @ 0x18
Dim buffer_rx_1 As Byte @ 0x19
Dim buffer_rx_2 As Byte @ 0x1a
Dim buffer_rx_3 As Byte @ 0x1b
Dim contador As Byte @ 0x1c
Dim dado As Byte @ 0x1d
Dim contra_senha_0 As Byte @ 0x1e
Dim contra_senha_1 As Byte @ 0x1f
'***********************************Constantes do systema************************************
'*************************************Atribuições de I/Os entre outros***********************
Symbol led_ok = GPIO.1
Symbol rx = GPIO.3
'************************************Direção dos I/Os****************************************
TRISGPIO.0 = 0 ' Saída.(tx).
TRISGPIO.1 = 0 ' Saída.(led_ok).
TRISGPIO.3 = 1 ' Entrada.(rx).
'***************************************Main*************************************************
contador = 0
ASM: movlw 0x18 'Ponteiro do buffer de senha.
ASM: movwf fsr
led_ok = 0
buffer_rx_0 = 0
buffer_rx_1 = 0
buffer_rx_2 = 0
buffer_rx_3 = 0
contra_senha_0 = 0x33
contra_senha_1 = 0x34
main:
If led_ok = 1 Then
Serout contra_senha_0,contra_senha_1
led_ok = 0
Endif
If contador = 4 Then Goto checa_senha
If rx = 0 Then
If contador < 4 Then Goto le_rx
checa_senha:
contador = 0
ASM: movlw 0x18 'Aponto para início do buffer novamente.
ASM: movwf fsr
ASM: movlw 0x31 'senha_0
ASM: xorwf buffer_rx_0,w
ASM: btfss status,z
ASM: goto $+ 0x0e
ASM: movlw 0x32 'senha_1
ASM: xorwf buffer_rx_1,w
ASM: btfss status,z
ASM: goto $+ 0x0a
ASM: movlw 0x33 'senha_2
ASM: xorwf buffer_rx_2,w
ASM: btfss status,z
ASM: goto $+ 0x06
ASM: movlw 0x34 'senha_3
ASM: xorwf buffer_rx_3,w
ASM: btfss status,z
ASM: goto $+ 0x02
ASM: bsf led_ok 'uso uma saída como flag para poder verificar e
ASM: nop 'transmitir a contra senha.
Endif
Goto main
le_rx:
Serin dado
contador = contador + 1
ASM: movf dado,w
ASM: movwf indf
ASM: incf fsr,f
Goto main
'******************************************Fim************************************************
End
Software feito por quem não tem oque fazer. :mrgreen:
News in version 6.70
- Improved timing issues for LCD routines in basic compiler
- Improved timing issues for GLCD routines in basic compiler
- Software version, microcontroller model and clock frequency saved in ASM files generated by basic compiler
- Improved Alternative SFR Viewer
- Changed order of items in Tools and Options menus
- Several small and/or invisible improvements
'*************************************************
'Ejemplo 32
'PIC16F88, 12/08, By COS, PSI v7.41
'Solo para simulación
'Devuelve el valor de un bit determinado
'de una varia de hasta 32Bits.
'El valor del los bits son enviados al puerto serie que son
'visualizados en el modulo Hardware UART Simulation Interface
'*************************************************
Define CLOCK_FREQUENCY = 4
Define SIMULATION_WAITMS_VALUE = 1 'Solo simulación, se aceleran los WaitMs
AllDigital
Hseropen 4800 'Configura puerto RS232 por hardware
Dim entrada As Long 'word 'byte
Dim dato As Byte
Dim n As Byte
entrada = %01000001000000001000000010001001
dato = 0
For n = 31 To 0 Step -1
dato.0 = v_bit(entrada, n) 'Selecciona el bit n
Hserout #dato, " "
WaitMs 1000
Next n
End
'Subrutinas y funciones
'--------------------------------------------------------------
'Devuelve valor: Bit
'V_BIT es una funcion que nos devuelve el estado
'de un bit de una variable determinada.
'ARG1 es la variable de entrada, hasta 32bit.
'ARG2 es el numero de orden del bit deseado de 0 a 31.
'Mediante V_BIT se transfiere el valor del bit deseado
Function v_bit(arg1 As Long, arg2 As Byte) As Bit
arg1 = ShiftRight(arg1, arg2) 'Desplazamiento de bit a la derecha
v_bit = arg1.0
End Function
'***************** Placa Entrenadora (PIC EBadic) ***************************************
'NOMBRE: 16F88_Pic_EBasic_EJEMPLO_33
'Descripcion: TEST DE LA PLACA EBasic_I2C (Led y DS1624), Temperatura positiva y negativa)
'Micro: PIC16F88 / 8mhz reloj interno
'Fecha/Autor: 23/01/09, 15/01/09, 2/08/07, 29/7/07 By COS, PSI v7.41
'Version: 1.3
'Se añaden temperaturas negativas
'Se crea la función lcdsig_ds1624, que permite seleccionar 0,1 o 2 decimales
'Version: 1.2
'Se eliminan elementos redundantes en la funcion
'Version: 1.1
'Se añade TEST para el DS1624 (temperatura)
'*****************************************************************************************
Define CONF_WORD = 0x2f50 'Configuración de bits (fuses)
Define CONF_WORD_2 = 0x3ffc 'Configuración de bits (fuses)
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Hace que se ignoren los tiempos de los WaitMs
'-------------------------------------Puertos del LCD-------------------------------------
Define LCD_BITS = 4 'Indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'Bus de datos sera el puerto A
Define LCD_DBIT = 0 'Bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'Bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E sera del puerto B
Define LCD_EBIT = 6 'RB6 como E
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comando del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera despues de inicializar el Display.
'Definicion de puertos--------------------------------
AllDigital 'los pin I/O digitales
'ANSEL = %00010000 'los pin I/O digitales y RA4 analogico
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
'TRISA.4 = 1 'como entrada (RA4, adc)
TRISA.6 = 1 'como entrada (RA6, tecla S1)
TRISA.5 = 1 'como entrada (RA5, tecla S2)
'Declaracion de constantes-----------------------------
Const p_off = 0 'apaga el led
Const p_on = 1 'enciende el led
Const p_nc = 2 'no cambia estado el led
'Reasignacion de nombres------------------------------
Symbol sda = RB1 'asignamos nombre al pin que hara de SDA del puerto I2C
Symbol scl = RB4 'asignamos nombre al pin que hara de SCL del puerto I2C
Symbol led_amarillo = RA7 'led amarillo
Symbol led_verde = RB0 'led verde
Symbol luz_lcd = RB3 'iluminación del lcd
Symbol s1 = RA6 'tecla S1
Symbol s2 = RA5 'tecla S2
'Variables generales---------------------------------------
Dim temperatura As Word 'temperatura entero .HB, decimales .LB
'Inicio------------------------------------------------
Lcdinit 'inicializa el LCD sin cursor
WaitMs 100 'pausa de 100 mSeg.
Lcdout "Test P. EB_I2C" 'Imprime el texto en el LCD
WaitMs 3000 'pausa de 3Seg.
Call led(p_off, p_off, p_on, p_off) 'led a off
'Rutina Programa---------------------------------------
main:
Call led(p_nc, p_nc, p_nc, p_on) 'Control luces
temperatura = d_ds1624(0) 'genera una lectura en el chip ds
Call led(p_nc, p_nc, p_nc, p_off) 'Control luces
WaitMs 1000 'pausa de 1Seg, tiempo maximo de conversion del chip ds
Call led(p_nc, p_nc, p_nc, p_on) 'Control luces
temperatura = d_ds1624(1) 'almacena la lectura en dos bytes
Call led(p_nc, p_nc, p_nc, p_off) 'Control luces
Lcdcmdout LcdLine2Home 'cursor al principio de la linea 2
Lcdout "Temp. " 'Imprime en el LCD
Call lcdsig_ds1624(temperatura, 1, 1) 'Llama a imprimir temperatura con formato
WaitMs 1000 'hace una pausa de 1Seg.
Goto main
End
'Rutinas-----------------------------------------------
'Detecta signo e imprime con 0, 1 o 2 decimales
'Parte entera con formato de 3 digitos
'arg1 = Valor de entrada de temperatura
'arg2 = 0 no hay decimales, arg2 = 1 un decimal, arg2 = 2 con dos decimales
'arg3 = 0 no imprime "C" despues de los decimales, arg3 = 1 si la imprime
Proc lcdsig_ds1624(arg1 As Word, arg2 As Byte, arg3 As Bit) 'Declara el tipo y argumentos de la funcion
If arg1.15 = 0 Then 'Selecciona +/-
If arg1 > 0 Then Lcdout "+" 'Imprime en el lcd
If arg1 = 0 Then Lcdout " " 'Imprime en el lcd
Else
arg1.15 = 0 'Deja la parte entera
If arg1 > 0 Then Lcdout "-" 'Imprime en el lcd
If arg1 = 0 Then Lcdout " " 'Imprime en el lcd
Endif
If arg1.HB < 100 Then Lcdout "0"
If arg1.HB < 10 Then Lcdout "0"
Lcdout #arg1.HB 'Escribe parte entera
If arg2 = 1 Or arg2 = 2 Then Lcdout "." 'Escribe lcd
If arg2 = 1 Then arg1.LB = arg1.LB / 10 'Suprime el segundo decimal
If arg2 = 2 And arg1.LB < 10 Then Lcdout "0" 'Mantiene el formato dos decimales
If arg2 = 1 Or arg2 = 2 Then Lcdout #arg1.LB 'Escribe los decimales
If arg3 = 1 Then Lcdout "C" 'Imprime en el lcd
End Proc
'Funcion de lectura/escritura del DS1624
'ds_rw=0 el chip prepara un lectura
'ds_rw=1 el chip entrega una lectura
'ds_rw=2 se hace una lectura del registro de control.
'd_ds1624, byte mas significativo parte entera, menos significativo 2 decimales
'Hay que recordar declarar SDA y SCL
Function d_ds1624(ds_rw As Byte) As Word ', d_aux As Long) As Word
Dim d_aux As Long
RA4 = 1 'Led placa I2c a On
If ds_rw = 0 Then 'Solicita una lectura de temperatura
I2CWrite sda, scl, %10010010, 0xac, 0x00 'Inicializa el registro de control
WaitMs 10 'Pausa para que termine la escritura
I2CWrite1 sda, scl, %10010010, 0xee 'Comienza una conversión
Endif
If ds_rw = 1 Then 'Hace la lectura de la temperatura
I2CWrite1 sda, scl, %10010010, 0xaa 'Prepara el chip para lectura de temperatura
I2CRead1 sda, scl, %10010011, d_ds1624.HB, d_ds1624.LB 'Lee la temperatura
If d_ds1624.15 = 1 Then 'Detecta signo de la temperatura
d_ds1624 = Not d_ds1624 'Pasa a complemento a 1
d_ds1624 = d_ds1624 + 1 'Pasa a complemento a 2
d_ds1624.15 = 1 'Activa bit de signo negativo que se pierde en la operación
Endif
d_ds1624.LB = ShiftRight(d_ds1624.LB, 3) 'Elimina bit que no se usan
d_aux = (d_ds1624.LB * 625) / 1000 'Calcula la parte decimal, 2 digitos
'd_aux = (d_ds1624.LB * 9) / 15 'Calcula la parte decimal, 2 digitos, operación simplificada
d_ds1624.LB = d_aux.LB 'Pasa los decimales a la variable de transferencia
Endif
If ds_rw = 2 Then 'Hace una lectura del registro de control
d_ds1624 = 0 'Inicializa variable
I2CRead sda, scl, %10010011, 0xac, d_ds1624.LB 'lee registro de control
Endif
RA4 = 0 'led placa i2c a Off
End Function
'Controla el estado de los led, Call(x1, x2, x3, x4)
'x=0 led apagado, x=1 led encendido, x=2 no hay cambio
Proc led(led_amarillo As Byte, led_verde As Byte, luz_lcd As Byte, led_ebi2c As Byte)
If led_amarillo = 1 Then RA7 = 0 'led amarillo a on
If led_amarillo = 0 Then RA7 = 1 'led amarillo a off
If led_verde = 1 Then RB0 = 0 'led verde a on
If led_verde = 0 Then RB0 = 1 'led verde a off
If luz_lcd = 1 Then RB3 = 1 'LCD iluminado
If luz_lcd = 0 Then RB3 = 0 'LCD apagado
If led_ebi2c = 1 Then RA4 = 1 'led EB_I2C a on
If led_ebi2c = 0 Then RA4 = 0 'led EB_I2C a off
End Proc
Buenas Noches Ariel soy nuevo en el foro, me llamó mucho la atencion tu programa del reloj aunque no pude correrlo xq no se como van conectados los pines de la pantalla LCD :( .....
X casualidad en el foro ya no han publicado como trabajar con un teclado matricial y que al pulsar cada tecla se vaya mostrando en cuatro displays 7segmentos?
es que estoy tratando de realizar esa asignacion pero tengo dudas a la hora de guardar por ejemplo el primer valor a mostrar en el display "Posicion menos significativa" xq cada vez que pulse otra tecla deben desplazarse hacia la izquierda los valores ya mostrados anteriormente en los displays....el teclado es de 4x4 y el display multiplexado 7x4....x favor seria de gran ayuda si me echan una hand.... :)
avisenme si debo ser mas explícito en mi duda x favor...
Otra duda, en PROTON el comando POT se que permite leer cualquier tipo de resistencia variable: potenciometros, termistores, etc...pero la sintaxis como tal que arroja la ayuda de PROTON dice lo siguiente:
Variable = POT Pin, scale
no entiendo como explicar que significa ese operador "scale" ¿?....espero su pronta respuesta GRACIAS....
'***************************************************************************************
'NOMBRE: 16F88_MandoJEVO_01
'MICRO: PIC16f88
'Version: 2.0
'Utilización de interrupciones
''**************************************************************************************
Define CONF_WORD = 0x2f50
Define CONF_WORD_2 = 0x3ffc
Define CLOCK_FREQUENCY = 8
'Define ADC_SAMPLEUS = 10
'Define ADC_CLOCK = 5
Dim duty(15) As Byte 'Duty Cicle
Dim curva(15) As Byte 'Curva grabada
Dim vg As Byte 'Valor gatillo
Dim ca As Byte 'Curva actual
Dim cn As Byte 'Curva nueva
Dim mca As Byte 'Modificacion curva actual P5
Dim mcn As Byte 'Modificacion curva nueva P5
Dim asa As Byte 'Antispin Actual P4
Dim asn As Byte 'Antispin nuevo P4
Dim ai As Byte 'Contador inicio
Dim af As Byte 'Contador fin
Dim a As Byte 'contador
Dim b As Byte
Dim va(4) As Byte
Dim mc(3) As Byte
Dim i As Byte
'---------------Variables el timer-------------------
Dim t1_ms As Byte 'Base de tiempos del timer 1
Dim t1_ms_t As Byte 'Contiene el valor de t1_ms
Dim t2_ms As Byte 'Base de tiempos del timer 2
Dim t2_ms_t As Byte 'Contiene el valor de t2_ms
Dim t3_ms As Byte 'Base de tiempos del timer 3
Dim t3_ms_t As Byte 'Contiene el valor de t3_ms
'--------------Definición de puertos
ANSEL = %00100011 'Los pin digitales y NA5, NA1 y NA0 como analogicos
TRISB = %11110111 'Configuración input/output
TRISA = %11111111 'Configuración input/output
CMCON = 0x07 'Comparador a off
OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz
ADCON0 = %00100001 'Fosc/16 a 8Mhz (ADCON1.ADCS2=1) =2uSeg (minimo 1.6uSeg), channel RA4
ADCON1 = %10000000 'Volt. ref.(AVdd/AVss), selec. de escala division clock/16 ADCON1.ADCS2=1, ADC a ON
'--------------Configuracion Interrupciones -----------------
T1CON.TMR1CS = 0 'asigna el reloj interno al timer 1, se incrementa cada ciclo de instruccion
T1CON.T1CKPS0 = 0 'Factor de preescaler del timer 1, 0
T1CON.T1CKPS1 = 0 'Factor de preescaler del timer 1, 0
TMR1H = 0xf8 'Carga el registro del contador para que desborde cada 1 msg. byte alto 248 x 256
TMR1L = 0x30 'Carga el registro del contador para que desborde cada 1 msg. byte bajo + 48
'-------------Carga los valores iniciales del timer ------------------------
t1_ms = 0
t2_ms = 0
t3_ms = 0
t1_ms_t = 3 'Valor para el timer del P4 Arranque
t2_ms_t = 5 'Valor para el timer del P5 Curva
t3_ms_t = 200 'Valor para el timer del selector de curva
'---------------------Habilita las interrupciones --------------------------------------
T1CON.TMR1ON = 1 'Habilita el timer 1, comienza a incrementar
PIE1.TMR1IE = 1 'Activa la interrupcion del timer
INTCON.PEIE = 1 'Bit de habilitación de interrupciones de perifericos
Enable 'INTCON.GIE habilita todas las interrupciones globales
'****************************************************************************
'Ver curva actual
Gosub vercurva
Gosub leermemoria
Gosub modificarcurva
Gosub modificararranque
'Activo el PWM
PWMon 1, 9
PWMduty 1, 0
'Rutina principal
loop:
'For i = 1 To 240 'Bucle solo para pruebas de tiempos
'Leo el valor del gatillo
ADCON0.CHS0 = 1 'Selecciono canal NA1 para el modulo ADC
ADCON0.CHS1 = 0
ADCON0.CHS2 = 0
'ADCON1.ADFM = 1 'Activaria lectura 10bit del ADC
ADCON1.ADFM = 0 'Activa lectura 8bit del ADC
ADCON0.GO = 1 'Activo una lectura
While ADCON0.GO = 1 'Espera hasta terminar la conversion ADC
Wend
'vg.HB = ADRESH 'ADC a 10bit
'vg.LB = ADRESL 'ADC a 10bit
vg = ADRESH 'ADC a 8 bit
Select Case vg
Case < 16
PWMduty 1, 0 'Freno
Case < 32
PWMduty 1, duty(0)
Case < 48
PWMduty 1, duty(1)
Case < 64
PWMduty 1, duty(2)
Case < 80
PWMduty 1, duty(3)
Case < 96
PWMduty 1, duty(4)
Case < 112
PWMduty 1, duty(5)
Case < 128
PWMduty 1, duty(6)
Case < 144
PWMduty 1, duty(7)
Case < 160
PWMduty 1, duty(8)
Case < 176
PWMduty 1, duty(9)
Case < 192
PWMduty 1, duty(10)
Case < 208
PWMduty 1, duty(11)
Case < 224
PWMduty 1, duty(12)
Case < 240
PWMduty 1, duty(13)
Case <= 255
PWMduty 1, duty(14)
EndSelect
If t1_ms >= t1_ms_t Then
'Leo el valor de p4 ADC 5
ADCON0.CHS0 = 1 'Selecciono canal AN5 para el modulo ADC
ADCON0.CHS1 = 0
ADCON0.CHS2 = 1
ADCON1.ADFM = 0 'Activa lectura 8bit del ADC
ADCON0.GO = 1 'Activo una lectura
While ADCON0.GO = 1 'Espera hasta terminar la conversion ADC
Wend
asn = ADRESH 'ADC a 8bit
If asn <> asa Then Gosub modificararranque
t1_ms = 0
Endif
If t2_ms >= t2_ms_t Then
'Leo el valor de p5 ADC 0
ADCON0.CHS0 = 0 'Selecciono canal AN0 para el modulo ADC
ADCON0.CHS1 = 0
ADCON0.CHS2 = 0
ADCON1.ADFM = 0 'Activa lectura 8bit del ADC
ADCON0.GO = 1 'Activo una lectura
While ADCON0.GO = 1 'Espera hasta terminar la conversion ADC
Wend
mcn = ADRESH 'ADC a 8bit
If mcn <> mca Then Gosub modificarcurva
t2_ms = 0
t1_ms = 0 'Esto lo hago para impedir que haga las dos lecturas en la misma interrupcion
'lo que convierte t1_ms en 5 tambien pero con un desfase de 2 ms
Endif
If t3_ms >= t3_ms_t Then
Gosub vercurva 'Comprueba que no se haya cambiado la curva
If cn <> ca Then Gosub leermemoria
t3_ms = 0
Endif
'next i 'Bucle para pruebas
Goto loop
End
'********************************************************
'Deteccion de la curva a leer
vercurva:
'Ver curva nueva
cn = 0
If PORTA.4 = 1 Then cn = cn + 1
If PORTA.3 = 1 Then cn = cn + 2
If PORTA.2 = 1 Then cn = cn + 4
If PORTA.5 = 1 Then cn = cn + 8
Return
leermemoria:
'Leer valores Guardados segun la curva a leer
ai = LookUp(0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240), cn 'Posicion inicial de memoria donde leer
af = LookUp(14, 30, 46, 62, 78, 94, 110, 126, 142, 158, 174, 190, 206, 222, 238, 254), cn 'Posicion final de memoria donde leer
For a = ai To af
b = a - ai
Read a, duty(b)
curva(b) = duty(b)
Next a
'Genera los valores para las modificaciones de curvas
va(0) = (curva(10) - curva(4)) / 5 'Calculo maxima modificacion
va(1) = va(0) * 2 '(va(0) * 10) / 5 es el valor de correccion del 100 % multiplicado por 10
va(2) = va(0) '(va(0) * 10) / (2 * 5) es el valor de correccion del 50 % multiplicado por 10
va(3) = (va(0) * 10) / 15 '(va(0) * 10) / (3 * 5) es el valor de correccion del 30 % multiplicado por 10
ca = cn
Return
'*************************************************************
'Ajuste fino de la curva grabada
'Rutina para modificar el centro de la curva
modificarcurva:
Select Case mcn
Case < 22 'P -5
mc(0) = ((va(3) * 5) / 10)
mc(1) = ((va(1) * 5) / 10)
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
Return
Case < 44 'P -4
mc(0) = ((va(3) * 4) / 10)
mc(1) = ((va(1) * 4) / 10)
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
Return
Case < 66 'P -3
mc(0) = ((va(3) * 3) / 10)
mc(1) = ((va(1) * 3) / 10)
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
Return
Case < 88 'P -2
mc(0) = ((va(3) * 2) / 10)
mc(1) = ((va(1) * 2) / 10)
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
Return
Case < 110 'P -1
mc(0) = va(3) / 10
mc(1) = va(1) / 10
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
Return
Case < 145 'P 0
duty(5) = curva(5)
duty(6) = curva(6)
duty(7) = curva(7)
duty(8) = curva(8)
duty(9) = curva(9)
mca = mcn
Return
Case < 165 'P +1
mc(0) = va(3) / 10
mc(1) = va(2) / 10
mc(2) = va(1) / 10
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
Return
Case < 185 'P +2
mc(0) = ((va(3) * 2) / 10)
mc(1) = ((va(2) * 2) / 10)
mc(2) = ((va(1) * 2) / 10)
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
Return
Case < 205 'P +3
mc(0) = ((va(3) * 3) / 10)
mc(1) = ((va(2) * 3) / 10)
mc(2) = ((va(1) * 3) / 10)
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
Return
Case < 230 'P +4
mc(0) = ((va(3) * 4) / 10)
mc(1) = ((va(2) * 4) / 10)
mc(2) = ((va(1) * 4) / 10)
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
Return
Case <= 255 'P +5
mc(0) = ((va(3) * 5) / 10)
mc(1) = ((va(2) * 5) / 10)
mc(2) = ((va(1) * 5) / 10)
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
Return
EndSelect
Return
'*****************************************************************
'Ajuste del control de arrancada
modificararranque:
Select Case asn
Case < 25 'P 1
duty(0) = curva(0)
duty(1) = curva(1)
duty(2) = curva(2)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 50 'P 2
duty(0) = curva(0) + (((curva(1) - curva(0)) * 50) / 100)
duty(1) = curva(1)
duty(2) = curva(2)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 75 'P 3
duty(0) = curva(1)
duty(1) = curva(1) + (((curva(2) - curva(1)) * 40) / 100)
duty(2) = curva(2)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 100 'P 4
duty(0) = curva(1) + (((curva(2) - curva(1)) * 40) / 100)
duty(1) = curva(1) + (((curva(2) - curva(1)) * 80) / 100)
duty(2) = curva(2)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 125 'P 5
duty(0) = curva(1) + (((curva(2) - curva(1)) * 80) / 100)
duty(1) = curva(2)
duty(2) = curva(2) + (((curva(3) - curva(2)) * 40) / 100)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 150 'P 6
duty(0) = curva(2)
duty(1) = curva(2) + (((curva(3) - curva(2)) * 40) / 100)
duty(2) = curva(2) + (((curva(3) - curva(2)) * 80) / 100)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 175 'P 7
duty(0) = curva(2) + (((curva(3) - curva(2)) * 40) / 100)
duty(1) = curva(2) + (((curva(3) - curva(2)) * 80) / 100)
duty(2) = curva(3)
duty(3) = curva(3) + (((curva(4) - curva(3)) * 40) / 100)
duty(4) = curva(4)
asa = asn
Return
Case < 200 'p 8
duty(0) = curva(2) + (((curva(3) - curva(2)) * 80) / 100)
duty(1) = curva(3)
duty(2) = curva(3) + (((curva(4) - curva(3)) * 40) / 100)
duty(3) = curva(3) + (((curva(4) - curva(3)) * 80) / 100)
duty(4) = curva(4)
asa = asn
Return
Case < 225 'P 9
duty(0) = curva(3)
duty(1) = curva(3) + (((curva(4) - curva(3)) * 40) / 100)
duty(2) = curva(3) + (((curva(4) - curva(3)) * 80) / 100)
duty(3) = curva(4)
duty(4) = curva(4) + (((curva(5) - curva(4)) * 40) / 100)
asa = asn
Return
Case <= 255 'P 10
duty(0) = curva(3) + (((curva(4) - curva(3)) * 40) / 100)
duty(1) = curva(3) + (((curva(4) - curva(3)) * 80) / 100)
duty(2) = curva(4)
duty(3) = curva(4) + (((curva(5) - curva(4)) * 40) / 100)
duty(4) = curva(4) + (((curva(5) - curva(4)) * 80) / 100)
asa = asn
Return
EndSelect
Return
'----------------------- Interrupciones ------------------------------------------
On Interrupt
Save System
If PIR1.TMR1IF = 1 Then
If t1_ms < t1_ms_t Then t1_ms = t1_ms + 1
If t2_ms < t2_ms_t Then t2_ms = t2_ms + 1
If t3_ms < t3_ms_t Then t3_ms = t3_ms + 1
Endif
TMR1H = 0xf8 'Carga el registro del contador para que desborde cada 1 msg. byte alto 248 x 256
TMR1L = 0x30 'Carga el registro del contador para que desborde cada 1 msg. byte bajo + 48
PIR1.TMR1IF = 0 'Borra el flag del salto del tmr1
Resume
.
.
.
Por cierto una pregunta ¿es posible generar un programa con el PSI (aunque no se pueda simular) para un micro que no este en la lista?. Quiero utilizar un PIC18f14k50 y no lo he encontrado en la lista de pic que admite el PSI.
'* * * * * * * * * * * * * adaptado para trabajar con el modulo adc sin interrupciones * * * * * * * * * * * * * *
'***************************************************************************************
'NOMBRE: 16F88_MandoJEVO_01
'MICRO: PIC16f88
'Version: 1.0
''**************************************************************************************
Define CONF_WORD = 0x2f50
Define CONF_WORD_2 = 0x3ffc
Define CLOCK_FREQUENCY = 8
'Define ADC_SAMPLEUS = 10
'Define ADC_CLOCK = 5
Dim duty(15) As Byte 'Duty Cicle
Dim curva(15) As Byte 'Curva grabada
Dim vg As Word 'Valor gatillo
Dim ca As Byte 'Curva actual
Dim cn As Byte 'Curva nueva
Dim mca As Byte 'Modificacion curva actual P5
Dim mcn As Byte 'Modificacion curva nueva P5
Dim asa As Byte 'Antispin Actual P4
Dim asn As Byte 'Antispin nuevo P4
Dim ai As Byte 'Contador inicio
Dim af As Byte 'Contador fin
Dim a As Byte 'contador
Dim b As Byte
Dim va(4) As Byte
Dim mc(3) As Byte
ANSEL = %00100011 'Los pin digitales y NA5, NA1 y NA0 como analogicos
TRISB = %11110111 'Configuración input/output todo entradas menos el port b 3
TRISA = %11111111 'Configuración input/output todo entradas
CMCON = 0x07 'Comparador a off "00000111"
'OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz "01111110"
'OSCCON.IRCF2 = 1 '= 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz "01111110"
'OSCCON.IRCF1 = 1
'OSCCON.IRCF0 = 1
ADCON0 = %01100001 'Fosc/16 a 8Mhz (ADCON1.ADCS2=1) =2uSeg (minimo 1.6uSeg), channel RA1
ADCON1 = %10000000 'Volt. ref.(AVdd/AVss), selec. de escala division clock/16 ADCON1.ADCS2=1, ADC a ON
PWMon 1, 9
PWMduty 1, 0
'****************************************************************************
'Rutina principal
loop:
'Adcin 1, vg 'lee el valor del gatillo
ADCON0.CHS0 = 1 'Selecciono canal NA1 para el modulo ADC
ADCON0.CHS1 = 0
ADCON0.CHS2 = 0
ADCON1.ADFM = 1 'Activa lectura 10bit del ADC
ADCON0.GO = 1 'Activo una lectura
While ADCON0.GO = 1 'Espera hasta terminar la conversion ADC
Wend
vg.HB = ADRESH 'ADC a 10bit
vg.LB = ADRESL 'ADC a 10bit
'vg = ADRESh 'ADC a 8 bit
Select Case vg
Case < 64
PWMduty 1, 0 'Freno
Case < 128
PWMduty 1, 10
Case < 192
PWMduty 1, 20
Case < 256
PWMduty 1, 30
Case < 320
PWMduty 1, 40
Case < 384
PWMduty 1, 50
Case < 448
PWMduty 1, 70
Case < 512
PWMduty 1, 90
Case < 576
PWMduty 1, 110
Case < 640
PWMduty 1, 130
Case < 704
PWMduty 1, 150
Case < 768
PWMduty 1, 170
Case < 832
PWMduty 1, 190
Case < 896
PWMduty 1, 200
Case < 960
PWMduty 1, 210
Case <= 1024
PWMduty 1, 230
EndSelect
Goto loop
End
'***************************************************************************************
'NOMBRE: 16F88_MandoJEVO_01
'MICRO: PIC16f88
'Version: 2.0
'Utilización de interrupciones
''**************************************************************************************
Define CONF_WORD = 0x2f50
Define CONF_WORD_2 = 0x3ffc
Define CLOCK_FREQUENCY = 8
'Define ADC_SAMPLEUS = 10
'Define ADC_CLOCK = 5
Dim duty(15) As Byte 'Duty Cicle
Dim curva(15) As Byte 'Curva grabada
Dim vg As Word 'Valor gatillo
Dim ca As Byte 'Curva actual
Dim cn As Byte 'Curva nueva
Dim mca As Byte 'Modificacion curva actual P5
Dim mcn As Byte 'Modificacion curva nueva P5
Dim asa As Byte 'Antispin Actual P4
Dim asn As Byte 'Antispin nuevo P4
Dim ai As Byte 'Contador inicio
Dim af As Byte 'Contador fin
Dim a As Byte 'contador
Dim b As Byte
Dim va(4) As Byte
Dim mc(3) As Byte
Dim i As Byte
'---------------Variables el timer-------------------
Dim t1_ms As Byte 'Base de tiempos del timer 1
Dim t1_ms_t As Byte 'Contiene el valor de t1_ms
Dim t2_ms As Byte 'Base de tiempos del timer 2
Dim t2_ms_t As Byte 'Contiene el valor de t2_ms
Dim t3_ms As Byte 'Base de tiempos del timer 3
Dim t3_ms_t As Byte 'Contiene el valor de t3_ms
'--------------Definición de puertos
ANSEL = %00100011 'Los pin digitales y NA5, NA1 y NA0 como analogicos
TRISB = %11110111 'Configuración input/output
TRISA = %11111111 'Configuración input/output
CMCON = 0x07 'Comparador a off
'OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz
ADCON0 = %00100001 'Fosc/16 a 8Mhz (ADCON1.ADCS2=1) =2uSeg (minimo 1.6uSeg), channel RA4
ADCON1 = %10000000 'Volt. ref.(AVdd/AVss), selec. de escala division clock/16 ADCON1.ADCS2=1, ADC a ON
'--------------Configuracion Interrupciones -----------------
T1CON.TMR1CS = 0 'asigna el reloj interno al timer 1, se incrementa cada ciclo de instruccion
T1CON.T1CKPS0 = 0 'Factor de preescaler del timer 1, 0
T1CON.T1CKPS1 = 0 'Factor de preescaler del timer 1, 0
TMR1H = 0xf8 'Carga el registro del contador para que desborde cada 1 msg. byte alto 248 x 256
TMR1L = 0x30 'Carga el registro del contador para que desborde cada 1 msg. byte bajo + 48
'-------------Carga los valores iniciales del timer ------------------------
t1_ms = 0
t2_ms = 0
t3_ms = 0
t1_ms_t = 1 'Valor para el timer del P4 Arranque
t2_ms_t = 3 'Valor para el timer del P5 Curva
t3_ms_t = 10 'Valor para el timer del selector de curva
'---------------------Habilita las interrupciones --------------------------------------
T1CON.TMR1ON = 1 'Habilita el timer 1, comienza a incrementar
PIE1.TMR1IE = 1 'Activa la interrupcion del timer
INTCON.PEIE = 1 'Bit de habilitación de interrupciones de perifericos
Enable 'INTCON.GIE habilita todas las interrupciones globales
'****************************************************************************
'Ver curva actual
Gosub vercurva
Gosub leermemoria
Gosub modificarcurva
Gosub modificararranque
'Activo el PWM
PWMon 1, 9
PWMduty 1, 0
'Rutina principal
loop:
'For i = 1 To 240 'Bucle solo para pruebas de tiempos
'Leo el valor del gatillo
ADCON0.CHS0 = 1 'Selecciono canal NA1 para el modulo ADC
ADCON0.CHS1 = 0
ADCON0.CHS2 = 0
ADCON1.ADFM = 1 'Activaria lectura 10bit del ADC
'ADCON1.ADFM = 0 'Activa lectura 8bit del ADC
ADCON0.GO = 1 'Activo una lectura
While ADCON0.GO = 1 'Espera hasta terminar la conversion ADC
Wend
vg.HB = ADRESH 'ADC a 10bit
vg.LB = ADRESL 'ADC a 10bit
'vg = ADRESH 'ADC a 8 bit
Select Case vg
Case < 64
PWMduty 1, 0 'Freno
Case < 128
PWMduty 1, duty(0)
Case < 192
PWMduty 1, duty(1)
Case < 256
PWMduty 1, duty(2)
Case < 320
PWMduty 1, duty(3)
Case < 384
PWMduty 1, duty(4)
Case < 448
PWMduty 1, duty(5)
Case < 512
PWMduty 1, duty(6)
Case < 576
PWMduty 1, duty(7)
Case < 640
PWMduty 1, duty(8)
Case < 704
PWMduty 1, duty(9)
Case < 768
PWMduty 1, duty(10)
Case < 832
PWMduty 1, duty(11)
Case < 896
PWMduty 1, duty(12)
Case < 1024
PWMduty 1, duty(13)
Case <= 255
PWMduty 1, duty(14)
EndSelect
If t1_ms >= t1_ms_t Then
'Leo el valor de p4 ADC 5
ADCON0.CHS0 = 1 'Selecciono canal AN5 para el modulo ADC
ADCON0.CHS1 = 0
ADCON0.CHS2 = 1
ADCON1.ADFM = 0 'Activa lectura 8bit del ADC
ADCON0.GO = 1 'Activo una lectura
While ADCON0.GO = 1 'Espera hasta terminar la conversion ADC
Wend
asn = ADRESH 'ADC a 8bit
If asn <> asa Then Gosub modificararranque
t1_ms = 0
Endif
If t2_ms >= t2_ms_t Then
'Leo el valor de p5 ADC 0
ADCON0.CHS0 = 0 'Selecciono canal AN0 para el modulo ADC
ADCON0.CHS1 = 0
ADCON0.CHS2 = 0
ADCON1.ADFM = 0 'Activa lectura 8bit del ADC
ADCON0.GO = 1 'Activo una lectura
While ADCON0.GO = 1 'Espera hasta terminar la conversion ADC
Wend
mcn = ADRESH 'ADC a 8bit
If mcn <> mca Then Gosub modificarcurva
t2_ms = 0
t1_ms = 0 'Esto lo hago para impedir que haga las dos lecturas en la misma interrupcion
'lo que convierte t1_ms en 5 tambien pero con un desfase de 2 ms
Endif
If t3_ms >= t3_ms_t Then
Gosub vercurva 'Comprueba que no se haya cambiado la curva
If cn <> ca Then Gosub leermemoria
t3_ms = 0
Endif
'next i 'Bucle para pruebas
Goto loop
End
'********************************************************
'Deteccion de la curva a leer
vercurva:
'Ver curva nueva
cn = 0
If PORTA.4 = 1 Then cn = cn + 1
If PORTA.3 = 1 Then cn = cn + 2
If PORTA.2 = 1 Then cn = cn + 4
If PORTA.5 = 1 Then cn = cn + 8
Return
leermemoria:
'Leer valores Guardados segun la curva a leer
ai = LookUp(0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240), cn 'Posicion inicial de memoria donde leer
af = LookUp(14, 30, 46, 62, 78, 94, 110, 126, 142, 158, 174, 190, 206, 222, 238, 254), cn 'Posicion final de memoria donde leer
For a = ai To af
b = a - ai
Read a, duty(b)
curva(b) = duty(b)
Next a
'Genera los valores para las modificaciones de curvas
va(0) = (curva(10) - curva(4)) / 5 'Calculo maxima modificacion
va(1) = va(0) * 2 '(va(0) * 10) / 5 es el valor de correccion del 100 % multiplicado por 10
va(2) = va(0) '(va(0) * 10) / (2 * 5) es el valor de correccion del 50 % multiplicado por 10
va(3) = (va(0) * 10) / 15 '(va(0) * 10) / (3 * 5) es el valor de correccion del 30 % multiplicado por 10
ca = cn
Return
'*************************************************************
'Ajuste fino de la curva grabada
'Rutina para modificar el centro de la curva
modificarcurva:
Select Case mcn
Case < 22 'P -5
mc(0) = ((va(3) * 5) / 10)
mc(1) = ((va(1) * 5) / 10)
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
Return
Case < 44 'P -4
mc(0) = ((va(3) * 4) / 10)
mc(1) = ((va(1) * 4) / 10)
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
Return
Case < 66 'P -3
mc(0) = ((va(3) * 3) / 10)
mc(1) = ((va(1) * 3) / 10)
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
Return
Case < 88 'P -2
mc(0) = ((va(3) * 2) / 10)
mc(1) = ((va(1) * 2) / 10)
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
Return
Case < 110 'P -1
mc(0) = va(3) / 10
mc(1) = va(1) / 10
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
Return
Case < 145 'P 0
duty(5) = curva(5)
duty(6) = curva(6)
duty(7) = curva(7)
duty(8) = curva(8)
duty(9) = curva(9)
mca = mcn
Return
Case < 165 'P +1
mc(0) = va(3) / 10
mc(1) = va(2) / 10
mc(2) = va(1) / 10
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
Return
Case < 185 'P +2
mc(0) = ((va(3) * 2) / 10)
mc(1) = ((va(2) * 2) / 10)
mc(2) = ((va(1) * 2) / 10)
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
Return
Case < 205 'P +3
mc(0) = ((va(3) * 3) / 10)
mc(1) = ((va(2) * 3) / 10)
mc(2) = ((va(1) * 3) / 10)
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
Return
Case < 230 'P +4
mc(0) = ((va(3) * 4) / 10)
mc(1) = ((va(2) * 4) / 10)
mc(2) = ((va(1) * 4) / 10)
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
Return
Case <= 255 'P +5
mc(0) = ((va(3) * 5) / 10)
mc(1) = ((va(2) * 5) / 10)
mc(2) = ((va(1) * 5) / 10)
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
Return
EndSelect
Return
'*****************************************************************
'Ajuste del control de arrancada
modificararranque:
Select Case asn
Case < 25 'P 1
duty(0) = curva(0)
duty(1) = curva(1)
duty(2) = curva(2)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 50 'P 2
duty(0) = curva(0) + (((curva(1) - curva(0)) * 50) / 100)
duty(1) = curva(1)
duty(2) = curva(2)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 75 'P 3
duty(0) = curva(1)
duty(1) = curva(1) + (((curva(2) - curva(1)) * 40) / 100)
duty(2) = curva(2)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 100 'P 4
duty(0) = curva(1) + (((curva(2) - curva(1)) * 40) / 100)
duty(1) = curva(1) + (((curva(2) - curva(1)) * 80) / 100)
duty(2) = curva(2)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 125 'P 5
duty(0) = curva(1) + (((curva(2) - curva(1)) * 80) / 100)
duty(1) = curva(2)
duty(2) = curva(2) + (((curva(3) - curva(2)) * 40) / 100)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 150 'P 6
duty(0) = curva(2)
duty(1) = curva(2) + (((curva(3) - curva(2)) * 40) / 100)
duty(2) = curva(2) + (((curva(3) - curva(2)) * 80) / 100)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
Return
Case < 175 'P 7
duty(0) = curva(2) + (((curva(3) - curva(2)) * 40) / 100)
duty(1) = curva(2) + (((curva(3) - curva(2)) * 80) / 100)
duty(2) = curva(3)
duty(3) = curva(3) + (((curva(4) - curva(3)) * 40) / 100)
duty(4) = curva(4)
asa = asn
Return
Case < 200 'p 8
duty(0) = curva(2) + (((curva(3) - curva(2)) * 80) / 100)
duty(1) = curva(3)
duty(2) = curva(3) + (((curva(4) - curva(3)) * 40) / 100)
duty(3) = curva(3) + (((curva(4) - curva(3)) * 80) / 100)
duty(4) = curva(4)
asa = asn
Return
Case < 225 'P 9
duty(0) = curva(3)
duty(1) = curva(3) + (((curva(4) - curva(3)) * 40) / 100)
duty(2) = curva(3) + (((curva(4) - curva(3)) * 80) / 100)
duty(3) = curva(4)
duty(4) = curva(4) + (((curva(5) - curva(4)) * 40) / 100)
asa = asn
Return
Case <= 255 'P 10
duty(0) = curva(3) + (((curva(4) - curva(3)) * 40) / 100)
duty(1) = curva(3) + (((curva(4) - curva(3)) * 80) / 100)
duty(2) = curva(4)
duty(3) = curva(4) + (((curva(5) - curva(4)) * 40) / 100)
duty(4) = curva(4) + (((curva(5) - curva(4)) * 80) / 100)
asa = asn
Return
EndSelect
Return
'----------------------- Interrupciones ------------------------------------------
On Interrupt
Save System
If PIR1.TMR1IF = 1 Then
If t1_ms < t1_ms_t Then t1_ms = t1_ms + 1
If t2_ms < t2_ms_t Then t2_ms = t2_ms + 1
If t3_ms < t3_ms_t Then t3_ms = t3_ms + 1
Endif
TMR1H = 0xf8 'Carga el registro del contador para que desborde cada 1 msg. byte alto 248 x 256
TMR1L = 0x30 'Carga el registro del contador para que desborde cada 1 msg. byte bajo + 48
PIR1.TMR1IF = 0 'Borra el flag del salto del tmr1
Resume
De todas formas hay varias mejoras posibles en el programa actual, utilizas las interrupciones para generar bases de tiempos pero también puedes aprovecharlas para hacer la lectura del ADC, con lo que ganas otra vez tiempo y puede que algún cambio más.
'VERSION: 1.0
'MICRO: PIC16f88A
'DESCRIPCION: MUESTRA EN EL DISPLAY EL SENTIDO DE GIRO DE UN ENCODER INCREMENTANDO O DISMINUYENDO EL VALOR
'***************************************************************************************************
'-------------------------------------Puertos del LCD-----------------------------------------------
Define LCD_BITS = 4 'indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA 'el bus de datos sera el puerto A
Define LCD_DBIT = 0 'el bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'el bit de control RS sera del puerto B
Define LCD_RSBIT = 7 'se usara el RB7 como RS
Define LCD_EREG = PORTB 'el bit de control E sera del puerto B
Define LCD_EBIT = 6 'se usara el RB6 como E
'Define LCD_RWREG = PORTx 'el bit de control RW sera del puerto x(no se usa)
'Define LCD_RWBIT = n 'se usara el Rxn como RW (no se usa)
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comand del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera despues de inicializar el Display, solo se ejecuta una vez en mSeg.
'***********************************DEFINICION DE VARIABLES**************************************
'--------------------------------------Variables Programa----------------------------------------
Dim pos As Long 'guarda el estado de la tecla hasta terminar la maniobra
Dim a As Bit 'guarda el estado del canal A
Dim b As Bit 'guarda el estado del canal B
Dim av As Bit 'guarda el estado anterior del canal A
Dim bv As Bit 'guarda el estado anterior del canal B
Dim dpos As Long 'Dato de presentacion de Pos
'------------------------------------------ASIGNACIONES------------------------------------------
pos = 0
a = 0
b = 0
av = 0
bv = 0
'**************************************DEFINICION DE PUERTOS*************************************
'----------------------ASIGNACION DE I/O y valores de inicio de las salidas---------------------
ANSEL = %00000000 'los pin I/O digitales
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
TRISA.6 = 1 'como entrada (RA6, Canal B Encoder)
TRISA.5 = 1 'como entrada (RA5, Canal A Encoder)
PORTB.3 = 1 'luz lcd a on (RB3)
PORTA.7 = 1 'led amarillo a off
PORTB.0 = 1 'led verde a off
'**************************************Inicio Programa*********************************************
Lcdinit 'inicializa el lcd sin cursor
WaitMs 1000 'espera 1Seg
Lcdout "16f88_LCD_I/O" 'escribe en el lcd
Lcdcmdout LcdLine2Home 'seleciona la linea dos como proxima para escritura
Lcdout "Pruebas Encoder" 'escribe en el lcd
WaitMs 3000 'espera 3Seg
'--------------------------------------Main Programa-----------------------------------------------
main:
av = a
bv = b
a = PORTA.5
b = PORTA.6
WaitMs 1
If a = av Then Goto chequearb
If a = 1 And av = 0 Then Goto chequearb1
decremento:
If pos = 0 Then Goto lcd
pos = pos - 1
Goto lcd
chequearb1:
b = PORTA.6
If b = 1 Then Goto incremento
Goto decremento
chequearb:
b = PORTA.6
If b = bv Then Goto lcd
If b = 1 And bv = 0 Then Goto chequeara
If a = 1 Then Goto incremento
Goto decremento
chequeara:
a = PORTA.5
If a = 1 Then Goto incremento
Goto decremento
incremento:
If pos = 255 Then Goto lcd
pos = pos + 1
Goto lcd
lcd:
Gosub print_lcd 'salto con retorno, rutina que imprime los valores en el lcd
WaitMs 100
Goto main
End
'--------------------------------------FIN DEL MAIN---------------------------------------------
'**************************************Subrrutinas**********************************************
print_lcd: '____________________muestra los datos por el display
Lcdcmdout LcdLine1Clear 'borra la primera linea y cursor al principio
If pos >= 128 Then
dpos = pos - 128
Lcdout " Valor= ", #dpos 'imprime los valores positivos en el lcd
End If
If pos < 128 Then
dpos = 128 - pos
Lcdout " Valor= -", #dpos 'imprime los valores negativos en el lcd
End If
Lcdcmdout LcdLine2Clear 'borra la segunda linea y cursor al principio
Lcdout "----------------" 'muestra los datos en el lcd
Return
Hola de nuevo
Una pregunta: ¿se puede hacer un reset por software para borrar todas las variables y volver a empezar?, ¿o es mejor poner un pulsador externo y cortar la alimentacion para hacer el reset?. Pues si yo desconecto el mando y lo vuelvo a conectar si que me acepta los cambios del potenciometro
Sal U2
NOTA: He editado el mesaje y eliminado el programa, pues he encontrado bastantes errores y cuando los tenga arreglados lo volvere a colgar, pues con los errores solucionados sigue dando los mimos errores que comentaba
Hola nuevamente,
acá les posteo el esquema del circuito correspondiente al post #558.
Los materiales que use fueron
R1,R2,R3,R4 1KOhm
R5 6.8KOhm
POT 10KOhm
C1 100uF
C2 0.01uF
CI SOCALO DIP 8
(http://img444.imageshack.us/img444/5558/fspcb.th.png) (http://img444.imageshack.us/i/fspcb.png/)
Descarga PCB (http://rapidshare.com/files/292930027/FS_PCB.pdf.html)
slds Hugo
'********************************************************************************
'NOMBRE: 16F88_Function_Timer1_10
'MICRO: PIC16F88, 8Mhz Interno
'DESCRIPCION: Ejemplo Timer por soft.
'FECHA/AUTOR: By COS, 12/09, PSI v7.41
'VERSION: 1.0
'Encendido y apagado de los indicadores luminosos de la EBasic a distina velocidad.
'Se crean 3 bases de tiempos para el control del flujo del progrma.
'Las bases de tiempos se basan en el tmr1.
'********************************************************************************
Define CONF_WORD = 0x2f50 '/*power-up timer = On, brown-out reset = On
Define CONF_WORD_2 = 0x3ffc '*/
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj en Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Hace que se ignoren los tiempos de los WaitMs
'Asignacion de nombres a pin ----------------------------------------------
Symbol led_vd = RB0 'Pin out, led verde
Symbol led_am = RA7 'Pin out, led amarillo
Symbol lcd_dy = RB3 'Pin out, iluminacion desplay
'Declaracion de variables generales----------------------------------------
'Asignacion de valores a las variables-------------------------------------
'Configuracion modulos generales (E/S)-------------------------------------
ANSEL = 0x00 'Los pin I/O digitales
CMCON = 0x07 'Comparador a off
OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'Puerto B como salidas
TRISA.4 = 1 'Como entrada (RA4, adc)
TRISA.6 = 1 'Como entrada (RA6, tecla S1)
TRISA.5 = 1 'Como entrada (RA5, tecla S2)
PORTB.3 = 1 'Luz lcd a on (RB3)
PORTA.7 = 1 'Led amarillo a off (RA7), negado
PORTB.0 = 1 'Led verde a off (RB0), negado
'Interrupciones a ON-------------------------------------------------------
'INTCON.PEIE = 1 'Habilitacion de interrupciones de perifericos
Enable 'INTCON.GIE = 1, Habilita las interrupciones generales
'Inicializacion Fuction, Proc, Variables I/O Function----------------------
Call timer(5, 30, 1, 0x3cb0, 0) '/*Inicializa bases de tiempos
'Timer.1 = 0.5 Seg., Timer.2 = 3 Seg., Timer.3 = 100mSeg. */
'Rutina MAIN---------------------------------------------------------------
main: 'Rutina principal (inicio)
If timer.1 = 1 Then 'Control por timer.1
Toggle led_am 'Invierte el valor del Pin
timer.1 = 0 'Activa el TMR01
Endif
If timer.2 = 1 Then 'Control por tiemer.2
Toggle led_vd 'Invierte el valor del Pin
timer.2 = 0 'Activa el TMR02
Endif
If timer.3 = 1 Then 'Control por timer.3
Toggle lcd_dy 'Invierte el valor del Pin
timer.3 = 0 'Activa el TMR03
Endif
Goto main 'Redirecciona el flujo del programa al inicio
End 'Fin del main
'Nombre: Function3BasesTiemposTMR1.bas
'Función bases de tiempos.
'Los tiempos en pasos de 100mSeg = 0x3cb0.
'Call timer(x, y, z, 0x3cb0, 0), Inicializa bases de tiempos.
'Call timer(x, y, z, 0x3cb0, 1), Llamada normal a la rutina despues incializacion.
'Los flag de los timer son: timer.1, timer.2 y timer.3
'tmr1hl = tiempo desborde timer1, Init = 0 incializa la rutina.
'Hay que incluir el progra las siguietnes lineas:
'Enable 'INTCON.GIE = 1, Hay que recordar insertarlo en el codigo fuente.
'y rutina interrupciones (On interrupt).
Function timer(tmr01_tm As Byte, tmr02_tm As Byte, tmr03_tm As Byte, tmr1hl As Word, init As Byte) As Byte
Dim tmr01 As Byte 'Declaracion de contadores locales
Dim tmr02 As Byte
Dim tmr03 As Byte
TMR1H = tmr1hl.HB '0x3c, carga el byte alto del regis. tiemr1 (100mSeg) a 8Mhz
TMR1L = tmr1hl.LB '0xb0, carga el byte bajo del regis. timer1 (100mSeg) a 8Mhz
If init = 0 Then 'Configuracion del timer1-------------------------------
timer = 0 'Incializa variables
tmr01 = 0
tmr02 = 0
tmr03 = 0
T1CON.TMR1CS = 0 'Bit de seleccion de reloj para el timer1, interno Fosc/4
T1CON.T1CKPS0 = 0 'Bit de seleccion del prescaler para el reloj del timer1
T1CON.T1CKPS1 = 1 'Bit de seleccion del prescaler para el reloj del timer1
INTCON.PEIE = 1 'Habilitacion de interrupciones de perifericos
T1CON.TMR1ON = 1 'Activa el contador del TMR1
PIE1.TMR1IE = 1 'Activa las interrupciones del timer1
Endif
If timer.1 = 0 Then 'Control base tiempos timer.1
tmr01 = tmr01 + 1 'Incrementa el contador
If tmr01 >= tmr01_tm Then 'Comprueba el tope del contaje
timer.1 = 1 'Para el contador e indica que termino
tmr01 = 0 'Prepara un nuevo contaje
Endif
Endif
If timer.2 = 0 Then 'Control base tiempos timer.2
tmr02 = tmr02 + 1 'Incrementa el contador
If tmr02 >= tmr02_tm Then 'Comprueba el tope del contaje
timer.2 = 1 'Para el contador e indica que termino
tmr02 = 0 'Prepara un nuevo contaje
Endif
Endif
If timer.3 = 0 Then 'Control base tiempos timer.3
tmr03 = tmr03 + 1 'Incrementa el contador
If tmr03 >= tmr03_tm Then 'Comprueba el tope del contaje
timer.3 = 1 'Para el contador e indica que termino
tmr03 = 0 'Prepara un nuevo contaje
Endif
Endif
PIR1.TMR1IF = 0 'Borra flag de interrupcion
End Function
'Rutina interrupciones----------------------------------------------
On Interrupt 'Para interrupciones
Save System 'Guarda valores de calculos intermedios del sistema
If PIR1.TMR1IF Then Call timer(5, 10, 1, 0x3cb0, 1) '/*Llama a la funcion de los timer
Resume 'Retorna y activa interrupciones
'********************************************************************************
'NOMBRE: 16F88_Function_Timer1_10_01
'MICRO: PIC16F88, 8Mhz Interno
'DESCRIPCION: Ejemplo Timer por soft.
'FECHA/AUTOR: By COS, 12/09, PSI v7.41
'VERSION: 1.0
'Encendido y apagado de los indicadores luminosos de la EBasic a distina velocidad.
'Se crean 3 bases de tiempos para el control del flujo del progrma.
'Las bases de tiempos se basan en el tmr1.
'********************************************************************************
Define CONF_WORD = 0x2f50 '/*power-up timer = On, brown-out reset = On
Define CONF_WORD_2 = 0x3ffc '*/
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj en Mhz
Include "Function3BasesTiemposTMR1.bas"
'Define SIMULATION_WAITMS_VALUE = 1 'Hace que se ignoren los tiempos de los WaitMs
'Asignacion de nombres a pin ----------------------------------------------
Symbol led_vd = RB0 'Pin out, led verde
Symbol led_am = RA7 'Pin out, led amarillo
Symbol lcd_dy = RB3 'Pin out, iluminacion desplay
'Declaracion de variables generales ---------------------------------------
'Asignacion de valores a las variables -------------------------------------
'Configuracion modulos generales (E/S) ----------------------------------
ANSEL = 0x00 'Los pin I/O digitales
CMCON = 0x07 'Comparador a off
OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'Puerto B como salidas
TRISA.4 = 1 'Como entrada (RA4, adc)
TRISA.6 = 1 'Como entrada (RA6, tecla S1)
TRISA.5 = 1 'Como entrada (RA5, tecla S2)
PORTB.3 = 1 'Luz lcd a on (RB3)
PORTA.7 = 1 'Led amarillo a off (RA7), negado
PORTB.0 = 1 'Led verde a off (RB0), negado
'Interrupciones a ON --------------------------------------------------------------
'INTCON.PEIE = 1 'Habilitacion de interrupciones de perifericos
Enable 'INTCON.GIE = 1, Habilita las interrupciones generales
'Inicializacion Fuction, Proc, Variables I/O Function ---------------------
Call timer(5, 30, 1, 0x3cb0, 0) '/*Inicializa bases de tiempos
'Timer.1 = 0.5 Seg., Timer.2 = 3 Seg., Timer.3 = 100mSeg. */
'Rutina MAIN -------------------------------------------------------------------------
main: 'Rutina principal (inicio)
If timer.1 = 1 Then 'Control por timer.1
Toggle led_am 'Invierte el valor del Pin
timer.1 = 0 'Activa el TMR01
Endif
If timer.2 = 1 Then 'Control por tiemer.2
Toggle led_vd 'Invierte el valor del Pin
timer.2 = 0 'Activa el TMR02
Endif
If timer.3 = 1 Then 'Control por timer.3
Toggle lcd_dy 'Invierte el valor del Pin
timer.3 = 0 'Activa el TMR03
Endif
Goto main 'Redirecciona el flujo del programa al inicio
End 'Fin del main
End Function
'Rutina interrupciones----------------------------------------------
On Interrupt 'Para interrupciones
Save System 'Guarda valores de calculos intermedios del sistema
If PIR1.TMR1IF Then Call timer(5, 10, 1, 0x3cb0, 1) '/*Llama a la funcion de los timer
Resume 'Retorna y activa interrupciones
Perdón si soy insistente.
Por ejemplo si estoy utilizando un pic 16F876 y quiero utlizar el puerto A solo con 3 entradas analogicas y el resto con señales digitales basta con configutar el registro ADCON1 con el valor= xxxx0100. Doy por descontado que el registro TRIS A lo configuro como entrada.
Entonces si quiero realizar la lectura de esas patillas me imagino que la secuencia sería: primero se realizaria la conversion de una, se guarda el valor de la conversion, se realiza la convesión de la segunda - se guardaria su valor y asi sucesivamente.
Despues de realizar esta operación ¿no es necesario reconfigurar el puerto A como entrada digital si quiero leer una entrada (digital) en el resto de pines configurados como entradas digitales? Lo pregunto por que en algun sitio leí(seguro que lo hice mal pues mi ingles es muy malo) que cuando se realiza la lectura del puerto a como emtrada analogica se configura todo el como analogico.
Es que si miro en el datasheet indica que si se puede.
AllDigital 'Todos los puertos digitales
'---------- CONFIGURACION PINES LCD ----------
Define LCD_BITS = 4 'Bus de datos de 4 bits
Define LCD_DREG = PORTB 'Bus de datos puerto B
Define LCD_DBIT = 0 'Bus de datos, los 4 menos significativos
Define LCD_RSREG = PORTB 'Puerto del RS
Define LCD_RSBIT = 4 'Bit del RS
Define LCD_EREG = PORTB 'Puerto del E
Define LCD_EBIT = 5 'Bit del E
Define LCD_RWREG = PORTB 'Puerto del RW
Define LCD_RWBIT = 6 'Bit del RW
Define LCD_COMMANDUS = 100 'Tiempo de espera despues de un comand
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato
Define LCD_INITMS = 10 'Tiempo de espera despues de inicializar
'----------CONFIGURACION I2C----------
Symbol sda = PORTA.0 'bit conexien SDA
Symbol scl = PORTA.1 'bit conexien SCL
'---------- VARIABLES----------
Dim bb As Byte 'Byte para enviar al sintonizador (VHF en banda alta)
Dim adbw As Byte 'Byte de direccien del sintonizador
Dim cb As Byte 'Byte de control del sintonizador (pasos de 50 Khz)
Symbol mas = PORTA.2 'Bit para subir frecuencia y memorias
Symbol menos = PORTA.3 'Bit para bajar frecuencia y memorias
Symbol mem = PORTA.4 'Bit para memorizar
Symbol conmu = PORTA.5 'Bit para conmutar entre oscilador y memorias
Dim modo As Bit 'Variable para conmutar entre oscilador y memoria
Dim divider As Word 'Frecuencia a cargar en el oscilador local del sintonizador
Dim frec As Long 'Frecuencia que se muestra en el LCD
Dim aux_frec As Long 'Variables auxiliares
Dim frec1 As Word 'para calcular la frecuencia
Dim frec2 As Word 'Gracias a dogflu66, el Lcdout #, no admite un Long
Dim memo As Byte 'Variable para cargar el numero de memoria
'----------CONFIGURACION DE INICIO----------
bb = 2 'VHF en banda alta
adbw = 194 'Dirección del sintonizador
cb = 200 'Pasos de 50Khz
Read 126, divider.HB 'He cogido los dos ultimos bytes de la memoria
Read 127, divider.LB 'del micro para guardar frecuencia
memo = 1 'Comienzo en 1
modo = 0 'Comienzo en oscilador
Lcdinit 'inicializa el lcd sin cursor
'----------INICIO DEL PROGRAMA----------
inicio:
If conmu = 1 Then Toggle modo 'Si se pulsa conmuto entre oscilador y memoria
If modo = 0 Then 'Si esta a cero
Goto oscilador 'Voy a oscilador
Else 'si no
Goto memoria 'voy a memoria
Endif
'---------- MODO OSCILADOR ----------
oscilador:
Lcdcmdout LcdLine2Pos(13)
Lcdout " VFO" 'Muestro en LCD que estoy en modo oscilador
If mem = 1 Then Gosub guardar 'Si se pulsa mem guardo en memoria la frecuencia
If mas = 1 Then divider = divider + 1 'Si se pulsa subo frecuencia
If divider > 8248 Then divider = 3580 'Si llego a tope vuelvo al principio
If menos = 1 Then divider = divider - 1 'Si se pulsa bajamos la frecuencia
If divider < 3580 Then divider = 8248 'Si llego al primcipio salto al final
Write 126, divider.HB 'Guardo la frecuencia en los dos
Write 127, divider.LB 'ultimos bytes de la ram
Gosub sintonizador 'Mando la frecuencia al sintonizador
Gosub display 'La muestro en el LCD
Goto inicio 'Comienzo de nuevo
'---------- MODO MEMORIA ----------
memoria:
Lcdcmdout LcdLine2Pos(13)
Lcdout "M: " 'Muestro en LCD que estoy en modo Memoria
Lcdcmdout LcdLine2Pos(13)
Lcdout "M:" #memo 'Y y el numero de memoria que voy a leer
If mas = 1 Then memo = memo + 1 'Si se pulsa subo memoria
If memo > 62 Then memo = 1 'Si llega a tope vuelvo al principio
If menos = 1 Then memo = memo - 1 'Si se pulsa bajo memoria
If memo < 1 Then memo = 62 'Si llega al principio vuelvo al final
memo = memo * 2 'Calculo la posicion
memo = memo - 1 'de la memoria ram
Read memo, divider.HB 'Leo el primer byte
memo = memo + 1 'calculo posicion del segundo byte
Read memo, divider.LB 'Lo leo
memo = memo / 2 'Dejo el numero de memoria como estaba
Lcdcmdout LcdLine2Pos(13)
Lcdout "M:" #memo 'Muestro numero de memoria
Gosub sintonizador 'Mando frecuencia obtenida al sintonizador
Gosub display 'La muestro en el LCD
Goto inicio 'Comienzo de nuevo
End
'---------- RUTINA PARA ENVIAR FRECUENCIA A SINTONIZADOR----------
sintonizador:
I2CPrepare sda, scl 'Preparamos el bus I2C
I2CStart 'Lo abrimos
I2CSend adbw 'Mandamos direccion del sintonizador
I2CSend divider.HB 'Mandamos el primer byte de frecuencia
I2CSend divider.LB 'Mandamos el segundo byte
I2CSend cb 'Mandamos byte de control
I2CSend bb 'Mandamos Banda
I2CStop 'Cerramos bus
Return
'---------- RUTINA PARA MOSTRAR FRECUENCIA ----------
display:
Lcdcmdout LcdLine1Home
Lcdout "FRECUENCIA"
frec = divider * 50 'Multiplicamos divider por 50 para obtener la frecuencia
frec = frec - 38900 'Restamos el oscilador local
aux_frec = frec / 1000 'Dividimos frecuencia entre 1000 para obtener
frec1 = aux_frec 'los tres primeros digitos
aux_frec = aux_frec * 1000 'Restamos a frecuencia el valor obtenido
frec2 = frec - aux_frec 'para obtener los siguientes tres digitos
Lcdcmdout LcdLine2Home 'Mostramos el valor obtenido
Select Case frec2 'Esta secuencia es para poner los ceros que faltan
Case < 49 'en los tres ultimos digitos
Lcdout #frec1, "000", "khz" 'Si no lo hago asi, el LCD no muestra nada
Case < 99 'mas que un cero no los tres que se necesitan
Lcdout #frec1, "0", #frec2, "khz"
Case > 99
Lcdout #frec1, #frec2, "Khz"
EndSelect
Return
'---------- RUTINA PARA GUARDAR MEMORIA ----------
guardar:
Lcdcmdout LcdLine2Pos(13)
Lcdout "M: " 'Limpio el numero de la memoria
Lcdcmdout LcdLine2Pos(13)
Lcdout "M:" #memo 'Lo muestro
If mas = 1 Then memo = memo + 1 'Si pulsamos sube memoria
If memo > 62 Then memo = 1 'Si llego a tope paso a 1
If menos = 1 Then memo = memo - 1 'Si pulsamos bsja memoria
If memo < 1 Then memo = 62 'Si retrocedo paso a la ultima
If mem = 0 Then Goto guardar 'Titila si no pulsamos guardar
memo = memo * 2 'Calculo la posicion
memo = memo - 1 'en la memoria ram
Write memo, divider.HB 'Escribo el primer byte
memo = memo + 1 'Calculo posicion del segundo byte
Write memo, divider.LB 'lo escribo
memo = memo / 2 'Dejo el numero como estaba
Lcdcmdout LcdLine2Pos(13)
Lcdout "M:" #memo 'Muestro numero de memoria en el LCD
Return
He tenido que retocar la rutina para mostrar en el LCD, he hecho dos grupos de 3 ( sólo necesito 6 digitos ) y al mostrar el segundo grupo se comía los ceros.
'****************************************************************************************
'NOMBRE: 16F88_PicEBasic_JugandoConBit_10
'MICRO: PIC16F88/8Mhz reloj interno
'Versión: 1.0, By COS, 2/10.
'Rutina que extrae el bit o bit´s seleccionados y consecutivos de una variable
'Uso del LCD con bus de datos a 4Bit y sin pin de RW
'****************************************************************************************
Define CONF_WORD = 0x2f10
Define CONF_WORD_2 = 0x3ffc
Define CLOCK_FREQUENCY = 8
'Define SIMULATION_WAITMS_VALUE = 1 'Solo para simulación, acelera las pausas WaitMs
'-------------------------------------Puertos del LCD---------------------------------------------
Define LCD_BITS = 4 'indicamos que el bus de datos del LCD será de 4bit
Define LCD_DREG = PORTA 'el bus de datos será el puerto A
Define LCD_DBIT = 0 'el bus de datos serán los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'el bit de control RS será del puerto B
Define LCD_RSBIT = 7 'se usara el RB7 como RS
Define LCD_EREG = PORTB 'el bit de control E será del puerto B
Define LCD_EBIT = 6 'se usara el RB6 como E
Define LCD_COMMANDUS = 2000 'Tiempo de espera después de ejecutar un comando del LCD en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera después de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 5 '(50) 'Tiempo de espera después de inicializar el Display, solo se ejecuta una vez en mSeg., trucado para simulación
'------------------------------------Definición de puertos------------------------------------------
ANSEL = 0x00 'los pin I/O digitales (no analógicos)
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
CMCON = 0x07 'comparador a off
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
'------------------------------------Inicio------------------------------------------------------------
Dim valor As Word
valor = %1100000000001101
Lcdinit 'inicializa el LCD sin cursor
WaitMs 500 'pausa para estabilizar
main: 'Inicio bucle principal
Call getbit(%00001101, 0, 1) 'Extrae el bit 1
Lcdcmdout LcdLine1Home 'Principio de línea 1
Lcdout #getbit, " " 'Imprime en decimal
Call getbit(valor, 15, 14) 'Extrae los bit´s 14 y 15
Lcdcmdout LcdLine2Home 'Principio de línea dos
Lcdout #getbit, " " 'Imprime bit en decimal
'Goto main
End
'Extrae los bit indicados hasta 16bit
'numero = constante o variable a extraer los bits
'inibit = constante o variable que indica el límite del bit más significativo
'endbit = constante o variable que indica el bit menos significativo
'Para extraer un solo bit entonces inibit = endbit o inibit = 0.
Function getbit(numero As Word, inibit As Byte, endbit As Byte) As Word
If inibit < endbit Then inibit = endbit 'Se asegura que inibit >= endbit
inibit = 15 - inibit 'Numero de lugares a desplazar hacia la izquierda
endbit = inibit + endbit 'Numero de lugares a desplazar a la derecha
numero = ShiftLeft(numero, inibit) 'Elimina los bit de más peso
getbit = ShiftRight(numero, endbit) 'Elimina los bit de menos peso
End Function
'**********************************************************************
'NOMBRE: 16F88_PicEBasic_JugandoConBit_11
'MICRO: PIC16F88/8Mhz reloj interno
'Versión: 1.1, By COS, 2/10, 3/10, PSI v6.83
'Imprime por el lcd en formato binario
'Rutina que extrae el bit o bits seleccionados y consecutivos de una variable
'Uso del LCD con bus de datos a 4Bit y sin pin de RW
'***********************************************************************
Define CONF_WORD = 0x2f10
Define CONF_WORD_2 = 0x3ffc
Define CLOCK_FREQUENCY = 8
'-------------------------------------Puertos del LCD---------------------------------------------
Define LCD_BITS = 4 'indicamos que el bus de datos del LCD será de 4bit
Define LCD_DREG = PORTA 'el bus de datos será el puerto A
Define LCD_DBIT = 0 'el bus de datos serán los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'el bit de control RS será del puerto B
Define LCD_RSBIT = 7 'se usara el RB7 como RS
Define LCD_EREG = PORTB 'el bit de control E será del puerto B
Define LCD_EBIT = 6 'se usara el RB6 como E
Define LCD_COMMANDUS = 2000 'Tiempo de espera después de ejecutar un comando del LCD en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera después de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera después de inicializar el Display, solo se ejecuta una vez en mSeg., trucado para simulación
'------------------------------------------------------------------------------------------------------
'Define SIMULATION_WAITMS_VALUE = 1 'Acelera los Waitms, solo activar esta línea en simulación
'------------------------------------Definición de puertos------------------------------------------
ANSEL = 0x00 'los pin I/O digitales (no analógicos)
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
CMCON = 0x07 'comparador a off
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
'------------------------------------Inicio------------------------------------------------------------
Dim valor As Word
Dim n As Byte
valor = %1100000000001101
Lcdinit 'inicializa el LCD sin cursor
WaitMs 500 'pausa para estabilizar
main: 'Inicio bucle principal
Lcdcmdout LcdLine1Home 'Principio de línea 1
Lcdout #valor, " " 'Imprime en decimal
Lcdcmdout LcdLine2Home 'Principio de línea dos, print bit
For n = 15 To 0 Step -1 'Contador para seleccionar bit
Call getbit(valor, 0, n) 'Extrae los bit n
Lcdout #getbit 'Imprime bit
Next n
'Goto main
End
'Extrae los bit indicados hasta 16bit
'numero = constante o variable a extraer los dígitos
'inibit = constante o variable que indica el límite del bit más significativo
'endbit = constante o variable que indica el bit menos significativo
'Para extraer un solo bit entonces inibit = endbit o inibit = 0.
Function getbit(numero As Word, inibit As Byte, endbit As Byte) As Word
If inibit < endbit Then inibit = endbit 'Se asegura que inibit >= endbit
inibit = 15 - inibit 'Numero de lugares a desplazar hacia la izquierda
endbit = inibit + endbit 'Numero de lugares a desplazar a la derecha
numero = ShiftLeft(numero, inibit) 'Elimina los bit de más peso
getbit = ShiftRight(numero, endbit) 'Elimina los bit de menos peso
End Function
'************************************************************************************************
'NOMBRE: 16F88_PicEBasic_JugandoConBit_12
'MICRO: PIC16F88/8Mhz reloj interno
'Versión: 1.2, By COS, 2/10, 3/10, PSI v6.83
'Codigo BCD decimal codificado en binario
'Extrae un digito determinado de hasta una variable tipo Word
'Los digitos se nombran de derecha a izquierda de 0 a 4.
'************************************************************************************************
Define CONF_WORD = 0x2f10
Define CONF_WORD_2 = 0x3ffc
Define CLOCK_FREQUENCY = 8
'-------------------------------------Puertos del LCD---------------------------------------------
Define LCD_BITS = 4 'indicamos que el bus de datos del LCD será de 4bit
Define LCD_DREG = PORTA 'el bus de datos será el puerto A
Define LCD_DBIT = 0 'el bus de datos serán los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'el bit de control RS será del puerto B
Define LCD_RSBIT = 7 'se usara el RB7 como RS
Define LCD_EREG = PORTB 'el bit de control E será del puerto B
Define LCD_EBIT = 6 'se usara el RB6 como E
Define LCD_COMMANDUS = 2000 'Tiempo de espera después de ejecutar un comando del LCD en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera después de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50 'Tiempo de espera después de inicializar el Display, solo se ejecuta una vez en mSeg., trucado para simulación
'------------------------------------------------------------------------------------------------------
'Define SIMULATION_WAITMS_VALUE = 1 'Acelera los Waitms, solo activar esta línea en simulación
'------------------------------------Definición de puertos-------------------------------------
ANSEL = 0x00 'los pin I/O digitales (no analógicos)
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
CMCON = 0x07 'comparador a off
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
'------------------------------------Inicio------------------------------------------------------------
Dim valor As Word
Dim n As Byte
valor = 65300
Lcdinit 'inicializa el LCD sin cursor
WaitMs 500 'pausa para estabilizar
main: 'Inicio bucle principal
Lcdcmdout LcdLine1Home 'Principio de línea 1
Lcdout #valor, " " 'Imprime en decimal
Lcdcmdout LcdLine2Home 'Principio de línea dos, print digito
For n = 4 To 0 Step -1 'Contador para seleccionar digito
Call getbcd(valor, n) 'Extrae digito n
Lcdout #getbcd, "_" 'Imprime digito
Next n
valor = valor + 1 'Inclementa el numero a descomponer
If valor = 0 Then Lcdcmdout LcdClear 'Borra display
WaitMs 100
Goto main
End
'Codigo BCD, decimal codificado en binario
'Extrae el digito indicado, hasta 5 digitos (Word)
'numero = Cifra a descomponer
'digito = Digito a extraer de 0 a 4
Function getbcd(numero As Word, digito As Byte) As Byte
'Descompone el numero a mostrar en digitos
If digito = 4 Then getbcd = numero / 10000 'Calculo decenas de millar
If digito = 3 Then getbcd = (numero Mod 10000) / 1000 'Calculo unidades de millar
If digito = 2 Then getbcd = (numero Mod 1000) / 100 'Calculo centenas
If digito = 1 Then getbcd = (numero Mod 100) / 10 'Calculo decenas
If digito = 0 Then getbcd = numero Mod 10 'Calculo unidades
End Function
'****************************************************************************************
'NOMBRE: 16F88_PicEBasic_JugandoConBit_13
'MICRO: PIC16F88/8Mhz reloj interno
'Versión: 1.3, By COS, 2/10, 3/10, PSI v6.83
'Codigo BCD a cifra decimal
'****************************************************************************************
Define CONF_WORD = 0x2f10
Define CONF_WORD_2 = 0x3ffc
Define CLOCK_FREQUENCY = 8
'Define SIMULATION_WAITMS_VALUE = 1 'Para simulación, acelera los WaitMs
'-------------------------------------Puertos del LCD---------------------------------------------
Define LCD_BITS = 4 'Indicamos que el bus de datos del LCD será de 4bit
Define LCD_DREG = PORTA 'Bus de datos será el puerto A
Define LCD_DBIT = 0 'Bus de datos serán los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'Bit de control RS será del puerto B
Define LCD_RSBIT = 7 'Usara el RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E será del puerto B
Define LCD_EBIT = 6 'Usara el RB6 como E
Define LCD_COMMANDUS = 2000 'Tiempo de espera después de ejecutar un comando del LCD en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera después de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 5 '(50) 'Tiempo de espera después de inicializar el Display, solo se ejecuta una vez en mSeg., trucado para simulación
'------------------------------------Definición de puertos------------------------------------------
ANSEL = 0x00 'los pin I/O digitales (no analógicos)
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
CMCON = 0x07 'comparador a off
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
'------------------------------------Inicio------------------------------------------------------------
Lcdinit 'Inicializa el LCD sin cursor
WaitMs 500 'Pausa para estabilizar
main: 'Inicio bucle principal
Call getdecimal(4, 3, 2, 1, 0) 'Pasa los numeros a una cifra decimal
Lcdcmdout LcdLine1Home 'Principio de línea 1
Lcdout "4-3-2-1-0= ", #getdecimal 'Imprime en decimal
'Goto main
End
'Include "_FunctionGetDecimal.bas"
'Versión: 1.0, By COS, 3/10, PSI v6.83
'Codigo BCD a cifra decimal
'getdecimal = Cifra decimal
'dig_4 al 0 = Digitos BCD
Function getdecimal(dig_4 As Byte, dig_3 As Byte, dig_2 As Byte, dig_1 As Byte, dig_0 As Byte) As Long
'Compone los digitos en una decimal
getdecimal = dig_4 * 10000 'Calculo decenas de millar
getdecimal = getdecimal + (dig_3 * 1000) 'Calculo unidades de millar
getdecimal = getdecimal + (dig_2 * 100) 'Calculo centenas
getdecimal = getdecimal + (dig_1 * 10) 'Calculo decenas
getdecimal = getdecimal + dig_0 'Calculo unidades
End Function
dlcd = 0
Adcin 2, gat
Select Case gat
Case > vgat(63)
dlcd = 0
Case > vgat(62)
dlcd = 1
Case > vgat(61)
dlcd = 2
Case > vgat(60)
dlcd = 3
Case > vgat(59)
dlcd = 4
...
Case > vgat(0)
dlcd = 63
EndSelect
Lcdinit 'Inicializa el lcd sin cursor
WaitMs 500 'Pausa para estabilizar
Lcdcmdout LcdClear 'borra el display
WaitMs 1000 'hace una pausa de 1Seg.
Lcdout "Adc ", #gat, " ", #dlcd 'escribe el caracter "A" en el display
Lcdcmdout LcdLine2Clear 'borra la segunda linea y cursor al principio
WaitMs 1000
Lcdout "P1 ", #vgat(63), " " #vgat(62) 'muestra los dato
WaitMs 1000 'hace una pausa de 1Seg.
REGISTRO 21-3: ADCON2: REGISTRO DE CONTROL A/D 2
BIT 7 BIT 6 BIT 5 BIT 4 BIT 3 BIT 2 BIT 1 BIT 0
ADFM - ACQT2 ACQT1 ACQT0 ADCS2 ADCS1 ADCS0
R/W-0 U-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0
BIT 7 ADFM: Bit selecto del formato A/D del resultado
1 = derecho justificado
0 = izquierdo justificado
BIT 5-3 ACQT2:ACQT0: Bits selectores del tiempo de adquisición
111 = 20 TAD
110 = 16 TAD
101 = 12 TAD
100 = 8 TAD
011 = 6 TAD
010 = 4 TAD
001 = 2 TAD
000 = 0 TAD
(1)
BIT 2-0 ADCS2:ADCS0: Bits selectores del reloj de conversión
111= FRC (reloj A/D derivado del oscilador RC)(1)
110= FOSC/64
101= FOSC/16
100= FOSC/4
011= FRC (reloj A/D derivado del oscilador RC)(1)
010= FOSC/32
001= FOSC/8
000= FOSC/2
Define CLOCK_FREQUENCY = 20
Define CONFIG1L = %00100100 '0x24 %00100100 USBDIV =1 ;CPUDIV1:CPUDIV0 = 00 Postcaler del sistema no se divide ; PLLDIV2:PLLDIV0 =100 Se divide por 5
Define CONFIG1H = %00001100 '0x0c %00001100 IESO=0 ;FCMEN=0; _ _ ;FOC3:FOSC0=1100 Oscilador HS
Define CONFIG2L = %00111110 '0x3e %00111110 VREGEN=1 ;BORV1:BORV0 =11 ; BOREN1:BOREN0=11; PWRTEN= 0
Define CONFIG2H = 0x00
Define CONFIG3L = 0x00
Define CONFIG3H = %10000001 '0x83 %10000011 MCLRE=1;_ _ _ _ ;LPT1OSC= 0 ; PBADEN = 0;CCP2MX= 1 "CCP2 en RC1"
Define CONFIG4L = %10000000 '0x80 %10000000
Define CONFIG4H = 0x00
Define CONFIG5L = 0x0f
Define CONFIG5H = 0xc0
Define CONFIG6L = 0x0f
Define CONFIG6H = 0xe0
Define CONFIG7L = 0x0f
Define CONFIG7H = 0x40
'Configuracion LCD
'-------------------------------------Puertos del LCD---------------------------------------------
Define LCD_BITS = 4 'indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTB 'el bus de datos sera el puerto B
Define LCD_DBIT = 4 'el bus de datos seran los 4 bit mas significativos del puerto B
Define LCD_RSREG = PORTC 'el bit de control RS sera del puerto C
Define LCD_RSBIT = 6 'se usara el RC6 como RS
Define LCD_EREG = PORTC 'el bit de control E sera del puerto C
Define LCD_EBIT = 7 'se usara el RC7 como E
'Define LCD_RWREG = PORTA 'el bit de control RW sera del puerto A (si se suprime el compilador no protesta)
'Define LCD_RWBIT = 5 'se usara el RA5 como RW (si se suprime el compilador no protesta)
Define LCD_COMMANDUS = 2000 'Tiempo de espera despues de ejecutar un comand del lcd en uSeg.
Define LCD_DATAUS = 50 'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 5 '(50) 'Tiempo de espera despues de inicializar el Display, solo se ejecuta una vez en mSeg., trucado para simulacion
'------------------------------------------------------------------------------------------------------
Define SIMULATION_WAITMS_VALUE = 1 'suprime los tiempos de espera Waitms, solo activar esta linea en simulacion
'------------------------------------Definicion de puertos------------------------------------------
AllDigital
ADCON1 = %00001010 'Seleccion de AN0 - AN4
CMCON = 0x07 'comparador a off
TRISA = %00101111 'Puerto A como E/S
TRISB = %00000111 'Puerto B como E/S
TRISC = %00000000 'Puerto C como salidas
Define ADC_CLOCK = 3
Define ADC_SAMPLEUS = 30
'--------------------------------------------------------------------------------------------------
'Variables menus
Dim linea1 As Byte
Dim linea2 As Byte
Dim menu1 As Byte 'Gestion de menus 1
Dim menu2 As Byte 'Gestion de menus 2
Dim boton As Bit
Dim encoder As Byte
'Variables para calculos
Dim va As Word
Dim vi As Byte
Dim valor As Word
Dim j As Byte
Dim e As Byte
Dim g As Byte
Dim h As Byte
Dim b As Byte
Dim ai As Byte
Dim af As Byte
Dim mem As Byte
Dim i As Byte
'------------------Interrupciones-----
RCON.IPEN = 1 'interrupciones con prioridad
INTCON.GIE = 1
INTCON.INT0IE = 1 'activo interrupcion INT0
INTCON3.INT1IE = 1 'activo interrupcion INT1
INTCON3.INT1IP = 1 'activo prioridad INT1
INTCON3.INT2IE = 1 'activo interrupcion int2
INTCON3.INT2IP = 1 'activo prioridad INT2
'------------------------------------------------------------------------------------------------------
PORTA = 0x00
PORTC.1 = 0
PORTC.2 = 0
PORTB.0 = 0
PORTB.1 = 0
PORTB.2 = 0
'------------------------------------Inicio------------------------------------------------------------
Break
Lcdinit 'inicializa el lcd sin cursor
WaitMs 500 'pausa para estabilizar
linea1 = 2
linea2 = 2
Gosub lcd
WaitMs 2000
linea1 = 1
linea2 = 1
Gosub lcd
'----------------------------------------- INICIO DEL MAIN
main:
If encoder = 1 Then linea1 = 4
If encoder = 2 Then linea1 = 5
If boton = 1 Then linea1 = 3
Gosub lcd
encoder = 0
boton = 0
Goto main
End
'**************************************Subrrutinas**********************************************
'_
'Control de interrupciones
On High Interrupt
Save System
PWMduty 1, 0
PWMduty 2, 0
INTCON.GIE = 0 'Desactivo interrupciones
If INTCON.INT0IF = 1 Then encoder = 1
If INTCON3.INT1IF = 1 Then encoder = 2
If INTCON3.INT2IF = 1 Then linea1 = 3
INTCON.INT0IF = 0 'Desactivo flag interrupcion INT0
INTCON3.INT1IF = 0 'Desactivo flag interrupcion INT1
INTCON3.INT2IF = 0 'Desactivo flag interrupcion int2
INTCON3.INT1IP = 1 'activo prioridad INT1
INTCON3.INT2IP = 1 'activo prioridad INT2
RCON.IPEN = 1 'interrupciones con prioridad
INTCON.GIE = 1 'activo interrupcions
Resume
'**************************************Subrrutinas**********************************************
menus: 'Rutina de seleciones y modificacion de parametros
Return
lcd:
Lcdcmdout LcdClear 'borra el display
WaitMs 10 'hace una pausa
Select Case linea1
Case 1
Lcdout "Menu 1"
Case 2
Lcdout "Memu 2"
Case 3
Lcdout "Boton pulsado"
Case 4
Lcdout "Encoder A"
Case 5
Lcdout "Encoder B"
Case > 5
Lcdout "No disponible"
EndSelect
Lcdcmdout LcdLine2Clear 'borra la segunda linea y cursor al principio
WaitMs 10
Select Case linea2
Case 1
Lcdout "Linea 2.1"
Case 2
Lcdout "Linea 2.2"
Case > 3
Lcdout "Linea 3.3"
EndSelect
WaitMs 200
Return
El tema de los voltajes fue lo primero que comprobe.
El ADC son cambios de canal, pero tambien me sucede al pulsar un pulsador que tengo en una entrada digital.
Tambien desconecte el LCD por si consumia mucho.
Filtrado, hay me pierdo , tengo puesto lo siguiente y con el siguiente orden.
Condensador 100 nf
Conden. Elec. 47 uf
Conden. Elec. 47 uf
Conden. Elec. 47 uf
7805
Conden. Elec. 47 uf
Condensador 100 nf
Por otro lado el tema del adc manual ya me funciona. No activaba el ADCON0.ADON
Lo que no acabo de comprender es como configurar ADCS0-2 y ACQT0-2 del registro ADCON2.
Nota: me refiero a los criterios a utilizar en la seleccion de una configuracion u otraCódigo: [Seleccionar]REGISTRO 21-3: ADCON2: REGISTRO DE CONTROL A/D 2
BIT 7 BIT 6 BIT 5 BIT 4 BIT 3 BIT 2 BIT 1 BIT 0
ADFM - ACQT2 ACQT1 ACQT0 ADCS2 ADCS1 ADCS0
R/W-0 U-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0
BIT 7 ADFM: Bit selecto del formato A/D del resultado
1 = derecho justificado
0 = izquierdo justificado
BIT 5-3 ACQT2:ACQT0: Bits selectores del tiempo de adquisición
111 = 20 TAD
110 = 16 TAD
101 = 12 TAD
100 = 8 TAD
011 = 6 TAD
010 = 4 TAD
001 = 2 TAD
000 = 0 TAD
(1)
BIT 2-0 ADCS2:ADCS0: Bits selectores del reloj de conversión
111= FRC (reloj A/D derivado del oscilador RC)(1)
110= FOSC/64
101= FOSC/16
100= FOSC/4
011= FRC (reloj A/D derivado del oscilador RC)(1)
010= FOSC/32
001= FOSC/8
000= FOSC/2
_______________________________________
hola amigos estoy programando el pic12f675 para controlar la potencia de un lampara de 230 v 0% a 100% con un potenciometro que esta conectado a la pata 1 del micro12f675 ...cruce por zero pata2 pata0 conectada al optotriac despues del optotriac tenemos triac entonces jugamos del desparo del traic
Define ADC_CLOCK = 3 'Set clock source (3=rc)
Define ADC_SAMPLEUS = 50 'Set sampling time in uS
TRISIO = %00000110
ADCON0 = 0x0e
TRISIO.1 = 1
TRISIO.2 = 1
TRISIO.0 = 0
Dim t2400 As Word
Const con = 396
Dim adval As Byte
Dim voltatge As Word
Dim angle2 As Word
Dim k As Byte
Symbol triac = GP0
ADCON0.7 = 1
ANSEL = %00000010
CMCON = 7
inici: Adcin 1, adval
voltatge = (adval * 500) / 1023 'Equates to: (adval * 500)/1024
If GP2 = 1 And voltatge = 50 Then
GP0 = 1
Endif
Select Case 32
angle2 = angle2 - 960
If angle2 < 0 Then
angle2 = 0
Endif
Select Case 33
angle2 = angle2 + 960
If angle2 > 9000 Then
angle2 = 9000
Endif
Goto inici
End
'Programa: JEVO33
'Micro: PIC18f2550, cristal externo 20 MHz
'Version: 04
Define CLOCK_FREQUENCY = 20
Define CONFIG1L = %00100100 '0x24 %00100100 USBDIV =1 ;CPUDIV1:CPUDIV0 = 00 Postcaler del sistema no se divide ; PLLDIV2:PLLDIV0 =100 Se divide por 5
Define CONFIG1H = %00001100 '0x0c %00001100 IESO=0 ;FCMEN=0; _ _ ;FOC3:FOSC0=1100 Oscilador HS
Define CONFIG2L = %00111110 '0x3e %00111110 VREGEN=1 ;BORV1:BORV0 =11 ; BOREN1:BOREN0=11; PWRTEN= 0
Define CONFIG2H = 0x00
Define CONFIG3L = 0x00
Define CONFIG3H = %10000001 '0x83 %10000011 MCLRE=1;_ _ _ _ ;LPT1OSC= 0 ; PBADEN = 0;CCP2MX= 1 "CCP2 en RC1"
Define CONFIG4L = %10000000 '0x80 %10000000
Define CONFIG4H = 0x00
Define CONFIG5L = 0x0f
Define CONFIG5H = 0xc0
Define CONFIG6L = 0x0f
Define CONFIG6H = 0xe0
Define CONFIG7L = 0x0f
Define CONFIG7H = 0x40
Hola de nuevo, si a alguien le interesa esta es la configuracion que tengo en un PIC18F2550 a 20Mhz con cristal externoCódigo: [Seleccionar]'Programa: JEVO33
'Micro: PIC18f2550, cristal externo 20 MHz
'Version: 04
Define CLOCK_FREQUENCY = 20
Define CONFIG1L = %00100100 '0x24 %00100100 USBDIV =1 ;CPUDIV1:CPUDIV0 = 00 Postcaler del sistema no se divide ; PLLDIV2:PLLDIV0 =100 Se divide por 5
Define CONFIG1H = %00001100 '0x0c %00001100 IESO=0 ;FCMEN=0; _ _ ;FOC3:FOSC0=1100 Oscilador HS
Define CONFIG2L = %00111110 '0x3e %00111110 VREGEN=1 ;BORV1:BORV0 =11 ; BOREN1:BOREN0=11; PWRTEN= 0
Define CONFIG2H = 0x00
Define CONFIG3L = 0x00
Define CONFIG3H = %10000001 '0x83 %10000011 MCLRE=1;_ _ _ _ ;LPT1OSC= 0 ; PBADEN = 0;CCP2MX= 1 "CCP2 en RC1"
Define CONFIG4L = %10000000 '0x80 %10000000
Define CONFIG4H = 0x00
Define CONFIG5L = 0x0f
Define CONFIG5H = 0xc0
Define CONFIG6L = 0x0f
Define CONFIG6H = 0xe0
Define CONFIG7L = 0x0f
Define CONFIG7H = 0x40
Una pregunta que seguramente sera basica, si tengo un PWM iniciado en un port, ¿puedo poner el port fijo mediante p.e. PWMduty 2, 0 y PORTC.1=1 ?, ¿o tengo que parar primero el PWM ?
Tambien tengo un problemilla con una variable que me va flotando durante toda la ejecucion del programa, he intentado cambiarla de nombre, añadir una mas para que la cargue en una direccion de memoria diferente (a pasado de 0x43 a 0x45 pero me sigue variando), pero con todo y con ello me sigue variando todo el programa, ¿alguna idea?
Saludos
Define SIMULATION_WAITMS_VALUE = 1
Define CONF_WORD = 0x3f72
Define CLOCK_FREQUENCY = 20
AllDigital
Define LCD_BITS = 8
Define LCD_DREG = PORTD
Define LCD_DBIT = 0
Define LCD_RSREG = PORTE
Define LCD_RSBIT = 0
'Define LCD_RWREG = PORTE
'Define LCD_RWBIT = 2
Define LCD_EREG = PORTE
Define LCD_EBIT = 1
Define LCD_READ_BUSY_FLAG = 1
Lcdinit 1
Symbol scl = PORTC.3
Symbol sda = PORTC.4
Dim b As Byte
Dim addr As Word
Dim data As Byte
Dim mask As Byte
Dim index As Byte
For addr = 0 To 25
index = addr
Lcdcmdout LcdClear
mask = LookUp("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), index
data = mask
I2CWrite sda, scl, 0xa0, addr, data
Lcdout "Write To EEPROM"
Lcdcmdout LcdLine2Home
Lcdout "(", #addr, ") = ", #data
WaitMs 500
Next addr
Lcdcmdout LcdClear
Lcdout "Read From EEPROM"
For addr = 0 To 12
I2CRead sda, scl, 0xa0, addr, data
Lcdcmdout LcdLine2Home
b = addr + 1
Lcdcmdout LcdLine2Pos(b)
If data = "A" Then Lcdout "A"
If data = "B" Then Lcdout "B"
If data = "C" Then Lcdout "C"
If data = "D" Then Lcdout "D"
If data = "E" Then Lcdout "E"
If data = "F" Then Lcdout "F"
If data = "G" Then Lcdout "G"
If data = "H" Then Lcdout "H"
If data = "I" Then Lcdout "I"
If data = "J" Then Lcdout "J"
If data = "K" Then Lcdout "K"
If data = "L" Then Lcdout "L"
If data = "M" Then Lcdout "M"
WaitMs 500
Next addr
Lcdcmdout LcdClear
Lcdout "Read From EEPROM"
For addr = 13 To 25
b = addr - 12
I2CRead sda, scl, 0xa0, addr, data
Lcdcmdout LcdLine2Home
Lcdcmdout LcdLine2Pos(b)
If data = "N" Then Lcdout "N"
If data = "O" Then Lcdout "O"
If data = "P" Then Lcdout "P"
If data = "Q" Then Lcdout "Q"
If data = "R" Then Lcdout "R"
If data = "S" Then Lcdout "S"
If data = "T" Then Lcdout "T"
If data = "U" Then Lcdout "U"
If data = "V" Then Lcdout "V"
If data = "W" Then Lcdout "W"
If data = "X" Then Lcdout "X"
If data = "Y" Then Lcdout "Y"
If data = "Z" Then Lcdout "Z"
WaitMs 500
Next addr
End
Define SIMULATION_WAITMS_VALUE = 1
Define CONF_WORD = 0x3f72
Define CLOCK_FREQUENCY = 20
AllDigital
Define LCD_BITS = 8
Define LCD_DREG = PORTD
Define LCD_DBIT = 0
Define LCD_RSREG = PORTE
Define LCD_RSBIT = 0
'Define LCD_RWREG = PORTE
'Define LCD_RWBIT = 2
Define LCD_EREG = PORTE
Define LCD_EBIT = 1
Define LCD_READ_BUSY_FLAG = 1
Lcdinit 1
Symbol scl = PORTC.3
Symbol sda = PORTC.4
Dim b As Byte
Dim addr As Word
Dim data As Byte
Dim mask As Byte
Dim index As Byte
For addr = 0 To 25
index = addr
Lcdcmdout LcdClear
mask = LookUp("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), index
data = mask
I2CWrite sda, scl, 0xa0, addr, data
Lcdout "Write To EEPROM"
Lcdcmdout LcdLine2Home
Lcdout "(", #addr, ") = ", #data
WaitMs 500
Next addr
Lcdcmdout LcdClear
Lcdout "Read From EEPROM"
Lcdcmdout LcdLine2Home
For addr = 0 To 12
I2CRead sda, scl, 0xa0, addr, data
b = addr + 1
'Lcdcmdout LcdLine2Pos(b)
If data = 0x20 Then Lcdout " "
If data = "A" Then Lcdout "A"
If data = "B" Then Lcdout "B"
If data = "C" Then Lcdout "C"
If data = "D" Then Lcdout "D"
If data = "E" Then Lcdout "E"
If data = "F" Then Lcdout "F"
If data = "G" Then Lcdout "G"
If data = "H" Then Lcdout "H"
If data = "I" Then Lcdout "I"
If data = "J" Then Lcdout "J"
If data = "K" Then Lcdout "K"
If data = "L" Then Lcdout "L"
If data = "M" Then Lcdout "M"
WaitMs 500
Next addr
Lcdcmdout LcdClear
Lcdout "Read From EEPROM"
Lcdcmdout LcdLine2Home
For addr = 13 To 25
b = addr - 12
I2CRead sda, scl, 0xa0, addr, data
'Lcdcmdout LcdLine2Pos(b)
If data = "N" Then Lcdout "N"
If data = "O" Then Lcdout "O"
If data = "P" Then Lcdout "P"
If data = "Q" Then Lcdout "Q"
If data = "R" Then Lcdout "R"
If data = "S" Then Lcdout "S"
If data = "T" Then Lcdout "T"
If data = "U" Then Lcdout "U"
If data = "V" Then Lcdout "V"
If data = "W" Then Lcdout "W"
If data = "X" Then Lcdout "X"
If data = "Y" Then Lcdout "Y"
If data = "Z" Then Lcdout "Z"
WaitMs 500
Next addr
End
Define SIMULATION_WAITMS_VALUE = 1
Define CONF_WORD = 0x3f72
Define CLOCK_FREQUENCY = 20
AllDigital
Define LCD_BITS = 8
Define LCD_DREG = PORTD
Define LCD_DBIT = 0
Define LCD_RSREG = PORTE
Define LCD_RSBIT = 0
'Define LCD_RWREG = PORTE
'Define LCD_RWBIT = 2
Define LCD_EREG = PORTE
Define LCD_EBIT = 1
Define LCD_READ_BUSY_FLAG = 1
Lcdinit 1
Symbol scl = PORTC.3
Symbol sda = PORTC.4
Dim b As Byte
Dim addr As Word
Dim data As Byte
Dim mask As Byte
Dim index As Byte
For addr = 0 To 25
index = addr
Lcdcmdout LcdClear
mask = LookUp("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), index
data = mask
I2CWrite sda, scl, 0xa0, addr, data
Lcdout "Write To EEPROM"
Lcdcmdout LcdLine2Home
Lcdout "(", #addr, ") = ", #data
WaitMs 500
Next addr
Lcdcmdout LcdClear
Lcdout "Read From EEPROM"
Lcdcmdout LcdLine2Home
For addr = 0 To 12
I2CRead sda, scl, 0xa0, addr, data
b = addr + 1
'Lcdcmdout LcdLine2Pos(b)
Lcdout data
WaitMs 500
Next addr
Lcdcmdout LcdClear
Lcdout "Read From EEPROM"
Lcdcmdout LcdLine2Home
For addr = 13 To 25
b = addr - 12
I2CRead sda, scl, 0xa0, addr, data
'Lcdcmdout LcdLine2Pos(b)
Lcdout data
WaitMs 500
Next addr
End
Bienvenido Amigo OSS yo tambien soy Tachira-Venezuela... pensé que casi nadie utilizaba este soft por estos lares saludos. me imagino que con la ayuda de nuestro amigo dogflu66 el cual es la Biblia propia del PSI lograste terminar parte del codigo
saludos
Los registros SSPCON y SSPCON2 si me los reconoce, y compilando no me tira errores.Es justo lo que te mencione amigo, aunque me he dado cuenta de que para configurar el modulo SSP en modo I2C esclavo no necesito ese registro.aunque seria bueno lo que mencioné acerca de que se pudiera asignar la direccion del registro a una variable de modo que pudieramos trabajar sin restriccion alguna.
PD. Con el SSPCON1 si me da error.
Consulta:
Alguno de ustedes hizo alguna experiencia con caracteres fuera de la tabla ascii? o un grafico, (aunque sea sencillo), con psi? he visto que en otros idiomas hay referencias de un soft que crea tablas para generar caracteres, pero creo que no iria bien con psi.
Desde ya gracias por adelantado a quien pueda aportar algun dato.
Saludos
Los registros SSPCON y SSPCON2 si me los reconoce, y compilando no me tira errores.Es justo lo que te mencione amigo, aunque me he dado cuenta de que para configurar el modulo SSP en modo I2C esclavo no necesito ese registro.aunque seria bueno lo que mencioné acerca de que se pudiera asignar la direccion del registro a una variable de modo que pudieramos trabajar sin restriccion alguna.
PD. Con el SSPCON1 si me da error.
otra cosa mas he estado navegando y me he topado con MIKROBASIC y me ha llamado la atencion, haz trabajado con este compilador??? se ve muy interesante.
'Ejemplo de programación del sistema de control electrónico de luz y temperatura.
'Versión con pulsador para seleccionar el programa 1,2 o 3'y Pulsador para resetear Max/Min
'-------------------------------------------
'Declaracion de Variables
Dim i As Byte ' Variable tipo Byte multiproposito
Dim j1 As Byte
Dim j2 As Byte
Dim auxw As Word ' Variable tipo Word multiproposito
Dim aux As Word ' Variable tipo Byte multiproposito
Dim text(16) As Byte
Dim tmax As Byte ' Valor de la temperatura Maxima Registrada en el ciclo
Dim tmin As Byte ' Valor de la temperatura Minima Registrada en el ciclo
Dim prog As Byte ' Programa en curso
Dim dias As Byte ' Dias en curso
Dim hora As Byte ' Hora en curso
Dim minu As Byte ' Minuto en curso
Dim segu As Byte ' Minuto en curso
Dim paso As Byte ' Segundos entre lecturas de Temperatura.
Dim pti1(3) As Byte 'Comienzo tiempo 1
Dim pti2(3) As Byte 'comienzo tiempo 2
Dim pte1(3) As Byte 'Temperatura Tiempo 1
Dim pte2(3) As Byte 'Temperatura Tiempo 2
Dim plu1(3) As Byte 'Luces Tiempo 1
Dim plu2(3) As Byte 'Luces Tiempo 2
Dim tiemp As Word 'Tiempo actual: Hora*60+Minutos
Dim aireok As Bit '1 = puedo usar el aire
Dim tiempf0 As Word 'tiempo que hace que prendí el aire
Dim comando As Byte 'Comando a enviar al DS1820
Dim tempe As Word 'Temperatura leida
Dim tempeaux(3) As Byte 'Temperatura auxiliar
Dim tempe1 As Byte 'PArte entera de la temperatura a mostrar
Dim tempe2 As Byte ' Decimales de la tempertatura a mostrar
Dim minua As Word ' minutos que lleva encendido el aire
Dim minu0 As Word ' minutos que lleva apagado el aire
'Valor Inicial de las Variables --------------------------------------------
'tmax = 0 'Valor de la temperatura Maxima Registrada en el ciclo
'tmin = 99 'Valor de la temperatura Minima Registrada en el ciclo
'prog = 1 'Programa en curso
'dias = 0 'Dias en curso
'hora = 0 'Hora en curso
'minu = 0 'Minuto en curso
segu = 0 'Auxiliar, para calcular los minutos
paso = 1 'Segundos entre lecturas de Temperatura.
pti1(1) = 8 'Programa 1, tiempo 1 (Horas)
pti2(1) = 16 'Programa 1, tiempo 2 (Horas)
pte1(1) = 20 'Programa 1, Temperatura Tiempo 1
pte2(1) = 20 'Programa 1, Temperatura Tiempo 2
plu1(1) = 1 'Programa 1, Luces Tiempo 1 (1=ON)
plu2(1) = 0 'Programa 1, Luces Tiempo 2 (1=ON)
pti1(2) = 8 'Programa 2, tiempo 1 (Horas)
pti2(2) = 16 'Programa 2, tiempo 2 (Horas)
pte1(2) = 25 'Programa 2, Temperatura Tiempo 1
pte2(2) = 25 'Programa 2, Temperatura Tiempo 2
plu1(2) = 1 'Programa 2, Luces Tiempo 1 (1=ON)
plu2(2) = 0 'Programa 2, Luces Tiempo 2 (1=ON)
pti1(3) = 8 'Programa 3, tiempo 1 (Horas)
pti2(3) = 16 'Programa 3, tiempo 2 (Horas)
pte1(3) = 20 'Programa 3, Temperatura Tiempo 1
pte2(3) = 30 'Programa 3, Temperatura Tiempo 2
plu1(3) = 1 'Programa 3, Luces Tiempo 1 (1=ON)
plu2(3) = 0 'Programa 3, Luces Tiempo 2 (1=ON)
tiemp = 0 'Tiempo actual: Hora*60+Minutos.
tiempf0 = 0
aireok = 1
minua = 0 'Minutos que lleva encendido el Aire.
'---- Leo los valores de la EEPROM ----
Read 1, prog 'Programa actual
Read 2, dias 'Dias en curso
Read 3, hora 'Hora en curso
Read 4, minu 'Minuto en curso
Read 6, tmax
Read 7, tmin
'Inicializo Puertos
AllDigital
TRISA = %00010000 '0 = salida
TRISB = %11111111 '0 = salida
PORTB = 0 ' PORTB todo en 0
'Declaro los "alias" a usar en el programa:
Symbol ds1820pin = PORTA.4 'Puerto en que se conecta el DS1820
Symbol ds1820rw = TRISA.4 '1=Leer DS1820 / 0=Escribir DS1820
'Estado inicial Reles y Display. -------------------------------------------
Symbol ventilador = PORTA.3
Symbol luz = PORTA.2
Symbol frio = PORTA.0
Symbol calor = PORTA.1
Symbol pprog = PORTB.6
Symbol preset = PORTB.7
ventilador = 0
luz = 0
frio = 0
calor = 0
'Configuro el puerto para el LCD:
Define LCD_BITS = 4
Define LCD_DREG = PORTB
Define LCD_DBIT = 0
Define LCD_RSREG = PORTB
Define LCD_RSBIT = 5
Define LCD_EREG = PORTB
Define LCD_EBIT = 4
Define LCD_RWREG = 0
Define LCD_RWBIT = 0
'Inicializo el LCD
Lcdinit 0 'Cursor apagado
WaitMs 500
Lcdout "Cont. automatico"
Lcdcmdout LcdLine2Home
Lcdout "(www.neoteo.com)"
WaitMs 5000
Lcdcmdout LcdClear
'Veo si es la primera vez que se conecta el aparato, para
'poner la eeprom en cero
If prog = 255 Then
prog = 1
Gosub cambioprog
Endif
'Veo si se pulso la tecla de cambio de programa--------
'Lcdout "P", #prog
For i = 1 To 25
Gosub leopulsadores
WaitMs 40
Next i
'----------------------------------------------------------
'-- CUERPO DEL PROGRAMA
'----------------------------------------------------------
loop:
'Calculo la "hora" actual (cantidad de minutos)--------
tiemp = hora * 60 + minu
'Leo la temperatura del sensor ------------------------
Gosub init1820 'Inicializo el sensor y...
comando = 0xcc '..salteo la ROM.
Gosub write1820
comando = 0x44 'Comienzo la conversion A/D de la temperatura
Gosub write1820
WaitUs 2000 ' Espero a que termine la conversion
Gosub init1820 'Inicializo el sensor y...
comando = 0xcc '..salteo la ROM.
Gosub write1820
comando = 0xbe 'Pido que me envie lo que calculo el sensor...
Gosub write1820
WaitMs 750 ' Espero ...
Gosub read1820 'Me lo devuelve en tempe1 y tempe2
'Actualizo y muestro Tempe1, TMax y TMin --------------
If tmax < tempe1 Then
tmax = tempe1
Write 6, tmax
Endif
If tmin > tempe1 Then
tmin = tempe1
Write 7, tmin
Endif
'Actualizo Hora y Minu , y los muestro ----------------
segu = segu + paso
If segu > 59 Then
minu = minu + 1
Write 4, minu
segu = 0
If minu > 59 Then
minu = 0
hora = hora + 1
Write 3, hora
If hora > 23 Then
dias = dias + 1
Write 2, dias
tiempf0 = 0
hora = 0
Endif
Endif
Endif
'Enciendo/Apago la luz, Aire, etc del programa en curso
auxw = pti1(prog) * 60
If tiemp < auxw Then 'Estoy en la primera parte del dia
'Enciendo/Apago la luz-------------------------------------------
If plu1(prog) = 1 Then
luz = 1
Else
luz = 0
Endif
'Enciendo/Apago fuente de calor----------------------------------
If tempe1 < pte1(prog) Then
calor = 1
'ventilador = 1
Endif
If tempe1 = pte1(prog) Then
calor = 0
'ventilador = 0
Endif
If tempe1 > pte1(prog) Then
calor = 0
'ventilador = 0
Endif
'Enciendo/apago fuente de FRIO ------------------------------------------
If tempe1 > pte1(prog) And aireok = 1 Then 'si hace calor....
frio = 1 '..lo enciendo y
ventilador = 0
Endif
If tempe1 < pte1(prog) Then
frio = 0
ventilador = 1
tiempf0 = tiemp 'Tomo nota de la hora de apagado
aireok = 0
Endif
Else 'Estoy en la segunda parte del dia
'Enciendo/Apago la luz-------------------------------------------
If plu2(prog) = 1 Then
luz = 1
Else
luz = 0
Endif
'Enciendo/Apago fuente de calor----------------------------------
If tempe1 < pte2(prog) Then
calor = 1
'ventilador = 1
Endif
If tempe1 = pte2(prog) Then
calor = 0
'ventilador = 0
Endif
If tempe1 > pte2(prog) Then
calor = 0
'ventilador = 0
Endif
'Enciendo/apago fuente de FRIO ------------------------------------------
If tempe1 > pte2(prog) And aireok = 1 Then 'si hace calor....
frio = 1 '..lo enciendo y
ventilador = 0
Endif
If tempe1 < pte2(prog) Then
frio = 0
ventilador = 1
tiempf0 = tiemp 'Tomo nota de la hora de apagado
aireok = 0
Endif
Endif '---Fin analisis Programa -------
'---------------------------------------------------
'Veo si pasaron 5 minutos de la ultima vez que se
'apago el aire
aux = tiempf0 + 4
If tiemp > aux Then
aireok = 1
Endif
If tiemp > 1438 Then 'casi medianoche
aireok = 1
Endif
'---------------------------------------------------
Lcdcmdout LcdClear
Lcdcmdout LcdLine1Pos(1)
Lcdout "P", #prog, " "
If luz = 1 Then
Lcdcmdout LcdLine1Pos(5)
Lcdout "L"
Endif
If frio = 1 Then
Lcdcmdout LcdLine1Pos(6)
Lcdout "F"
Endif
If calor = 1 Then
Lcdcmdout LcdLine1Pos(6)
Lcdout "C"
Endif
If ventilador = 1 Then
Lcdcmdout LcdLine1Pos(7)
Lcdout "V"
Endif
Lcdcmdout LcdLine1Pos(9)
Lcdout "00:00:00"
If minu > 9 Then
Lcdcmdout LcdLine1Pos(15)
Else
Lcdcmdout LcdLine1Pos(16)
Endif
Lcdout #minu
If hora > 9 Then
Lcdcmdout LcdLine1Pos(12)
Else
Lcdcmdout LcdLine1Pos(13)
Endif
Lcdout #hora
If dias > 9 Then
Lcdcmdout LcdLine1Pos(9)
Else
Lcdcmdout LcdLine1Pos(10)
Endif
Lcdout #dias
'Veo si se movio la llave de cambio de programa--------
Gosub leopulsadores
Lcdcmdout LcdLine2Home
Lcdout "T:", #tempe1, " M:", #tmax, " m:", #tmin, " "
WaitMs 180
Goto loop
End
leopulsadores:
'Veo si se pulso la tecla o es un ruido -------
If pprog = 1 Then
WaitMs 50
If pprog = 1 Then
prog = prog + 1
If prog = 4 Then
prog = 1
Endif
Gosub cambioprog
Endif
Endif
'Veo si se resetearon TMax y TMin
If preset = 1 Then
WaitMs 50
If preset = 1 Then
tmax = 0
tmin = 99
Endif
Lcdcmdout LcdLine2Home
Lcdout "T:", #tempe1, " M:", #tmax, " m:", #tmin, " "
Endif
Return
cambioprog:
'Muestro el programa actual en el display
Lcdcmdout LcdClear
Lcdcmdout LcdLine1Pos(1)
Lcdout "P", #prog
Write 1, prog
tmax = 0 'Valor de la temperatura Maxima Registrada en el ciclo
tmin = 99 'Valor de la temperatura Minima Registrada en el ciclo
Write 6, tmax
Write 7, tmin
dias = 0 'Dias en curso
hora = 0 'Hora en curso
minu = 0 'Minuto en curso
Write 2, dias
Write 3, hora
Write 4, minu
segu = 0 'Auxiliar, para calcular los minutos
tiempf0 = 1
ventilador = 0
luz = 0 'Rele Luces
frio = 0 'Rele Frio
calor = 0 'Rele Calor
Return
'-------------------------------------------------
'Inicializa el DS1820
'-------------------------------------------------
init1820:
ds1820rw = 0 ' Pongo el pin como salida
ds1820pin = 0 'Pongo en cero el pin del DS1820
WaitUs 500 ' Espero mas de 480 us
ds1820rw = 1 ' Pongo el pin como entrada
WaitUs 100 ' Espero mas de 60 us a que "reaccione"
WaitUs 500 ' Espero a que finalice de enviarme el estado
Return
'-------------------------------------------------
'Envia comandos al DS1820
'-------------------------------------------------
write1820:
For aux = 1 To 8 'Recorro los 8 bits de "Comando"
If comando.0 = 0 Then
Gosub write0
Else
Gosub write1
Endif
comando = ShiftRight(comando, 1)
Next aux
Return
'-------------------------------------------------
'Envia un cero al DS1820
'-------------------------------------------------
write0:
ds1820rw = 0 ' Pongo el pin como salida
ds1820pin = 0
WaitUs 60 'hay que mantener bajo el pin mas 60 us
ds1820rw = 1
Return
'-------------------------------------------------
'Envia un uno al DS1820
'-------------------------------------------------
write1:
ds1820rw = 0 ' Pongo el pin como salida
ds1820pin = 0
WaitUs 1 'hay que mantener bajo el pin menos de 15 60 us
ds1820rw = 1
WaitUs 60 'espero el resto del tiempo...
Return
'-------------------------------------------------
'Lee temperatura del DS1820
'-------------------------------------------------
read1820:
For aux = 1 To 16 ' los 16 bits de temp (word)
tempe = ShiftRight(tempe, 1)
Gosub readbit
Next aux
'Calculo la temperatura(tempe1) y las decimas (tempe2)
tempe1 = ShiftRight(tempe.LB, 1)
tempe1 = 128 - tempe1
If tempe.0 = 1 Then
tempe2 = 0
Else
tempe2 = 5
Endif
Return
'-------------------------------------------------
'Lee un bit del DS1820
'-------------------------------------------------
readbit:
tempe.15 = 1
ds1820rw = 0 ' Pongo el pin como salida
ds1820pin = 0
WaitUs 1
ds1820rw = 1
If ds1820pin = 1 Then
tempe.15 = 0
Endif
WaitUs 60
Return
Hola necesio que me ayuden con el siguiente codigo ya que al compilarle con el pic sumulator ide me da los siguientes errores
Line 7: Unused declaration. Not compiled: Dim j1 As Byte
Line 8: Unused declaration. Not compiled: Dim j2 As Byte
Line 11: Unused declaration. Not compiled: Dim text(16) As Byte
Line 35: Unused declaration. Not compiled: Dim tempeaux(3) As Byte 'Temperatura auxiliar
Line 39: Unused declaration. Not compiled: Dim minu0 As Word 'minutos que lleva apagado el aire
espero que me puedan ayudar ya que BASIC no me llevo tan bien. :oops:Código: [Seleccionar]'Ejemplo de programación del sistema de control electrónico de luz y temperatura.
'Versión con pulsador para seleccionar el programa 1,2 o 3'y Pulsador para resetear Max/Min
'-------------------------------------------
'Declaracion de Variables
Dim i As Byte ' Variable tipo Byte multiproposito
Dim j1 As Byte
Dim j2 As Byte
Dim auxw As Word ' Variable tipo Word multiproposito
Dim aux As Word ' Variable tipo Byte multiproposito
Dim text(16) As Byte
Dim tmax As Byte ' Valor de la temperatura Maxima Registrada en el ciclo
Dim tmin As Byte ' Valor de la temperatura Minima Registrada en el ciclo
Dim prog As Byte ' Programa en curso
Dim dias As Byte ' Dias en curso
Dim hora As Byte ' Hora en curso
Dim minu As Byte ' Minuto en curso
Dim segu As Byte ' Minuto en curso
Dim paso As Byte ' Segundos entre lecturas de Temperatura.
Dim pti1(3) As Byte 'Comienzo tiempo 1
Dim pti2(3) As Byte 'comienzo tiempo 2
Dim pte1(3) As Byte 'Temperatura Tiempo 1
Dim pte2(3) As Byte 'Temperatura Tiempo 2
Dim plu1(3) As Byte 'Luces Tiempo 1
Dim plu2(3) As Byte 'Luces Tiempo 2
Dim tiemp As Word 'Tiempo actual: Hora*60+Minutos
Dim aireok As Bit '1 = puedo usar el aire
Dim tiempf0 As Word 'tiempo que hace que prendí el aire
Dim comando As Byte 'Comando a enviar al DS1820
Dim tempe As Word 'Temperatura leida
Dim tempeaux(3) As Byte 'Temperatura auxiliar
Dim tempe1 As Byte 'PArte entera de la temperatura a mostrar
Dim tempe2 As Byte ' Decimales de la tempertatura a mostrar
Dim minua As Word ' minutos que lleva encendido el aire
Dim minu0 As Word ' minutos que lleva apagado el aire
'Valor Inicial de las Variables --------------------------------------------
'tmax = 0 'Valor de la temperatura Maxima Registrada en el ciclo
'tmin = 99 'Valor de la temperatura Minima Registrada en el ciclo
'prog = 1 'Programa en curso
'dias = 0 'Dias en curso
'hora = 0 'Hora en curso
'minu = 0 'Minuto en curso
segu = 0 'Auxiliar, para calcular los minutos
paso = 1 'Segundos entre lecturas de Temperatura.
pti1(1) = 8 'Programa 1, tiempo 1 (Horas)
pti2(1) = 16 'Programa 1, tiempo 2 (Horas)
pte1(1) = 20 'Programa 1, Temperatura Tiempo 1
pte2(1) = 20 'Programa 1, Temperatura Tiempo 2
plu1(1) = 1 'Programa 1, Luces Tiempo 1 (1=ON)
plu2(1) = 0 'Programa 1, Luces Tiempo 2 (1=ON)
pti1(2) = 8 'Programa 2, tiempo 1 (Horas)
pti2(2) = 16 'Programa 2, tiempo 2 (Horas)
pte1(2) = 25 'Programa 2, Temperatura Tiempo 1
pte2(2) = 25 'Programa 2, Temperatura Tiempo 2
plu1(2) = 1 'Programa 2, Luces Tiempo 1 (1=ON)
plu2(2) = 0 'Programa 2, Luces Tiempo 2 (1=ON)
pti1(3) = 8 'Programa 3, tiempo 1 (Horas)
pti2(3) = 16 'Programa 3, tiempo 2 (Horas)
pte1(3) = 20 'Programa 3, Temperatura Tiempo 1
pte2(3) = 30 'Programa 3, Temperatura Tiempo 2
plu1(3) = 1 'Programa 3, Luces Tiempo 1 (1=ON)
plu2(3) = 0 'Programa 3, Luces Tiempo 2 (1=ON)
tiemp = 0 'Tiempo actual: Hora*60+Minutos.
tiempf0 = 0
aireok = 1
minua = 0 'Minutos que lleva encendido el Aire.
'---- Leo los valores de la EEPROM ----
Read 1, prog 'Programa actual
Read 2, dias 'Dias en curso
Read 3, hora 'Hora en curso
Read 4, minu 'Minuto en curso
Read 6, tmax
Read 7, tmin
'Inicializo Puertos
AllDigital
TRISA = %00010000 '0 = salida
TRISB = %11111111 '0 = salida
PORTB = 0 ' PORTB todo en 0
'Declaro los "alias" a usar en el programa:
Symbol ds1820pin = PORTA.4 'Puerto en que se conecta el DS1820
Symbol ds1820rw = TRISA.4 '1=Leer DS1820 / 0=Escribir DS1820
'Estado inicial Reles y Display. -------------------------------------------
Symbol ventilador = PORTA.3
Symbol luz = PORTA.2
Symbol frio = PORTA.0
Symbol calor = PORTA.1
Symbol pprog = PORTB.6
Symbol preset = PORTB.7
ventilador = 0
luz = 0
frio = 0
calor = 0
'Configuro el puerto para el LCD:
Define LCD_BITS = 4
Define LCD_DREG = PORTB
Define LCD_DBIT = 0
Define LCD_RSREG = PORTB
Define LCD_RSBIT = 5
Define LCD_EREG = PORTB
Define LCD_EBIT = 4
Define LCD_RWREG = 0
Define LCD_RWBIT = 0
'Inicializo el LCD
Lcdinit 0 'Cursor apagado
WaitMs 500
Lcdout "Cont. automatico"
Lcdcmdout LcdLine2Home
Lcdout "(www.neoteo.com)"
WaitMs 5000
Lcdcmdout LcdClear
'Veo si es la primera vez que se conecta el aparato, para
'poner la eeprom en cero
If prog = 255 Then
prog = 1
Gosub cambioprog
Endif
'Veo si se pulso la tecla de cambio de programa--------
'Lcdout "P", #prog
For i = 1 To 25
Gosub leopulsadores
WaitMs 40
Next i
'----------------------------------------------------------
'-- CUERPO DEL PROGRAMA
'----------------------------------------------------------
loop:
'Calculo la "hora" actual (cantidad de minutos)--------
tiemp = hora * 60 + minu
'Leo la temperatura del sensor ------------------------
Gosub init1820 'Inicializo el sensor y...
comando = 0xcc '..salteo la ROM.
Gosub write1820
comando = 0x44 'Comienzo la conversion A/D de la temperatura
Gosub write1820
WaitUs 2000 ' Espero a que termine la conversion
Gosub init1820 'Inicializo el sensor y...
comando = 0xcc '..salteo la ROM.
Gosub write1820
comando = 0xbe 'Pido que me envie lo que calculo el sensor...
Gosub write1820
WaitMs 750 ' Espero ...
Gosub read1820 'Me lo devuelve en tempe1 y tempe2
'Actualizo y muestro Tempe1, TMax y TMin --------------
If tmax < tempe1 Then
tmax = tempe1
Write 6, tmax
Endif
If tmin > tempe1 Then
tmin = tempe1
Write 7, tmin
Endif
'Actualizo Hora y Minu , y los muestro ----------------
segu = segu + paso
If segu > 59 Then
minu = minu + 1
Write 4, minu
segu = 0
If minu > 59 Then
minu = 0
hora = hora + 1
Write 3, hora
If hora > 23 Then
dias = dias + 1
Write 2, dias
tiempf0 = 0
hora = 0
Endif
Endif
Endif
'Enciendo/Apago la luz, Aire, etc del programa en curso
auxw = pti1(prog) * 60
If tiemp < auxw Then 'Estoy en la primera parte del dia
'Enciendo/Apago la luz-------------------------------------------
If plu1(prog) = 1 Then
luz = 1
Else
luz = 0
Endif
'Enciendo/Apago fuente de calor----------------------------------
If tempe1 < pte1(prog) Then
calor = 1
'ventilador = 1
Endif
If tempe1 = pte1(prog) Then
calor = 0
'ventilador = 0
Endif
If tempe1 > pte1(prog) Then
calor = 0
'ventilador = 0
Endif
'Enciendo/apago fuente de FRIO ------------------------------------------
If tempe1 > pte1(prog) And aireok = 1 Then 'si hace calor....
frio = 1 '..lo enciendo y
ventilador = 0
Endif
If tempe1 < pte1(prog) Then
frio = 0
ventilador = 1
tiempf0 = tiemp 'Tomo nota de la hora de apagado
aireok = 0
Endif
Else 'Estoy en la segunda parte del dia
'Enciendo/Apago la luz-------------------------------------------
If plu2(prog) = 1 Then
luz = 1
Else
luz = 0
Endif
'Enciendo/Apago fuente de calor----------------------------------
If tempe1 < pte2(prog) Then
calor = 1
'ventilador = 1
Endif
If tempe1 = pte2(prog) Then
calor = 0
'ventilador = 0
Endif
If tempe1 > pte2(prog) Then
calor = 0
'ventilador = 0
Endif
'Enciendo/apago fuente de FRIO ------------------------------------------
If tempe1 > pte2(prog) And aireok = 1 Then 'si hace calor....
frio = 1 '..lo enciendo y
ventilador = 0
Endif
If tempe1 < pte2(prog) Then
frio = 0
ventilador = 1
tiempf0 = tiemp 'Tomo nota de la hora de apagado
aireok = 0
Endif
Endif '---Fin analisis Programa -------
'---------------------------------------------------
'Veo si pasaron 5 minutos de la ultima vez que se
'apago el aire
aux = tiempf0 + 4
If tiemp > aux Then
aireok = 1
Endif
If tiemp > 1438 Then 'casi medianoche
aireok = 1
Endif
'---------------------------------------------------
Lcdcmdout LcdClear
Lcdcmdout LcdLine1Pos(1)
Lcdout "P", #prog, " "
If luz = 1 Then
Lcdcmdout LcdLine1Pos(5)
Lcdout "L"
Endif
If frio = 1 Then
Lcdcmdout LcdLine1Pos(6)
Lcdout "F"
Endif
If calor = 1 Then
Lcdcmdout LcdLine1Pos(6)
Lcdout "C"
Endif
If ventilador = 1 Then
Lcdcmdout LcdLine1Pos(7)
Lcdout "V"
Endif
Lcdcmdout LcdLine1Pos(9)
Lcdout "00:00:00"
If minu > 9 Then
Lcdcmdout LcdLine1Pos(15)
Else
Lcdcmdout LcdLine1Pos(16)
Endif
Lcdout #minu
If hora > 9 Then
Lcdcmdout LcdLine1Pos(12)
Else
Lcdcmdout LcdLine1Pos(13)
Endif
Lcdout #hora
If dias > 9 Then
Lcdcmdout LcdLine1Pos(9)
Else
Lcdcmdout LcdLine1Pos(10)
Endif
Lcdout #dias
'Veo si se movio la llave de cambio de programa--------
Gosub leopulsadores
Lcdcmdout LcdLine2Home
Lcdout "T:", #tempe1, " M:", #tmax, " m:", #tmin, " "
WaitMs 180
Goto loop
End
leopulsadores:
'Veo si se pulso la tecla o es un ruido -------
If pprog = 1 Then
WaitMs 50
If pprog = 1 Then
prog = prog + 1
If prog = 4 Then
prog = 1
Endif
Gosub cambioprog
Endif
Endif
'Veo si se resetearon TMax y TMin
If preset = 1 Then
WaitMs 50
If preset = 1 Then
tmax = 0
tmin = 99
Endif
Lcdcmdout LcdLine2Home
Lcdout "T:", #tempe1, " M:", #tmax, " m:", #tmin, " "
Endif
Return
cambioprog:
'Muestro el programa actual en el display
Lcdcmdout LcdClear
Lcdcmdout LcdLine1Pos(1)
Lcdout "P", #prog
Write 1, prog
tmax = 0 'Valor de la temperatura Maxima Registrada en el ciclo
tmin = 99 'Valor de la temperatura Minima Registrada en el ciclo
Write 6, tmax
Write 7, tmin
dias = 0 'Dias en curso
hora = 0 'Hora en curso
minu = 0 'Minuto en curso
Write 2, dias
Write 3, hora
Write 4, minu
segu = 0 'Auxiliar, para calcular los minutos
tiempf0 = 1
ventilador = 0
luz = 0 'Rele Luces
frio = 0 'Rele Frio
calor = 0 'Rele Calor
Return
'-------------------------------------------------
'Inicializa el DS1820
'-------------------------------------------------
init1820:
ds1820rw = 0 ' Pongo el pin como salida
ds1820pin = 0 'Pongo en cero el pin del DS1820
WaitUs 500 ' Espero mas de 480 us
ds1820rw = 1 ' Pongo el pin como entrada
WaitUs 100 ' Espero mas de 60 us a que "reaccione"
WaitUs 500 ' Espero a que finalice de enviarme el estado
Return
'-------------------------------------------------
'Envia comandos al DS1820
'-------------------------------------------------
write1820:
For aux = 1 To 8 'Recorro los 8 bits de "Comando"
If comando.0 = 0 Then
Gosub write0
Else
Gosub write1
Endif
comando = ShiftRight(comando, 1)
Next aux
Return
'-------------------------------------------------
'Envia un cero al DS1820
'-------------------------------------------------
write0:
ds1820rw = 0 ' Pongo el pin como salida
ds1820pin = 0
WaitUs 60 'hay que mantener bajo el pin mas 60 us
ds1820rw = 1
Return
'-------------------------------------------------
'Envia un uno al DS1820
'-------------------------------------------------
write1:
ds1820rw = 0 ' Pongo el pin como salida
ds1820pin = 0
WaitUs 1 'hay que mantener bajo el pin menos de 15 60 us
ds1820rw = 1
WaitUs 60 'espero el resto del tiempo...
Return
'-------------------------------------------------
'Lee temperatura del DS1820
'-------------------------------------------------
read1820:
For aux = 1 To 16 ' los 16 bits de temp (word)
tempe = ShiftRight(tempe, 1)
Gosub readbit
Next aux
'Calculo la temperatura(tempe1) y las decimas (tempe2)
tempe1 = ShiftRight(tempe.LB, 1)
tempe1 = 128 - tempe1
If tempe.0 = 1 Then
tempe2 = 0
Else
tempe2 = 5
Endif
Return
'-------------------------------------------------
'Lee un bit del DS1820
'-------------------------------------------------
readbit:
tempe.15 = 1
ds1820rw = 0 ' Pongo el pin como salida
ds1820pin = 0
WaitUs 1
ds1820rw = 1
If ds1820pin = 1 Then
tempe.15 = 0
Endif
WaitUs 60
Return
Varias veces me preguntaron si se pueden tener arrays (vectores) de varias dimensiones en el Basic del PSI. Lo que es el lenguaje hasta ahora no lo tiene implementado, pero podemos construirnos una función que nos simule el proceso, no queda tan lucida como una función interna del sistema, ya que necesitamos una variable de paso e indicar si escribiremos o leeremos el array, pero el caso es que la función nos permite trabajar con array de dos dimensiones.
La rutina esta declarada en el ejemplo como array(2,5).Código: Visual Basic
'Rutina para trabajar con array de dos dimensiones (Vectores) 'By dogflu66 '******************************************************************** Dim x As Byte Dim y As Byte Dim n As Byte AllDigital TRISA = 0 TRISB = 0 main: n = 0 For x = 0 To 1 For y = 0 To 4 max = n 'Valor a guardar Call max(x, y, "W") 'Actualiza array n = n + 1 'Valor a guardar Next y Next x Serout RB0, 9600, CrLf 'Linea en blanco For x = 0 To 1 For y = 0 To 4 Call max(x, y, "R") 'Lee array Serout RB0, 9600, "max(", #x, ",", #y, ")=", #max, CrLf 'Imprime valores Next y Next x 'Goto main End 'Rutina para trabajar con arrays de dos dimensiones 'max = variable de paso 'i1 = Primer indice del array 'i2 = Segundo indice del array 'rw = "W" o "w" o 1 => Escribe en array 'rw = "R" o "r" o 0 => Lee del array Function max(i1 As Byte, i2 As Byte, rw As Byte) As Byte Const ind2 = 5 'Valor del indice2 Dim array(10) As Byte 'Se declara vector de longitud Indice1*indice2 Dim ind As Byte 'Indice del vector de trabajo Dim aux As Byte 'Variable auxiliar aux = ind2 - 1 'Valor de ajuste If i1 > 0 Then aux = i1 * aux 'Ajuste si i1>0 If i1 = 0 Then aux = 0 'Ajuste si i1=0 ind = i1 + i2 + aux 'Calcula indice array If rw = "R" Or rw = "r" Or rw = 0 Then max = array(ind) 'Lee array If rw = "W" Or rw = "w" Or rw = 1 Then array(ind) = max 'Escribe array End Function
Dejo la foto de la simulacion:
(http://img820.imageshack.us/img820/6205/arrayenpsi.jpg)
De pesado para nada, lo que ocurre es que algunas veces mis repuestas pueden hacerme parecer seco o muy seco, :x, pero es porque lo mismo estoy con un proceso que me deja 5 o 6 minutos libres en el curro, y contesto rapidamente desde el trabajo. :DSi decia lo de pesado era por la cantidad de preguntas, no por las repuestas ni por la forma de las mismas, ya que siempre me han ayudado mucho.
Equipo de control para un motocompresor. Éste motocompresor dispone en la parte del compresor
de unos presostatos(mínima y máxima) para supervisar la generacion de la presión. Tambien dispone
de un sensor de temperatura para controlar la temperatura del aceite del carter del compresor.
Por otra parte para el control del motor se utiliza el correspondiente contactor trifásico 400V a.c. con
las correspondientes protecciones térmicas.
La tarjeta de control además procesa las señales de puesta en marcha y parada; vigila cuando se produce
una falta de tensión alterna o está fuera de un valor; y la señal de rearme de averías.
El sistema motocompresor también lleva incorporado un sistema para secar el aire generado por el motocompresor.
Ésta opción se vigila también con la tarjeta de control.
No dispone de comunicaciones que se incluirán más adelante.
Saludos y muchas gracias por las ayudas recibidas.'****************************************************************
'* Nombre : 1-wire.bas *
'* Autor : ARM (Tenerife-España) *
'* Fecha : 14/02/2011 *
'* Version : 1.0 *
'* Compilador : Básic del Pic Simulator IDE v. 6.83 *
'* Notas : Este programa lee un dispositivo tipo 1-wire™ *
'* : y muestra la familia, su ID y el CRC grabado *
'* : en la ROM y la muestra en un display LCD32 *
'****************************************************************
'Definición de la conexión del LCD: tipo 2x16, bus de 8 datos a
'través del puerto B, rs en RA0, e en RA1 y r/W en RA2
'----------------------------------------------------------------
Define LCD_LINES = 2 '2 filas
Define LCD_CHARS = 16 '16 columnas
Define LCD_BITS = 8 '4 bits
Define LCD_DREG = RB 'puerto a conectar los 4 bits
Define LCD_RSREG = RA 'puerto para rs
Define LCD_RSBIT = 1 'rb0 a rs
Define LCD_EREG = RA 'puerto para e
Define LCD_EBIT = 2 'rb1 a e
Define LCD_RWREG = RA 'puerto para r/W
Define LCD_RWBIT = 3 'rb2 a r/W
'Define LCD_READ_BUSY_FLAG = 1
'Definición de la frecuencia de reloj (4 MHz) y de la palabra de
'configuración: XT, CP off, PWRT On y Watchdog Timer off
'----------------------------------------------------------------
Define CONF_WORD = 0x3ff1
Define CLOCK_FREQUENCY = 4 'Se usa un oscilador de 4 MHz
'Definición del puerto y bit de conexión del dispositivo 1-Wire™
'----------------------------------------------------------------
Define 1WIRE_REG = PORTA
Define 1WIRE_BIT = 0
'Asignación de variables
'----------------------------------------------------------------
Dim id(8) As Byte
Dim index As Byte
Dim dig1 As Byte
Dim dig2 As Byte
Dim x As Byte
'Inicialización de dispositivos (LCD)
'----------------------------------------------------------------
Lcdinit 'Inicializa el LCD
WaitMs 500 'Pausa de 1/2 segundo para estabilizar el LCD
'Programa principal
'----------------------------------------------------------------
main:
'Iniciar la comunicación y ordenar la lectura ($33 = Leer ROM):
1wireInit 'Inicializa el bus de comunicación 1-Wire™
1wireSendByte 0x33 'Envía comando $33 al dispositivo esclavo
WaitMs 1 'Pausa de 1 milisegundo
'Obtener la ID:
For x = 0 To 7 'Bucle para la lectura del código ROM completo
1wireGetByte id(x) 'Lee 1 byte y lo almacena en el array
Next x 'repite el bucle hasta completar las 8 lecturas
'Enviar ROM al lcd:
Lcdout "Familia = " 'Mostrar en el LCD
x = 0 'Primer índice del array a visualizar (tipo de familia)
Gosub mostrar_hexadecimal 'Rutina de conversión a hexadecimal
Lcdcmdout LcdLine2Home 'Cursor a la 1ª posición de la 2ª linea
For x = 6 To 1 Step -1 'Los 6 siguientes índices del array (ID)
Gosub mostrar_hexadecimal 'Rutina de conversión a hexadecimal
Next x 'Repite el bucle hasta mostrar los 6 bytes del ID
Lcdout "-" 'Mostrar en el LCD
x = 7 'Último índice del array a visualizar (CRC)
Gosub mostrar_hexadecimal 'Rutina de conversión a hexadecimal
End 'Fin del programa
'Rutina de conversión a hexadecimal y visualizado en LCD
'----------------------------------------------------------------
mostrar_hexadecimal:
index = id(x) / 16 'Cálculo del primer dígito en hexadecimal,
dig1 = LookUp("0123456789ABCDEF"), index 'y su obtención
index = id(x) Mod 16 'Cálculo del segundo dígito en hexadecimal,
dig2 = LookUp("0123456789ABCDEF"), index 'y su obtención
Lcdout dig1, dig2 'Mostrar la conversión en el LCD
Return 'Regresa de la subrutina
Hola Amaro Pargo, no puedo compilar el codigo, me tira error. Parece que falta la etiqueta de la subrutina "mostrar_hexadecimal".
Define LCD_Lines = 2 '2 filas
Define LCD_CHARS = 16 '16 columnas
Define LCD_BITS = 8 '4 bits
Define LCD_DREG = RB 'puerto a conectar los 4 bits
Define LCD_RSREG = RA 'puerto para rs
Define LCD_RSBIT = 1 'rb0 a rs
Define LCD_EREG = RA 'puerto para e
Define LCD_EBIT = 2 'rb1 a e
Define LCD_RWREG = RA 'puerto para r/W
Define LCD_RWBIT = 3 'rb2 a r/W
'Define LCD_READ_BUSY_FLAG = 1
Define CONF_WORD = 0x3ff1
Define CLOCK_FREQUENCY = 4 'Se usa un oscilador de 4 MHz
Define 1WIRE_REG = PORTA
Define 1WIRE_BIT = 0
Dim id(8) As Byte
Dim index As Byte
Dim dig1 As Byte
Dim dig2 As Byte
Dim x As Byte
Lcdinit
WaitMs 500 'Pausa de 1/2 segundo para estabilizar el LCD
iniciar_conversion:
1wireInit
1wireSendByte 0x33
WaitMs 1
obtener_id:
For x = 0 To 7
1wireGetByte id(x)
Next x
enviar_lcd:
Lcdout "Familia = "
x = 0
GoSub mostrar_hexadecimal
Lcdcmdout LcdLine2Home
For x = 6 To 1 Step -1
GoSub mostrar_hexadecimal
Next x
Lcdout "-"
x = 7
GoSub mostrar_hexadecimal
End 'Fin del programa
mostrar_hexadecimal:
index = id(x) / 16
dig1 = LookUp("0123456789ABCDEF"), index
index = id(x) Mod 16
dig2 = LookUp("0123456789ABCDEF"), index
Lcdout dig1, dig2
Return
AllDigital
TRISA = %00000111
TRISB = %00000000
'USO DE SUBRUTINAS
'"PARPADEO DE UN LED"
'MENU
main:
If PORTA.0 = 1 Then Gosub parpadeo
If PORTA.1 = 1 Then Gosub red
Goto main
End
'SUBRUTINAS
parpadeo:
PORTB.4 = 1
WaitMs 500 'RETRASO DE APAGADO
PORTB.4 = 0
If PORTA.2 = 1 Then Return 'RESETEO
Goto parpadeo
red:
PORTB.4 = 1
If PORTA.2 = 1 Then Return 'RESETEO
Goto red
AllDigital
TRISA = %00000111
TRISB = %00000000
'USO DE SUBRUTINAS
'"PARPADEO DE UN LED"
'MENU
main:
If PORTA.0 = 1 Then Gosub parpadeo
If PORTA.1 = 1 Then Gosub red
Goto main
End
'SUBRUTINAS
parpadeo:
PORTB.4 = 1
WaitMs 500 'RETRASO DE APAGADO
PORTB.4 = 0
If PORTA.2 = 1 Then Return 'RESETEO
Goto parpadeo
Return
red:
PORTB.4 = 1
If PORTA.2 = 1 Then Return 'RESETEO
Goto red
Return
Define SIMULATION_WAITMS_VALUE = 1
AllDigital
TRISA = %00000111
TRISB = %00000000
'USO DE SUBRUTINAS
'"PARPADEO DE UN LED"
'MENU
main:
If PORTA.0 = 1 Then Gosub parpadeo
If PORTA.1 = 1 Then Gosub red
Goto main
End
'SUBRUTINAS
parpadeo:
Dim bucle As Bit 'Variable control bucle
bucle = True
While bucle = True 'Bucle infinito
PORTB.4 = 1
WaitMs 500 'RETRASO DE APAGADO
PORTB.4 = 0
If PORTA.2 = 1 Then bucle = False 'RESETEO
Wend
Return
red:
Dim bucle As Bit 'Variable control bucle
bucle = True
While bucle = True 'Bucle infinito
PORTB.4 = 1
If PORTA.2 = 1 Then Return 'bucle = False 'RESETEO
Wend
Return
AllDigital
TRISA = %00000111
TRISB = %00000000
'USO DE SUBRUTINAS
'"PARPADEO DE UN LED"
Dim tmrbase0 As Bit
Dim tmrbase1 As Bit
Dim tmrbase2 As Bit
Dim flagparpadeo As Byte
flagparpadeo = 0
'MENU
main:
If RA.0 = 1 Then flagparpadeo = 1
If RA.1 = 1 Then
flagparpadeo = 0
Gosub red
Endif
If RA.2 = 1 Then
flagparpadeo = 0 'RESETEO
RB4 = 0
Endif
If flagparpadeo = 1 Then Gosub parpadeo
Gosub basetimer
Goto main
End
'SUBRUTINAS
parpadeo: 'Parpadeo al 50%
If tmrbase0 = 1 Then
Toggle RB.4
tmrbase0 = 0
Endif
Return
parpadeo1: 'Parpadeo led programable tiempo a on y a off independiente
Dim flag As Bit
If tmrbase0 = 1 And flag = 0 Then
RB.4 = 1
tmrbase1 = 0
flag = 1
Endif
If tmrbase1 = 1 And flag = 1 Then
RB.4 = 0
tmrbase0 = 0
flag = 0
Endif
Return
red:
RB.4 = 1
Return
basetimer: 'Saltos aproximados de 10mSeg.
Dim basecont0 As Word
Dim basecont1 As Word
Dim basecont2 As Word
Dim base0_tm As Word
Dim base1_tm As Word
Dim base2_tm As Word
base0_tm = 30 'Carga base0 con 300mSeg.
base1_tm = 60 'Carga base0 con 600mSeg.
base2_tm = 100 'Carga base0 con 1Seg.
If tmrbase0 = 0 Then 'Base timer 0
basecont0 = basecont0 + 1
If basecont0 > base0_tm Then
tmrbase0 = 1
basecont0 = 0
Endif
Endif
If tmrbase1 = 0 Then 'Base timer 1
basecont1 = basecont1 + 1
If basecont1 > base1_tm Then
tmrbase1 = 1
basecont1 = 0
Endif
Endif
If tmrbase2 = 0 Then 'Base timer 2
basecont2 = basecont2 + 1
If basecont2 > base2_tm Then
tmrbase2 = 1
basecont2 = 0
Endif
Endif
WaitUs 9500
Return
AllDigital
TRISA = %00000111
TRISB = %00000000
'USO DE SUBRUTINAS
'"PARPADEO DE UN LED"
Dim flagparpadeo As Byte 'Activa el parpadeo del Led
flagparpadeo = 0 'Parpadeo del Led a Off
'MENU
Call tmrbase(1, 1, 0) 'Incializa base de tiempos 1
Call tmrbase(2, 1, 0) 'Incializa base de tiempos 2
Call tmrbase(3, 1, 0) 'Incializa base de tiempos 3
main: 'Rutina principal
If RA.0 = 1 Then flagparpadeo = 1 'Activa el parpadeo del Led
If RA.1 = 1 Then 'Para parpadeo y Led a On fijo
flagparpadeo = 0 'Parpadeo a Off
Gosub red 'Salto rutina control led a On
Endif
If RA.2 = 1 Then 'Reset al estado del Led
flagparpadeo = 0 'Para el parpadeo del Led
RB4 = 0 'Apaga el Led
Endif
If flagparpadeo = 1 Then Gosub parpadeo 'Salta a la rutina de control parpadeo Led
Call tmrbase(0, 0, 0) 'Actualiza las bases de tiempos
Goto main
End
'SUBRUTINAS
parpadeo: 'Parpadeo al 50%
If tmrbase.1 = 1 Then 'Control led a On
Toggle RB.4 'Led a On
Call tmrbase(1, 0, 5) 'Recarga la base de tiempos 1
Endif
Return
parpadeo1: 'Parpadeo led programable tiempo a On y Off independiente
Dim flag As Bit 'Marca el ciclo
If tmrbase.1 = 1 And flag = 0 Then 'Control led a On
RB.4 = 1 'Led a ON
Call tmrbase(1, 0, 3) 'Recarga base de tiempos 1
flag = 1 'Cambia de ciclo
Endif
If tmrbase.2 = 1 And flag = 1 Then 'Control led a Off
RB.4 = 0 'Led a Off
Call tmrbase(2, 0, 6) 'Recarga base de tiempos 2
flag = 0 'Cambia de ciclo
Endif
Return
red: 'Control Led a On fijo
RB.4 = 1 'Led a On
Return
'FUNCIONES
'Función que controla hasta 7 bases de tiempos
'Datos de entrada son los encerrados entre paréntesis
'Datos de salida los bit de la variable que da nombre a la función
'Se ponen antes del Main
'Call tmrbase(1, 1, 0) 'Incializa base de tiempos 1
'Call tmrbase(2, 1, 0) 'Incializa base de tiempos 2
'Call tmrbase(3, 1, 0) 'Incializa base de tiempos 3
'Actualiza las bases de tiempos, se tiene que repetir cada 10mSeg.
'Call tmrbase(0, 0, 0) 'Actualiza las bases de tiempos, deberia de ir en la rutina de interrupciones.
'Configuración general de las bases de tiempos
'Call tmrbase(x,y,z)
'x toma valores comprendidos entre 1 y 7, indica el numero de base que se quiere configurar
'y = 1 base parada, y = 0 base contando
'z tiempo que cuenta la base en mSeg x 10.
'Control del flujo de las rutinas del programa mediante los bit que componen la variable que da
'nombre a la función:
'tmrbase.x, x = al bit de control de la base de tiempos referida.
'If tmrbase.1 =1 then ----------------
'x=0 no se como base de tiempos, se usa para la actualización de los registros de las bases de tiempos creadas.
Function tmrbase(nbase As Byte, _onoff As Bit, base_tm As Word) As Byte 'Saltos aproximados de 10mSeg.
Dim basecont1 As Word 'Contadores
Dim basecont2 As Word
Dim basecont3 As Word
Dim base1_tm As Word 'Tiempo a contar
Dim base2_tm As Word
Dim base3_tm As Word
If nbase = 1 Then 'Configuración base tiempos 1
base1_tm = base_tm 'Carga base1 con el tiempo a contar
tmrbase.1 = _onoff 'Inicia=0, para=1
Endif
If nbase = 2 Then 'Configuración base tiempos 2
base2_tm = base_tm 'Carga base2 con el tiempo a contar
tmrbase.2 = _onoff 'Inicia=0, para=1
Endif
If nbase = 3 Then 'Configuración base tiempos 3
base3_tm = base_tm 'Carga base3 con el tiempo a contar
tmrbase.3 = _onoff 'Inicia=0, para=1
Endif
If tmrbase.1 = 0 Then 'Base timer 1
basecont1 = basecont1 + 1 'Incrementa contador base 1
If basecont1 > base1_tm Then 'Determina el estado de la base
tmrbase.1 = 1 'Base parada o termino de contar
basecont1 = 0 'Inicializa el contador de la base
Endif
Endif
If tmrbase.2 = 0 Then 'Base timer 2
basecont2 = basecont2 + 1 'Incrementa contador base 2
If basecont2 > base2_tm Then 'Determina el estado de la base
tmrbase.2 = 1 'Base parada o termino de contar
basecont2 = 0 'Inicializa el contador de la base
Endif
Endif
If tmrbase.3 = 0 Then 'Base timer 3
basecont3 = basecont3 + 1 'Incrementa contador base 3
If basecont3 > base3_tm Then 'Determina el estado de la base
tmrbase.3 = 1 'Base parada o termino de contar
basecont3 = 0 'Inicializa el contador de la base
Endif
Endif
WaitUs 9500 'Patron de la base de tiempos
Return
'He instalado la ultima version y la coma flotante no me funciona.
'Intento ver la tensión que entra en el AD y visualizo en un display solo las unidades.
'En la ayuda, veo que la coma flotante esta activada. Hace falta algun comando para activarla?
'Os dejo el programa para que veais lo que prento hacer, saludos.
'Leo el AD y se visualiza en el display. Calculo la tension de entrada del AD. (Voltimetro)
'16F876A
'''''''''''''''''''''''''''LOS VALORES DEL LCD HAY QUE CAMBIARLOS PARA MI PLACA'''''''''''''''''''''''''''''
Define CLOCK_FREQUENCY = 8
Define ADC_CLOCK = 3 'default value is 3
Define ADC_SAMPLEUS = 20 'default value is 20
Define LCD_BITS = 4 'allowed values are 4 and 8 - the number of data interface lines
Define LCD_DREG = PORTB
Define LCD_DBIT = 0 '0 or 4 for 4-bit interface, ignored for 8-bit interface
Define LCD_RSREG = PORTB
Define LCD_RSBIT = 4
Define LCD_EREG = PORTB
Define LCD_EBIT = 5
Define LCD_RWREG = 0 'set to 0 if not used, 0 is default
Define LCD_RWBIT = 0 'set to 0 if not used, 0 is default
Define LCD_COMMANDUS = 5000 'delay after LCDCMDOUT, default value is 5000
Define LCD_DATAUS = 50 'delay after LCDOUT, default value is 50
Define LCD_INITMS = 100 'delay used by LCDINIT, default value is 100
'the last three Define directives set the values suitable for simulation; they should be omitted for a real device
Lcdinit
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
AllDigital
TRISA.0 = 1 'configuro RA0 como entrada
TRISC.5 = 0 'RC5 como salida
'Define COUNT_MODE = 1
Dim entrada As Word
Dim voltaje As Single 'word
'Dim decima As Word 'variable para displayar las decimas de voltios
ADCON1 = 0 'conversor AD de an0 on
Lcdcmdout LcdLine1Clear
main:
Adcin 0, entrada
voltaje = (entrada * 5) / 1023
Lcdcmdout LcdLine1Home 'set cursor at the beginning of line 2
Lcdout "entrada: ", #voltaje, "v "
'WaitMs 100
Goto main
La coma flotante es un módulo que hay que comprar a parte, te tiene que salir en el IDE los siguiente para que esté activado.
(http://img3.imageshack.us/img3/28/picsimulatoride.jpg)
No he trabajado con coma flotante porque los micros que estoy utilizando últimamente tienen 1Kword de flash y la coma flotante es nueva y ocupa mucha memoria flash, por lo que no se si funciona bien, creo que debe de ir bien porque no ha salido ninguna otra versión para corregir errores. En general en el caso de errores en el PSI sale una nueva versión de un dia para otro y los usuarios registrados recibimos un aviso.
hola amigos de TODOPIC.
Solicito su ayuda por favor, tengo el siguiente problema.
Tengo una variable tipo WORD. Es un registro de eventos que necesito almacenar y no perder por cortes de energia. Asi que lo guardo en memoria EEPROM. El problema esta en que solo me guarda hasta 255 y reinicia el conteo de 0.
Como puedo hacer para guardar datos mayores a 255 por ejempo 23456 y poder leerlo cuando quiera..
Anexo una parte de rutina de mi programa: Saludos y gracias
tventas var word ;Variable que cuenta el total recibidos en monedas
credito var byte ;Varibale credito
read 10, tventas ;lee de la EEPROM a una variable tventas (total de ventas)
read 12
read 14
printvtotal:
lcdout $fe, 1 ;limpia display
lcdout $fe, $80, "TOTAL VENTAS" ;escribe en display 1ra fila
lcdout $fe, $c0, "$", dec tventas, ".00" ;muestra en display signo $ y total de pesos recibidos
grabatventas: ;para incrementar evento
tventas = tventas + credito ;sumar a total de ventas la cantidas de credito pesos recibidos
write 10, tventas ;grabar total de ventas en memoria EEPROM direccion 10
write 12
write 14
end
hola amigos estoy programando el pic12f675 para controlar la potencia de un lampara de 230 v 0% a 100% con un potenciometro que esta conectado a la pata 1 del micro12f675 ...cruce por zero pata2 pata0 conectada al optotriac despues del optotriac tenemos triac entonces jugamos del desparo del traic
Define ADC_CLOCK = 3 'Set clock source (3=rc)
Define ADC_SAMPLEUS = 50 'Set sampling time in uS
TRISIO = %00000110
ADCON0 = 0x0e
TRISIO.1 = 1
TRISIO.2 = 1
TRISIO.0 = 0
Dim t2400 As Word
Const con = 396
Dim adval As Byte
Dim voltatge As Word
Dim angle2 As Word
Dim k As Byte
Symbol triac = GP0
ADCON0.7 = 1
ANSEL = %00000010
CMCON = 7
inici: Adcin 1, adval
voltatge = (adval * 500) / 1023 'Equates to: (adval * 500)/1024
If GP2 = 1 And voltatge = 50 Then
GP0 = 1
Endif
Select Case 32
angle2 = angle2 - 960
If angle2 < 0 Then
angle2 = 0
Endif
Select Case 33
angle2 = angle2 + 960
If angle2 > 9000 Then
angle2 = 9000
Endif
Goto inici
End
dim nom1(10) as byte
dim nom2(10) as byte
dim nom3(20) as byte
nom1 = "Pepito"
nom2 = "Perez"
nom3 = nom1 + " " + nom2
lcdout "Hola " + nom3 + "!"
nom3 = strcat(nom1, nom2)
call Saludar ("Carlos")
call Saludar ("Juan")
call Saludar ("Ana")
end
Proc Saludar (nom(10) As byte)
Lcdcmdout LcdLine1Clear
Lcdout "Hola ", #nom
WaitMs 900
End Proc
Por el momento no tiene funciones del sistema que permitan asignar una cadena a una variable. Si quieres trabajar con cadenas de una forma cómoda te tienes que crear la función. Tampoco permite por el momento pasar una variable tipo vector a una función, se tiene que declarar como global para trabajar con ella en las funciones u otro modo seria pasarle la dirección de inicio de la variable para trabajar como punteros, pero el problema que también hay es que aunque tiene una tabla que indica la dirección de cada variable aun no tienen un modificador o símbolo en el código que permita hacer esta operación de forma automática, habría que pasar la dirección de forma manual. He tenido que trabajar pocas veces con cadenas, pero memorizar tramas de datos de entrada por un puerto y después buscar coincidencias con otros textos prememorizados realmente no me ha sido difícil.
Te tienes que crear la función que asigna una cadena de datos a una variable, ya entren por un puerto o se asignen de forma directa de la forma tradicional tipo “Hola mundo” y después una función más para comparar la cadena o buscar coincidencias que son las más utilizadas. Recuerda que todas las cadenas de texto tienen un caracter que indica fin de cadena.
Si estas muy interesado cuando tenga un rato te preparo una función que asigne una cadena a una variable tipo vector. Cuando veas el código observaras que es muy simple desarrollar las funciones para trabajar con cadenas.
'******************************************************************************
'Funciones para operar con cadenas cadenas
'By Dogflu66, 11/11.
'Basic del Pic Simulator IDE (PSI).
'******************************************************************************
'Puertos del LCD para simulador************************************************
Define LCD_BITS = 4 'Bus de datos del lcd a 4bit
Define LCD_DREG = PORTA 'Bus de datos el puerto A
Define LCD_DBIT = 0 'Bus datos los 4 bit menos significativos, puerto A
Define LCD_RSREG = PORTB 'Bit de control RS a puerto B
Define LCD_RSBIT = 7 'Se usa RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E del puerto B
Define LCD_EBIT = 6 'Se usa RB6 como E
Define LCD_COMMANDUS = 100 '2000 'Espera despues de ejecutar comando lcd, uSeg.
Define LCD_DATAUS = 50 'Espera despues de enviar un dato al LCD, uSeg.
Define LCD_INITMS = 5 '50 'Espera despues de inicializar el Display
'******************************************************************************
Define SIMULATION_WAITMS_VALUE = 1 'Ignora los valores de Waitms
'*****************************************************************
Dim clave As Byte @ 0x12f 'Se declara variable en la dirección establecida
Dim nombre As Byte @ 0x13a 'Se declara variable en la dirección establecida
Dim apellido As Byte @ 0x145 'Se declara variable en la dirección establecida
Dim p_clave As Word 'Variable que apunta a otra variable
Dim p_nombre As Word 'Variable que apunta a otra variable
Dim p_apellido As Word 'Variable que apunta a otra variable
p_clave = 0x12f 'p_clave apunta a clave
p_nombre = 0x13a 'p_nombre apunta a nombre
p_apellido = 0x145 'p_apellido apunta a apellido
Lcdinit 'Incializa el LCD
main:
Call strclr(p_clave) 'Inicializa/Borra la variable
Call strcdn(p_clave, 0) 'Asigna la cadena 0 a la variable
Call strcdn(p_nombre, 1) 'Asigna la cadena 1 a la variable
Call strcdn(p_apellido, 2) 'Asigna la cadena 2 a la variable
Call strchr(p_nombre, 0) 'Devuelve el caracter indicado en strchr
Call strlen(p_apellido) 'Devuelve en strlen la longitud de la cadena
Call strcpy(p_nombre, p_clave) 'Convierte la primera en la segunda
Call strcmp(p_nombre, p_clave) 'Compara dos cadenas, strcmp = 0 (diferentes), = 1 (iguales)
Lcdout "Clave:" 'Imprime en el LCD
Call strlen(p_nombre) 'Extrae la longitud de la cadena
Call strlcd(p_nombre, 0, strlen) 'Imprime en el LCD la cadena
'Goto main
End
'Asigna la cadena a la variable elegida
Proc strcdn(direccion As Word, valor As Byte)
Dim indice As Byte 'Indica el elemento de la lista
Dim paso As Byte 'Contendrá el elemento de la lista segun el indice
Dim x As Bit 'Variable auxiliar
x = 1
indice = 0
While x = 1 'Bucle de asignación
If valor = 0 Then paso = LookUp("123456", 0), indice
If valor = 1 Then paso = LookUp("Todopic", 0), indice
If valor = 2 Then paso = LookUp("Basic", 0), indice
Pointer(direccion) = paso 'Asigna el valor de paso a la dirección que hace referencia variable
If paso = 0 Then Exit 'Fin del Proc
indice = indice + 1 'Incrementa indice
direccion = direccion + 1 'Apunta a la siguiente dirección del vector seleccionado
Wend
End Proc
'Devuelve el caracter especificado, de izquierda a derecha
'El numero de orden para el primer caracter es el cero
Function strchr(direccion As Word, valor As Byte) As Byte
strchr = 0
direccion = direccion + valor 'Calcula la posición del caracter
strchr = Pointer(direccion) 'Extra el caracter de la posición
End Function
'Devuelve en strlen la longitud de la cadena,
'no incluye el caracter fin de cadena
Function strlen(direccion As Word) As Byte
Dim paso As Byte
Dim x As Bit
x = 1
strlen = 0
While x = 1
paso = Pointer(direccion) 'Lee valor
If paso = 0 Then Exit 'Sale de la Function
strlen = strlen + 1 'Incrementa longuitud
direccion = direccion + 1 'Incrementa posición
Wend
End Function
'Copia la segunda variable en la primera
Proc strcpy(direccion As Word, direccion1 As Word)
Dim paso As Byte
Dim x As Bit
x = 1
While x = 1
paso = Pointer(direccion1)
Pointer(direccion) = paso
If paso = 0 Then Exit
direccion = direccion + 1
direccion1 = direccion1 + 1
Wend
End Proc
'Compara las dos variables, devuelve strcmp = 0 si no son iguales
'devuelve strcmp = 1 si son iguales.
Function strcmp(direccion As Word, direccion1 As Word) As Byte
Dim paso As Byte
Dim paso1 As Byte
Dim x As Bit
strcmp = 0
x = 1
While x = 1
paso = Pointer(direccion)
paso1 = Pointer(direccion1)
If paso = paso1 Then strcmp = 1
If paso <> paso1 Then
strcmp = 0
Exit
Endif
If paso = 0 Or paso1 = 0 Then Exit
direccion = direccion + 1
direccion1 = direccion1 + 1
Wend
End Function
'Borra o inicializa la variable
Proc strclr(direccion As Word)
Pointer(direccion) = 0 'Asigna a la primera posición fin de cadena
End Proc
'Envia la cadena al LCD, apartir de inicio y tantos caracteres como marque numero
'Si numero = 0 es lo mismo = 1.
Proc strlcd(direccion As Word, inicio As Byte, numero As Word)
Dim paso As Byte
Dim x As Bit
x = 1
direccion = direccion + inicio 'Dirección del primer elemento de la variable
While x = 1
paso = Pointer(direccion) 'Lee valor
Lcdout paso
If paso = 0 Then Exit 'Sale de la Function
If numero > 0 Then numero = numero - 1 'Decrementa caracteres pendientes
If numero = 0 Then Exit 'Sale de la Función
direccion = direccion + 1 'Incrementa posición
Wend
End Proc
Dejo las funciones más significativas para operar con cadenas, he optado por trabajar con direcciones de memoria porque el código sale más reducido.
Si hay alguna duda sobre algo, pues por aquí estaré.
Los vectores se definen en las ultimas posiciones de memoria para que no sean ocupados por las declaraciones normales de variables que tienden a ocupar las primeras posiciones, y tienen que ser direcciones consecutivas. El código de control ASII 0 indica fin de cadena, pues para declarar una variable tipo vector de una longitud de 10 elementos se necesitan 11 bytes para que pueda ser gestionada por las funciones. En realidad todo esto se hace mas o menos de esta forma para cualquier lenguaje lo que ocurre es que el compilador nos lo oculta.
Los elementos de los vectores se nombran de la forma tradicional comenzando con el 0, 1, ..., hasta el final = (strlen-1). Es decir que el 0 cuenta.Código: [Seleccionar]'******************************************************************************
'Funciones para operar con cadenas cadenas
'By Dogflu66, 11/11.
'Basic del Pic Simulator IDE (PSI).
'******************************************************************************
'Puertos del LCD para simulador************************************************
Define LCD_BITS = 4 'Bus de datos del lcd a 4bit
Define LCD_DREG = PORTA 'Bus de datos el puerto A
Define LCD_DBIT = 0 'Bus datos los 4 bit menos significativos, puerto A
Define LCD_RSREG = PORTB 'Bit de control RS a puerto B
Define LCD_RSBIT = 7 'Se usa RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E del puerto B
Define LCD_EBIT = 6 'Se usa RB6 como E
Define LCD_COMMANDUS = 100 '2000 'Espera despues de ejecutar comando lcd, uSeg.
Define LCD_DATAUS = 50 'Espera despues de enviar un dato al LCD, uSeg.
Define LCD_INITMS = 5 '50 'Espera despues de inicializar el Display
'******************************************************************************
Define SIMULATION_WAITMS_VALUE = 1 'Ignora los valores de Waitms
'*****************************************************************
Dim clave As Byte @ 0x12f 'Se declara variable en la dirección establecida
Dim nombre As Byte @ 0x13a 'Se declara variable en la dirección establecida
Dim apellido As Byte @ 0x145 'Se declara variable en la dirección establecida
Dim p_clave As Word 'Variable que apunta a otra variable
Dim p_nombre As Word 'Variable que apunta a otra variable
Dim p_apellido As Word 'Variable que apunta a otra variable
p_clave = 0x12f 'p_clave apunta a clave
p_nombre = 0x13a 'p_nombre apunta a nombre
p_apellido = 0x145 'p_apellido apunta a apellido
Lcdinit 'Incializa el LCD
main:
Call strclr(p_clave) 'Inicializa/Borra la variable
Call strcdn(p_clave, 0) 'Asigna la cadena 0 a la variable
Call strcdn(p_nombre, 1) 'Asigna la cadena 1 a la variable
Call strcdn(p_apellido, 2) 'Asigna la cadena 2 a la variable
Call strchr(p_nombre, 0) 'Devuelve el caracter indicado en strchr
Call strlen(p_apellido) 'Devuelve en strlen la longitud de la cadena
Call strcpy(p_nombre, p_clave) 'Convierte la primera en la segunda
Call strcmp(p_nombre, p_clave) 'Compara dos cadenas, strcmp = 0 (diferentes), = 1 (iguales)
Lcdout "Clave:" 'Imprime en el LCD
Call strlen(p_nombre) 'Extrae la longitud de la cadena
Call strlcd(p_nombre, 0, strlen) 'Imprime en el LCD la cadena
'Goto main
End
'Asigna la cadena a la variable elegida
Proc strcdn(direccion As Word, valor As Byte)
Dim indice As Byte 'Indica el elemento de la lista
Dim paso As Byte 'Contendrá el elemento de la lista segun el indice
Dim x As Bit 'Variable auxiliar
x = 1
indice = 0
While x = 1 'Bucle de asignación
If valor = 0 Then paso = LookUp("123456", 0), indice
If valor = 1 Then paso = LookUp("Todopic", 0), indice
If valor = 2 Then paso = LookUp("Basic", 0), indice
Pointer(direccion) = paso 'Asigna el valor de paso a la dirección que hace referencia variable
If paso = 0 Then Exit 'Fin del Proc
indice = indice + 1 'Incrementa indice
direccion = direccion + 1 'Apunta a la siguiente dirección del vector seleccionado
Wend
End Proc
'Devuelve el caracter especificado, de izquierda a derecha
'El numero de orden para el primer caracter es el cero
Function strchr(direccion As Word, valor As Byte) As Byte
strchr = 0
direccion = direccion + valor 'Calcula la posición del caracter
strchr = Pointer(direccion) 'Extra el caracter de la posición
End Function
'Devuelve en strlen la longitud de la cadena,
'no incluye el caracter fin de cadena
Function strlen(direccion As Word) As Byte
Dim paso As Byte
Dim x As Bit
x = 1
strlen = 0
While x = 1
paso = Pointer(direccion) 'Lee valor
If paso = 0 Then Exit 'Sale de la Function
strlen = strlen + 1 'Incrementa longuitud
direccion = direccion + 1 'Incrementa posición
Wend
End Function
'Copia la segunda variable en la primera
Proc strcpy(direccion As Word, direccion1 As Word)
Dim paso As Byte
Dim x As Bit
x = 1
While x = 1
paso = Pointer(direccion1)
Pointer(direccion) = paso
If paso = 0 Then Exit
direccion = direccion + 1
direccion1 = direccion1 + 1
Wend
End Proc
'Compara las dos variables, devuelve strcmp = 0 si no son iguales
'devuelve strcmp = 1 si son iguales.
Function strcmp(direccion As Word, direccion1 As Word) As Byte
Dim paso As Byte
Dim paso1 As Byte
Dim x As Bit
strcmp = 0
x = 1
While x = 1
paso = Pointer(direccion)
paso1 = Pointer(direccion1)
If paso = paso1 Then strcmp = 1
If paso <> paso1 Then
strcmp = 0
Exit
Endif
If paso = 0 Or paso1 = 0 Then Exit
direccion = direccion + 1
direccion1 = direccion1 + 1
Wend
End Function
'Borra o inicializa la variable
Proc strclr(direccion As Word)
Pointer(direccion) = 0 'Asigna a la primera posición fin de cadena
End Proc
'Envia la cadena al LCD, apartir de inicio y tantos caracteres como marque numero
'Si numero = 0 es lo mismo = 1.
Proc strlcd(direccion As Word, inicio As Byte, numero As Word)
Dim paso As Byte
Dim x As Bit
x = 1
direccion = direccion + inicio 'Dirección del primer elemento de la variable
While x = 1
paso = Pointer(direccion) 'Lee valor
Lcdout paso
If paso = 0 Then Exit 'Sale de la Function
If numero > 0 Then numero = numero - 1 'Decrementa caracteres pendientes
If numero = 0 Then Exit 'Sale de la Función
direccion = direccion + 1 'Incrementa posición
Wend
End Proc
(http://img683.imageshack.us/img683/846/funcionesconcadenas.th.jpg) (http://imageshack.us/photo/my-images/683/funcionesconcadenas.jpg/)
PD. También se pueden declarar los vectores de la forma tradicional, ejemplo: Dim clave(10) as byte, y con una rutina al inicio los rastrea hasta que les encuentra su ubicación en la memoria y, les extrae sus direcciones de memoria de inicio asignandolas posteriormente de forma automatica. Pero el problema que tiene esta rutina es que es muy larga y consume mucha memoria de código, es muy simple pero usa mucho código redundante para cada variable, eso si, solo habría que ejecutarla una solo vez al principio.
'******************************************************************
'Escribiendo números grandes en LCD de dos líneas
'Para placa PicEBasic, By dogflu66, 12/11
'Basic Pic Simulator IDE (PSI), v6.91, Pic16F88
'******************************************************************
Define CONF_WORD = 0x2f50
Define CONF_WORD_2 = 0x3ffc
Define CLOCK_FREQUENCY = 8
'Define SIMULATION_WAITMS_VALUE = 1 'Activar para simulación
'Puerto del LCD----------------------------------------------------
Define LCD_BITS = 4 'Bus de datos del lcd, a 4bit
Define LCD_DREG = PORTA 'Bus de datos, puerto A
Define LCD_DBIT = 0 'Bus datos 4, bit menos significativos del puerto A
Define LCD_RSREG = PORTB 'Bit de control RS, puerto B
Define LCD_RSBIT = 7 'RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E, puerto B
Define LCD_EBIT = 6 'RB6 como E
Define LCD_COMMANDUS = 2000 'Espera despues de cada comando
Define LCD_DATAUS = 100 'Espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 100 'Espera despues inicializar Display
'*******************************************************************
'Configuración Placa EBasic ----------------------------------------
ANSEL = 0x00 'Los pin I/O digitales
CMCON = 0x07 'Comparador a off
OSCCON = 0x7e 'Reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'Puerto B como salidas
TRISA.4 = 1 'Como entrada (RA4, adc)
TRISA.6 = 1 'Como entrada (RA6, tecla S1)
TRISA.5 = 1 'Como entrada (RA5, tecla S2)
'TRISB.5 = 0 'RB5(Tx, RS232)
TRISB.2 = 1 'RB2 (Rx, RS232)
PORTB.3 = 1 'Luz lcd a on (RB3)
PORTA.7 = 1 'Led amarillo a off
PORTB.0 = 1 'Led verde a off
'*********************************************************************
Lcdinit 'Inicializa el LCD sin cursor
'*********************************************************************
Call p_word01() 'Inicializa cadena y puntero para trabajar con caractes
Call _intstrngrandes() 'Incializa caracteres CGRam del LCD, números grandes
'Variables------------------------------------------------------------
Dim numero As Long
Dim linea As Bit
numero = 0
'********************************************************************
Lcdout "Patrones:"
Lcdcmdout LcdLine2Home
Lcdout 0, 1, 2, 3, 4, 5, 6, 7 'Se imprimen los nuevos chr
WaitMs 5000 'Pausa de 3Seg
Lcdcmdout LcdClear 'Borrar el LCD
'********************************************************************
'Ejemplo: agranda el número contenido en la variable "numero"
'********************************************************************
main:
Call _nmrstr(numero, p_word01) 'Convierte un número a cadena
Call _strngrandes(p_word01, 4, linea) 'Escribe números grandes
Lcdout #numero
numero = numero + 1
Toggle linea
WaitMs 400
Lcdcmdout LcdClear
Goto main
End
Include "_FuncionesCadenasNumeros.bas"
'*********************************************************************
'****************Función Numeros Grandes******************************
'Guarda los patrones de bits en laCG Ram
'Call _intstrngrandes() 'Poner al principio
Proc _intstrngrandes()
Lcddefchar 0, 16, 24, 24, 24, 24, 24, 24, 16 'Media barra lateral derecha.
Lcddefchar 1, 1, 3, 3, 3, 3, 3, 3, 1 'Media barra lateral izquierda.
Lcddefchar 2, 31, 31, 0, 0, 0, 0, 0, 0 'Barra superior sola.
Lcddefchar 3, 0, 0, 0, 0, 0, 0, 31, 31 'Barra inferior sola
Lcddefchar 4, 31, 31, 0, 0, 0, 0, 31, 31 'Barra superior e inferior.
Lcddefchar 5, 2, 6, 14, 30, 14, 6, 2, 0 'Flecha Izquierda.
Lcddefchar 6, 8, 12, 14, 15, 14, 12, 8, 0 'Flecha Derecha.
Lcddefchar 7, 0, 0, 0, 0, 0, 0, 0, 0 'Todo vacio.
Lcdcmdout LcdClear 'Se borra el LCD despues de guardar los chr
End Proc
'**********************************************************************
'Función que agranda los caracteres numéricos de una cadena
'No está limitada en longitud, escrita para lcd de 2 líneas
'Parámetro de entrada: cadena tipo numérica
'Parámetro de entrada: posición en el LCD
'dirección: dirección en memoria de comienzo de la cadena
'xpos: posición de comienzo a imprimir en el LCD
'linea: indica la linea activa despues de escribir los números grandes
'linea = 0: linea activa inferior, linea=1: linea activa superior
'_strngrandes: devuelve la proxima posición a imprimir
'Call _strngrandes(dirección Ram cadena, posición a imprimir)
'*********************************************************************
Function _strngrandes(direccion As Word, xpos As Byte, linea As Bit) As Byte
Dim data As Byte 'Mascara
Dim index As Byte 'Indice mascara
Dim line As Bit 'Linea
Dim xx As Byte 'Contador caracteres de la cadena
Dim fin0 As Bit 'Control exit bucle linea
Dim fin As Bit 'Control bucle mascaras
Dim wline As Bit 'Se puede escribir mascara inferior
Dim strlen As Byte 'Longitud cadena
Dim strchr As Byte 'Exrae digito tipo cadena o ASCII
Dim cnt0 As Byte 'Indica la posición siguiente a imprimir
cnt0 = 0
line = False 'Se comienza con las mascaras superiores
wline = False 'No se puede imprimir mascaras inferiores
fin0 = False 'Bucle control lineas
fin = False 'Bucle imprime mascaras
xx = 0 'Contador digitos
strlen = _strlen(direccion) 'Asigna la longitud de la cadena
Lcdcmdout LcdLine1Pos(xpos) 'Establece posición en la linea 1
While fin0 = 0 'Bucle control líneas
strchr = _strchr(direccion, xx) 'Extrae caracter a agrandar de la cadena
index = 0 'Indica mascara a imprimir
wline = False 'No permite escribir mascara inferior, la mascara es superior
fin = 0 'Fin línea superior o inferior
While fin = False 'Bucle control de ipresión mascaras superior e inferior
If strchr = "0" Then data = LookUp(1, 2, 0, ".", 1, 3, 0, "*"), index 'Mascaras del 0
If strchr = "1" Then data = LookUp(0, ".", 0, "*"), index 'Mascaras del chr 1
If strchr = "2" Then data = LookUp(" ", 4, 0, ".", 1, 3, " ", "*"), index 'M. chr 2
If strchr = "3" Then data = LookUp(2, 0, ".", 4, 0, "*"), index 'M. chr 3
If strchr = "4" Then data = LookUp(1, 3, 0, ".", " ", " ", 0, "*"), index 'M. chr 4
If strchr = "5" Then data = LookUp(1, 4, " ", ".", " ", 3, 0, "*"), index 'M. chr 5
If strchr = "6" Then data = LookUp(1, 2, " ", ".", 1, 4, 0, "*"), index 'M. chr 6
If strchr = "7" Then data = LookUp(2, 0, ".", " ", 0, "*"), index 'M. chr 7
If strchr = "8" Then data = LookUp(1, 2, 0, ".", 1, 4, 0, "*"), index 'M. chr 8
If strchr = "9" Then data = LookUp(1, 4, 0, ".", " ", " ", 0, "*"), index 'M. chr 9
If data <> "." Or data <> "*" Then index = index + 1 'Selecciona mascara del mismo número
If line = False Then 'Mascaras línea superior
If data <> "." Then Lcdout data 'Imprime mascara actual
If data <> "." Then cnt0 = cnt0 + 1
If data = "." Then fin = True 'Fin mascaras superior del número seleccionado
Endif
If line = True Then 'Mascaras línea inferior
If data <> "*" And wline = True Then Lcdout data 'Imprime mascara actual
If data = "." Then wline = True 'Permite escribir mascara inf., mascara es inferior
If data = "*" Then fin = True 'Fin mascaras inferior del número seleccionado
Endif
Wend
xx = xx + 1 'Indica el proximo caracter a imprimir
If xx >= strlen And line = True Then fin0 = True 'Fin, todos impresos
If xx >= strlen And line = False Then Lcdcmdout LcdLine2Pos(xpos) 'Cambia a línea inferior
If xx >= strlen Then line = True 'Selecciona linea inferior
If xx >= strlen Then xx = 0 'Principio de línea
Wend
_strngrandes = cnt0 + xpos 'Siguiente posición a imprimir en el lcd
If linea = 0 Then Lcdcmdout LcdLine2Pos(_strngrandes) 'Establece línea inferior
If linea = 1 Then Lcdcmdout LcdLine1Pos(_strngrandes) 'Establece línea superior
End Function
'**************************************************************************
Por que programo de esta manera?... sera porque me gusta complicarme la vida....
Por que crear una rutina especial "pause_ms" para las perdidas de tiempo "delay" y no utilizar las que suministra el Basic?
-pues porque al utilizar las interrupciones en especial las bases de tiempos, "Waitms y Waitus" se ven afectados los tiempos indicados se les alargan.
Por que utilizo siempre las interrupciones?
-pues me permite asegurarme que ciertas rutinas ya sean para control de tiempo, control de periféricos exteriores o modulos internos del pic, no se veran afectados por el crecimiento del programa.
Por que no suelo utilizar las funciones que facilita el lenguaje?
-pues porque son muy lentas y consumen mucha memoria comparadas con los modulos internos del pic, a de mas se ven afectadas por las interrupciones.
Por que en la mayoria de los casos solo utilizo estructuras simples?
-porque de esta manera sera mas facil migrar el programa a otro lenguaje.
Por que el uso de las bases de tiempos?
-primero, como este lenguaje no las tiene tengo que crearlas
-segundo, me permite controlar las veces que se ejecutara una rutina por segundo,
por ejemplo, para que quiero que se ejecute la funcion del LCD de continuo con lo lenta que es, si con solo refrescar los datos cada 100mSeg. es suficiente.
Define CONF_WORD = 0x3ff1
Define CLOCK_FREQUENCY = 4
'-----CONFIGURAMOS PUERTOS----------
'AllDigital 'Todos los pines del PORTA como E/S
TRISA = 0xff 'Configuro el PORTA completo como entrada.
TRISB = 0x00 'Configuro el PORTB completo como salida.
PORTB.7 = 1
'------DECLARO VARIABLES -----------
Dim i As Byte 'i contendrá el valor del dado en cada momento.
loop: 'bucle principal
PORTB = %10000000 'Apago todos los leds menos el de Standby
If PORTA.0 = 1 Then 'Si el pulsador esta en alto...
Gosub lanzo_dado
Endif
Goto loop
End 'Fin del programa principal
'--------------------------------------------------
'Esta rutina lanza el dado y muestra el resultado
'--------------------------------------------------
lanzo_dado:
PORTB.7 = 0 'apago el standby
i = 0 'Valor inicial de i
While PORTA.0 = 1 'bucle principal
i = i + 1 'Sumo 1 a i
If i = 7 Then 'si pasa de 6...
i = 1 '..empiezo de 1 otra vez.
Endif
Wend
'Ahora, muestro el valor de "i" en los leds:
PORTB = LookUp(0x01, 0x08, 0x09, 0x0a, 0x0b, 0x0e), i
WaitMs 5000 'espero 5 segundos, y vuelvo al programa ppal.
PORTB.7 = 1 'prendo StandBy
Return
Hola de nuevo, si a alguien le interesa esta es la configuración que tengo en un PIC18F2550 a 20Mhz con cristal externoCódigo: [Seleccionar]'Programa: JEVO33
'Micro: PIC18f2550, cristal externo 20 MHz
'Version: 04
Define CLOCK_FREQUENCY = 20
Define CONFIG1L = %00100100 '0x24 %00100100 USBDIV =1 ;CPUDIV1:CPUDIV0 = 00 Postcaler del sistema no se divide ; PLLDIV2:PLLDIV0 =100 Se divide por 5
Define CONFIG1H = %00001100 '0x0c %00001100 IESO=0 ;FCMEN=0; _ _ ;FOC3:FOSC0=1100 Oscilador HS
Define CONFIG2L = %00111110 '0x3e %00111110 VREGEN=1 ;BORV1:BORV0 =11 ; BOREN1:BOREN0=11; PWRTEN= 0
Define CONFIG2H = 0x00
Define CONFIG3L = 0x00
Define CONFIG3H = %10000001 '0x83 %10000011 MCLRE=1;_ _ _ _ ;LPT1OSC= 0 ; PBADEN = 0;CCP2MX= 1 "CCP2 en RC1"
Define CONFIG4L = %10000000 '0x80 %10000000
Define CONFIG4H = 0x00
Define CONFIG5L = 0x0f
Define CONFIG5H = 0xc0
Define CONFIG6L = 0x0f
Define CONFIG6H = 0xe0
Define CONFIG7L = 0x0f
Define CONFIG7H = 0x40
Una pregunta que seguramente sera basica, si tengo un PWM iniciado en un port, ¿puedo poner el port fijo mediante p.e. PWMduty 2, 0 y PORTC.1=1 ?, ¿o tengo que parar primero el PWM ?
Tambien tengo un problemilla con una variable que me va flotando durante toda la ejecucion del programa, he intentado cambiarla de nombre, añadir una mas para que la cargue en una direccion de memoria diferente (a pasado de 0x43 a 0x45 pero me sigue variando), pero con todo y con ello me sigue variando todo el programa, ¿alguna idea?
Saludos
Define CONFIG1L = %00100100 '0x24 %00100100 USBDIV =1 ;CPUDIV1:CPUDIV0 = 00 Postcaler del sistema no se divide ; PLLDIV2:PLLDIV0 =100 Se divide por 5
Define CONFIG1H = %00001100 '0x0c %00001100 IESO=0 ;FCMEN=0; _ _ ;FOC3:FOSC0=1100 Oscilador HS
Define CONFIG2L = %00111110 '0x3e %00111110 VREGEN=1 ;BORV1:BORV0 =11 ; BOREN1:BOREN0=11; PWRTEN= 0
Define CONFIG2H = 0x00
Define CONFIG3L = 0x00
Define CONFIG3H = %10000001 '0x83 %10000011 MCLRE=1;_ _ _ _ ;LPT1OSC= 0 ; PBADEN = 0;CCP2MX= 1 "CCP2 en RC1"
Define CONFIG4L = %10000000 '0x80 %10000000
Define CONFIG4H = 0x00
Define CONFIG5L = 0x0f
Define CONFIG5H = 0xc0
Define CONFIG6L = 0x0f
Define CONFIG6H = 0xe0
Define CONFIG7L = 0x0f
Define CONFIG7H = 0x40
Hola tengo el siguiete problema:
quiero generar un cambio de estado en un pin cada 244µs por lo que configuré el TMR2 con el prescale en 1:1 y el postcale en 1:5. Tengo un PIC16F877A con un cristal de 20Mhz por lo que el calculo me dioCódigo: [Seleccionar]Define CONF_WORD = 0x3f72
AllDigital
TRISA = 0x00 'PORTA Outputs
INTCON.GIE = 1 'Int General
INTCON.PEIE = 1 'Int Perifericos
PIE1.TMR2IE = 1 'Int TMR2
T2CON.T2CKPS0 = 0 'TMR2 Prescale
T2CON.T2CKPS1 = 0 'TMR2 Prescale
T2CON.TOUTPS0 = 0 'TMR2 Postcale
T2CON.TOUTPS1 = 0 'TMR2 Postcale
T2CON.TOUTPS2 = 1 'TMR2 Postcale
T2CON.TOUTPS3 = 0 'TMR2 Postcale
PR2 = 244 'Overload TMR2
T2CON.TMR2ON = 1 'TMR2 ON
End
On Interrupt
PORTA.0 = Not PORTA.0
PIE1.TMR2IF = 0
Resume
'******************************************
'Funciones para modificar o leer el Bit ***
'de una variable o registro hasta tipo Long
'By dogflu66, 03/2013 *********************
'Para simulación **************************
'******************************************
Hseropen 4600
Dim variable As Byte
Dim aux As Byte
Dim n As Byte
variable = %10011000
aux = 0
main:
aux = 0
TRISA = 0
TRISA = _bittrue(TRISA, 0)
aux.0 = TRISA.0
Hserout "TRISA.0=", #aux, CrLf
aux = 0
TRISA = _bitfalse(TRISA, 1)
aux.0 = TRISA.1
Hserout "TRISA.1=", #aux, CrLf
Hserout "-------------------", CrLf
aux = 0
variable = _bittrue(variable, 0)
variable = _bitfalse(variable, 3)
For n = 0 To 7
aux.0 = _getbit(variable, n)
Hserout "VARIABLE.", #n, "=", #aux, CrLf
Next n
Halt
End
'Cambia a 1 el valor de un bit especifico de un registro hasta Long
'_reg es la variable o registro de entrada
'_bit es el numero de orden del bit a modificar, de 0 a ...
'Mediante _bittrue se transfiere el valor del bit modificado
Function _bittrue(_reg As Long, _bit As Byte) As Long
Dim _byte As Long
_byte = 1
_byte = ShiftLeft(_byte, _bit)
_reg = _reg Or _byte
_bittrue = _reg
End Function
'Cambia a 0 el valor de un bit especifico de un registro hasta Long
'_reg es la variable o registro de entrada
'_bit es el numero de orden del bit a modificar, de 0 a ...
'Mediante _bitfalse transfiere el valor del bit modificado
Function _bitfalse(_reg As Long, _bit As Byte) As Long
Dim _byte As Long
_byte = 1
_byte = ShiftLeft(_byte, _bit)
_byte = _byte Nand 0xffff
_reg = _reg And _byte
_bitfalse = _reg
End Function
'_getbit es una funcion que nos devuelve el estado
'de un bit de una variable determinada hasta Long.
'_reg es la variable de entrada
'_bit es el numero de orden del bit deseado, de 0 a ...
'Mediante _getbit transfiere el valor del bit deseado
Function _getbit(_reg As Long, _bit As Byte) As Bit
_reg = ShiftRight(_reg, _bit)
_getbit = _reg.0
End Function
Si los escribes como viene en el datasheet del micro si los reconoce.
T2CON.T2OUTPS0 = 0 'TMR2 Postcale
T2CON.T2OUTPS1 = 0 'TMR2 Postcale
T2CON.T2OUTPS2 = 1 'TMR2 Postcale
T2CON.T2OUTPS3 = 0 'TMR2 Postcale
'***********************************************
'Funciones para W/R un Long en la Eeprom del pic
'By Dogflu66
'Para simulación
'***********************************************
End
'Escribe una variable tipo Long en la Eeprom del Pic
'_reg = variable tipo Long a guardar en la Eeprom
'_direccion = direccion del Byte menos significativo de _reg
'Ejemplo (WriteLongEeprom):
'Call _wlongeeprom(vpaso, 200)
Proc _wlongeeprom(_reg As Long, _direccion As Word)
Write _direccion, _reg.LB
_direccion = _direccion + 1
Write _direccion, _reg.HB
_direccion = _direccion + 1
Write _direccion, _reg.3B
_direccion = _direccion + 1
Write _direccion, _reg.4B
End Proc
'Lee una variable tipo Long almacenada en la Eeprom del Pic
'_direccion = direccion del Byte menos significativo de la variable
'Ejemplo (ReadLongEeprom):
'vpaso = _rlongeeprom(200)
Function _rlongeeprom(_direccion As Word) As Long
Dim _reg As Long
_reg = 0
Read _direccion, _reg.LB
_direccion = _direccion + 1
Read _direccion, _reg.HB
_direccion = _direccion + 1
Read _direccion, _reg.3B
_direccion = _direccion + 1
Read _direccion, _reg.4B
_rlongeeprom = _reg
End Function
'Para simulación
Hseropen 4600
Call _intcuadrado() 'Inicializa la función cuadrado de un número
main:
Dim numero As Long
Dim contador As Long
Dim x As Byte
For x = 0 To 50
numero = _cuadrado(x) 'Calcula el cuadrado de x
contador = _nvcuadrado() 'Retorna el número de veces que se ejecutó la función cuadrado
Hserout #x, "*", #x, "=", #numero, " Veces ejecutó la función =", #contador, CrLf
Next x
Halt
Goto main
End
'Inicializa la función cuadrado de un número
'Esta función no retorna valor
Proc _intcuadrado()
Call _pcuadrado(0, 1)
End Proc
'Retorna el numero de veces que se ejecutó la función cuadrado
'Retorna un numero tipo Long
Function _nvcuadrado() As Long
_nvcuadrado = _pcuadrado(0, 2)
End Function
'Calcula el cuadrado de un número dado
'Se le suministra un número
'Retorna un numero tipo Long
Function _cuadrado(_numero As Long) As Long
_cuadrado = _pcuadrado(_numero, 0)
End Function
'Función principal cuadrado
'Se le suministran dos numero:
'_numero = a calcular el cuadrado
'_ctrl = para el control de la función
'Retorna un número tipo Long
Function _pcuadrado(_numero As Long, _ctrl As Byte) As Long
Dim _contador As Long
If _ctrl = 1 Then
_contador = 0
Exit
Endif
If _ctrl = 2 Then
_pcuadrado = _contador
Exit
Endif
_numero = _numero * _numero
_pcuadrado = _numero
_contador = _contador + 1
End Function
OPTION_REG.T0CS = 0 'selecciona reloj interno
OPTION_REG.PSA = 0 'asigna el prescales al timer0
OPTION_REG.PS0 = 1 'bits de la seleccion del factor de division,prescaler 16
OPTION_REG.PS1 = 1 'bits de la seleccion del factor de division,prescaler 16
OPTION_REG.PS2 = 0 'bits de la seleccion del factor de division,prescaler 16
INTCON.PEIE = 1 'bit de habilitacion de interrupciones de perifericos
Enable 'INTCON.GIE habilita todas las interrupciones globales
INTCON.TMR0IF = 0 'borra el flag de desbordamiento del timer0
TMR0 = 130 'cargo el registro del tmr0 para que desborde cada 1mS
'***************************************************************
'Funciones para trabajar con números con signo tipo Byte y Word.
'By dogflu66
'***************************************************************
Hseropen 4800
Dim sig_word As Word
Dim sig_word1 As Word
Dim sig_byte As Byte
Dim sig_aux As Word
'--------------------------
sig_word = _sigset16("-", 1)
sig_word1 = _sigset16("+", 0)
sig_byte = _sigset8("-", 50)
main:
Call _sigsprint16(sig_word)
Call _sprintcrlf()
Call _sigsprint16(sig_word1)
Call _sprintcrlf()
Call _sprintcrlf()
Hserout "Suma: "
sig_aux = _sigadd16(sig_word, sig_word1)
Call _sigsprint16(sig_aux)
Call _sprintcrlf()
Call _sprintcrlf()
Hserout "Resta: "
sig_aux = _sigsub16(sig_word, sig_word1)
Call _sigsprint16(sig_aux)
Call _sprintcrlf()
Call _sprintcrlf()
Hserout "División: "
sig_aux = _sigdiv16(sig_word, sig_word1)
Call _sigsprint16(sig_aux)
Call _sprintcrlf()
Call _sprintcrlf()
Hserout "Multiplicación: "
sig_aux = _sigmul16(sig_word, sig_word1)
Call _sigsprint16(sig_aux)
Call _sprintcrlf()
Call _sprintcrlf()
Hserout "Comparación: "
sig_aux = _sigcmp16(sig_word, sig_word1)
Call _sigsprint16(sig_word)
If sig_aux = 0 Then Hserout " < "
If sig_aux = 1 Then Hserout " > "
If sig_aux = 2 Then Hserout " = "
Call _sigsprint16(sig_word1)
Call _sprintcrlf()
End
'División con signo 16Bit, entera.
Function _sigdiv16(_op2 As Word, _op1 As Word) As Word
Dim _sigop1 As Bit
Dim _sigop2 As Bit
Dim _sigaux As Word
_sigop1 = _sigget16(_op1)
_sigop2 = _sigget16(_op2)
_op2 = _sigmod16(_op2)
_op1 = _sigmod16(_op1)
If _op1 > 0 Then
_sigaux = _op2 / _op1
If _sigop2 = 1 And _sigop1 = 0 Then
If _sigaux > 0 Then _sigaux = _sigcpl16(_sigaux)
Endif
If _sigop2 = 0 And _sigop1 = 1 Then
If _sigaux > 0 Then _sigaux = _sigcpl16(_sigaux)
Endif
Endif
If _op1 = 0 Then _sigaux = 32768 'E = -0
_sigdiv16 = _sigaux
End Function
'Multiplicación con signo 16Bit, entera.
Function _sigmul16(_op2 As Word, _op1 As Word) As Word
Dim _sigop1 As Bit
Dim _sigop2 As Bit
Dim _sigaux As Word
_sigop1 = _sigget16(_op1)
_sigop2 = _sigget16(_op2)
_op2 = _sigmod16(_op2)
_op1 = _sigmod16(_op1)
_sigaux = _op2 * _op1
If _sigop2 = 1 And _sigop1 = 0 Then
If _sigaux > 0 Then _sigaux = _sigcpl16(_sigaux)
Endif
If _sigop2 = 0 And _sigop1 = 1 Then
If _sigaux > 0 Then _sigaux = _sigcpl16(_sigaux)
Endif
_sigmul16 = _sigaux
End Function
'Resta con signo 16Bit,entera.
Function _sigsub16(_op2 As Word, _op1 As Word) As Word
Dim _sigop1 As Bit
_op1 = _sigcpl16(_op1)
_sigsub16 = _sigadd16(_op2, _op1)
End Function
'Suma con signo 16Bit, entera.
Function _sigadd16(_op2 As Word, _op1 As Word) As Word
Dim _sigop1 As Bit
Dim _sigop2 As Bit
Dim _sigaux As Word
_sigop1 = _sigget16(_op1)
_sigop2 = _sigget16(_op2)
_op2 = _sigmod16(_op2)
_op1 = _sigmod16(_op1)
If _sigop2 = 0 And _sigop1 = 0 Then _sigaux = _op1 + _op2
If _sigop2 = 1 And _sigop1 = 0 Then
If _op2 > _op1 Then
_sigaux = _op2 - _op1
If _sigaux > 0 Then _sigaux = _sigcpl16(_sigaux)
Endif
If _op2 < _op1 Then _sigaux = _op1 - _op2
If _op2 = _op1 Then _sigaux = 0
Endif
If _sigop2 = 0 And _sigop1 = 1 Then
If _op2 > _op1 Then
_sigaux = _op2 - _op1
Endif
If _op2 < _op1 Then
_sigaux = _op1 - _op2
If _sigaux > 0 Then _sigaux = _sigcpl16(_sigaux)
Endif
If _op2 = _op1 Then _sigaux = 0
Endif
If _sigop2 = 1 And _sigop1 = 1 Then
_sigaux = _op2 + _op1
_sigaux = _sigcpl16(_sigaux)
Endif
_sigadd16 = _sigaux
End Function
'Compara dos números con signo de 16bit
'0 = op2 < op1
'1 = op2 > op1
'2 = op2 = op1
Function _sigcmp16(_op2 As Word, _op1 As Word) As Byte
Dim _sigop2 As Bit
Dim _sigop1 As Bit
_sigop2 = _sigget16(_op2)
_sigop1 = _sigget16(_op1)
_op1 = _sigmod16(_op1)
_op2 = _sigmod16(_op2)
If _sigop2 = 0 And _sigop1 = 0 Then
If _op2 < _op1 Then _sigcmp16 = 0
If _op2 > _op1 Then _sigcmp16 = 1
If _op2 = _op1 Then _sigcmp16 = 2
Endif
If _sigop2 = 0 And _sigop1 = 1 Then
_sigcmp16 = 1
Endif
If _sigop2 = 1 And _sigop1 = 0 Then
_sigcmp16 = 0
Endif
If _sigop2 = 1 And _sigop1 = 1 Then
If _op2 > _op1 Then _sigcmp16 = 0
If _op2 < _op1 Then _sigcmp16 = 1
If _op2 = _op1 Then _sigcmp16 = 2
Endif
End Function
'Devuelve el signo variables 16bit, 1 = -, 0 = +
Function _sigget16(_op As Word) As Bit
_sigget16 = _op.15
End Function
'Devuelve el signo variables 8bit, 1 = -, 0 = +
Function _sigget8(_op As Byte) As Bit
_sigget8 = _op.7
End Function
'Invierte el signo de una variable 16Bit
Function _sigcpl16(_op As Word) As Word
Toggle _op.15
_sigcpl16 = _op
End Function
'Invierte el signo de una variable 8Bit
Function _sigcpl8(_op As Byte) As Byte
Toggle _op.7
_sigcpl8 = _op
End Function
'Devuelve el modulo de una variable con signo 16Bit
Function _sigmod16(_op As Word) As Word
_op.15 = 0
_sigmod16 = _op
End Function
'Devuelve el modulo de una variable con signo 8Bit
Function _sigmod8(_op As Byte) As Byte
_op.7 = 0
_sigmod8 = _op
End Function
'Asigna signo a las variables 16Bit
Function _sigset16(sig As Byte, _op As Word) As Word
If _op = 0 Then sig = "+"
If sig = "+" Then _sigset16 = _op
If sig = "-" Then
_op.15 = 1
_sigset16 = _op
Endif
End Function
'Asigna signo a las variables 8Bit
Function _sigset8(sig As Byte, _op As Byte) As Byte
If _op = 0 Then sig = "+"
If sig = "+" Then _sigset8 = _op
If sig = "-" Then
_op.7 = 1
_sigset8 = _op
Endif
End Function
'Extender signo tipo 8bit a tipo 16bit
Function _sigextw16(op As Byte) As Word
Dim sig_op As Bit
sig_op = op.7
op.7 = 0
_sigextw16 = op
_sigextw16.15 = sig_op
End Function
'Funciones de salida de datos por el puerto serie UART.
'--------------------------------------------------
'Envia al puerto serie una variable con signo 16Bit
Proc _sigsprint16(_op As Word)
Dim _sigop As Bit
_sigop = _op.15
_op.15 = 0
If _sigop = 1 And _op = 0 Then
Hserout "E"
Exit
Endif
If _sigop = 1 Then Hserout "-"
Hserout #_op
End Proc
'Envia al puerto serie una variable con signo 8Bit
Proc _sigsprint8(op As Byte)
If op.7 = 1 Then Hserout "-"
op.7 = 0
Hserout #op
End Proc
'Linea nueva al puerto serie
Proc _sprintcrlf()
Hserout CrLf
End Proc
Define CLOCK_FREQUENCY = 20
'configuracion de display
Define LCD_BITS = 8
Define LCD_DREG = PORTD
Define LCD_DBIT = 0
Define LCD_RSREG = PORTB
Define LCD_RSBIT = 2
Define LCD_RWREG = PORTB
Define LCD_RWBIT = 3
Define LCD_EREG = PORTB
Define LCD_EBIT = 4
Lcdinit
'configuracion de entradas
AllDigital 'todas las entradas como digital
TRISA = %00000000 'entrasdas puerto a como salidas
TRISB = %00000000 'entradas puerto b como salidas
Symbol dht_11 = PORTA.1 'puerto a0 se conportara bidireccionalmente, es decir enviara pulso para pedir datos y recibir informacion
Dim colector(31) As Byte
Dim humedad As Byte
Dim humedad1 As Byte
Dim temperatura As Byte
Dim temperatura1 As Byte
Dim temp As Byte
Dim temp1 As Byte
Dim hume As Byte
Dim hume1 As Byte
inicio:
'leer DHT11
Config dht_11 = Output
High dht_11 'enviamos un 1 al sensor
WaitUs 1 '10
Low dht_11 'enviamos un 0 para indicarle al sensor
WaitMs 18
High dht_11 'enviamos un 1 para completar la peticon de comunicacion
WaitUs 30 '30
Config dht_11 = Input
WaitUs 180
Dim i As Byte
For i = 31 To 0 Step -1
'dht_11 = colector(1)
'WaitUs 2.5
'Next i
Define COUNT_MODE = 2
Count dht_11, 1, colector(i)
WaitUs 3
Next i
'transofrmacion humedad parte entera
If colector(31) > 3 Then
humedad.7 = 1
Else
humedad.7 = 0
Endif
If colector(30) > 3 Then
humedad.6 = 1
Else
humedad.6 = 0
Endif
If colector(29) > 3 Then
humedad.5 = 1
Else
humedad.5 = 0
Endif
If colector(28) > 3 Then
humedad.4 = 1
Else
humedad.4 = 0
Endif
If colector(27) > 3 Then
humedad.3 = 1
Else
humedad.3 = 0
Endif
If colector(26) > 3 Then
humedad.2 = 1
Else
humedad.2 = 0
Endif
If colector(25) > 3 Then
humedad.1 = 1
Else
humedad.1 = 0
Endif
If colector(24) > 3 Then
humedad.0 = 1
Else
humedad.0 = 0
Endif
'transformacion humedad parte decimal
If colector(23) > 3 Then
humedad1.7 = 1
Else
humedad1.7 = 0
Endif
If colector(22) > 3 Then
humedad1.6 = 1
Else
humedad1.6 = 0
Endif
If colector(21) > 3 Then
humedad1.5 = 1
Else
humedad1.5 = 0
Endif
If colector(20) > 3 Then
humedad1.4 = 1
Else
humedad1.4 = 0
Endif
If colector(19) > 3 Then
humedad1.3 = 1
Else
humedad1.3 = 0
Endif
If colector(18) > 3 Then
humedad1.2 = 1
Else
humedad1.2 = 0
Endif
If colector(17) > 3 Then
humedad1.1 = 1
Else
humedad1.1 = 0
Endif
If colector(16) > 3 Then
humedad1.0 = 1
Else
humedad1.0 = 0
Endif
'transformacion temperatura parte entera
If colector(15) > 3 Then
temperatura.7 = 1
Else
temperatura.7 = 0
Endif
If colector(14) > 3 Then
temperatura.6 = 1
Else
temperatura.6 = 0
Endif
If colector(13) > 3 Then
temperatura.5 = 1
Else
temperatura.5 = 0
Endif
If colector(12) > 3 Then
temperatura.4 = 1
Else
temperatura.4 = 0
Endif
If colector(11) > 3 Then
temperatura.3 = 1
Else
temperatura.3 = 0
Endif
If colector(10) > 3 Then
temperatura.2 = 1
Else
temperatura.2 = 0
Endif
If colector(9) > 3 Then
temperatura.1 = 1
Else
temperatura.1 = 0
Endif
If colector(8) > 3 Then
temperatura.0 = 1
Else
temperatura.0 = 0
Endif
'temperatura parte decimal
If colector(7) > 3 Then
temperatura1.7 = 1
Else
temperatura1.7 = 0
Endif
If colector(6) > 3 Then
temperatura1.6 = 1
Else
temperatura1.6 = 0
Endif
If colector(5) > 3 Then
temperatura1.5 = 1
Else
temperatura1.5 = 0
Endif
If colector(4) > 3 Then
temperatura1.4 = 1
Else
temperatura1.4 = 0
Endif
If colector(3) > 3 Then
temperatura1.3 = 1
Else
temperatura1.3 = 0
Endif
If colector(2) > 3 Then
temperatura1.2 = 1
Else
temperatura1.2 = 0
Endif
If colector(1) > 3 Then
temperatura1.1 = 1
Else
temperatura1.1 = 0
Endif
If colector(0) > 3 Then
temperatura1.0 = 1
Else
temperatura1.0 = 0
Endif
Gosub calculo
Gosub lcd
Goto inicio
End
calculo:
temp = temperatura + temperatura1
temp1 = temp / 10
hume = humedad + humedad1
hume1 = hume / 10
Return
lcd:
Lcdcmdout LcdClear
Lcdout "hum:", #hume, "/", #humedad, "/", #humedad1
Lcdcmdout LcdLine2Home
Lcdout "temp:", #temp, "/", #temperatura, "/", #temperatura1
WaitMs 5000
Return
Define CLOCK_FREQUENCY = 20
'Define SIMULATION_WAITMS_VALUE = 1
'configuracion de display
Define LCD_BITS = 8
Define LCD_DREG = PORTD
Define LCD_DBIT = 0
Define LCD_RSREG = PORTB
Define LCD_RSBIT = 2
Define LCD_RWREG = PORTB
Define LCD_RWBIT = 3
Define LCD_EREG = PORTB
Define LCD_EBIT = 4
Lcdinit
'Configuracion de puertos
AllDigital 'Los pin I/O como digitales
TRISA = %00000000 'Puerto A como salidas
TRISB = %00000000 'Puerto B como salidas
Dim rh As Word 'Humedad relativa
Dim tmp As Word 'Temperatura
Dim _bit As Bit 'Auxiliar
Dim n As Byte 'Auxiliar
Dim x As Byte 'Auxiliar
main:
'Puesta a cero
rh = 0
tmp = 0
'Demanda de lectura al sensor
RA0 = 0
WaitUs 2000
'MCU se prepara para recibir datos
TRISA.0 = 1 'Bus como Read
WaitUs 5 'Estabilización
While RA0 = 1 'Esperando respuesta
Wend
While RA0 = 0 'Esperando respuesta
Wend
While RA0 = 1 'Esperando respuesta
Wend
'Read data transmission RH
For n = 0 To 15
x = 0
While RA0 = 0
Wend
While RA0 = 1
WaitUs 1
x = x + 1
Wend
If x < 40 Then rh.0 = 0
If x > 40 Then rh.0 = 1
If n < 15 Then rh = ShiftLeft(rh, 1)
Next n
'Read data transmission TMP
For n = 0 To 15
x = 0
While RA0 = 0
Wend
While RA0 = 1
WaitUs 1
x = x + 1
Wend
If x < 40 Then tmp.0 = 0
If x > 40 Then tmp.0 = 1
If n < 15 Then tmp = ShiftLeft(tmp, 1)
Next n
fin: 'Bucle infinito
Goto fin
Goto main
End
Define CLOCK_FREQUENCY = 20
Define SIMULATION_WAITMS_VALUE = 1
'configuracion de display
Define LCD_BITS = 8
Define LCD_DREG = PORTD
Define LCD_DBIT = 0
Define LCD_RSREG = PORTB
Define LCD_RSBIT = 2
Define LCD_RWREG = PORTB
Define LCD_RWBIT = 3
Define LCD_EREG = PORTB
Define LCD_EBIT = 4
Lcdinit
'Configuracion de puertos
AllDigital 'Los pin I/O como digitales
TRISA = %00000000 'Puerto A como salidas
TRISB = %00000000 'Puerto B como salidas
Dim rh As Word 'Humedad relativa
Dim tmp As Word 'Temperatura
Dim n As Byte 'Auxiliar
Dim x As Byte 'Auxiliar
main:
'Puesta a cero
rh = 0
tmp = 0
'Demanda de lectura al sensor
RA0 = 0
WaitUs 2000
'MCU se prepara para recibir datos
TRISA.0 = 1 'Bus como Read
WaitUs 5 'Estabilización
x = 0
While RA0 = 1 And x < 200 'Esperando respuesta
WaitUs 1
x = x + 1
Wend
x = 0
While RA0 = 0 And x < 200 'Esperando respuesta
WaitUs 1
x = x + 1
Wend
x = 0
While RA0 = 1 And x < 200 'Esperando respuesta
WaitUs 1
x = x + 1
Wend
'Read data transmission RH
For n = 0 To 15
x = 0
While RA0 = 0 And x < 200
WaitUs 1
x = x + 1
Wend
x = 0
While RA0 = 1 And x < 200
WaitUs 1
x = x + 1
Wend
If x < 40 Then rh.0 = 0
If x > 40 Then rh.0 = 1
If n < 15 Then rh = ShiftLeft(rh, 1)
Next n
'Read data transmission TMP
For n = 0 To 15
x = 0
While RA0 = 0 And x < 200
WaitUs 1
x = x + 1
Wend
x = 0
While RA0 = 1 And x < 200
WaitUs 1
x = x + 1
Wend
If x < 40 Then tmp.0 = 0
If x > 40 Then tmp.0 = 1
If n < 15 Then tmp = ShiftLeft(tmp, 1)
Next n
fin: 'Bucle infinito
Goto fin
Goto main
End
'**********************************************************************************
'Función de lectura de humedad relativa y temperatura para el sensor RHT03 0 DHT22 con TMR1
'Placa PicEBasic, By dogflu66, 07/2013
'Basic Pic Simulator IDE (PSI), v6.92, Pic16F88
'**********************************************************************************
'----------------------------------------------------------------------------------
Define CONF_WORD = 0x2f50
Define CONF_WORD_2 = 0x3ffc
Define CLOCK_FREQUENCY = 8
'Define SIMULATION_WAITMS_VALUE = 1 'Activar para simulación
'Puerto del LCD ----------------------------------------------------------
Define LCD_BITS = 4 'Bus de datos del lcd, a 4bit
Define LCD_DREG = PORTA 'Bus de datos, puerto A
Define LCD_DBIT = 0 'Bus datos 4, bit menos significativos del puerto
Define LCD_RSREG = PORTB 'Bit de control RS, puerto B
Define LCD_RSBIT = 7 'RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E, puerto B
Define LCD_EBIT = 6 'RB6 como E
Define LCD_COMMANDUS = 2000 'Espera despues de cada comando
Define LCD_DATAUS = 100 'Espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 100 'Espera inicialización del Display
'Configuración Placa Pic EBasic -----------
ANSEL = 0x00 'Los pin I/O digitales
CMCON = 0x07 'Comparador a off
OSCCON = 0x7e 'Reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'Puerto B como salidas
TRISA.4 = 1 'Como entrada (RA4, adc)
TRISA.6 = 1 'Como entrada (RA6, tecla S1)
TRISA.5 = 1 'Como entrada (RA5, tecla S2)
TRISB.5 = 0 'Como salida(RB5,Tx RS232)
TRISB.2 = 1 'Como entrada (RB2, Rx RS232)
TRISB.4 = 1 'Como entrada (RHT03 inicio)
PORTB.3 = 1 'Luz lcd a ON (RB3)
PORTA.7 = 1 'Led amarillo a OFF
PORTB.0 = 1 'Led verde a OFF
PORTB.1 = 0 'LED RHT03 a OFF
'-----------------------------------------
Hseropen 4800 'Inicializa puerto RS232 por hardware a 4800Baudios
Lcdinit 'Inicializa el LCD sin cursor
'Constantes y variables ------------------
Dim hr As Word 'Humedad relativa
Dim tmp As Word 'Temperatura
Dim chk As Byte 'Checksum suministrado por el sensor
'-----------------------------------------
WaitMs 100 'Pausa de 100 mSeg.
Lcdout "Test P. RHT03" 'Imprime el texto en el LCD
Call _rht03ini(8) 'Se comunica a la función del RHT03 la velocidad del reloj en Mhz
WaitMs 2000 'Pausa de 2 Seg.
main:
'Muestra lecturas
Call _rht03read() 'Lee sensor, 500mSeg. minimo entre lectura y lectura
hr = _ped1(_rht03read.HW) 'Asigna humedad relativa, parte entera hr.HB y decimal hr.LB
tmp = _ped1(_rht03read.LW) 'Asigna temperatura, parte entera tmp.HB y decimal tmp.LB
chk = _rht03chk() 'Asigna lectura valida o erronea
Lcdcmdout LcdLine1Home 'Cursor del lcd al principio linea 1
Lcdout "HR:", #hr.HB, ".", #hr.LB, " T:", #tmp.HB, ".", #tmp.LB, "C " 'Salida de datos
Lcdcmdout LcdLine2Home 'Cursor del Lcd al principio linea 2
Lcdout "Checksum: " 'Salida de datos
If chk = 0 Then Lcdout "OK. "
If chk = 1 Then Lcdout "ERROR. "
WaitMs 500 'Deja que el sensor se prepare para la siguiente lectura, tiempo recomendado 2Seg.
Call _flashled(50) 'Parpadeo led en mSeg.
Goto main
End
Include "Trabajando con bit.bas"
'-------------------------------------------------
'Cambia de formato una variable Word, retorna valor
'Cambia de formato un Word que contiene un decimal
'integrado en la parte entera (151 = 15.1 * 10)
'variable = _ped1(151) o call _ped1(151)
'para _numero = 151, _ped1.HB = 15 y _ped1.LB = 1
Function _ped1(_numero As Word) As Word
_ped1.HB = _numero / 10 'Extrae parte entera
_ped1.LB = _numero - (_ped1.HB * 10) 'Extra parte decimal
End Function
'Inicaliza la función de lectura del RHT03, no retorna valor
'Argumento de entrada _clk = a Mhz del reloj del sistema
'Call _rht03ini(8) 'se trabaja a 8 Mhz
Proc _rht03ini(_clk As Byte)
Call _rht03(0, _clk)
End Proc
'Devuelve el checksum de la ultima lectura, retorna valor
'para _rht03chk = 0 lectura correcta, = 1 fallo en lectura
'checksum = _rht03chk() o Call _rht03chk()
Function _rht03chk() As Byte
_rht03chk = _rht03(1, 0)
End Function
'Pide una lectura de temperatura a la función principal, retorna valor
'_rht03read.HW = tiene la lectura de la humedad relativa con un decimal integrado en la parte entera
'_rht03read.LW = tiene la lectura de la temperatura con un decimal integrado en la parte entera
'hr = _rht03read.HW 'Humedad relativa de la última lectura
'tmp = _rht03read.LW 'Temperatura de la última lectura
Function _rht03read() As Long
_rht03read = _rht03(2, 0)
End Function
'Funcion de lectura y control del sensor RHT03, devuelve valor
'_clk = velocidad del oscilador en Mhz
'para _ctrl = 0, devuelve _rht03 = 0, pone checksum en error, se incializa la función
'para _ctrl = 1, devuelve False o True de la última lectura, True = lectura erronea
'para _ctrl resto valores, devuelve en _rht03 la humedad relativa (_rht03.HW) y la temperatura (_rht03.LW)
Function _rht03(_ctrl As Byte, _clk As Byte) As Long
Symbol t1db = PIR1.TMR1IF 'Se renombra el flag de desbordamiento del Timer
Dim rh As Word
Dim tmp As Word
Dim chk As Byte
Dim chk_aux As Byte
Dim clock As Byte
Dim n As Byte
Dim x As Byte
Dim v_aux(40) As Byte
'Inicializa la función
If _ctrl = 0 Then
'Configuración del TIMER1---------------------------------------------------
T1CON.TMR1CS = 0 'asigna el reloj interno al timer1, se incrementa cada ciclo de instruccion
T1CON.T1CKPS0 = 0 'factor del preescales del timer1, 0
T1CON.T1CKPS1 = 0 'factor del preescales del timer1, 0
T1CON.TMR1ON = 0 'parado el contador del TMR1
PIE1.TMR1IE = 0 'desactiva las interrupciones del timer1
'Inicializa las variables de la función
chk_aux = 1 'Se activa el checkum de la función como error
chk = 0
clock = _clk * 10 'Calcula y asigna el tiempo que dura el ancho de pulso correspondiente al cero
_rht03 = 0 'Variable de salida de la función a cero
Exit 'Fuerza la salida de la función
Endif
'Devuelve el checksum, 0 = OK, 1 = error de lectura ---------------------
If _ctrl = 1 Then
If chk_aux = chk Then _rht03 = 0 'Dato válido
If chk_aux <> chk Then _rht03 = 1 'Dato no válido
Exit 'Fuerza la salida de la función
Endif
'Puesta a cero --'---------------------------------------------------------
rh = 0
tmp = 0
chk_aux = 1 'Se activa error de checksum por defecto
chk = 0
_rht03 = 0
'Espera que el puerto de comunicaciones del sensor quede libre ----------
Call _initmer() 'Puesta a cero del Timer
While RB4 = 0 And t1db = 0 'Espera cambio de estado del puerto o desborde Timer
Wend
If t1db = True Then Exit 'Termina la función si Timer se desbordo
'Solicitud de una lectura al sensor -------------------------------------
TRISB.4 = 0
RB4 = 0
WaitMs 2
'MCU se prepara para recibir datos --------------------------------------
Call _initmer() 'Puesta a cero del Timer
TRISB.4 = 1 'Bus como Read
While RB4 = 1 And t1db = False 'Esperando respuesta o desborde del Timer
Wend
If t1db = True Then Exit 'Termina la función si Timer se desbordo
Call _initmer() 'Puesta a cero del Timer
While RB4 = 0 And t1db = 0 'Esperando respuesta o desborde del Timer
Wend
If t1db = True Then Exit 'Termina la función si Timer se desbordo
Call _initmer() 'Puesta a cero del Timer
While RB4 = 1 And t1db = False 'Esperando respuesta o desborde del Timer
Wend
If t1db = True Then Exit 'Termina la función si Timer se desbordo
'Read data, recepción RH, TMP y Checksum ---------------------------------
n = 0
While n < 40
Call _initmer() 'Puesta a cero del Timer
While RB4 = 0 And t1db = False 'Esperando que termine sincronismo del dato o desborde Timer
Wend
If t1db = True Then Exit 'Termina la función si tmr se desbordo
Call _initmer() 'Puesta a cero del Timer
While RB4 = 1 And t1db = False 'Midiendo el ancho del pulso de la parte del dato significativa
Wend
v_aux(n) = _tmer() 'Va asignando los tiempos medidos a los elementos del vector contenedor
n = n + 1 'Incrementa el indice del vector contenedor
If t1db = True Then Exit 'Termina la función si tmr se desbordo
Wend
'Transfiere los tiempos capturados a datos -------------------------------
'Humedad relativa
n = 0
x = 15
While n < 16
If v_aux(n) < clock Then rh = _bitfalse(rh, x)
If v_aux(n) > clock Then rh = _bittrue(rh, x)
n = n + 1
x = x - 1
Wend
'Temperatura
n = 16
x = 15
While n < 32
If v_aux(n) < clock Then tmp = _bitfalse(tmp, x)
If v_aux(n) > clock Then tmp = _bittrue(tmp, x)
n = n + 1
x = x - 1
Wend
'Checksum del sensor
n = 32
x = 7
While n < 40
If v_aux(n) < clock Then chk = _bitfalse(chk, x)
If v_aux(n) > clock Then chk = _bittrue(chk, x)
n = n + 1
x = x - 1
Wend
'Comprueba que los checksum son iguales y asigna valores a la variable de salida ----
chk_aux = rh.HB + rh.LB + tmp.HB + tmp.LB 'Checksum calculado
If chk_aux = chk Then 'Si los checksum son iguales...
_rht03.HW = rh 'Asigna la humedad realativa al Word superior
_rht03.LW = tmp 'Asigna la temperatura al Word inferior
Endif
End Function
'Flash led en mSeg., no retorna valor
'Call _flashled(50) 'Flash led de 50 mSeg.
Proc _flashled(_timeflash As Byte)
_timeflash = _timeflash / 2
RB1 = 1
WaitMs _timeflash
RB1 = 0
WaitMs _timeflash
End Proc
'Reinicia y pone a contar al TMR1, no retorna valor
'Call _initmer()
Proc _initmer()
TMR1H = 0x00 'Borra el registro alto del timer1
TMR1L = 0x00 'Borra el registro bajo del timer1
PIR1.TMR1IF = 0 'Flash dosborde a cero
T1CON.TMR1ON = 1 'Activa el contador del TMR1
End Proc
'Devuelve la lectura del TMR1, retorna valor
'Retorna en _tmer el contador del Timer
'valor_contador = _tmer() o Call _tmer()
Function _tmer() As Word
T1CON.TMR1ON = 0 'Para el contador del TMR1
_tmer.HB = TMR1H 'Asigna registro de más peso
_tmer.LB = TMR1L 'Asigna registro de menos peso
End Function
'**************************************************************************
'Cambia a 1 el valor de un bit especifico de un registro hasta Long
'_reg es la variable o registro de entrada
'_bit es el numero de orden del bit a modificar, de 0 a ...
'Mediante _bittrue se transfiere el valor del bit modificado
Function _bittrue(_reg As Long, _bit As Byte) As Long
Dim _byte As Long
_byte = 1
_byte = ShiftLeft(_byte, _bit)
_reg = _reg Or _byte
_bittrue = _reg
End Function
'Cambia a 0 el valor de un bit especifico de un registro hasta Long
'_reg es la variable o registro de entrada
'_bit es el numero de orden del bit a modificar, de 0 a ...
'Mediante _bitfalse transfiere el valor del bit modificado
Function _bitfalse(_reg As Long, _bit As Byte) As Long
Dim _byte As Long
_byte = 1
_byte = ShiftLeft(_byte, _bit)
_byte = _byte Nand 0xffff
_reg = _reg And _byte
_bitfalse = _reg
End Function
AllDigital
Define CLOCK_FREQUENCY = 20
'configuracion de display
Define LCD_BITS = 8
Define LCD_DREG = PORTD
Define LCD_DBIT = 0
Define LCD_RSREG = PORTB
Define LCD_RSBIT = 2
Define LCD_RWREG = PORTB
Define LCD_RWBIT = 3
Define LCD_EREG = PORTB
Define LCD_EBIT = 4
Lcdinit
'configuracion puerto I2C
Symbol sda = PORTB.0
Symbol scl = PORTB.1
'configuracion de variables
'Dim var_tabla(22) As Byte
Dim ac1 As Word
Dim ac2 As Word
Dim ac3 As Word
Dim ac4 As Word
Dim ac5 As Word
Dim ac6 As Word
Dim b1 As Word
Dim b2 As Word
Dim mb As Word
Dim mc As Word
Dim md As Word
Dim lsb As Byte
Dim xlsb As Byte
Dim msb As Byte
Dim up As Word
Dim up2 As Word
Dim oss As Long
oss = 0
Dim t As Byte
t = 8 - oss
'Gosub leer_memo
Gosub leer_memo
WaitMs 25
Gosub mostrar
inicio:
Gosub presion
'Gosub cal_press
Goto inicio
End
leer_memo:
I2CRead sda, scl, 0x77, 0xaa, ac1.LB
WaitMs 20
I2CRead sda, scl, 0x77, 0xac, ac2.LB
WaitMs 20
I2CRead sda, scl, 0x77, 0xae, ac3.LB
WaitMs 20
I2CRead sda, scl, 0x77, 0xb0, ac4.LB
WaitMs 20
I2CRead sda, scl, 0x77, 0xb2, ac5.LB
WaitMs 20
I2CRead sda, scl, 0x77, 0xb4, ac6.LB
WaitMs 20
I2CRead sda, scl, 0x77, 0xb6, b1.LB
WaitMs 20
I2CRead sda, scl, 0x77, 0xb8, b2.LB
WaitMs 20
I2CRead sda, scl, 0x77, 0xba, mb.LB
WaitMs 20
I2CRead sda, scl, 0x77, 0xbc, mc.LB
WaitMs 20
I2CRead sda, scl, 0x77, 0xbe, md.LB
WaitMs 20
Return
mostrar:
Lcdcmdout LcdClear
Lcdout "ac1:", #ac1, "/", "ac2:", #ac2
Lcdcmdout LcdLine2Home
Lcdout "ac3:", #ac3, "/", "ac4:", #ac4
WaitMs 5000
Lcdcmdout LcdClear
Lcdout "ac5:", #ac5, "/", "ac6:", #ac6
Lcdcmdout LcdLine2Home
Lcdout "b1:", #b1, "/", "b2:", #b2
WaitMs 5000
Lcdcmdout LcdClear
Lcdout "mb:", #mb, "/", "mc:", #mc
Lcdcmdout LcdLine2Home
Lcdout "md:", #md
WaitMs 5000
Return
presion:
I2CWrite sda, scl, 0x77, 0x34, 0xf4
WaitMs 5
I2CRead sda, scl, 0x77, 0xf6, msb
I2CRead sda, scl, 0x77, 0xf7, lsb
I2CRead sda, scl, 0x77, 0xf8, xlsb
msb = ShiftRight(msb, 16)
lsb = ShiftRight(lsb, 8)
up = msb + lsb + xlsb
up2 = ShiftLeft(up, t)
WaitMs 5000
Gosub lcd
Return
lcd:
lcd:
Lcdcmdout LcdClear
Lcdout "msb:", #msb, "/", "LSB:", #lsb
Lcdcmdout LcdLine2Home
Lcdout "xlsb:", #xlsb, "/"
WaitMs 5000
Lcdcmdout LcdClear
Lcdout "up:", #up
Lcdcmdout LcdLine2Home
Lcdout "up2:", #up
WaitMs 5000
Return
'******************************************************************************
'Ejemplo de RingBuffer + Bases de Tiempos *************************************
'Eco al puerto serie 38400 Baudios, control LCD, parpadeo Led *****************
'By COS, 11/2013, Pic Simulator IDE v6.94 *************************************
'Pic EBasic con 16F88 *********************************************************
'******************************************************************************
Define CONFIG = 0x2f50 'Definición de fuses
Define CONFIG2 = 0x0000
Define CLOCK_FREQUENCY = 8 'Clock a 8Mhz
Call _setupebasic() 'Iniciliza la placa entrenadora Pic EBasic
Lcdinit 'Activa el LCD
Hseropen 38400 'Selecciona la velocidad del puerto serie RS232
Call _setuprbf() 'Inicializa el Ring Buffer
Call _setupbt(0xf830) 'Incializa el TMR1 (1mSeg. a 8Mhz) y bases de tiempos
INTCON.PEIE = 1 'Bit habilita interrupciones perifericos
Enable 'INTCON.GIE habilita las interrupciones globales
Lcdout "Test RingBuffer" 'Datos al Lcd
Hserout CrLf, CrLf 'Linea en blanco al hyperterminal
Call _pause(1000) 'Pausa de 1Seg.
'Rutina principal
main:
If _btimer.0 = True Then 'Se refresca el display cada 50mSeg.
Call _rldbt(0, 50) 'Recarga base de tiempos 0 con 50mSeg.
Lcdcmdout LcdLine2Home 'Se imprimira al principio de la linea dos
Lcdout "Buffer:", #_buffer, " " 'Muestra los carracteres que tiene Buffer
Endif
Call error_buffer() 'Controla el posible bloqueo del módulo Usart en modo Rx
If _btimer.2 = 1 Then ledv = 1 'Led amarillo apagado
If _buffer > 0 Then 'Si hay datos en el buffer se lee
Call _rldbt(2, 50) 'Recarga la base de tiempos 2 con 50mSeg.
ledv = 0 'Led amarillo encendido, actividad en el buffer
Call _receive() 'Lee un caracter del buffer
If _receive = 13 Then Hserout CrLf 'Línea nueva en el hyperterminal
Hserout _receive 'Envia el dato recibido al hyperterminal
Endif
'Parpadea led amarillo
If _btimer.1 Then 'Si la base de tiempos 1 termino de contar
Call _rldbt(1, 500) 'Recarga base de tiempos 0 con 500mSeg.
Toggle leda 'Invierte el estado del led amarillo
Endif
Goto main
End
'Biblioteca de funciones
Include "_ProcSetUpEBasic.bas"
Include "_FuncionesUartRingBuffer.bas"
Include "_FuncionesBasesTimer8_Pic16.bas"
'*******************************************************************************
'Gestión de interrupciones
On Interrupt
Save System
Call _ringbuffer(0) 'Llama a la función ringbuffer, desde las interrupciones
Call _basestiempos() 'Actualiza las bases de tiempos
Resume
'******************************************************************************
'Ejemplo de RingBuffer + Bases de Tiempos_01 **********************************
'Eco al puerto serie 38400 Baudios, control LCD, parpadeo Led *****************
'By COS, 11/2013, Pic Simulator IDE v6.94 *************************************
'Pic EBasic con 16F88 *********************************************************
'******************************************************************************
Define CONFIG = 0x2f50 'Definición de fuses
Define CONFIG2 = 0x0000
Define CLOCK_FREQUENCY = 8 'Clock a 8Mhz
Call _setupebasic() 'Iniciliza la placa entrenadora Pic EBasic
Lcdinit 'Activa el LCD
Hseropen 38400 'Selecciona la velocidad del puerto serie RS232
Call _setuprbf() 'Inicializa el Ring Buffer
Call _setupbt(0xf830) 'Incializa el TMR1 (1mSeg. a 8Mhz) y bases de tiempos
INTCON.PEIE = 1 'Bit habilita interrupciones perifericos
Enable 'INTCON.GIE habilita las interrupciones globales
Lcdout "Test RingBuffer" 'Datos al Lcd
Hserout CrLf, CrLf 'Linea en blanco al hyperterminal
Call _pause(1000) 'Pausa de 1Seg.
'Rutina principal
Dim string(26) As Byte
Dim indice As Byte
Dim vdatos As Word 'Tiempo de validación de los datos recibidos.
indice = 0
vdatos = 3000 'Validación de los datos a los 3Seg. de no haber actividad en el puerto serie.
main:
If _btimer.0 = True Then 'Se refresca el display cada 50mSeg.
Call _rldbt(0, 50) 'Recarga base de tiempos 0 con 50mSeg.
Lcdcmdout LcdLine2Home 'Se imprimira al principio de la linea dos
Lcdout "Buffer:", #_buffer, " " 'Muestra los carracteres que tiene Buffer
Endif
Call error_buffer() 'Controla el posible bloqueo del módulo Usart en modo Rx
If _btimer.2 = True Then ledv = 1 'Led amarillo apagado
If _buffer > 0 Then 'Si hay datos en el buffer se lee
Call _rldbt(2, 50) 'Recarga la base de tiempos 2 con 50mSeg.
ledv = 0 'Led amarillo encendido, actividad en el buffer
Call _receive() 'Lee un caracter del buffer
If _receive = 13 Then Hserout CrLf 'Línea nueva en el hyperterminal
Hserout _receive 'Envia el dato recibido al hyperterminal (modo eco)
string(indice) = _receive 'Añade el byte del buffer al vector
If indice < 25 Then indice = indice + 1 'Incrementa el indice del vector
string(indice) = 0 'Marca fin de cadena
Call _rldbt(3, vdatos) 'Reset al contador de actividad del puerto serie, tiempo validación
Endif
'Envia al puerto serie la cadena almacenada si no se recibieron datos por más de 1Seg.
If _btimer.3 = True Then 'Flag base de tiempos 3
indice = 0 'Reset al indice
Hserout CrLf 'Nueva línea al pureto serie
While string(indice) > 0 'Bucle que recorre la cadena
Hserout string(indice) 'Envia un elemento de la cadena al puerto serie
indice = indice + 1 'Incrementa el indice
Wend
Hserout CrLf 'Nueva al puerto serie
indice = 0 'Reset al indice
_btimer.3 = False 'Impide que se repita esta rutina
Endif
'Parpadea led amarillo
If _btimer.1 Then 'Si la base de tiempos 1 termino de contar
Call _rldbt(1, 500) 'Recarga base de tiempos 0 con 500mSeg.
Toggle leda 'Invierte el estado del led amarillo
Endif
Goto main
End
'Biblioteca de funciones
Include "_ProcSetUpEBasic.bas"
Include "_FuncionesUartRingBuffer.bas"
Include "_FuncionesBasesTimer8_Pic16.bas"
'*******************************************************************************
'Gestión de interrupciones
On Interrupt
Save System
Call _ringbuffer(0) 'Llama a la función ringbuffer, desde las interrupciones
Call _basestiempos() 'Actualiza las bases de tiempos
Resume
'******************************************************************************
'Ejemplo de Buffer Serie ******************************************************
'Puerto serie 38400 Baudios, almacena en una cadena los bytes recibidos *******
'By COS, 11/2013, Pic Simulator IDE v6.94 *************************************
'Pic EBasic con 16F88 *********************************************************
'******************************************************************************
Define CONFIG = 0x2f50 'Definición de fuses
Define CONFIG2 = 0x0000
Define CLOCK_FREQUENCY = 8 'Clock a 8Mhz
Call _setupebasic() 'Iniciliza la placa entrenadora Pic EBasic
Lcdinit 'Activa el LCD
Hseropen 38400 'Selecciona la velocidad del puerto serie RS232
Call _setupbf() 'Inicializa el Buffer
INTCON.PEIE = 1 'Bit habilita interrupciones perifericos
Enable 'INTCON.GIE habilita las interrupciones globales
Lcdout "Test Buffer" 'Datos al Lcd
Hserout CrLf, CrLf 'Linea en blanco al hyperterminal
WaitMs 100
'Rutina principal
Dim indice As Byte
indice = 0
main:
Call _error_buffer() 'Controla el posible bloqueo del módulo Usart en modo Rx
'Envia los datos recibidos dureante 3Seg al puerto serie.
If _buffer > 0 Then 'Hay datos en el buffer, numero de bytes.
WaitMs 3000 'Pausa de 3Seg. más demoras interrupciones
indice = 0 'Reset al indice
Hserout CrLf 'Nueva línea al puerto serie
While _string(indice) > 0 'Bucle que recorre la cadena
Hserout _string(indice) 'Envia un elemento de la cadena al puerto serie
indice = indice + 1 'Incrementa el indice
Wend
Hserout CrLf 'Nueva línea al puerto serie
Call _setupbf() 'Inicializa el buffer, permite recibir una nueva trama de datos
Endif
Goto main
End
'Biblioteca de funciones
Include "_ProcSetUpEBasic.bas"
'*******************************************************************************
'Funciones para la implementación de un buffer serie
Dim _string(81) As Byte 'Vector del buffer
Dim _buffer As Byte 'Numero de bytes recibidos
Function _rsbuffer(_ctrol As Byte) As Byte
Dim _lenbuffer As Byte
Dim _indice As Byte
'Incializa el buffer
If _ctrol = 1 Then 'Inicializa la función ringbuffer
_buffer = 0
_lenbuffer = 80 'Numero de elementos -1
RCSTA.CREN = 0 'Disable, continua recepción
Hserget _indice 'Vacia registros usart
Hserget _indice
Hserget _indice
RCSTA.CREN = 1 'Enable, Continuous Receive Enable bit*/
_indice = 0
Endif
'Buffer y control
If _ctrol = 0 Then
If PIR1.RCIF = 1 Then 'Si la interrupción de la Usart está activa
Hserget _string(_indice) 'Extrae el byte de la Usart y lo almacena
If _indice < _lenbuffer Then _indice = _indice + 1 'Incrementa el indice del buffer
_string(_indice) = 0 'Marca final de la cadena recibida
Endif
Endif
_buffer = _indice 'Numero de caracteres recibidos
End Function
'Incializa el buffer
Proc _setupbf()
PIE1.RCIE = 0 'Disable la interrupcion de la usart en modo rx*/
Call _rsbuffer(1)
PIE1.RCIE = 1 'Activa la interrupcion de la usart en modo rx*/
End Proc
'Comprueba si hay error de recepción en la Usart y la desbloquea.
Proc _error_buffer()
If RCSTA.OERR = True Then
Disable
Call _rsbuffer(1)
PIE1.RCIE = 1 'Activa la interrupcion de la usart en modo rx*/
Enable
Endif
End Proc
'*******************************************************************************
'Gestión de interrupciones
On Interrupt
Save System
Call _rsbuffer(0) 'Llama a la función _rsbuffer, desde las interrupciones
Resume
'**********************************************************************************
'Funsion para HC-SR04.bas
'Funciones para la medición de distancia con el sensor HC-SR04 con TMR1
'Placa PicEBasic, By COS, 11/2018, 11/2013
'Basic Pic Simulator IDE (PSI), v7.48, Pic16F88
'**********************************************************************************
'----------------------------------------------------------------------------------
Define CONF_WORD = 0x2f50
Define CONF_WORD_2 = 0x3ffc
Define CLOCK_FREQUENCY = 8 'Oscilador a 8Mhz
'Define SIMULATION_WAITMS_VALUE = 1 'Activar para simulación
Include "_ProcSetUpEBasic.bas"
Include "_FuncionesPic16F88.bas"
'-----------------------------------------
Call _setupebasic() 'Inicializa la placa entrenadora PicEBasic.
Hseropen 38400 'Inicializa puerto RS232 por hardware a 38400Baudios
Lcdinit 'Inicializa el LCD sin cursor
WaitMs 100 'Pausa de 100 mSeg.
Lcdout "Test P. HC-SR04" 'Imprime el texto en el LCD
WaitMs 2000 'Pausa de 2 Seg.
'-----------------------------------------
void_main:
Symbol _ledsr04 = RA4 'Se asigna pin del LED placa adaptadora
ConfigPin _ledsr04 = Output 'Led, salida
Call _setup_hcsr04(8, 0, 0) 'Oscilador, compensación positiva, compensación negativa
Dim distancia_mm As Word
Dim main As Byte
While main = main
'Muestra lecturas
_ledsr04 = True 'Led a On
distancia_mm = _gethcsr04() 'Lee sensor
WaitMs 50 'Pausa para que se vea el led iluminado
_ledsr04 = False 'Led a Off
Lcdcmdout LcdLine2Home 'Cursor al principio de la linea2
Lcdout "HC-SR04: ", #distancia_mm, "mm " 'Salida de datos por el LCD
Hserout "HC-SR04: ", #distancia_mm, "mm", CrLf 'Salida de datos por Usart
Wend
End
'-------------------------------------------------
'Funciones para el control del sensor HC-SR04
'********************************************************************
'Funcion para la configuración de la función principal
'_clk = Mhz del reloj del sistema
'_mas = factor de correción positivo, incrementa la lectura final
'_menos = factor de correción negativo, decrementa la lectura final
'Call _setup_hcsr04(Mhz reloj, incremento, decremento)
Proc _setup_hcsr04(_clk As Byte, _mas As Byte, _menos As Byte)
Call _hcsr04(_clk, _mas, _menos, 0)
End Proc
'Función para la lectura del sensor
'Retorna una lectura en mm del sensor HC-SR04
'_GetHCSR04 = retorna la lectura en mm del sensor
'Lectura = _GetHCSR04()
Function _gethcsr04() As Word
_gethcsr04 = _hcsr04(0, 0, 0, 1)
End Function
'Función principal de lectura y control del sensor HC-SR04
'Funcion de lectura y control del sensor HC-SR04, devuelve valor
'_clk = Mhz del reloj del sistema
'_mas = factor de correción positivo, incrementa la lectura final
'_menos = factor de correción negativo, decrementa la lectura final
'_ctrl = configración
'Call _gethcsr04(Mhz reloj, incremento, decremento, control)
'_gethcsr04 > de 0 lectura en mm, = 0 error de lectura
Symbol _echosr04 = RB4 'Se asigna pin del ECHO
Symbol _trigersr04 = RB1 'Se asigna pin del TRIGER
Function _hcsr04(_mhz As Byte, _mas As Byte, _menos As Byte, _ctrl As Byte) As Word
Dim _auxw As Word
Dim _auxl As Long
Dim _aux_mhz As Byte
Dim _aux_mas As Byte
Dim _aux_menos As Byte
_hcsr04 = 0 'Se marca error de lectura por defecto
'Inicializa la función
If _ctrl = 0 Then
ConfigPin _echosr04 = Input 'Echo, entrada
ConfigPin _trigersr04 = Output 'Triger, salida
_trigersr04 = False 'Inicializa el Triger
_aux_mhz = _mhz / 4 'Factor corrección a uSeg.
_aux_mas = _mas 'Calibrado positivo
_aux_menos = _menos 'Calibrado negativo
Call _setup_timer1(_tmr1_internal, _tmr1_div1) 'Configura el timer1
Call _timer1(True) 'Pone en marcha el timer1
'Call _disable_interrupts(_int_timer1) 'Desactiva las interrupciones del Timer1
Exit 'Fuerza la salida de la función
Endif
'Solicitud de una lectura al sensor -------------------------------------
'Se demanda lectura
_trigersr04 = True 'Inicia pulso del Triger
WaitUs 15 'Ancho del pulso del Triger en uSeg., minimo 10uSeg.
_trigersr04 = False 'Fin del pulso del Triger
Call _clear_timer1() 'Se borra el contador del Timer
While _echosr04 = False 'Se espera hasta que el sensor inicie una lectura
If _tmr1if = True Then Exit 'Fin si desbordo el Timer
Wend
Call _clear_timer1() 'Se borra el contador del Timer
While _echosr04 = True 'Se espera hasta que el sensor inicie fin de lectura
If _tmr1if = True Then Exit 'Fin si desbordo el Timer
Wend
_auxw = _get_timer1() 'Asigna la lectura del Timer
_auxw = ((_auxw / _aux_mhz) + _aux_mas) - _aux_menos 'Calibrado
'_auxl = ((_auxw * 340) / 2) / 1000 'Milimetros
_auxl = (_auxw * 34) / 200 'Milimetros
_hcsr04 = _auxl 'Pasa valor
End Function
'**************************************************************************
'**********************************************************************************
'Funcion _getpulsewidthin aplicado HC-SR04.bas
'Funciones para la medición del ancho de pulso de una señal externa con TMR1
'Aplicado a la lectura del sensor por ultrasonidos HC-SR04
'Placa PicEBasic, By COS, 11/2018, 12/2013
'Basic Pic Simulator IDE (PSI), v7.48, Pic16F88
'**********************************************************************************
'----------------------------------------------------------------------------------
Define CONF_WORD = 0x2f50
Define CONF_WORD_2 = 0x3ffc
Define CLOCK_FREQUENCY = 8 'Oscilador a 8Mhz
Define SINGLE_DECIMAL_PLACES = 1
'Define SIMULATION_WAITMS_VALUE = 1 'Activar para simulación
'Bibliotecas usadas:
Include "_ProcSetUpEBasic.bas"
Include "_FuncionesPic16F88.bas"
Include "_FuncionesCapturaAnchoPulso.bas"
'-----------------------------------------
Call _setupebasic() 'Inicializa la placa entrenadora PicEBasic.
Hseropen 38400 'Inicializa puerto RS232 por hardware a 38400Baudios
Lcdinit 'Inicializa el LCD sin cursor
WaitMs 100 'Pausa de 100 mSeg.
Lcdout "Sensor HC-SR04" 'Imprime el texto en el LCD
WaitMs 2000 'Pausa de 2 Seg.
'-----------------------------------------
voidmain:
Symbol trigger = RB1 'Se asigna pin del TRIGGER para HC-SR04
Symbol _ledsr04 = RA4 'Se asigna pin del LED placa adaptadora HC-SR04
ConfigPin _ledsr04 = Output 'Led, salida
ConfigPin trigger = Output 'Trigger, salida
'Espencificar pin de adquisición en la función
'(Symbol _pinpulsewidthin = RB4 'Se asigna pin por donde se aplica la señal)
Call _setup_pulsewidthin(8) 'Se inicializa la función _pulsewidthin (oscilador y TMR1).
trigger = False 'Inicializa el Trigger
_ledsr04 = False 'Led a Off
Dim useg As Word
Dim main As Byte
Dim mm As Long
While main = main
'Activa una lectura del sensor HC-SR04
trigger = True 'Inicia pulso del Triger
WaitUs 15 'Ancho del pulso del Triger en uSeg., minimo 10uSeg.
trigger = False 'Fin del pulso del Triger
'Devuelve la lectura en uSegundos.
_ledsr04 = True 'Led a On
'Lee el ancho de pulso positivo del sensor durante un tiempo máximo de espera de 10mSeg.
useg = _getpulsewidthin(1, 100)
mm = (useg * 34) / 200 'Pasa a milimetros la lectura dada en uSeg.
WaitMs 300 'Pausa para que de tiempo a ver el led iluminado.
_ledsr04 = False 'Led a Off
'Muestra los datos por LCD y puerto serie RS232
Lcdcmdout LcdLine1Home 'Cursor al principio de la linea1
Lcdout "Tmp: ", #useg, "uSeg. " 'Salida de datos por el LCD
Lcdcmdout LcdLine2Home 'Cursor al principio de la linea2
Lcdout "Dist: ", #mm, "mm " 'Salida de datos por el LCD
Hserout "Lectura: ", #useg, "uSeg." 'Salida de datos por Usart (RS232)
Hserout "Distancia: ", #mm, "mm", CrLf 'Salida de datos por Usart (RS232)
Wend
End
'********************************************************************
AllDigital
Define CLOCK_FREQUENCY = 20
'configuracion de parametros para dht22
CMCON = 0x07
OSCCON = 0x7e
Dim hr As Word
Dim tmp As Word
Dim chk As Word
TRISA.1 = 1 'entrada RHT03 inicio
WaitMs 100
Call _rht03ini(8)
WaitMs 2000
'configuracion canales analogicos
'ADCON1 = %00001010
'Dim adc As Word
'adc = 0
'configuracion de puerto
Symbol tx = PORTC.6
'configuracion puerto i2c
Symbol sda = PORTB.0
Symbol scl = PORTB.1
'configuracion parametros de reloj
Dim seg As Byte
Dim min As Byte
Dim hora As Byte
Dim daym As Byte
Dim dias As Byte
Dim mes As Byte
Dim anno As Byte
Dim seg1 As Byte
Dim min1 As Byte
Dim hora1 As Byte
Dim dias1 As Byte
Dim mes1 As Byte
Dim anno1 As Byte
Dim y As Word
'sincronizacion de reloj y toma de datos
Gosub lcd3
Gosub reloj_rtc
Gosub calculo1
Gosub calculo
While y > 0
y = y - 1
Gosub lcd
Wend
'termino sincronizacion salto a inicio y comienza trabajo datalogger
inicio:
Call _rht03read()
hr = _ped1(_rht03read.HW)
tmp = _ped1(_rht03read.LW)
chk = _rht03chk()
'Adcin 1, adc
Gosub reloj_rtc
Gosub lcd3
Gosub calculo1
If seg1 = 0 Or seg1 = 10 Or seg1 = 20 Or seg1 = 30 Or seg1 = 40 Or seg1 = 50 Then
Gosub enviar
Endif
Goto inicio
End
Include "humedad.bas"
Include "trabajando con bits.bas"
reloj_rtc:
I2CRead sda, scl, 0xd1, 0x00, seg
WaitMs 20
I2CRead sda, scl, 0xd1, 0x01, min
WaitMs 20
I2CRead sda, scl, 0xd1, 0x02, hora
WaitMs 20
I2CRead sda, scl, 0xd1, 0x03, daym
WaitMs 20
I2CRead sda, scl, 0xd1, 0x04, dias
WaitMs 20
I2CRead sda, scl, 0xd1, 0x05, mes
WaitMs 20
I2CRead sda, scl, 0xd1, 0x06, anno
WaitMs 20
Return
calculo1:
'conversion de hexa a decimal segundos
If seg >= 0 And seg <= 9 Then seg1 = seg
If seg >= 16 And seg <= 25 Then seg1 = seg - 6
If seg >= 32 And seg <= 41 Then seg1 = seg - 12
If seg >= 48 And seg <= 57 Then seg1 = seg - 18
If seg >= 64 And seg <= 73 Then seg1 = seg - 24
If seg >= 80 And seg <= 89 Then seg1 = seg - 30
'conversion de hexa a decimal minutos
If min >= 0 And min <= 9 Then min1 = min
If min >= 16 And min <= 25 Then min1 = min - 6
If min >= 32 And min <= 41 Then min1 = min - 12
If min >= 48 And min <= 57 Then min1 = min - 18
If min >= 64 And min <= 73 Then min1 = min - 24
If min >= 80 And min <= 89 Then min1 = min - 30
'conversion de hexa a decimal hora
If hora >= 0 And hora <= 9 Then hora1 = hora
If hora >= 16 And hora <= 25 Then hora1 = hora - 6
If hora >= 32 And hora <= 41 Then hora1 = hora - 12
'conversion de hexa a decimal dias
If dias >= 0 And dias <= 9 Then dias1 = dias
If dias >= 16 And dias <= 25 Then dias1 = dias - 6
If dias >= 32 And dias <= 41 Then dias1 = dias - 12
If dias >= 48 And dias <= 57 Then dias1 = dias - 18
'conversion de hexa A decimal mes
If mes >= 0 And mes <= 9 Then mes1 = mes
If mes >= 16 And mes <= 25 Then mes1 = mes - 6
'conversion de hexa a decimal año
If anno >= 0 And anno <= 9 Then anno1 = anno
If anno >= 16 And anno <= 25 Then anno1 = anno - 6
Return
calculo:
If min1 >= 0 And min1 <= 4 Then y = 300 - min1 * 60 - (60 - (63 - seg1))
If min1 >= 5 And min1 <= 9 Then y = 600 - min1 * 60 - (60 - (63 - seg1))
If min1 >= 10 And min1 <= 14 Then y = 900 - min1 * 60 - (60 - (63 - seg1))
If min1 >= 15 And min1 <= 19 Then y = 1200 - min1 * 60 - (60 - (63 - seg1))
If min1 >= 20 And min1 <= 24 Then y = 1500 - min1 * 60 - (60 - (63 - seg1))
If min1 >= 25 And min1 <= 29 Then y = 1800 - min1 * 60 - (60 - (63 - seg1))
If min1 >= 30 And min1 <= 34 Then y = 2100 - min1 * 60 - (60 - (63 - seg1))
If min1 >= 35 And min1 <= 39 Then y = 2400 - min1 * 60 - (60 - (63 - seg1))
If min1 >= 40 And min1 <= 44 Then y = 2700 - min1 * 60 - (60 - (63 - seg1))
If min1 >= 45 And min1 <= 49 Then y = 3000 - min1 * 60 - (60 - (63 - seg1))
If min1 >= 50 And min1 <= 54 Then y = 3300 - min1 * 60 - (60 - (63 - seg1))
If min1 >= 55 And min1 <= 59 Then y = 3600 - min1 * 60 - (60 - (63 - seg1))
Return
enviar:
Serout tx, 9600, #hora1
WaitMs 10
Serout tx, 9600, ":"
WaitMs 10
Serout tx, 9600, #min1
WaitMs 10
Serout tx, 9600, ":"
WaitMs 10
Serout tx, 9600, #seg1
WaitMs 10
Serout tx, 9600, ";"
WaitMs 10
Serout tx, 9600, #hr.HB
WaitMs 10
Serout tx, 9600, "."
WaitMs 10
Serout tx, 9600, #hr.LB
WaitMs 10
Serout tx, 9600, ";"
WaitMs 10
Serout tx, 9600, #tmp.HB
WaitMs 10
Serout tx, 9600, "."
WaitMs 10
Serout tx, 9600, #tmp.LB, CrLf
WaitMs 10
Return
¿Que datalogger es para echarle un vistazo?.
MODE = 0
ASCII = y
Baud = 4
Frequency = 100
Trigger Character = $
Text Frame = 100
AD1.3 = N
AD0.3 = N
AD0.2 = N
AD0.1 = N
AD1.2 = N
AD0.4 = N
AD1.7 = N
AD1.6 = N
Saftey On = Y
'Funciones Push/Pop por software
'PIC16F88, PSI v.7.39_02, By DogFlu66
'02/09/2015: Se implementan funciones Push_Single/Pop_Single
'09/2014: Funcion Stack (Push y Pop), trabajando con un software stack
'hay que especificar los tipos asbyte, aswork y aslong
'-------------------------------------------------------------------
Include "FuncionesStack_Push&Pop.bas"
Define CLOCK_FREQUENCY = 8
Define SINGLE_DECIMAL_PLACES = 2
Define SIMULATION_WAITMS_VALUE = 1 'Ignora los Waitms
'-------------------------------------------------------------------
AllDigital 'Pin como digitales
TRISA = %00000000 'Pin como salidas (si lo permiten)
TRISB = %00000000 'Pin como salidas
'Abre puerto serie
Hseropen 4800 'Configura puerto serie harware a 4800baudios
'-------------------------------------------------------------------
'Rutina principal
main:
Dim x As Byte
Dim x1 As Word
Dim x2 As Long
Dim x3 As Single
Dim y As Long
Dim y1 As Single
Call _setup_stack() 'Inicializa la pila Stack por software
x = 101
x1 = 1001
x2 = 910001
x3 = 0.1
Hserout "x = 101, x1 = 1001, x2 = 910001, x3 = 0.1", CrLf, CrLf 'Imprime en el Hyperterminal
Call _stack_buffer() 'Actualiza los bytes libres de la pila
Hserout "Stack_buffer = ", #_stack_buffer, CrLf
Call _push(x, _asbyte) 'Pone un Byte en la pila
Call _push(x1, _asword) 'Pone un Word en la pila
y = _pop(_asword)
Hserout "_Push(x, _asbyte)", CrLf
Hserout "_Push(x1, _asword)", CrLf
Hserout "y = _Pop(_asword)", CrLf
Hserout "Y:", #y, CrLf
Call _stack_buffer()
Hserout "Stack_Buffer = ", #_stack_buffer, CrLf, CrLf
Call _push(x1, _asword) 'Pone un Word en la pila
Call _push(x2, _aslong) 'Pone un Long en la pila
Call _push_single(x3) 'Pone un Single (Float simple) en la pila
Hserout "_Push(x1, _asword)", CrLf
Hserout "_Push(x2, _aslong)", CrLf
Hserout "_Push_single(x3)", CrLf
Call _stack_buffer()
Hserout "Stack_Buffer = ", #_stack_buffer, CrLf, CrLf
y1 = _pop_single() 'Extrae un Single de la pila
Hserout "y1 = _Pop_Single()", CrLf
Hserout "Y1:", #y1, CrLf
y = _pop(_aslong) 'Extrae un long de la pila
Hserout "y = _Pop(_aslong)", CrLf
Hserout "Y:", #y, CrLf
y = _pop(_asword) 'Extrae un Word de la pila
Hserout "y = _Pop(_asword)", CrLf
Hserout "Y:", #y, CrLf
y = _pop(_asbyte) 'Extrae un Byte de la pila
Hserout "y = _Pop(_asbyte)", CrLf
Hserout "Y:", #y, CrLf
Call _stack_buffer()
Hserout "Stack_Buffer = ", #_stack_buffer, CrLf, CrLf
x = 102
x1 = 1002
x2 = 910002
x3 = 0.2
Hserout "x = 102, x1 = 1002, x2 = 910002, x3 = 0.2", CrLf, CrLf
Call _push(x, _asbyte)
Call _push(x1, _asword)
Call _push(x2, _aslong)
Call _push_single(x3)
Call _stack_buffer()
Hserout "Stack_Buffer=", #_stack_buffer, CrLf, CrLf
y1 = _pop_single()
Hserout "Y1:", #y1, CrLf
y = _pop(_aslong)
Hserout "Y:", #y, CrLf
y = _pop(_asword)
Hserout "Y:", #y, CrLf
y = _pop(_asbyte)
Hserout "Y:", #y, CrLf
Call _stack_buffer()
Hserout "Stack_Buffer = ", #_stack_buffer, CrLf
Halt 'Stop
End