Autor Tema: Como recibir un float utilizando int_rda()  (Leído 6567 veces)

0 Usuarios y 2 Visitantes están viendo este tema.

Desconectado aitorsp

  • PIC18
  • ****
  • Mensajes: 296
Como recibir un float utilizando int_rda()
« en: 19 de Octubre de 2011, 12:21:10 »
Hola:

intento recibir un numero float mediante int_rda() pero no lo consigo.


#include <16f88.h>
//#device adc=10
#fuses INTRC_IO,NOWDT,NOPROTECT,NOLVP,NOWRT,NODEBUG,NOMCLR
#use delay(internal=8M)
#use rs232(baud=38400,xmit=PIN_B5,rcv=PIN_B2)

#use fast_io(b)
#use fast_io(a)

#define LCD_DB4 PIN_A0
#define LCD_DB5 PIN_A1
#define LCD_DB6 PIN_A2
#define LCD_DB7 PIN_A3

#define LCD_RS PIN_A4
#define LCD_E PIN_A6

#include "flex_lcd.c"

float num;
char c;

#int_rda //vector de interrupción al recibir por la UART
RDA_isr(){
lcd_gotoxy(1,1);
c=getc();
num=c;
printf(lcd_putc,"Recibiendo %f",num);
lcd_gotoxy(2,1);
}
void main(){
setup_adc_ports(NO_ANALOGS);
set_tris_a(0x00);
set_tris_b(0b00000100); // Rx entrada
//int aux;
//float voltage;
//setup_adc_ports(SAN2|VSS_VDD);
//setup_adc(ADC_CLOCK_INTERNAL);
output_b(0x00);
output_a(0x00);
lcd_init();
enable_interrupts(INT_RDA); //habilita interrupción por recepción
enable_interrupts(global);
//set_adc_channel(2);
while( 1 ){
}
}

En el codigo transmisor como prueba envio el numero 2.8 que es lo que deberia recibir el pic.
« Última modificación: 19 de Octubre de 2011, 12:34:15 por aitorsp »

Desconectado MerLiNz

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2463
Re: Como recibir un float utilizando int_rda()
« Respuesta #1 en: 19 de Octubre de 2011, 13:06:22 »
un float contiene 32 bits, osea 4 char, si putc solo admite un char, debes hacer putc 4 veces, y el receptor getc 4 veces, todo ello incrementando el estado de memoria para enviar los 4 bytes del float.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Como recibir un float utilizando int_rda()
« Respuesta #2 en: 19 de Octubre de 2011, 13:33:32 »
Una forma de hacerlo puede ser la siguiente:

Código: C
  1. float Data;
  2.  
  3. #int_rda //vector de interrupción al recibir por la UART
  4. RDA_isr(){
  5.  
  6.     *((char *)&Data)=getc();
  7.     // puede que sea necesario agregar la espera de disponibilidad de datos para lectura...
  8.     *((char *)&Data+1)=getc();
  9.     *((char *)&Data+2)=getc();
  10.     *((char *)&Data+3)=getc();
  11.  
  12.     kbhit_data_serial=1;
  13. }
  14.  
  15.  
  16.  
  17.  
  18. void main(void){
  19.  
  20.  
  21.     //  ...
  22.  
  23.     while(1){
  24.          if(kbhit_data_serial==1){
  25.               kbhit_data_serial=0;
  26.               lcd_gotoxy(1,1);
  27.               printf(lcd_putc,"Recibiendo %f",Data);
  28.          }
  29.     }
  30.  
  31. }


Recuerda que el que transmite el dato debe hacerlo de la misma manera, o sea el primer byte que envia es el LSB

Saludos!
« Última modificación: 20 de Octubre de 2011, 10:45:07 por Suky »
No contesto mensajes privados, las consultas en el foro

Desconectado aitorsp

  • PIC18
  • ****
  • Mensajes: 296
Re: Como recibir un float utilizando int_rda()
« Respuesta #3 en: 19 de Octubre de 2011, 15:58:10 »
Una forma de hacerlo puede ser la siguiente:

    float Data;

