电子产业一站式赋能平台

PCB联盟网

搜索
查看: 216|回复: 0
收起左侧

解决printf无法打印输出的问题

[复制链接]

397

主题

397

帖子

2463

积分

三级会员

Rank: 3Rank: 3

积分
2463
发表于 2024-1-3 21:00:00 | 显示全部楼层 |阅读模式

0cp4rvurl3h64087478456.png

0cp4rvurl3h64087478456.png

; g. Q' j8 w+ I) @5 V4 h2 U; N% V1 b/ z' k1 c  |7 b
FreeRTOS中直接使用newlib库是有问题的,相信使用过freertos进行printf都能发现这个问题,这个问题网上有两种方法:1、使用printf.stdarg.c,问题在于,这个库没有包含float型的输出!你没办法printf出浮点数。2、使用优化过的printf,这个能输出float型,但是在中断中如果使用float输出,就会莫名其妙的整个程序卡住,我找不出bug。
  • static int inHandlerMode (void) //若在中断中__get_IPSR()返回1,否则返回0{   return __get_IPSR();} void print_usart2(char *format, ...){   char buf[64];   if(inHandlerMode() != 0)  {       taskDISABLE_INTERRUPTS();  }   else   {     while(HAL_UART_GetState(&huart2) == HAL_UART_STATE_BUSY_TX)//若串口忙则挂起此任务     taskYIELD();  }  va_list ap;  va_start(ap, format);  vsprintf(buf, format, ap);  HAL_UART_Transmit(&huart2, (uint8_t *)buf, strlen(buf), 100);  va_end(ap);  if(inHandlerMode() != 0)    taskENABLE_INTERRUPTS();}这破问题一直找不到bug在哪里,烦死了,我忍不了了!敲了个伪printf,思路很简单,遍历一遍要输出的字符串,这过程中遇到%就标记,再遇到'.'这个字符就记录一下'.'后面的数字,然后从va_list中根据%x 判断一下属于哪个类型,用va_arg读取到值,再将该值的每个十进制位读取成字符后放进输出字符串里面,就完成了!代码如下:
  • #include"iostream"#include "stdarg.h"using namespace std; void GetIntToString(char *target,int* target_site,int value,int num_value){char temp[20];int temp_site = 0,site = *target_site,flag = 0,neg_flag = 0;0 Z/ A5 I0 K9 [& J
    if(num_value != 0)flag = 1;if(value 0){neg_flag = 1;value = -value;}# Q- R7 r- G% ~, |, Z$ O* }
    while(value){temp[temp_site++] = (value % 10) + '0';value /= 10;}if(neg_flag)target[site++] = '-';while(temp_site--){if(flag){if(num_value != 0)num_value --;elsebreak;}target[site++] = temp[temp_site];}*target_site = site;} void my_sprintf(char* target,char* string,...){va_list next_value;int percent_flag = 0;    // mark the emergence of percentage signint num_value = 0,num_flag = 0;      // mark the value from the back of  %.int target_site = 0,i = 0,value;double float_value;char *string_value;  U" ^( D$ P+ e3 Y
    va_start(next_value,string);while(string != '\0'){if(string == '%'){percent_flag = 1;}else if(percent_flag && string == '.'){num_value = string[i+1] - '0';i++;}else if(percent_flag && percent_flag && (string == 'd' || string == 'c')){value = va_arg(next_value,int);if(value == 0)target[target_site++] = '0';elseGetIntToString(target,&target_site,value,num_value);
    . M! d, S$ J  f0 k: r- qpercent_flag = num_value = 0;}else if(percent_flag && string == 's'){value = va_arg(next_value,int);string_value = (char *)value;for(int j = 0;string_value[j] != '\0';j++)target[target_site++] = string_value[j];
    & u4 ^3 N" i" p: ^& m. gpercent_flag = num_flag = num_value = 0;}else if(percent_flag && string == 'f'){float_value = va_arg(next_value,double);          // 2.14if((int)float_value == 0)target[target_site++] = '0';elseGetIntToString(target,&target_site,(int)float_value,0);  // 2if(float_value 0)float_value = -float_value;float_value -= (int)float_value;target[target_site++] = '.';            // 2.5 b! J, k* `0 ]1 H
    if(num_value != 0)num_flag = 1;while(!(float_value >= -0.000001 && float_value 0.000001)){if(num_flag){if(num_value != 0)num_value --;elsebreak;}float_value *= 10;target[target_site++] = (int)float_value + '0';float_value -= (int)float_value;}                          // 2.14
    3 O9 E- T7 I- Q+ ]$ |percent_flag = num_flag = num_value = 0;}elsetarget[target_site++] = string;i++;}target[target_site] = '\0';va_end(next_value);}  void my_printf(char* string,...){va_list next_value;int percent_flag = 0;    // mark the emergence of percentage signint num_value = 0,num_flag = 0;      // mark the value from the back of  %.int target_site = 0,i = 0,value;double float_value;char target[100];char *string_value;
    . H! R) e- ~$ }; f2 X/ D1 @va_start(next_value,string);while(string != '\0'){if(string == '%'){percent_flag = 1;}else if(percent_flag && string == '.'){num_value = string[i+1] - '0';i++;}else if(percent_flag && percent_flag && (string == 'd' || string == 'c')){value = va_arg(next_value,int);if(value == 0)target[target_site++] = '0';elseGetIntToString(target,&target_site,value,num_value);
    & `- g6 H/ l) M6 d/ a2 H. }0 A: qpercent_flag = num_value = 0;}else if(percent_flag && string == 's'){value = va_arg(next_value,int);string_value = (char *)value;for(int j = 0;string_value[j] != '\0';j++)target[target_site++] = string_value[j];3 u/ j4 Z: G! J. Z! O
    percent_flag = num_flag = num_value = 0;}else if(percent_flag && string == 'f'){float_value = va_arg(next_value,double);          // 2.14if((int)float_value == 0)target[target_site++] = '0';elseGetIntToString(target,&target_site,(int)float_value,0);  // 2if(float_value 0)float_value = -float_value;float_value -= (int)float_value;target[target_site++] = '.';            // 2.
    . p3 K3 Y& g- qif(num_value != 0)num_flag = 1;while(!(float_value >= -0.000001 && float_value 0.000001)){if(num_flag){if(num_value != 0)num_value --;elsebreak;}float_value *= 10;target[target_site++] = (int)float_value + '0';float_value -= (int)float_value;}                          // 2.14
    $ M/ p4 w4 A# E( d% N2 d7 cpercent_flag = num_flag = num_value = 0;}elsetarget[target_site++] = string;i++;}target[target_site] = '\0';va_end(next_value);/ H" j. n' u+ H: s% J( a
    for(int i = 0;i // 在devc++ 调试时的输出 printf("%c",target);} int main(){uint8_t k = 10;char target[100];char a = -10,b = -100;my_printf("MotorRun,%d,%d3 Y$ {$ Q2 U1 I& D  W7 E0 }. ~$ @
    ",a,b);printf("%c %c",55,32);//my_printf("temp value is %c and %d
    7 d' u6 B3 o+ N! i) m  a5 ^; Z0 }",k,k);//my_printf("you are so %s,yes   b6 \3 a( c! V9 j$ \
    %f","handsome",0.09);}不过精度的问题,不知道怎么改,所以使用这个程序输出float应该限制小数点长度。代码应该不难看懂,不过这段代码还没有实现字符宽度输出,也就是没有实现%后跟着数字的输出,在用该代码也不应该在%后加数字。突然发现这个函数的target字符串 就可以作为sprintf的输出耶,把得到target字符串的那一大串代码包装一下,就是sprintf了。在单片机的代码:通过uart2输出:
  • static char getint_temp[20];void GetIntToString(char *target,int* target_site,int value,int num_value){int temp_site = 0,site = *target_site;uint8_t flag = 0,neg_flag = 0; if(num_value != 0)flag = 1;if(value 0){neg_flag = 1;value = -value;}while(value){getint_temp[temp_site++] = (value % 10) + '0';value /= 10;}if(neg_flag)target[site++] = '-';while(temp_site--){if(flag){if(num_value != 0)num_value --;elsebreak;}target[site++] = getint_temp[temp_site];}*target_site = site;} uint8_t percent_flag;    // mark the emergence of percentage signuint8_t num_value,num_flag;      // mark the value from the back of  %.int target_site;int i,value;double float_value;char* string_value;char target[100];void my_printf(char* string,...){#if USE_PRINTF   if(inHandlerMode() != 0){   taskDISABLE_INTERRUPTS();}   else    {while(HAL_UART_GetState(&huart2) == HAL_UART_STATE_BUSY_TX) //若串口忙则挂起此任务taskYIELD();} va_list next_value;i = target_site = percent_flag = num_flag = num_value = 0; va_start(next_value,string);while(string != '\0'){if(string == '%'){percent_flag = 1;}else if(percent_flag && string == '.'){num_value = string[i+1] - '0';i++;}else if(percent_flag && (string == 'd' || string == 'c')){value = va_arg(next_value,int);if(value == 0)target[target_site++] = '0';elseGetIntToString(target,&target_site,value,num_value); percent_flag = num_value = 0;}else if(percent_flag && string == 's'){value = va_arg(next_value,int);string_value = (char *)value;for(int j = 0;string_value[j] != '\0';j++)target[target_site++] = string_value[j]; percent_flag = num_flag = num_value = 0;}else if(percent_flag && string == 'f'){float_value = va_arg(next_value,double);          // 2.14if((int)float_value == 0)target[target_site++] = '0';elseGetIntToString(target,&target_site,(int)float_value,0);  // 2if(float_value 0)float_value = -float_value;float_value -= (int)float_value;target[target_site++] = '.';            // 2. if(num_value != 0)num_flag = 1;while(!(float_value >= -0.000001 && float_value 0.000001)){if(num_flag){if(num_value != 0)num_value --;elsebreak;}float_value *= 10;target[target_site++] = (int)float_value + '0';float_value -= (int)float_value;}                          // 2.14 percent_flag = num_flag = num_value = 0;}elsetarget[target_site++] = string;i++;}//target[target_site++] = '\0';va_end(next_value); HAL_UART_Transmit(&PRINTF_UART, (uint8_t *)target, target_site, 100); if(inHandlerMode() != 0)taskENABLE_INTERRUPTS();#endif} void my_sprintf(char* target,char* string,...){   if(inHandlerMode() != 0){   taskDISABLE_INTERRUPTS();}   else{while(HAL_UART_GetState(&huart2) == HAL_UART_STATE_BUSY_TX) //若串口忙则挂起此任务taskYIELD();} va_list next_value;uint8_t percent_flag = 0;    // mark the emergence of percentage signuint8_t num_value = 0,num_flag = 0;      // mark the value from the back of  %.int target_site = 0;int i = 0,value;double float_value;char *string_value; va_start(next_value,string);while(string != '\0'){if(string == '%'){percent_flag = 1;}else if(percent_flag && string == '.'){num_value = string[i+1] - '0';i++;}else if(percent_flag && percent_flag && (string == 'd' || string == 'c')){value = va_arg(next_value,int);if(value == 0)target[target_site++] = '0';elseGetIntToString(target,&target_site,value,num_value); percent_flag = num_value = 0;}else if(percent_flag && string == 's'){value = va_arg(next_value,int);string_value = (char *)value;for(int j = 0;string_value[j] != '\0';j++)target[target_site++] = string_value[j]; percent_flag = num_flag = num_value = 0;}else if(percent_flag && string == 'f'){float_value = va_arg(next_value,double);          // 2.14if((int)float_value == 0)target[target_site++] = '0';elseGetIntToString(target,&target_site,(int)float_value,0);  // 2if(float_value 0)float_value = -float_value;float_value -= (int)float_value;target[target_site++] = '.';            // 2. if(num_value != 0)num_flag = 1;while(!(float_value >= -0.000001 && float_value 0.000001)){if(num_flag){if(num_value != 0)num_value --;elsebreak;}float_value *= 10;target[target_site++] = (int)float_value + '0';float_value -= (int)float_value;}                          // 2.14 percent_flag = num_flag = num_value = 0;}elsetarget[target_site++] = string;i++;}target[target_site] = '\0';va_end(next_value); if(inHandlerMode() != 0)taskENABLE_INTERRUPTS();}在freertos两个任务中输出,并且在串口中断中输出浮点数成功(突然发现,task拼成了tast。。
    5 l4 N+ x; \9 I7 L0 b/ ?& T

    mymqhaybmqf64087478556.png

    mymqhaybmqf64087478556.png
    1 L# q! v8 n: e8 S
    彻底解决!目前使用没有bug,有bug我再来改文章。存在个bug,当传入过多参数时,后面的参数会出现乱码,如下$ C" D4 l+ j7 M$ k% D% e

    4rwr54zqize64087478656.png

    4rwr54zqize64087478656.png

    - `8 k7 F' O2 _$ W& Z
    , g  ^0 q! N8 W! i& K$ P; @最后一个%d会出现乱码。将其分成两个printf输出,可以成功输出。 ==========
    ) f* ]5 C& v7 z' s) v5 u: T# D8 D! j往期回顾:
    + u( ^4 j; x" P9 @3 P" oSHT3x-DIS驱动及应用详解
    ) G5 T4 A) u' x9 G. ~两步判断一款U盘读写性能
    $ Z6 r* w  r% N# C2 W1 K0 U示波器最重要的三个参数) K* z- Y( ?# S2 {; P2 N
    全攻略自制esp8266 WIFI智能排插教程
    $ X- _) x* C' k' z( ~一个通道如何捕获PWM的频率和占空比
    6 ?' L: Z9 v' _==========+ R( a* Z. ]0 X- j9 w0 X
    原文链接:点击阅读原文( [1 c# y; R; v& H/ u5 B) A: v, j
    作者:黄帅比。
    7 i/ F# O8 M% v7 o: C* p平台:CSDN* H9 l% Z" c- P6 U/ {  P! z% u
    ; t7 W7 {! z! U5 S- p$ H7 b( S, P

    oxldfgsfbl564087478756.png

    oxldfgsfbl564087478756.png
    : Q2 y8 ?% W2 t

    : r" {9 z  {$ d6 E9 m

    br0lu3absxh64087478857.png

    br0lu3absxh64087478857.png

    - M+ x6 n; X2 [. I/ n( z: [4 l3 h5 `5 v1 g1 g

    pmwgt53bvlj64087478957.png

    pmwgt53bvlj64087478957.png
  • 回复

    使用道具 举报

    发表回复

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则


    联系客服 关注微信 下载APP 返回顶部 返回列表