TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: japifer_22 en 15 de Febrero de 2011, 16:52:37

Título: pasar cadena a float o int
Publicado por: japifer_22 en 15 de Febrero de 2011, 16:52:37
hola otra vez, tengo una duda, estoy en un codigo en el cual quiero ir almasenando unos valores de ascii en un string, esto es a medida que van llegando, pero luego al presionar la tecla de retorno, quiero que este string se transforme en entero. osea el programa manda por la rs232 numeros en ascii y yo quiero que cuando ayan siertos numero inprimir estos pero en entero. como lo puedo hacer, he esto intentando con el atoi y atol y no me resulta.

saludos
Título: Re: pasar cadena a float o int
Publicado por: migsantiago en 15 de Febrero de 2011, 16:57:45
Es al revés, usa ftoa (float to ascii).
Título: Re: pasar cadena a float o int
Publicado por: japifer_22 en 15 de Febrero de 2011, 17:37:36
hola migsantiago, gracias por responder, pero no me sirve asi, tiene que ser de ascii a int o float, o simplemente como puedo leer todo el string que tiene estos numeros  en ascci
y mostrarlo en una ldc como un solo numero ?¡?¡
saludos
Título: Re: pasar cadena a float o int
Publicado por: AngelGris en 15 de Febrero de 2011, 19:11:35
  Se pueden almacenar en un buffer en forma contigua y luego mostrás todo. La idea sería algo así...

Código: C
  1. char buffer[15]; defino un buffer que almacene 14 caracteres + el caracter nulo para indicar el fin
  2. char indice;
  3. // luego en la rutina de llegada de informacion del rs232
  4.  
  5. char caracter;
  6. indice = 0;
  7.  
  8. do
  9. {
  10.   caracter = getch();
  11.   if (caracter != 13) // si no es el enter
  12.   {
  13.     buffer[indice] = caracter;
  14.     indice++;
  15.     buffer[indice] = '\0'; // me aseguro de colocar el caracter nulo que indica el fin de la cadena
  16.   }
  17. }
  18. while (caracter != 13)  // se repite todo lo anterior hasta que llega un enter

  Con lo anterior lograríamos almacenar en la variable buffer una cadena de caracteres
Título: Re: pasar cadena a float o int
Publicado por: migsantiago en 15 de Febrero de 2011, 19:35:46
hola migsantiago, gracias por responder, pero no me sirve asi, tiene que ser de ascii a int o float, o simplemente como puedo leer todo el string que tiene estos numeros  en ascci
y mostrarlo en una ldc como un solo numero ?¡?¡
saludos

Angelgris te ha resuelto todo el problema.
Título: Re: pasar cadena a float o int
Publicado por: japifer_22 en 15 de Febrero de 2011, 22:26:53
hola gracias por la respuestas se pasaron, pero me queda la ultima duda, y es con respecto a que si yo puedo copiar en este caso buffer con strcpy y, asi asignar lo que tiene este a otro string, y por ultimo para yo poder ver los datos  que estan en este buffer en una LCD tendria que poner printf(lcd_putc,"%s"buffer); es asi o no ??y reitero gracias a los dos por las respuestas.

saludos
Título: Re: pasar cadena a float o int
Publicado por: AngelGris en 15 de Febrero de 2011, 22:44:40
  Se puede usar strcpy para copiar el buffer sin problemas, en cuanto a usar printf de la forma que decís no sabría decirte porque no uso CCS.
Título: Re: pasar cadena a float o int
Publicado por: pocher en 16 de Febrero de 2011, 06:59:07
Perdonadme si meto la pata, pero
Código: [Seleccionar]
buffer[indice] = '\0';, ¿no añadiria un nulo después de cada caracter recibido?

¿no se tiene que recibir la cadena toda seguida?
Título: Re: pasar cadena a float o int
Publicado por: japifer_22 en 16 de Febrero de 2011, 08:10:00
a oka, pero entonces de que forma puedo visualisar el buffer entero en una lcd ????
Título: Re: pasar cadena a float o int
Publicado por: AngelGris en 16 de Febrero de 2011, 09:08:23
Perdonadme si meto la pata, pero
Código: [Seleccionar]
buffer[indice] = '\0';, ¿no añadiria un nulo después de cada caracter recibido?