Código: C
  1. #int_rda //vector de interrupción al recibir por la UART
  2. RDA_isr(){
  3.  
  4.     *((char *)Data)=getc();
  5.     // puede que sea necesario agregar la espera de disponibilidad de datos para lectura...
  6.     *((char *)Data+1)=getc();
  7.     *((char *)Data+2)=getc();
  8.     *((char *)Data+3)=getc();
  9.  
  10.     kbhit_data_serial=1;
  11. }
  12.  
  13.  
  14.  
  15.  
  16. void main(void){
  17.  
  18.  
  19.     //  ...
  20.  
  21.     while(1){
  22.          if(kbhit_data_serial==1){
  23.               kbhit_data_serial=0;
  24.               lcd_gotoxy(1,1);
  25.               printf(lcd_putc,"Recibiendo %f",Data);
  26.          }
  27.     }
  28.  
  29. }


Recuerda que el que transmite el dato debe hacerlo de la misma manera, o sea el primer byte que envia es el LSB

Saludos!

Suky, porque pones Data, Data+1, Data+2, Data+3 ?. Supongo que Data se definira como char no?

En la transmision lo envio asi:

float valor=2.8;

while(1){
    printf("%f",valor);
}
« Última modificación: 19 de Octubre de 2011, 16:01:52 por aitorsp »

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Como recibir un float utilizando int_rda()
« Respuesta #4 en: 19 de Octubre de 2011, 16:06:19 »
Data es float, lo defino en el mismo ejemplo  ;-) En ese caso se recibe directamente la variable float, que es de 4-bytes, como dice MerLiNz. En ese caso tu tienes que recibir un string.

Podrías hacer:

printf("%f\n",valor);

Y para recibir, cargar todo en un arreglo hasta recibir el carácter '\n'


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado aitorsp

  • PIC18
  • ****
  • Mensajes: 296
Re: Como recibir un float utilizando int_rda()
« Respuesta #5 en: 19 de Octubre de 2011, 16:22:05 »
Data es float, lo defino en el mismo ejemplo  ;-) En ese caso se recibe directamente la variable float, que es de 4-bytes, como dice MerLiNz. En ese caso tu tienes que recibir un string.

Podrías hacer:

printf("%f\n",valor);

Y para recibir, cargar todo en un arreglo hasta recibir el carácter '\n'


Saludos!

Ah ok, creo haberlo entendido. Has creado un puntero que va aumentado su posicion en 1 cada vez que recibes un byte.

*((char *)Data+1)=getc();

por tanto haces casting a char. es asi?

Al implementarlo de este modo

RDA_isr(){
   *((char *)Data)=getc();
   // puede que sea necesario agregar la espera de disponibilidad de datos para lectura...
   *((char *)Data+1)=getc();
   *((char *)Data+2)=getc();
   *((char *)Data+3)=getc();
   kbhit_data_serial=1;
}

habria que enviar desde el transmisor del mismo modo, es decir, los 5 bytes correspondientes a float pero claro, si yo lo hago asi:

float numero=2.8;
printf(" %f ", numero);

numero que es float habria que separarlo en 5 bytes no?
« Última modificación: 19 de Octubre de 2011, 16:43:12 por aitorsp »

Desconectado MerLiNz

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2463
Re: Como recibir un float utilizando int_rda()
« Respuesta #6 en: 19 de Octubre de 2011, 17:38:34 »
mas sencillo:

char *p;
float aa;

p=&aa;

*p++=getc();
*p++=getc();
*p++=getc();
*p++=getc();

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Como recibir un float utilizando int_rda()
« Respuesta #7 en: 19 de Octubre de 2011, 19:21:57 »
Data es float, lo defino en el mismo ejemplo  ;-) En ese caso se recibe directamente la variable float, que es de 4-bytes, como dice MerLiNz. En ese caso tu tienes que recibir un string.

Podrías hacer:

printf("%f\n",valor);

Y para recibir, cargar todo en un arreglo hasta recibir el carácter '\n'


