TODOPIC

Microcontroladores PIC => dsPIC => Mensaje iniciado por: pic32 en 23 de Agosto de 2012, 07:17:19

Título: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: pic32 en 23 de Agosto de 2012, 07:17:19
Hola a todos foreros,



A ver si alguien me puede hechar una mano con este tema. Resulta que en mi programa necesito enviar 2700 números en coma flotante a una pantalla por el puerto RS232



#include <30F6010A.h>
#fuses HS,NOWDT,NOMCLR,NODEBUG,NOPROTECT,NOCKSFSM,NOBROWNOUT,PUT64
#use rs232 (BAUD=38400, XMIT=PIN_F3,RCV=PIN_F2,PARITY=N,STOP=1,BITS=8,stream=PC)//UART2

const float valores[2700]={0.3453,-3.3453 ...,0.00234} //guardo el vector de numeros en la ROM

main()
{
int i=0;
for(i=0;i<2700;i++)
printf("%f",valores);
}

Cual es mi sorpresa que cada iteracion tarda: 23,77ms, por 2700veces = 64,1 segundos en enviarme todos los numeros. Alguien tiene optimizada la funcion printf() del compilador CCS?? estoy empezando a hacerla en ensamblador para que no sea tan lentaaa, alguien sabe porque tarda tanto?? ¿Quién a tenido problemas con esto? helppp
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: Nocturno en 23 de Agosto de 2012, 08:05:49
Es mucho tiempo, a 38400, y si tus valores ocupan 10 dígitos, debería tardar la décima parte de lo que tarda.

¿Estás usando la USART física del micro o emulándola por software?
¿Has probado a enviar los dígitos individualmente con PUTC?
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: pic32 en 23 de Agosto de 2012, 08:28:44
Pues me imagino que el DSPic usará la USART física, esta tal cual escrito el código.

En cuando a la instruccion putc() si es verdad que es mas rapida, pero es para caracteres, te refieres a ir troceando el número float de 10 digitos e ir enviando uno por uno? como se puede hacer eso?
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: Nocturno en 23 de Agosto de 2012, 08:33:59
No imagines, con CCS nunca se sabe, mejor pruébalo.
Métele FORCE_HW en la sentencia #use rs232 y así te aseguras.

Para trocear el float en los distintos dígitos habría que hacer divisiones sucesivas y quedarte con el resto de cada división, luego pasarlo a ASCII y por último hacer un PUTC. No es complicado, pero lógicamente es más cómodo el printf.
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: pic32 en 23 de Agosto de 2012, 09:36:51
Gracias voy a probar, luego te digo
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: pic32 en 23 de Agosto de 2012, 10:11:31
La sentencia FORCE_HW no esta disponible, al menos en la version 4.128, pero si emular por soft el puerto, con la sentencia FORCE_SW

#use rs232 (BAUD=38400,XMIT=PIN_F3,RCV=PIN_F2,PARITY=N,STOP=1,BITS=8,stream=PC,FORCE_SW)

y lo curioso es que tarda 1ms menos!! lo que indica que lo debe hacer por soft, no entiendo nada..
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: Nocturno en 23 de Agosto de 2012, 12:26:16
Pásame tu código, voy a bichearlo con la 4.134 a ver si encuentro algo.
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: pic32 en 23 de Agosto de 2012, 12:51:58
Para hacer las pruebas he acortado el vector de 2700 elementos, y lo deje en 96 valores por comodidad, esto es muy raro, pero tarda 23.77ms por iteracion para enviar un dato tipo float por serie asincrono, me parece lentisimo.