¿no se tiene que recibir la cadena toda seguida?

  Si, pero la cadena se sigue recibiendo hasta que llega el caracter "CarrierRetunr" que es 13 en decimal. Fijate que en la forma en que lo puse, primero se almacena el caracter que llega, luego incremento el índice y recién entonces pongo el caracter nulo. Eso lo hago por las dudas que antes hubiera almacenado una cadena más larga, y poniendo eso me aseguro que corte donde quiero.

  A ver si con un ejemplo lo muestro mejor.

  Estado anterior de buffer "hola mundo". Si ahora recibo sólo "chau" <CarrierReturn>. La variable buffer sería "chau mundo" porque el caracter nulo aparecía originalmente después de la o de mundo. Pero al ir agregando yo el caracter nulo, me va a quedar el caracter nulo luego de "chau" y por lo tanto en la variable buffer quedará sólo lo recibido.
Título: Re: pasar cadena a float o int
Publicado por: pocher en 16 de Febrero de 2011, 09:11:40
Despues de la recepcion de la cadena borra el buffer.

Busca en el FORO recepcion de caracteres por interrupcion, hay mucha informacion. Si no te sale ya te ayudamos.
Título: Re: pasar cadena a float o int
Publicado por: japifer_22 en 16 de Febrero de 2011, 09:37:06
oka voy a buscar ahora entonces lo que dice. gracias
Título: Re: pasar cadena a float o int
Publicado por: japifer_22 en 16 de Febrero de 2011, 11:12:20
hola, bueno veran he estado dandole a este tema y empece a darle al debug y lo raro de todo esto que la variable asociada a mi getc(), cada vez que le envio el R mayuscula o 0x52, me dice que llega un FF a esta variable y quedo sin entender del por que se produce esto, alguien save?????. dejo el codigo para que lo discutamos un poco ya ??

Código: [Seleccionar]
#INCLUDE <16F877a.h>
#FUSES NOWDT, HS, NOPUT, NOPROTECT, BROWNOUT, NOLVP, NOCPD, NOWRT
#USE delay (clock=20000000)         //clock=20Mhz
#USE rs232(baud=9600,parity=N,xmit=PIN_C6, rcv=PIN_C7,bits=8) //Configuracion del puerto serie....
#DEFINE use_portd_lcd TRUE //definir portb lcd
#INCLUDE<LCD420puertD.c>  //libreria manejo lcd de 20x4 modificada por suky para el puerto D
#INCLUDE <stdlib.h>
#include <string.h>


char lectura=0x00,destino[8],dato[8];
//char convert[8];
int x=0,w=0;

#int_RDA
void  RDA_isr(void)
{
lectura=getc();                             //leo el puerto serie del pic
dato[x++]=lectura;                          //almaceno en variable dato el caracter ingresado....
                                            //he incremento en 1 para guardar le siguiente ddato....
if(lectura==0x52){                          //a llegado el caracter R...Sí... entonces....
dato[0]=0x00;                               //el primer caracter de la se borra del string...
x=0;                                        //y buelvo a posicion cero del string..
}
else if(lectura==0x0D){                     //llego el retorno de carro.. (caracter 0x13)...sí..
dato[x-1]='\0';                             //borro el caracter de retorno de carro y lo reemplazo por..
                                            //caracter nulo..
strcpy( destino,dato );                     //copio el dato de recepcion serial a otra variable...

for(w=0;w<x;w++){                           //borro el buff de recepcion de dato, "dato"....
dato[w]=0x00;
}
x=0;                                        //pongo en la posicon cero el dato de recepcion nuevo..
}
}

void main() {
 
////////////////////////////////////////// INICIALIZACIONES GENERALES
   lcd_init();                              //inicializa pantalla LCD
   enable_interrupts(INT_RDA);              //avilito interrupcion de resepcion serial   
   enable_interrupts(GLOBAL);               // avilito todo lo necesario...

   output_low(PIN_C0);                      //pone en cero el sensor2
   output_low(PIN_C1);                      //pone en uno el sensor1

While(TRUE){                                //infinito..........

   

   lcd_gotoxy( 1, 1);
   printf(lcd_putc,"%s",destino);           //imprimo en LCD los datos del puerto serie.....
                                            //sin contar con la R y el retorno de carro....
   printf("%s",destino);                    // imprimo en PC lo que llega al puerto serie..

}}
Título: Re: pasar cadena a float o int
Publicado por: AngelGris en 16 de Febrero de 2011, 12:17:47
  ¿El circuito lo tenés armado en físico o estás simulando en Proteus? En el caso que estés simulando, corroborá que tengas bien la velocidad del PIC en Proteus, la velocidad del VirtualTerminal.