Saludos!

Ah ok, creo haberlo entendido. Has creado un puntero que va aumentado su posicion en 1 cada vez que recibes un byte.

*((char *)&Data+1)=getc();

por tanto haces casting a char. es asi?

Al implementarlo de este modo

RDA_isr(){
   *((char *)&Data)=getc();
   // puede que sea necesario agregar la espera de disponibilidad de datos para lectura...
   *((char *)&Data+1)=getc();
   *((char *)&Data+2)=getc();
   *((char *)&Data+3)=getc();
   kbhit_data_serial=1;
}

habria que enviar desde el transmisor del mismo modo, es decir, los 5 bytes correspondientes a float pero claro, si yo lo hago asi:

float numero=2.8;
printf(" %f ", numero);

numero que es float habria que separarlo en 5 bytes no?

Claro, tendrías que enviarlo de la misma forma sin formatear la variable a un string:

Código: C
  1. float Data;
  2.  
  3.    putc(*((char *)&Data));
  4.    putc(*((char *)&Data+1));
  5.    putc(*((char *)&Data+2));
  6.    putc(*((char *)&Data+3));

Lo que se hace es enviar cada byte que compone la variable float.

Una variable float se puede descomponer en 4 bytes:

MB                        | UB                         | HB                           | LB

*((char *)&Data+3)  | *((char *)&Data+2)  |  *((char *)&Data+1)   |  *((char *)&Data+0)








mas sencillo:

char *p;
float aa;

p=&aa;

 :) Casi, si lo haces así te indicará error, lo que hay que hacer es:

p=(char *)&aa;


 ;-)


Saludos!
« Última modificación: 20 de Octubre de 2011, 10:45:47 por Suky »
No contesto mensajes privados, las consultas en el foro

Desconectado MerLiNz

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2463
Re: Como recibir un float utilizando int_rda()
« Respuesta #8 en: 19 de Octubre de 2011, 19:53:48 »
en el C18 no indica error, unicamente un warning de conversion de tipo, pero el compilador lo hace bien, date cuenta que un puntero almacena una direccion de memoria, independientemente al tipo que pertenezca, un puntero de char tiene la misma capacidad que uno de float, en el C18 puedes declararlo como near o far para que el puntero pueda almacenar una direccion mas lejana o cercana.

Pero como estamos en CCS pues nidea, supongo que algo similar pasara.

Desconectado jeremylf

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1341
Re: Como recibir un float utilizando int_rda()
« Respuesta #9 en: 19 de Octubre de 2011, 19:56:04 »
En el archivo input.c puedes encontrar una función que se llama get_float(). Nunca he usado nada de ahi, pero puedes darle una mirada haber si te sirve.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Como recibir un float utilizando int_rda()
« Respuesta #10 en: 19 de Octubre de 2011, 21:05:40 »
en el C18 no indica error, unicamente un warning de conversion de tipo, pero el compilador lo hace bien, date cuenta que un puntero almacena una direccion de memoria, independientemente al tipo que pertenezca, un puntero de char tiene la misma capacidad que uno de float, en el C18 puedes declararlo como near o far para que el puntero pueda almacenar una direccion mas lejana o cercana.

 :mrgreen:  Seguro? Puede ser la versión del compilador :rolleyes:

Porque aveces dice Error [1131] type mismatch in assignment   :undecided:  :mrgreen:


Eso de near y far intento explicarlo por aquí


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado MerLiNz

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2463
Re: Como recibir un float utilizando int_rda()
« Respuesta #11 en: 19 de Octubre de 2011, 21:43:38 »
si, yo a veces he tenido casos de que te da errores, y en otro no. Tampoco me he puesto a investigarlo xD, cuando da error (char*) y se acabo xD

