TODOPIC
Microcontroladores PIC => Lenguaje Basic para microcontroladores PIC => Mensaje iniciado por: WALTER ALEJANDRO en 29 de Septiembre de 2015, 20:02:09
-
Imprime en el LCD una variable tipo Long (Respuesta 659), este ejemplo esta mal, verificar que cuando llega a 1000 imprime cualquier cosa, en algun lugar hay un error y no lo puedo encontrar por favor revisar. Desde ya muchas gracias
-
Seria de gran ayuda que colocaras el programa que realizastes para poderte ayudar :mrgreen:
Saludos
-
Define CONF_WORD = 0x2f50 '/* FUSES
Define CONF_WORD_2 = 0x3ffd '*/
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj
'********************************************************
'FUNCION PARA IMPRIMIR UNA VARIABLE TIPO LONG EN EL LCD *
'NOMBRE: 16F88_PicEBasic_IMPRIMIR LONG POR EL LCD *******
'*************** 12/10/10 By COS ************************
'********************************************************
'----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 'Se usara el RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E sera del puerto B
Define LCD_EBIT = 6 'Se usara el RB6 como E
Define LCD_COMMANDUS = 2000 'Tmp de espera despues de ejecutar un comand del lcd en uSeg.
Define LCD_DATAUS = 50 'Tmp de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 5 '50 'Tmp 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. Configura ADC
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)
TRISA.6 = 1 'Como entrada (RA6, tecla E1)
TRISA.5 = 1 'Como entrada (RA5, tecla E2)
'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
'----VARIABLES GLOBALES
Dim dato As Long
'---INICIO
Lcdinit 'Inicializa el lcd sin cursor
Lcdcmdout LcdClear 'Limpia lcd y cursor principio linea 1
'----Rutina principal
main:
dato = 1234567890 'Dato a imprimir en el LCD
Lcdout "Print Long:" 'Imprime el texto en la primera linea display
Lcdcmdout LcdLine2Home 'Curso a principio de linea 2
Call longlcd(dato) 'Va a la funcion
End
'Imprime variable por el Lcd, hasta Long.
'Call longlcd(x), x es el numero a mostrar en el LCD.
'No devuelve datos
Proc longlcd(x As Long) 'Define funcion
Dim word2 As Word '/*Declaraciones de las variables
Dim word1 As Word
Dim word0 As Word
Dim aux_x As Long '*/
aux_x = x / 1000000 'Se extrae parte más significativa del Long
word2 = aux_x 'Se asigna los digitos más significativos del Long
aux_x = aux_x * 1000000 '/* Calculo de la segunda tanda de digitos del Long
x = x - aux_x
aux_x = x / 1000 '*/
word1 = aux_x 'Se asigna la segunda tanda de digitos
aux_x = aux_x * 1000 'Ultima tanda de digitos
word0 = x - aux_x 'Se asignan los ultimos digitos
If word2 > 0 Then Lcdout #word2 'Filtra valor cero
If word2 > 0 Or word1 > 0 Then Lcdout #word1 'Filtra valor cero
Lcdout #word0 'Imprime
End Proc
-
si corres el programa vas a ver que cuando deberia pasar de 999 a1000 imprime cualquier cosa,no probe al cambiar de 65535 a 65536 pero ya hay un error
-
arranque con el dato =0 y lo fui incrementado de a 1 cada ciclo del goto main de modo que pasaba 1,2,3...etc pero al llegar a 999 y pasar a 1000 ahi se cuelga
-
Nunca he usado PSI, pero viendo el manual, PSI soporta directamente la variable tipo LONG que es de 32 bits. No entiendo para que estas tratando de descomponer el valor el variables tipo word.
Todo lo que tendrias que hacer es imprimir el valor directamente usando:
lcdout #dato
a menos que PSI tenga alguna restriccion en cuanto al uso de las variables tipo long.
Saludos.
Elreypic.
-
tengo que aclarar que ese es un ejemplo que postearon los moderadores acerca del usodel PSI , y por lo visto no puede imprimir en el lcd directamente un long xq me da error al compilar, de ahi que seguramente se us la instruccion call
-
Una pregunta WALTER; el valor que te imprime despues del 999 es un 10 en lugar de 1000, o es un valor aleatorio?
Elreypic.
-
El ejemplo se quedó antiguo, actualmente si permite enviar los tipo Long (enteros sin signo 4Bytes) e incluso los reales (llamados Single en PSI y Float de 4Bytes en otros lenguajes).
De todos modos probare el ejemplo cuando tenga un rato libre.
-
He simulado el ejemplo como indicas y parece que el algoritmo no esta bien del todo, buscaré el ejemplo a ver si al hacer copy paste metí la pata.
De todas formas te dejo este otro para que experimentes:
Define CONF_WORD = 0x2f50 '/* FUSES
Define CONF_WORD_2 = 0x3ffd '*/
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj
'********************************************************
'FUNCION PARA IMPRIMIR UNA VARIABLE TIPO LONG EN EL LCD *
'NOMBRE: 16F88_PicEBasic_IMPRIMIR LONG POR EL LCD *******
'*************** 12/10/10 By COS ************************
'********************************************************
'----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 'Se usara el RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E sera del puerto B
Define LCD_EBIT = 6 'Se usara el RB6 como E
Define LCD_COMMANDUS = 2000 'Tmp de espera despues de ejecutar un comand del lcd en uSeg.
Define LCD_DATAUS = 50 'Tmp de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 5 '50 'Tmp 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. Configura ADC
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)
TRISA.6 = 1 'Como entrada (RA6, tecla E1)
TRISA.5 = 1 'Como entrada (RA5, tecla E2)
'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
'----VARIABLES GLOBALES
Dim dato As Long
'---INICIO
Lcdinit 'Inicializa el lcd sin cursor
Lcdcmdout LcdClear 'Limpia lcd y cursor principio linea 1
Lcdout "Print Long:"
'----Rutina principal
dato = 995
main:
Lcdcmdout LcdLine2Home 'Curso a principio de linea 2
Call _putlcd32(dato) 'Va a la funcion
dato = dato + 1
Goto main
End
'Retorna valor: Byte
'Extrae el digito indicado, hasta 10 digitos
'numero = Cifra a descomponer
'digito = Digito a extraer de 0 a 9
'Los digitos se nombras de derecha a izquierda, cero es el primero
'_getdig32, retorna el digito.
Function _getdig32(_numero As Long, _digito As Byte) As Byte
'Descompone el numero a mostrar en digitos
Dim _n As Byte
For _n = 1 To _digito
_numero = _numero / 10
Next _n
_getdig32 = _numero Mod 10
End Function
'No retorna valor
'Envia una variable numérica al LCD
Proc _putlcd32(_numero As Long)
Dim i As Byte
Dim digito As Byte
Dim flag As Byte
flag = 0
For i = 9 To 0 Step -1
digito = _getdig32(_numero, i)
If digito > 0 Then flag = 1
If flag > 0 Then Lcdout #digito
Next i
End Proc
-
Que tal WALTER,
El último ejemplo que colocó nuestro buen amigo dogflu es correcto. Prueba este último.
Saludos.
Elreypic.
-
Define CONF_WORD = 0x2f50 '/* FUSES
Define CONF_WORD_2 = 0x3ffd '*/
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj
'********************************************************
'FUNCION PARA IMPRIMIR UNA VARIABLE TIPO LONG EN EL LCD *
'NOMBRE: 16F88_PicEBasic_IMPRIMIR LONG POR EL LCD *******
'*************** 12/10/10 By COS ************************
'********************************************************
'----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 'Se usara el RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E sera del puerto B
Define LCD_EBIT = 6 'Se usara el RB6 como E
Define LCD_COMMANDUS = 2000 'Tmp de espera despues de ejecutar un comand del lcd en uSeg.
Define LCD_DATAUS = 50 'Tmp de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 5 '50 'Tmp 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. Configura ADC
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)
TRISA.6 = 1 'Como entrada (RA6, tecla E1)
TRISA.5 = 1 'Como entrada (RA5, tecla E2)
'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
'----VARIABLES GLOBALES
Dim dato As Long
'---INICIO
Lcdinit 'Inicializa el lcd sin cursor
Lcdcmdout LcdClear 'Limpia lcd y cursor principio linea 1
'----Rutina principal
main:
dato = 1234567890 'Dato a imprimir en el LCD
Lcdout "Print Long:" 'Imprime el texto en la primera linea display
Lcdcmdout LcdLine2Home 'Curso a principio de linea 2
Call longlcd(dato) 'Va a la funcion
End
'Imprime variable por el Lcd, hasta Long.
'Call longlcd(x), x es el numero a mostrar en el LCD.
'No devuelve datos
Proc longlcd(x As Long) 'Define funcion
Dim word2 As Word '/*Declaraciones de las variables
Dim word1 As Word
Dim word0 As Word
Dim aux_x As Long '*/
aux_x = x / 1000000 'Se extrae parte más significativa del Long
word2 = aux_x 'Se asigna los digitos más significativos del Long
aux_x = aux_x * 1000000 '/* Calculo de la segunda tanda de digitos del Long
x = x - aux_x
aux_x = x / 1000 '*/
word1 = aux_x 'Se asigna la segunda tanda de digitos
aux_x = aux_x * 1000 'Ultima tanda de digitos
word0 = x - aux_x 'Se asignan los ultimos digitos
If word2 > 0 Then Lcdout #word2 'Filtra valor cero
If word2 > 0 Or word1 > 0 Then Lcdout #word1 'Filtra valor cero
Lcdout #word0 'Imprime
End Proc
Ya probé el programa tal cual y no se cuelga.
-
lo corri en el simulador y cuando llega aproximadamente a 2700000000 ahi se cuelga y empieza a tirar datos erroneos
consideren que fui aproximado passando de 999 y ver como cambiaba y 9999 y asi seguidamente.Pero segun el simulador hay algun error. Cuando tenga un rato lo paso al mundo real ya que la plaqueta la tengo armada.Gracias x el momento y a seguir luchando
-
si erreypic2 efectivamente ese era un error
-
el programa que puso dogflu66 tambien se cuelga, veras, si en lugar de 1234567890 le pones 1000000000 tambien tira cualquier cosa en el display , ese programa fue el peimero que tome de hilo de psi y ahi empezo mi consulta.Correlo colocandole ese numero o cualquiera con muchos ceros, un millon o cien mil
-
Ok, no había entendido el problema, de todas formas he actualizado el programa para que muestre correctamente los números:
http://www.todopic.com.ar/foros/index.php?topic=14917.msg270069#msg270069
Ahora realizare las pruebas que comentas para verificar el error, si mi versión tira los mismos errores comunicare el error para que lo corrijan en futuras versiones. ;-)
-
Pues a mi me falla cuando pasa del 3999999999 + 1
Nota: he comunicado los errores, falla con números grandes tipo Long y Single.
-
dogflu66 ese programa del enlace que publecaste lo corri y tambien falla... :(
-
lo voy a poner directamente en la plaqueta total ya la tengo armada.Despues te aviso como fue gracias
-
Parece que no me expliqué bien, ya no es problema del programa, es un fallo interno del compilador que no maneja bien esas cantidades tan grandes.
-
Dejo el antiguo ejemplo con el modulo que controla el posicionado del cero a la izquierda que por algún error lo había omitido al pegar el código en el foro.
Define CONF_WORD = 0x2f50 '/* FUSES
Define CONF_WORD_2 = 0x3ffd '*/
Define CLOCK_FREQUENCY = 8 'Frecuencia del reloj
'********************************************************
'FUNCION PARA IMPRIMIR UNA VARIABLE TIPO LONG EN EL LCD *
'NOMBRE: 16F88_PicEBasic_IMPRIMIR LONG POR EL LCD *******
'*************** 12/10/10 By COS ************************
'********************************************************
'----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 'Se usara el RB7 como RS
Define LCD_EREG = PORTB 'Bit de control E sera del puerto B
Define LCD_EBIT = 6 'Se usara el RB6 como E
Define LCD_COMMANDUS = 2000 'Tmp de espera despues de ejecutar un comand del lcd en uSeg.
Define LCD_DATAUS = 50 'Tmp de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 5 '50 'Tmp 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. Configura ADC
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)
TRISA.6 = 1 'Como entrada (RA6, tecla E1)
TRISA.5 = 1 'Como entrada (RA5, tecla E2)
'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
'----VARIABLES GLOBALES
Dim dato As Long
'---INICIO
Lcdinit 'Inicializa el lcd sin cursor
Lcdcmdout LcdClear 'Limpia lcd y cursor principio linea 1
'----Rutina principal
Lcdout "Print Long:" 'Imprime el texto en la primera linea display
dato = 4000009998 '4,294,967,295 'Dato a imprimir en el LCD
main:
'WaitMs 200
Lcdcmdout LcdLine2Home 'Curso a principio de linea 2
Call longlcd(dato) 'Va a la funcion
dato = dato + 1
Goto main
End
'Imprime variable por el Lcd, hasta Long.
'Call longlcd(x), x es el numero a mostrar en el LCD.
'No devuelve datos
Proc longlcd(x As Long) 'Define funcion
Dim word2 As Word '/*Declaraciones de las variables
Dim word1 As Word
Dim word0 As Word
Dim aux_x As Long '*/
aux_x = x / 1000000 'Se extrae parte más significativa del Long
word2 = aux_x 'Se asigna los digitos más significativos del Long
aux_x = aux_x * 1000000 '/* Calculo de la segunda tanda de digitos del Long
x = x - aux_x
aux_x = x / 1000 '*/
word1 = aux_x 'Se asigna la segunda tanda de digitos
aux_x = aux_x * 1000 'Ultima tanda de digitos
word0 = x - aux_x 'Se asignan los ultimos digitos
If word2 > 0 Then Lcdout #word2 'Filtra valor cero
'Establece el cero a la izquierda
If dato >= 1000000 And word1 >= 10 And word1 < 100 Then Lcdout "0"
If dato >= 1000000 And word1 < 10 Then Lcdout "00"
If word2 > 0 Or word1 > 0 Then Lcdout #word1 'Filtra valor cero
If dato >= 1000 And word0 >= 10 And word0 < 100 Then Lcdout "0"
If dato >= 1000 And word0 < 10 Then Lcdout "00"
'-----------------
Lcdout #word0 'Imprime
End Proc
-
Es el mismo código pero con el control del cero:
'Establece el cero a la izquierda
If dato >= 1000000 And word1 >= 10 And word1 < 100 Then Lcdout "0"
If dato >= 1000000 And word1 < 10 Then Lcdout "00"
If word2 > 0 Or word1 > 0 Then Lcdout #word1 'Filtra valor cero
If dato >= 1000 And word0 >= 10 And word0 < 100 Then Lcdout "0"
If dato >= 1000 And word0 < 10 Then Lcdout "00"
'-----------------
Si os apetece lo probáis y comentáis como va.
-
Pero recuerdo que el ejemplo solo a quedado como practica por que hoy en día una sola línea de código soluciona el problema:
Lcdout #dato 'Imprime el valor de la variable en el LCD, ya este declarada como Byte, Word, Long o Single (Float).
-
corri el programa en un circuito real hasta varios millones y parece que no se cuelga.
Por lo tanto doy por satisfecha mi consulta, gracias a todos por su aporte