Título: Re: pasar cadena a float o int
Publicado por: japifer_22 en 16 de Febrero de 2011, 12:25:49
hola lo tengo en placa de desarroyo, pero no me di cuenta que lo tenia corriendo a distinta velocidad  :oops: :oops: ,
pero el punto que sigo sin podr ver los valoresp or la LCD   :x
Título: Re: pasar cadena a float o int
Publicado por: pocher en 16 de Febrero de 2011, 14:17:16
Te debiera de funcionar. Revisa conexiones, cristal de 20Mhz, 9600 baudios...

Si lo que quieres es recibir 15 caracteres por ejemplo, porque no los vas guardando e incrementando en la interrupción y en el while haces: si x==15 hacer tal y tal, seguido del borrado del buffer.

O también en el while si lectura==CR hacer tal y tal.

No es necesario que borres el CR, tan solo guarda la cadena que va delante del CR.
Título: Re: pasar cadena a float o int
Publicado por: japifer_22 en 16 de Febrero de 2011, 15:09:28
hola pocher, nose en que me equivoco pero el punto es que no me quiere salir en la pantalla lo que llega al bufer, lo unico que logro es tener una variacion de 12 a 255, arrojando este ultimo como lectura maxima, siendo que deveria tener una variacion de 0 a 765, he recontra revisado el codigo, en conjunto con el debug y nada todo anda bien en conjunto con proteus, nose que anda mal, lo que pienso es que le estoy mandando mal el dato a la LCD. incluso modifique nuevamente el codigo.

Código: [Seleccionar]
#INCLUDE <16F877a.h>
#FUSES NOWDT,XT, NOPUT, NOPROTECT, BROWNOUT, NOLVP, NOCPD, NOWRT
#USE delay (clock=4000000)         //clock=20Mhz
#USE rs232(baud=9600,parity=N,xmit=PIN_C6, rcv=PIN_C7,bits=8) //Configuracion del puerto serie....
#DEFINE use_portd_lcd TRUE //definir portb lcd
#INCLUDE<LCD420puertD.c>  //libreria manejo lcd de 20x4 modificada por suky para el puerto D
#INCLUDE <stdlib.h>
#include <string.h>


int lectura=0x00,destino[8],dato[8];
//char convert[8];
int x=0,w=0,z=0;

#int_RDA
void  RDA_isr(void)
{
lectura=getc();                             //leo el puerto serie del pic
dato[x++]=lectura;                          //almaceno en variable dato el caracter ingresado....
                                            //he incremento en 1 para guardar le siguiente ddato....
if(lectura==0x52){                          //a llegado el caracter R...Sí... entonces....
                  dato[0]=0x00;                               //el primer caracter de la se borra del string...
                  x=0;                                        //y buelvo a posicion cero del string..
}
else if(lectura==0x0D || x==4){                     //llego el retorno de carro.. (caracter 0x13)...sí..

                              if(lectura==0x0D){
                                                z=x-1;
                                                dato[z]='\0';                               //borro el caracter de retorno de carro y lo reemplazo por..                                      //caracter nulo..
                                                strcpy( destino,dato );                     //copio el dato de recepcion serial a otra variable...
}

                    for(w=0;w<x;w++){                           //borro el buff de recepcion de dato, "dato"....
                                      dato[w]=0x00;
                                    }
x=0;                                        //pongo en la posicon cero el dato de recepcion nuevo..
   }
}