Lo del near far es sencillo, creo recordar que el near intentaba usar un puntero con 16bits maximo, y el far usa 24bits de direccion. Ahora dependiendo si es rom o ram pues cambia, pero no tiene mucha historia, la guia del C18 lo explica en 1 pagina.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Como recibir un float utilizando int_rda()
« Respuesta #12 en: 20 de Octubre de 2011, 00:42:39 »
si, yo a veces he tenido casos de que te da errores, y en otro no. Tampoco me he puesto a investigarlo xD, cuando da error (char*) y se acabo xD

xD

Lo del near far es sencillo, creo recordar que el near intentaba usar un puntero con 16bits maximo, y el far usa 24bits de direccion. Ahora dependiendo si es rom o ram pues cambia, pero no tiene mucha historia, la guia del C18 lo explica en 1 pagina.

+1  :mrgreen:
No contesto mensajes privados, las consultas en el foro

Desconectado aitorsp

  • PIC18
  • ****
  • Mensajes: 296
Re: Como recibir un float utilizando int_rda()
« Respuesta #13 en: 20 de Octubre de 2011, 06:45:46 »
No me funciona bien, no envia correctamente el valor float. dejo los codigos de emisor y receptor.

Codigo emisor:

#device adc=10
#fuses INTRC_IO,NOWDT,NOPROTECT,NOLVP,NOWRT,NODEBUG,NOMCLR
#use delay(internal=8M)
#use rs232(baud=38400,xmit=PIN_B5,rcv=PIN_B2)
#use fast_io(a)
#use fast_io(b)

#define LCD_DB4 PIN_A0
#define LCD_DB5 PIN_A1
#define LCD_DB6 PIN_A7
#define LCD_DB7 PIN_A6

#define LCD_RS PIN_B7
#define LCD_E PIN_B6

#include "flex_lcd420.c"

void main(){
float Data;
set_tris_a(0b00000000);
set_tris_b(0b00000000);
setup_adc_ports(NO_ANALOGS);

lcd_init();
lcd_gotoxy(1,1);
printf(lcd_putc("Inicio Bluetooth"));
delay_ms(2000);
while(1){
Data=2.6;
putc(*((char *)Data));
delay_ms(10);
putc(*((char *)Data+1));
delay_ms(10);
putc(*((char *)Data+2));
delay_ms(10);
putc(*((char *)Data+3));
}
}


Codigo receptor:

#include <16f88.h>
#fuses INTRC_IO,NOWDT,NOPROTECT,NOLVP,NOWRT,NODEBUG,NOMCLR
#use delay(internal=8M)
#use rs232(baud=38400,xmit=PIN_B5,rcv=PIN_B2)

#use fast_io(b)
#use fast_io(a)

#define LCD_DB4 PIN_A0
#define LCD_DB5 PIN_A1
#define LCD_DB6 PIN_A2
#define LCD_DB7 PIN_A3

#define LCD_RS PIN_A4
#define LCD_E PIN_A6

#include "flex_lcd.c"

int kbhit_data_serial;
float Data;
#int_rda //vector de interrupción al recibir por la UART
RDA_isr(){
   *((char *)Data)=getc();
   delay_ms(10);
   *((char *)Data+1)=getc();
   delay_ms(10);
   *((char *)Data+2)=getc();
   delay_ms(10);
   *((char *)Data+3)=getc();
   kbhit_data_serial=1;
}
void main(){
setup_adc_ports(NO_ANALOGS);
set_tris_a(0x00);
set_tris_b(0b00000100); // Rx entrada
output_b(0x00);
output_a(0x00);
lcd_init();
enable_interrupts(INT_RDA); //habilita interrupción por recepción
enable_interrupts(global);

while(1){
   if(kbhit_data_serial==1){
      kbhit_data_serial=0;
      lcd_gotoxy(1,1);
      printf(lcd_putc,"Recibiendo %f",Data);
      }
   }
}

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Como recibir un float utilizando int_rda()
« Respuesta #14 en: 20 de Octubre de 2011, 10:44:26 »
 :x Me olvide lo importante, el operador &

Es así por ejemplo:

*((char)&Data+1)


Agregarle a todos. Disculpas.


Saludos!
No contesto mensajes privados, las consultas en el foro


 

anything