在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

解決printf無(wú)法打印輸出的問(wèn)題

撞上電子 ? 2024-01-04 08:00 ? 次閱讀

FreeRTOS中直接使用newlib庫(kù)是有問(wèn)題的,相信使用過(guò)freertos進(jìn)行printf都能發(fā)現(xiàn)這個(gè)問(wèn)題,這個(gè)問(wèn)題網(wǎng)上有兩種方法:1、使用printf.stdarg.c,問(wèn)題在于,這個(gè)庫(kù)沒(méi)有包含float型的輸出!你沒(méi)辦法printf出浮點(diǎn)數(shù)。2、使用優(yōu)化過(guò)的printf,這個(gè)能輸出float型,但是在中斷中如果使用float輸出,就會(huì)莫名其妙的整個(gè)程序卡住,我找不出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)//若串口忙則掛起此任務(wù) 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();}

這破問(wèn)題一直找不到bug在哪里,煩死了,我忍不了了!敲了個(gè)偽printf,思路很簡(jiǎn)單,遍歷一遍要輸出的字符串,這過(guò)程中遇到%就標(biāo)記,再遇到'.'這個(gè)字符就記錄一下'.'后面的數(shù)字,然后從va_list中根據(jù)%x 判斷一下屬于哪個(gè)類(lèi)型,用va_arg讀取到值,再將該值的每個(gè)十進(jìn)制位讀取成字符后放進(jìn)輸出字符串里面,就完成了!代碼如下:

#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;
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)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];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)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];i++;}target[target_site] = '\0';va_end(next_value);
for(int i = 0;i < target_site ;i ++) // 在devc++ 調(diào)試時(shí)的輸出 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);}

不過(guò)精度的問(wèn)題,不知道怎么改,所以使用這個(gè)程序輸出float應(yīng)該限制小數(shù)點(diǎn)長(zhǎng)度。代碼應(yīng)該不難看懂,不過(guò)這段代碼還沒(méi)有實(shí)現(xiàn)字符寬度輸出,也就是沒(méi)有實(shí)現(xiàn)%后跟著數(shù)字的輸出,在用該代碼也不應(yīng)該在%后加數(shù)字。突然發(fā)現(xiàn)這個(gè)函數(shù)的target字符串 就可以作為sprintf的輸出耶,把得到target字符串的那一大串代碼包裝一下,就是sprintf了。在單片機(jī)的代碼:通過(guò)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) //若串口忙則掛起此任務(wù)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)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];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) //若串口忙則掛起此任務(wù)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)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];i++;}target[target_site] = '\0';va_end(next_value); if(inHandlerMode() != 0)taskENABLE_INTERRUPTS();}