void main() {
 
////////////////////////////////////////// INICIALIZACIONES GENERALES
   lcd_init();                              //inicializa pantalla LCD
   enable_interrupts(INT_RDA);              //avilito interrupcion de resepcion serial   
   enable_interrupts(GLOBAL);               // avilito todo lo necesario...

   output_low(PIN_C0);                      //pone en cero el sensor2
   output_low(PIN_C1);                      //pone en uno el sensor1

While(TRUE){                                //infinito..........

   

   lcd_gotoxy( 1, 1);
   printf(lcd_putc,"%C%C%C",dato[0],dato[1]dato[2]);           //imprimo en LCD los datos del puerto serie.....
                                            //sin contar con la R y el retorno de carro....
   lcd_gotoxy( 1, 3);
   printf(lcd_putc,"%S",destino);
   lcd_gotoxy( 1, 4);
   printf(lcd_putc,"%i",x);
}}

saludos y espero que me puedan ayudar ya que no se que pasa
Título: Re: pasar cadena a float o int
Publicado por: japifer_22 en 16 de Febrero de 2011, 15:54:59
bueno despues de una tarde de estar con el debugg llege a la conclucion que es problema de transformar un numero en hex  a decimal, para que se vea por la lcd, alguien save como hacer esto, ya que los numeros que trabajo estan en hexa como digo y quiero pasarlo a la lcd en decimal ???'
Título: Re: pasar cadena a float o int
Publicado por: japifer_22 en 16 de Febrero de 2011, 22:31:30
hola les comento wue despues de una tremenda lucha para poder imprimir los datos que trabajaba en un string en forma de hex y acsii pude comprender he implementar como podia yo imprimir estos datos en la pantaalla LCD del pic, y es por medio de del prefijo %U, que sirve para imprimir enteros sin signos, y buala aparesio mi solucion. ahora solo me queda arreglar un poc mas el codigo pero para mi lo mas dificil esta hecho. gracias a todos por la ayuda otorgada, pero despues pongo el codigo cuando lo termine para que lo lean y comenten aver si voy bn.

saludos

Título: Re: pasar cadena a float o int
Publicado por: pocher en 17 de Febrero de 2011, 03:27:14
Bien, me alegro que consigas avanzar.

Intenta no escribir tanto codigo en la interrupcion, es mejor (aunque funcione) que lo transportes todo al while(1).

He simulado el programa que te dije que debia de funcionar y sí que imprime en la LCD correctamente.
Título: Re: pasar cadena a float o int
Publicado por: japifer_22 en 18 de Febrero de 2011, 18:46:56
gola gracias. pero ahora tengo otra duda y es por que me di cuenta que voy a tener activar y desactivar la resepcion, para que pueda trabajar los datos bien, es por esto que queria preguntat como puedo activar y desactivar la RDA a medida que voy obteniedo los datos que quiero ??

saludos y gracias por lo ya ayudado
Título: Re: pasar cadena a float o int
Publicado por: japifer_22 en 18 de Febrero de 2011, 21:12:25
hola de nuevo, les comento que me siento frustrado con lo que estoy asiendo, ya que he intentado hacer todo y no me resulta, he probado todos mis codigos en proteus y me funcionan bien, lo he debugiado y anda todo bien, pero le pongo el sensor que tiene que controlar y arroja cualquier cosa y no se por que. es por esto que les pido que me ayuden nuevamente con sus conosimientos.

como he dicho en reiteradas veces, intento de controlar 2 sensores ultrasonicos por medio de la interrupcion RDA del puerto serie del pic 16f877a, estos sensores tiran un buff de datos de 5 caracteres, los cuales el primero correspondo a una R mayuscula, seguido de tres diguitos en acsii que equivalen a la medicion del sensor, y por ultimo un retorno de carro = a 0x0D, pero lo raro es que mi codigo que lo he echo de muchas formas no me toma los valores reales que tira el sensor, que en este caso va de 0 a 765, y esto no se por que, lo que pienso ahora esque el sensor satura el puerto con tanto datos, ya que tira el buff y espera un poco y vuelve a tirar el siguiente buff con la nueva medida. reitero que todo funciona bien, incluso conecto el circuito al pc para mandar los datos y tambien funciona, pero no al conectar el sensor. esp or esto que les pido ideas para ver que puede estar pasando, y que puedo estar pasandoen alto.

