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读取到值,再将该值的每个十进制位读取成字符后放进输出字符串里面,就完成了!代码如下:
#includeiostream#include stdarg.husing 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;
if(num_value != 0)flag = 1;if(value < 0){neg_flag = 1;value = -value;}
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;
va_start(next_value,string);while(string[i] != '\0'){if(string[i] == '%'){percent_flag = 1;}else if(percent_flag && string[i] == '.'){num_value = string[i+1] - '0';i++;}else if(percent_flag && percent_flag && (string[i] == 'd' || string[i] == '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[i] == '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[i] == '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.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];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;
va_start(next_value,string);while(string[i] != '\0'){if(string[i] == '%'){percent_flag = 1;}else if(percent_flag && string[i] == '.'){num_value = string[i+1] - '0';i++;}else if(percent_flag && percent_flag && (string[i] == 'd' || string[i] == '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[i] == '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[i] == '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.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];i++;}target[target_site] = '\0';va_end(next_value);
for(int i = 0;i < target_site ;i ++) // 在devc++ 调试时的输出 printf(%c,target[i]);} int main(){uint8_t k = 10;char target[100];char a = -10,b = -100;my_printf(motorrun,%d,%d\n,a,b);printf(%c %c,55,32);//my_printf(temp value is %c and %d\n,k,k);//my_printf(you are so %s,yes \n%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[i] != '\0'){if(string[i] == '%'){percent_flag = 1;}else if(percent_flag && string[i] == '.'){num_value = string[i+1] - '0';i++;}else if(percent_flag && (string[i] == 'd' || string[i] == '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[i] == '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[i] == '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.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];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[i] != '\0'){if(string[i] == '%'){percent_flag = 1;}else if(percent_flag && string[i] == '.'){num_value = string[i+1] - '0';i++;}else if(percent_flag && percent_flag && (string[i] == 'd' || string[i] == '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[i] == '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[i] == '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.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];i++;}target[target_site] = '\0';va_end(next_value); if(inhandlermode() != 0)taskenable_interrupts();}
在freertos两个任务中输出,并且在串口中断中输出浮点数成功(突然发现,task拼成了tast。。
彻底解决!目前使用没有bug,有bug我再来改文章。存在个bug,当传入过多参数时,后面的参数会出现乱码,如下
最后一个%d会出现乱码。将其分成两个printf输出,可以成功输出。
路由器WAN口获取不了IP地址怎么办?
在动力电池研发的上比亚迪和宁德时代谁更强
磁带库驱动器的类型
荣耀畅玩7C性价比高 支持三卡槽
交流串电阻分压存在哪些问题
解决printf无法打印输出的问题
Uber可能错过了购买Grubhub的机会
5V升压12.6V1A三节串联锂电池充电管理板PW4053M
接线端子排选型_接线端子排识别方法
基尔霍夫定律仿真
海信新风增氧空调 疫情当前凸显优秀品牌的能力与担当
基于FPGA实现电路的同步提取性能设计
基于VersaClock6系列的多输出可编程时钟发生器的应用研究
芯北科技同步降压转换器CN2020替代TI的LMR33620
CES总结:2017遇小年 技术到了中间期
电商直播的火爆 给了电视全新的运营方向和盈利可能
英码低功耗智能视频分析边缘小红盒,低成本替代Hi3559A平台智能边缘方案
如何制作一个简易的声光控节电开关?
Diodes推出热门发声器驱动器增强版 在较低电压的情况下提供更高效能
美国人对工作中的机器人并不担心 反而担心工作岗位的流失