在freertos兩個(gè)任務(wù)中輸出,并且在串口中斷中輸出浮點(diǎn)數(shù)成功(突然發(fā)現(xiàn),task拼成了tast。。

523ce930-aa94-11ee-8a62-92fbcf53809c.png

徹底解決!目前使用沒(méi)有bug,有bug我再來(lái)改文章。存在個(gè)bug,當(dāng)傳入過(guò)多參數(shù)時(shí),后面的參數(shù)會(huì)出現(xiàn)亂碼,如下

5243b85a-aa94-11ee-8a62-92fbcf53809c.png

最后一個(gè)%d會(huì)出現(xiàn)亂碼。將其分成兩個(gè)printf輸出,可以成功輸出。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • FreeRTOS
    +關(guān)注

    關(guān)注

    12

    文章

    492

    瀏覽量

    63924
  • Printf
    +關(guān)注

    關(guān)注

    0

    文章

    84

    瀏覽量

    14157
收藏 人收藏

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    使用printf打印輸出壓力值為什么會(huì)導(dǎo)致程序無(wú)法運(yùn)行

    我用STM32F107片子對(duì)壓力傳感器MMR901XA 進(jìn)行控制采集氣囊壓力值,在使用中為了能使用printf打印輸出壓力值,于是對(duì)printf進(jìn)行了重定義,因?yàn)?b class='flag-5'>printf()之類(lèi)的
    發(fā)表于 08-05 07:53

    重定向printf到串口打印輸出

    嵌入式的開(kāi)發(fā)離不開(kāi) log 的打印,我們常常使用的是重定向printf到串口打印輸出,但是會(huì)對(duì)系統(tǒng)的實(shí)時(shí)性產(chǎn)生一定的影響,RTT技術(shù)可以在一定程度解決這個(gè)問(wèn)題。
    發(fā)表于 08-24 07:11

    如何對(duì)printf()函數(shù)所依賴的打印輸出函數(shù)fputc進(jìn)行重定向呢

    如何對(duì)printf()函數(shù)所依賴的打印輸出函數(shù)fputc進(jìn)行重定向呢?
    發(fā)表于 11-30 06:28

    如何去使用printf這個(gè)C語(yǔ)言常用的打印輸出函數(shù)呢

    如何去實(shí)現(xiàn)基于C庫(kù)的printf函數(shù)呢?如何去使用printf這個(gè)C語(yǔ)言常用的打印輸出函數(shù)呢?
    發(fā)表于 11-30 06:41

    為什么用串口3 printf打印輸出會(huì)調(diào)試失敗呢

    為什么用串口3 printf打印輸出會(huì)調(diào)試失敗呢?是什么原因呢?如何去解決呢?
    發(fā)表于 11-30 07:24

    怎么去實(shí)現(xiàn)printf函數(shù)打印輸出

    什么是串口通信?同步通信與異步通信有何區(qū)別?怎么去實(shí)現(xiàn)printf函數(shù)打印輸出呢?
    發(fā)表于 12-01 07:12

    怎么實(shí)現(xiàn)printf作為串口打印輸出函數(shù)?

    怎么實(shí)現(xiàn)printf作為串口打印輸出函數(shù)?
    發(fā)表于 12-02 06:19

    如何實(shí)現(xiàn)STM32對(duì)printf打印輸出信息的支持呢

    如何實(shí)現(xiàn)STM32對(duì)printf打印輸出信息的支持呢?
    發(fā)表于 12-02 06:10

    使用printf進(jìn)行打印輸出步驟記錄

    如何使用printf進(jìn)行打印輸出呢?有哪些關(guān)鍵步驟?
    發(fā)表于 12-02 06:11

    在Keil中printf函數(shù)打印輸出到哪里了?

    在Keil中,printf函數(shù),打印輸出到哪里了? 我的項(xiàng)目中沒(méi)有使用UART0,而是使用了UART3
    發(fā)表于 08-29 07:05

    什么是串口通信?基于STM32的printf打印輸出

    平時(shí)我們進(jìn)行c語(yǔ)言編程的時(shí)候會(huì)經(jīng)常用到printf函數(shù)進(jìn)行打印輸出,來(lái)調(diào)試代碼。可是這個(gè)printf函數(shù)C庫(kù)已經(jīng)幫我們實(shí)現(xiàn)好了,通常只需要直接調(diào)用即可,但是如果在一個(gè)新的開(kāi)發(fā)平臺(tái),如果庫(kù)沒(méi)有幫我們實(shí)現(xiàn)好,比如STM32開(kāi)發(fā)板,那
    發(fā)表于 06-22 09:08 ?1.4w次閱讀
    什么是串口通信?基于STM32的<b class='flag-5'>printf</b><b class='flag-5'>打印輸出</b>

    簡(jiǎn)述單片機(jī)常見(jiàn)的打印輸出方式及區(qū)別

    作者 |strongerHuang 微信公眾號(hào) | 嵌入式專(zhuān)欄 單片機(jī)開(kāi)發(fā)中,打印輸出比較常見(jiàn),也比較重要,今天就為大家分享一下常見(jiàn)的打印輸出內(nèi)容以及區(qū)別。 1寫(xiě)在前面 在MCU項(xiàng)目中,printf
    的頭像 發(fā)表于 09-23 09:58 ?4222次閱讀
    簡(jiǎn)述單片機(jī)常見(jiàn)的<b class='flag-5'>打印輸出</b>方式及區(qū)別

    stm32實(shí)現(xiàn)串口打印輸出

    學(xué)習(xí)目標(biāo):stm32實(shí)現(xiàn)串口打印輸出學(xué)習(xí)內(nèi)容:1、串口原理圖分析右上圖可以看出:我們采用USB轉(zhuǎn)串口的形式,進(jìn)行pc與單片機(jī)之間的通信,其中我們運(yùn)用的芯片為ch340c。2、實(shí)現(xiàn)串口的printf
    發(fā)表于 11-26 13:51 ?52次下載
    stm32實(shí)現(xiàn)串口<b class='flag-5'>打印輸出</b>

    單片機(jī)常見(jiàn)的打印輸出方式及區(qū)別

    單片機(jī)開(kāi)發(fā)中,打印輸出比較常見(jiàn),也比較重要,今天就為大家分享一下常見(jiàn)的打印輸出內(nèi)容以及區(qū)別。
    發(fā)表于 02-08 15:13 ?0次下載
    單片機(jī)常見(jiàn)的<b class='flag-5'>打印輸出</b>方式及區(qū)別

    投稿 | 基于IAR搭建RA MCU的RTT打印輸出

    基于IAR搭建RA MCU的RTT打印輸出
    的頭像 發(fā)表于 11-04 10:40 ?1540次閱讀
    投稿 | 基于IAR搭建RA MCU的RTT<b class='flag-5'>打印輸出</b>
    主站蜘蛛池模板: 亚洲精品二区中文字幕 | 唐人呦一呦xxxx视频 | 美女扒开尿口给男人捅 | 色视频在线看 | 二级黄绝大片中国免费视频0 | 欧美区亚洲区 | 欧美性猛交aa一级 | 韩国三级在线不卡播放 | 欧美一区二区三区不卡免费观看 | 亚洲一区二区中文 | 午夜国产精品视频 | 色 ed2k| 欧美一级免费在线观看 | 欧美性生交xxxxx久久久 | 男女无遮挡在线完整视频 | a黄色网| 国产caoni111在线观看视频 | 国产午夜视频在线观看第四页 | 日本亚洲卡一卡2卡二卡三卡四卡 | 午夜男人天堂 | 国产精品一区牛牛影视 | 欧美日韩影院 | 国产99久久九九精品免费 | 天天操天天干天天干 | bt天堂在线www最新版资源网 | 六月丁香色婷婷 | 久草五月| 四虎在线最新永久免费 | 久久午夜影院 | 69ww免费视频播放器 | 成人夜色视频网站在线观看 | 国产精品四虎在线观看免费 | 欧美日韩视频综合一区无弹窗 | 99亚洲自拍| 日本特黄色大片 | 天天操天天射天天插 | 国内精品久久久久影院男同志 | 天堂网在线播放 | 亚洲综合色在线观看 | 午夜免费视频福利集合100 | 五月婷婷激情综合网 |