Toy empezando a hacerlo a pelo, cargando los valores en U1TXREG y con interrupciones a ver si asi se acorta, si avanzo ya te digo, desconocia que la funcion fprintf() o printf fueran tan lentas..
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: Suky en 23 de Agosto de 2012, 13:52:46
Y a que frecuencia trabaja el micro? 24 ms!  :shock:
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: Nocturno en 23 de Agosto de 2012, 14:35:39
He estado haciendo algunas pruebas separando la conversión a string (con sprintf) del envío por la usart (con putc) y la lentitud está efectivamente en el printf, pero no en el envío de la usart.
No te esfuerces en intentar el envío mediante registros del micro, eso va bien, deberías dirigir tu esfuerzo a convertir el float a string.
He estado buscando algún ejemplo que esté hecho por ahí, pero todos vienen con sprintf y eso no te sirve.
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: Suky en 23 de Agosto de 2012, 15:34:42
Busca alguna rutina ftoa que sea más eficiente  ;-)
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: pic32 en 24 de Agosto de 2012, 03:40:20
Y a que frecuencia trabaja el micro? 24 ms!  :shock:
A 20MHz, Nocturno efectivamente tienes razón, cargar en los registros no consigo mayor rapidez, la funcion printf no esta optimizada en CCS, intentare pasarlo a string pero ya me huelo el percal jeje
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: MGLSOFT en 24 de Agosto de 2012, 08:14:29
Lo que no tienen en cuenta, es que para enviar una float, la funcion printf, primero la convierte a una cadena de valores de 8 bits en formato char, por lo tanto siempre va a ser mas efectivo hacer primero la conversion a string y enviarlo asi, de ese modo no tarda tanto entre iteracciones.
Si hay interrupciones en el programa, ademas, van a ser respetadas y el tiempo agregado a la sentencia printf... :mrgreen:

Ademas, que tipo de display soporta que le envies 2700 valores float y puede mostrarlos ademas?? (esto es solo curiosidad mia)... :mrgreen:
Podrias convertirlos a enteros de coma fija, con fixed, y despues enviarlos.
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: Nocturno en 24 de Agosto de 2012, 08:26:06
Sí, Marcos, eso es precisamente lo que hemos comentado; la conversión es lo que lo enlentece.

Aquí he encontrado una función para realizar la conversión, pero a juzgar por su complejidad, no sé si será más rápida que el printf

¿No te sirve si envías el dato sin convertir a float y lo conviertes en destino?

Código: C
  1. #include <stdlib.h>
  2.  
  3. typedef union {
  4. long    L;
  5. float   F;
  6. }        LF_t;
  7.  
  8. char *ftoa(float f, int *status)
  9. {
  10. long mantissa, int_part, frac_part;
  11. short exp2;
  12. LF_t x;
  13. char *p;
  14. static char outbuf[15];
  15.  
  16. *status = 0;
  17. if (f == 0.0)
  18. {
  19. outbuf[0] = '0';
  20. outbuf[1] = '.';
  21. outbuf[2] = '0';
  22. outbuf[3] = 0;
  23. return outbuf;
  24. }
  25. x.F = f;
  26.  
  27. exp2 = (unsigned char)(x.L >> 23) - 127;
  28. mantissa = (x.L & 0xFFFFFF) | 0x800000;
  29. frac_part = 0;
  30. int_part = 0;
  31.  
  32. if (exp2 >= 31)
  33. {
  34. *status = _FTOA_TOO_LARGE;
  35. return 0;
  36. }
  37. else if (exp2 < -23)
  38. {
  39. *status = _FTOA_TOO_SMALL;
  40. return 0;
  41. }
  42. else if (exp2 >= 23)
  43. int_part = mantissa << (exp2 - 23);
  44. else if (exp2 >= 0)
  45. {
  46. int_part = mantissa >> (23 - exp2);
  47. frac_part = (mantissa << (exp2 + 1)) & 0xFFFFFF;
  48. }
  49. else /* if (exp2 < 0) */
  50. frac_part = (mantissa & 0xFFFFFF) >> -(exp2 + 1);
  51.  
  52. p = outbuf;
  53.  
  54. if (x.L < 0)
  55. *p++ = '-';
  56.  
  57. if (int_part == 0)
  58. *p++ = '0';
  59. else
  60. {
  61. ltoa(p, int_part, 10);
  62. while (*p)
  63. p++;
  64. }
  65. *p++ = '.';
  66.  
  67. if (frac_part == 0)
  68. *p++ = '0';
  69. else
  70. {
  71. char m, max;
  72.  
  73. max = sizeof (outbuf) - (p - outbuf) - 1;
  74. if (max > 7)
  75. max = 7;
  76. /* print BCD */
  77. for (m = 0; m < max; m++)
  78. {
  79. /* frac_part *= 10;     */
  80. frac_part = (frac_part << 3) + (frac_part << 1);
  81.  
  82. *p++ = (frac_part >> 24) + '0';
  83. frac_part &= 0xFFFFFF;
  84. }
  85. /* delete ending zeroes */
  86. for (--p; p[0] == '0' && p[-1] != '.'; --p)
  87. ;
  88. ++p;
  89. }
  90. *p = 0;
  91.  
  92. return outbuf;
  93. }
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: pic32 en 26 de Agosto de 2012, 08:08:23
Claro sería lo mas fácil convertir en destino, pero no puedo. En destino tengo un pc con pantalla, tengo que visulizar los números, de hecho va ser una imagen, cada número indica la posicion de una estrella, de ahi que prime la velocidad, pero si siempre la funcion printf pasa a tipo char, tendré que pensar en hacerlo de otra manera
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: MGLSOFT en 26 de Agosto de 2012, 11:43:08
Pregunta 1:
Porque usar una constante y no un string preformateado con esos valores ??