saludos y espero ayuda de ustedes, cualquier idea que se les ocurra seran bienvenida.
Título: Re: pasar cadena a float o int
Publicado por: AngelGris en 18 de Febrero de 2011, 22:10:55
  ¿Cómo es el sensor? ¿Tiene algún pin de habilitación, o algún comando para habilitarlo o que quede en modo sleep? ¿Tenés el datasheet?

  Si te envía constantemente la información es posible que se esté llenando el registro RCREG (que es donde el PIC almacena lo que llega por el UART) y cuando quiera llegar otro dato se genere un error de overflow.
Título: Re: pasar cadena a float o int
Publicado por: pocher en 19 de Febrero de 2011, 03:24:14
También añadiria que pusieses el código para revisarlo.
Título: Re: pasar cadena a float o int
Publicado por: japifer_22 en 19 de Febrero de 2011, 10:16:16
hola, bueno el sensor tieneun pin el cual sirve para que quede en estado sleep. pero me tinca que sucede lo que dice angelGris:

Citar
Si te envía constantemente la información es posible que se esté llenando el registro RCREG (que es donde el PIC almacena lo que llega por el UART) y cuando quiera llegar otro dato se genere un error de overflow.

como digo lo he probado con todo y funciona bien menos con el sensor.
les dejo el codigo y el data del sensor:

http://www.maxbotix.com/uploads/LV-MaxSonar-WR1-Datasheet.pdf

es por eso que estoy pensando en abilitat y desabilitar la interrupcion cuando me aya llegado el buffer del sensor, esto para ambos sensores,seracorrecto esto ??? y como l podria hacer ??

Código: [Seleccionar]
#INCLUDE <16F877a.h>
#FUSES NOWDT,XT, NOPUT, NOPROTECT, BROWNOUT, NOLVP, NOCPD, NOWRT
#USE delay (clock=4000000)         //clock=20Mhz
#USE rs232(baud=9600,parity=N,xmit=PIN_C6, rcv=PIN_C7,bits=8) //Configuracion del puerto serie....
#DEFINE use_portb_lcd TRUE //definir portb lcd
#INCLUDE<LCD420.c> 
#INCLUDE <stdlib.h>
#include <string.h>


char escritura=0x00,dato[8],sensor1[8];
int x=0,w=0;
float convert=0;

void copia_de_string(void){
strcpy( dato , sensor1 );
}

#int_RDA
void  RDA_isr(void)
{
escritura=getc();
if(escritura==0x52){
x=1;
}
else if(escritura==0x0D && x==1){
w=0;
x=0;
copia_de_string();
}
else if((escritura!=0x52 || escritura!=0x0D) && x==1){
dato[w]=escritura;
w++;
dato[w]='\0';
}
}

void main() { 
 lcd_init();                              //inicializa pantalla LCD
 
output_low(PIN_D1);
delay_ms(500);
////////////////////////////////////////// INICIALIZACIONES GENERALES

   enable_interrupts(INT_RDA);              //avilito interrupcion de resepcion serial   
   enable_interrupts(GLOBAL);               // avilito todo lo necesario...
   
output_high(PIN_D1);

While(TRUE){                                //infinito..........
convert=atof(sensor1);
lcd_gotoxy(1,1);
printf(lcd_putc,"%s",sensor1);
lcd_gotoxy(1,3);
printf(lcd_putc,"sensor 1 portb_LCD");
}}
Título: Re: pasar cadena a float o int
Publicado por: AngelGris en 19 de Febrero de 2011, 12:00:51
  Estoy leyendo el datasheet del sensor, y me parece que habría que prestarle atención a la descripción del pin 4.

"Pin 4 - (RX) This pin is internally pulled high. The MB7001 will continually measure range and output if the pin is left unconnected or held high. If held low the MB7001 will stop ranging. Bring high 20uS or more for range reading."

  Por lo que parece, si dicho pin se mantiene en estado bajo, no tomaría la medición y posiblemente no emita nada. Luego se lo vuelve a poner en estado alto por 20uS o mas y allí te envían nuevamente la medición.

  Entonces podrías dejar el loop del programa para que haga lo siguiente

hacer 1 el pin 4 del dispositivo (para activar la medición)
esperar unos 30us
hacer lectura de uart hasta que aparezca la R
hacer lectura de uart y almacenar lo leído hasta que aparezca el 13 (0x0D) (este último caracter no almacenarlo)
hacer 0 el pin 4 del dispositivo (para desactivar la medición)
imprimir la medición en el LCD

 y obviamente se vuelven a repetir todos los pasos.
