Autor Tema: printf() muy lenta imprimiendo caracteres en RS232  (Leído 8970 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado pic32

  • PIC12
  • **
  • Mensajes: 57
printf() muy lenta imprimiendo caracteres en RS232
« 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

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18310
    • MicroPIC
Re: printf() muy lenta imprimiendo caracteres en RS232
« Respuesta #1 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?

Desconectado pic32

  • PIC12
  • **
  • Mensajes: 57
Re: printf() muy lenta imprimiendo caracteres en RS232
« Respuesta #2 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?

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18310
    • MicroPIC
Re: printf() muy lenta imprimiendo caracteres en RS232
« Respuesta #3 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.

Desconectado pic32

  • PIC12
  • **
  • Mensajes: 57
Re: printf() muy lenta imprimiendo caracteres en RS232
« Respuesta #4 en: 23 de Agosto de 2012, 09:36:51 »
Gracias voy a probar, luego te digo

Desconectado pic32

  • PIC12
  • **
  • Mensajes: 57
Re: printf() muy lenta imprimiendo caracteres en RS232
« Respuesta #5 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..

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18310
    • MicroPIC
Re: printf() muy lenta imprimiendo caracteres en RS232
« Respuesta #6 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.

Desconectado pic32

  • PIC12
  • **
  • Mensajes: 57
Re: printf() muy lenta imprimiendo caracteres en RS232
« Respuesta #7 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..

Desconectado Suky

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: printf() muy lenta imprimiendo caracteres en RS232
« Respuesta #8 en: 23 de Agosto de 2012, 13:52:46 »
Y a que frecuencia trabaja el micro? 24 ms!  :shock:
No contesto mensajes privados, las consultas en el foro

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18310
    • MicroPIC
Re: printf() muy lenta imprimiendo caracteres en RS232
« Respuesta #9 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.

Desconectado Suky

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: printf() muy lenta imprimiendo caracteres en RS232
« Respuesta #10 en: 23 de Agosto de 2012, 15:34:42 »
Busca alguna rutina ftoa que sea más eficiente  ;-)
No contesto mensajes privados, las consultas en el foro

Desconectado pic32

  • PIC12
  • **
  • Mensajes: 57
Re: printf() muy lenta imprimiendo caracteres en RS232
« Respuesta #11 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

Desconectado MGLSOFT

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 7918
Re: printf() muy lenta imprimiendo caracteres en RS232
« Respuesta #12 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.
« Última modificación: 24 de Agosto de 2012, 08:17:03 por MGLSOFT »
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18310
    • MicroPIC
Re: printf() muy lenta imprimiendo caracteres en RS232
« Respuesta #13 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. }

Desconectado pic32

  • PIC12
  • **
  • Mensajes: 57
Re: printf() muy lenta imprimiendo caracteres en RS232
« Respuesta #14 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