Pregunta 2:
Estas seguro que no te envia 2700 veces el string completo??
Porque no veo que pongas el indice en Valores, y es muy posible que el compilador lo tome como que debe enviar el string completo cada vez...
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: Suky en 26 de Agosto de 2012, 11:44:17
Si necesitas velocidad podes usar la rutina más eficiente que encuentres y un micro que lo puedas llevar a 60/70 MIPS por ejemplo, los nuevos dsPIC o PIC24E.


Saludos!
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: pic32 en 27 de Agosto de 2012, 04:17:00
Pregunta 1:
Porque usar una constante y no un string preformateado con esos valores ?? No puedo enviar los numeros como una cadena de string y pista? Teneis algun ejemplo, o poder enviar los numeros preformados float, pero de forma mucho mas rápida

Pregunta 2:
Estas seguro que no te envia 2700 veces el string completo??
Porque no veo que pongas el indice en Valores, y es muy posible que el compilador lo tome como que debe enviar el string completo cada vez...

En cada iteración envio una constante, no toda la matriz númerica. inicializa cada vez el printf() y envia un valor del vector.

No entiendo como tarda tanto en enviar los numeros, si estan utilizando los DSpic para enviar video por VGA.
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: Nocturno en 27 de Agosto de 2012, 05:41:41
No entiendo como tarda tanto en enviar los numeros, si estan utilizando los DSpic para enviar video por VGA.

El problema no es el envío, es la conversión de float a string. Si quieres enviar el float sin convertir a string, directamente con los bytes que lo componen, tendrías de sobras.
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: pic32 en 27 de Agosto de 2012, 06:00:36
Si eso lo tengo claro, y como puedo enviar directamente los bytes que lo componen? te refieres a usar puts() ?
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: Suky en 27 de Agosto de 2012, 09:19:50
Para enviar un flotante de 32 bits podes hacer:

Código: C
  1. float temp=12.3;
  2.  
  3. putc(*((char*)&temp));    // <- LSB
  4. putc(*((char*)&temp+1));
  5. putc(*((char*)&temp+2));
  6. putc(*((char*)&temp+3));
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: pic32 en 27 de Agosto de 2012, 09:46:20
he probado tu codigo y lo he grabado en el DSPic, imprime en pantalla lo siguiente:

xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Asi que o esta muy caliente o algo raro no hace bien al imprimir en ascii
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: MGLSOFT en 27 de Agosto de 2012, 09:52:46
Enviandolo asi, cada dato deberas volver a componerlo en float cuando vayas a usarlo. :mrgreen:
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: pic32 en 27 de Agosto de 2012, 10:52:29
jajaj ya entiendo, pero como pasar de ascii a formato float?
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: pic32 en 28 de Agosto de 2012, 05:39:09
al final los mejores resultados los estoy logrando con:


for(i=0;i<2700;i++)

{    putc(*((char*)&vis));    // <- LSB
    putc(*((char*)&vis+1));
    putc(*((char*)&vis+2));
    putc(*((char*)&vis+3));
}
Aun asi da una imagen cada 1.4 segundos, esta lejos de tiempo real, pero al menos ya no tarda 1 minuto, en imprimir una imagen estelar    :P
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: Nocturno en 28 de Agosto de 2012, 15:38:09
Si necesitas más velocidad tienes que cambiar de tecnología, quizás SPI o paralelo.
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: MGLSOFT en 28 de Agosto de 2012, 17:56:51
Y porque no subirla a 115200 Bps ??
Tardarias 1/4 de ese tiempo... :mrgreen: :mrgreen:
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: pic32 en 29 de Agosto de 2012, 07:43:54
ya lo probe a esa velocidad 115200 bps pero no tira. la velocidad limite lo establece el conversor FT232RL
Título: Re: printf() muy lenta imprimiendo caracteres en RS232
Publicado por: MGLSOFT en 29 de Agosto de 2012, 08:23:50
Heyyy !!!
Yo estoy usando un conversor de esos a esa velocidad !!
Por que dices que no tira??