Problema para separar parte decimal de entera en C

Hola Chicos!
Necesito ayuda :( como hago para hacer que la parte decimal y entera se separen por medio de la respectiva coma? Lo que sucede es que estoy midiendo por ejemplo, 23.5V pero en la LCD aparece 235V....Este es el código en c:

Código:
#include "16F877a.h"
#fuses hs,nowdt,noput,nolvp,noprotect
#device adc=10
#use delay (clock=4M)
#BYTE TRISC = 0x87 // Asignamos a la etiqueta TRISC la dirección 87h de memoria RAM.
#BYTE portC = 0x07 // Asignamos a la etiqueta portC la dirección 07h de memoria RAM.
#BYTE TRISB = 0x86 // Asignamos a la etiqueta TRISB la dirección 86h de memoria RAM.
#BYTE portB = 0x06 // Asignamos a la etiqueta portB la dirección 06h de memoria RAM.
#BYTE TRISA = 0x85 // Asignamos a la etiqueta TRISA la dirección 85h de memoria RAM.
#BYTE portA = 0x05 // Asignamos a la etiqueta portA la dirección 05h de memoria RAM
#BYTE OPTION_REG = 0x81
#use standard_io(B)
#define LCD_DATA_PORT getenv("SFR:PORTD")
#define LCD_ENABLE_PIN PIN_D0
#define LCD_RS_PIN PIN_D1
#define LCD_RW_PIN PIN_D2
#include "lcd.c"

int16 first_adcreading;

char look(int a)
{
switch(a)
{
case 0:
return '0';
case 1:
return '1';
case 2:
return '2';
case 3:
return '3';
case 4:
return '4';
case 5:
return '5';
case 6:
return '6';
case 7:
return '7';
case 8:
return '8';
case 9:
return '9';
default:
return '.';
}
}

void main()
{
setup_adc_ports(ALL_Analog);
setup_adc(ADC_CLOCK_DIV_8);
set_adc_channel(3);
delay_us(20);
first_adcreading= read_ADC();
first_adcreading = (first_adcreading * 4.89)/0.47;
unsigned int16 v,vp,ip,i;
Char *volt;
Char *current;
Char *current1;
volt = "00.000";
current = "0.00";
current1 = "0.00";
lcd_init();
do
{
set_adc_channel(2);
delay_us(20);
v = read_ADC();
set_adc_channel(3);
delay_us(20);
i= read_ADC();
i = (i*4.89)/0.47;
v = ((v*4.89)/20)*120;
if(v!=vp || i!=ip )
lcd_putc("\f");
vp = v;
ip = i;
volt[0] = look(v/10000);
volt[1] = look((v/1000)%10);
volt[3] = look((v/100)%100);
//volt[1] = look((v/100)%10);
lcd_gotoxy(1,1);
printf(lcd_putc,"Voltage = %.4sV",volt);
//lcd_gotoxy(1,1);
//printf(lcd_putc,"Voltage = "
//lcd_gotoxy(11,1);
//printf(lcd_putc,volt);
//lcd_gotoxy(16,1);
//printf(lcd_putc,"V"
//lcd_gotoxy(1,2);
//int16 volt1=volt/1000;
//printf(lcd_putc,"Voltage = %sV",volt1);

if ( i == first_adcreading) {
current[0] = look(i/1000); //extraer digito de
current[2] = look((i/100)%10);
current[3] = look((i/10)%10);
lcd_gotoxy(1,2);
printf(LCD_PUTC, "L1 = %sA",current);
}
else
{
int16 k;
k = i - first_adcreading;
current1[0] = look(k/1000);
current1[2] = look((k/100)%10);
current1[3] = look((k/10)%10);
lcd_gotoxy(1,2);
printf(LCD_PUTC,"L1=%s",current);
lcd_gotoxy(9,2);
printf(LCD_PUTC,"L2=%s",current1);
}
Delay_ms(250);
} while(1);
}
 
Última edición por un moderador:
como hago para hacer que la parte decimal y entera se separen por medio de la respectiva coma? Lo que sucede es que estoy midiendo por ejemplo, 23.5V pero en la LCD aparece 235V
¿Por qué mejor no usas variables del tipo float para obtener el resultado con punto flotante?
Algo así:
Declaras las variables...
float resultado,x; // Éstas deben ser del tipo float.
int16 valor_adc; // Ésta debe ser de 16 bits para leer los 11 bits del ADC.
Lees el valor del conversor y lo guardas en valor_adc
valor_adc = read_adc();
Haces una primer conversión para obtener el voltaje de entrada de 0 a 5V.
x = 5.0 * adc_value / 1023;
Luego otra conversión en donde usarás x para obtener el resultado que quieras mostrar.
resultado = (Aquí tu fórmula usando x);
Y muestras el resultado en la pantalla de esta forma por ejemplo...
printf(lcd_putc,"\nResultado: %1.2f ",resultado);

Nota: Los espacios después de la f sirven para borrar dígitos al aumentar y disminuir el valor.
Y el 2 son la cantidad de dígitos a mostrar a la derecha del punto.

Saludos.
 
Última edición:
hola a todos, tengo una duda. como hago para mostrar un numero con decimales en una patalla grafica, por ejemplo el 2234,763. lo hago de la siguiente forma, pero no funciona:

char dato23[20]={' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
float tiempo_codigo;

tiempo_codigo=2234,76;
floatToStr(tiempo_codigo, dato23);
Glcd_Write_text(dato1, 70, 4, 1);

asi solo muestra el 2234 en pantalla. uso el dspic30f4011
 
Has probado cambiar la coma decimal por punto decimal? puede que la libreria o mismo PICC no reconozca la regionalización de la PC, el formato cambia de acuerdo al país y todos los ejemplos del CCS utilizan el (.) punto como separador decimal.

Otro dato: si dato23[20] para éste caso no necesita ser inicializado y por defecto todos sus valores son cero (\0).
 
Hola.

Mirá, no se si estarás acostumbrado a usar todo el microcontrolador, o abusar de sus prestaciones. Siempre es fácil poner float y que el micro haga las cuentas, pero te recomiendo que siempre trates de hacer las cosas para que sigan funcionando bien, pero usando la menor cantidad de recursos posibles.. es una buena costumbre.

Lo que yo te recomiendo hacer, es una cuenta que usando el operador resto (%), vayas descomponiendo al número en sus diferentes cifras, y que a la hora de mostrarlo en el LCD, pongas la parte entera, después "manualmente" el punto o la coma (con manualmente me refiero a que lo imprimas como carácter), y después la decimal.

No sé que cuenta tengas que hacer, ni cómo sea la lectura de tu ADC, pero por ejemplo:

Para sacar la decena del número "28":

n=28;
decena=(n/10)%10;

y ahí vas sacando cada carácter del número, el cual te recomiendo que imprimas en el LCD cifra por cifra.

Un saludo, espero que te sirva.
 
Para separar la parte entera de la decimal por qué no restar al número decimal su parte entera?

float numero = 3.1415;
int32 entero = (int32)numero;//---------------entero = 3
float mantisa = numero - (int32)numero;//-----mantisa = 0.1415
int unDecimal = mantisa * 10; //--------------unDecimal = 1
int16 dosDecimales = mantisa * 100;//-----------dosDecimales = 14
int32 cuatroDecimales = mantisa * 10000;//------cuatroDecimales = 1415
 
Última edición:
Hola
tengo este programa en Mickro C es un contador de pulsos para un medidor de viento es solo que quisiera me pudieran ayudar para que en lugar de contar pulsos en valores enteros midiera pulsos en unidades, decenas y centenas, es decir que en el LCD aparezcan los dígitos con punto decimal ejemplo: 000.000

Anexo código en C para el PIC16F628A, Espero puedan ayudarme ya que no se mucho de programación.

Código:
// LCD module connections
sbit LCD_RS at RA1_bit;
sbit LCD_EN at RA0_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;

sbit LCD_RS_Direction at TRISA1_bit;
sbit LCD_EN_Direction at TRISA0_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// End LCD module connections

      unsigned int CONTADOR_SAVE ;
      unsigned int CONTADOR_TOTAL ;
      char CONTADOR_L[6];
      char A ;
      char B ;


 void main() {
   CMCON=7   ;
  TRISA = 0;           // set direction to be output
  TRISB = 0B01000000;           // set direction to be output
  PORTA=0 ;
  PORTB=0;
  delay_ms(100)  ;
    T1CON=0B00000111 ;
     Lcd_Init();                        // Initialize LCD

  Lcd_Cmd(_LCD_CLEAR);               // Clear display
  Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off
  
  
  A = EEPROM_Read(0);
  B = EEPROM_Read(1);
 
  CONTADOR_SAVE= A*256 + B;
  
  if(CONTADOR_SAVE==65535)
  {
   CONTADOR_SAVE=0  ;
   
//
}
   Lcd_Out(1,1,"Flow Viento:");
       // Write text in first row
    TMR1H=0;
    TMR1L=0;
VISUALIZAR:   ;
    if(PORTA.B5==0)
{
    Delay_ms(30);
    if(PORTA.B5==0)
{
    CONTADOR_SAVE=0  ;
     TMR1H=0;
     TMR1L=0;
     EEPROM_Write(0,0);

     EEPROM_Write(1,0);

     CONTADOR_TOTAL=0 ;
       WordToStr(CONTADOR_TOTAL, CONTADOR_L);
     Lcd_Out(2,12,CONTADOR_L);
     while(PORTA.B5==0)
     {
//
}
//
}
//
} ...
 
Última edición por un moderador:
aveces imprimir float no esta disponible en los compiladores por que ocupa mucha memoria
el CCS si lo trae por ser un compilador facilito

lo que puedes hacer es multiplicar

lo que hago para imprimir un flotante en una LCD es lo siguiente:
primero declaro unas variables que no ocupen mucha memoria y un bufer ejemplo

float flotante;
unsigned char entero, decimal;
char buffer [15];

hago mi codigo ejemplo leo un ADC y lo guardo en un float

entero=flotante; //aqui se hace la convercion de flotante a cadena de caracteres
decimal=(flotante- entero)*100;

lo que hace el sprintf es guardar todo en la cadena de caracteres y despues esa cadena la puedes imprimir comodamente en una LCD

sprintf(buffer,"valor:%d %1d ",entero,decimal); //se guarda en el bufer la convercion

y despues imprimo en la LCD

gotoxyLCD(1,2);
putsXLCD(buffer);

de chamacos ;)
 
Hola, ¿qué tal?

Vengo iniciando en el tema de microcontroladores. Les cuento cómo está mi problema.
Se trata de un proyecto con un menú de 3 opciones mostrado en una pantalla LCD de 16x2. Para elegir una opción, tendré que hacerlo con un celular y un Circuito Integrado CM8870.
Simulo el proyecto en Proteus 8 y programo en mikroC PRO 5.61. Como en Proteus no está el CI CM8870, utilizo un DIP Switch de 5 posiciones.
En la primera opción debo mostrar la temperatura con un sensor LM35, en la segunda opción debo ingresar 3 dígitos que serán el valor para el PWM (un LED conectado ahí),
y en la tercera opción debo simular dos semáforos.

Tengo problemas con la primera opción. Yo deseo mostrar la temperatura con decimales, para ello utilizo la función FloatToStr. Pero cuando inicio la simulación en Proteus,
la pantalla LCD se enciende pero no muestra nada. He notado que eso me pasa cuando realizo operaciones con decimales y/o utilizo la función FloatToStr.
Decidí entonces mostrar la temperatura como número entero (sin los decimales), pero es el mismo problema.

Probé el código que uso para mostrar con decimales en otro proyecto (únicamente un LM35 y una LCD de 16x2) y funciona correctamente. También probé con el otro código para
mostrar enteros e igual, funciona correctamente. No sé cuál sea el problema al pasarlo al proyecto del menú.

Uso un PIC16F887. Cuando armo todo en el protoboard, pasa lo mismo; enciende la pantalla LCD (se ven los cuadros de la primera fila) pero no muestra nada.

Dejo el proyecto (código y simulación) en el que funcionan ambos códigos, y también el proyecto del menú (Proyecto Final).
El código que muestra el número entero es de la línea 88 a la línea 171.
El código que muestra el número decimal es de la línea 173 a la línea 183.
Por cierto, en los demás proyectos no conecto los pines VSS, VDD ni VEE de la LCD en Proteus y funciona todo bien. Cuando lo armo en el protoboard, sí los conecto.

Espero que me puedan ayudar diciéndome cuál sería el problema, por favor.
De ante mano muchas gracias. Saludos!

P.D.: así como dejé la configuración del DIP Switch entrará directamente a la primera opción. Para que no tengan que mover cada vez que reinicien la simulación.
Y decidí no poner el código aquí porque son 329 líneas. Pero si les parece, lo pongo acá.
 

Adjuntos

  • mikroC.rar
    125.1 KB · Visitas: 13
Última edición por un moderador:
Atrás
Arriba