Título: Re: pasar cadena a float o int
Publicado por: japifer_22 en 19 de Febrero de 2011, 21:15:34
yo tenia pensado activar y desactivar la RDA, pero como lo planteas tu suena mejor angelGris, gracias, ahora otra pregunta el por que de que no arroja valores raros nen la lcd es por que entonces se producia un error en la uart del pic en este caso ???. saludos y gracias.
Título: Re: pasar cadena a float o int
Publicado por: AngelGris en 19 de Febrero de 2011, 23:29:13
  No sabría decirte el porque arroja valores raros en el LCD.

  Yo soy muy poco práctico para las cosas, así que si tuvieras otro PIC a mano te propondría hacer pruebas interconectando ambos PIC para ver si lo que es enviado por uno de ellos es bien recibido por el otro y mostrado en el LCD.
Título: Re: pasar cadena a float o int
Publicado por: japifer_22 en 21 de Febrero de 2011, 22:11:53
hola, bueno he encontrado el problema de mi situacion, y es que el datasheet se contradice en una parte segun yo, y es por que dice que mice de 0 a 765cm, pero en otra parte, mejor dicho en el encabazado dice que mide en pulgada, y bueno, me di cuenta que las mediciones que yo obtenia de este codigo estaba bien, ya que me arrojava los vales en pulgadas y no en cm como especifica, en una parte. uff alivio por eso, asi que ya funciona un sensor, pero ahora me pasa otra cosa y es que al energizar el pic se queda pegado y no toma lectura del sensor, luego lo reseteo y hay empiesa bn, he intentado con desavilitar la interrupcion al principio del main mas unos delay de 300ms, pero aun asi sigue sin efecto, como podre desavilitar la interrupcion o algo para que la uart no tome registro alguno de lo que le llega al pic??. otra pregunta con respecto a la ejecucion del programa, cuanto se demora en poner el pic los pines de la forma que se le dice adentro del main?? abra otra forma para que al energizar el pic, los pines que quiero ya esten un el esto que le indico??
o el pic parte inicialmente con los pines en alta impedancia ?????
Título: Re: pasar cadena a float o int
Publicado por: AngelGris en 21 de Febrero de 2011, 23:08:45
........, pero ahora me pasa otra cosa y es que al energizar el pic se queda pegado y no toma lectura del sensor, luego lo reseteo y hay empiesa bn, he intentado con desavilitar la interrupcion al principio del main mas unos delay de 300ms, pero aun asi sigue sin efecto, como podre desavilitar la interrupcion o algo para que la uart no tome registro alguno de lo que le llega al pic??. otra pregunta con respecto a la ejecucion del programa, cuanto se demora en poner el pic los pines de la forma que se le dice adentro del main?? abra otra forma para que al energizar el pic, los pines que quiero ya esten un el esto que le indico??
o el pic parte inicialmente con los pines en alta impedancia ?????

  En el datasheet indica cual es el estado de los pines en un PowerOnReset, con los pocos PICs que trabajé, el estado luego de un PowerOnReset es alta impedancia.
  Una forma de que el PIC no reciba nada de lo que supuestamente le llegaría por el UART es que no esté habilitado el UART. Deberías buscar en el Manual de CCS como se puede hacer eso.

  Otra forma que se me ocurre es que no esté habilitada la interrupción por UART (RDA), pero hay que tener en cuenta que si un dispositivo envió datos y fueron almacenados en el registro RCREG (ya que la interrupción sucede cuando dicho registro está lleno) y a su vez siguió mandando datos se produce un error. El PIC tiene el bit OERR que indica justamente un error de overflow. También tendrías que ver en el manual de CCS como eliminar dicho error. Según el datasheet del PIC se consigue limpiar el bit de error al deshabilitar y volver a habilitar la recepción.
Título: Re: pasar cadena a float o int
Publicado por: pocher en 22 de Febrero de 2011, 06:25:01
Hola.

Se me ha ocurrido simular el programa que dejaste aquí arriba, haciendo comunicación de PIC a PIC, y ¡no funciona!

¿Seguro que es este el programa que dices te funciona? ... miratelo bien, no nos lies.