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

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

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

【經(jīng)驗(yàn)分享】單片機(jī)中如何實(shí)現(xiàn)printf輸出log?

嵌入式物聯(lián)網(wǎng)開(kāi)發(fā) ? 來(lái)源:嵌入式物聯(lián)網(wǎng)開(kāi)發(fā) ? 作者:嵌入式物聯(lián)網(wǎng)開(kāi)發(fā) ? 2022-12-08 08:42 ? 次閱讀

【經(jīng)驗(yàn)分享】C51單片機(jī)中如何實(shí)現(xiàn)printf輸出log?

你在真實(shí)的項(xiàng)目工程開(kāi)發(fā)中,有考慮過(guò)在類(lèi)似C51單片機(jī)中實(shí)現(xiàn)printf輸出log嗎?本文給出一種參考實(shí)現(xiàn)。

1 需求說(shuō)明2 源碼實(shí)現(xiàn)2.1 函數(shù)申明2.2 功能實(shí)現(xiàn)3 源碼測(cè)試4 小小總結(jié)5 更多分享

1 需求說(shuō)明

這個(gè)需求比較簡(jiǎn)單,就是要在C51單片機(jī)中實(shí)現(xiàn)printf函數(shù),并使用它來(lái)打印輸出常用的幾種類(lèi)型的數(shù)據(jù),比如整型數(shù)據(jù),字符串?dāng)?shù)據(jù)等等。

2 源碼實(shí)現(xiàn)

2.1 函數(shù)申明

通過(guò)查看man幫助,我們可以知道printf函數(shù)的功能及其簡(jiǎn)要申明。

?

2.2 功能實(shí)現(xiàn)

以下是我的一個(gè)簡(jiǎn)單實(shí)現(xiàn)源碼,僅供參考:

?
 #include 
 #include "log.h"
 #include "stdarg.h"
 #include "types.h"
 ?
 static  xdata char  Simple_Prn_Buf[6]; 
 uchar Align_Bit = 0;
 ?
 void Dark_Fill_String(void)
 {
     unsigned char i, j;
 ?
     j = 4;
     for(i=0;i<5;i++)
     {
         if (Simple_Prn_Buf[i] != '0')
         {
             j = i;
             break;
         }
     }
 ?
     if (j != 0)
     {
         for (i=j;i<6;i++)
             Simple_Prn_Buf[i-j] = Simple_Prn_Buf[i];
     }
     
     j = strlen(Simple_Prn_Buf);
 ?
     if (Align_Bit>j)
     {
         for (i=0;i1;i++)
             Simple_Prn_Buf[Align_Bit-i] = Simple_Prn_Buf[j-i];
 ?
         for (i=0;i'0';
     }
 }
 ?
 void IntToStr(int Int_Data)
 {
     unsigned char i;
     int Shang, Div_Data;
 ?
     Shang = Int_Data;
     Div_Data = 10000;
 ?
     for(i=0;i<5;i++)
     {
         Simple_Prn_Buf[i] = Shang / Div_Data + '0';
         Shang = Shang % Div_Data;
         Div_Data /= 10;
     }
     Simple_Prn_Buf[5] = '';
     Dark_Fill_String();
 }
 ?
 void HexToStr(int Int_Data, unsigned char x)
 {
     unsigned char i;
 ?
     if (Int_Data == 0) {
         if (Align_Bit == 0) {
             Align_Bit = 1;
         } 
         memset(Simple_Prn_Buf, '0', Align_Bit);
         Simple_Prn_Buf[Align_Bit] = '';
         return;
     }
 ?
     x = (x) ? 'A' : 'a';
 ?
     for (i=0;i<4;i++)
     {
         Simple_Prn_Buf[i] = ((Int_Data >> (3-i)*4)) & 0x000F;
 ?
         if (Simple_Prn_Buf[i] > 9)
             Simple_Prn_Buf[i] += (x - 10);
         else
             Simple_Prn_Buf[i] += '0';
     }
 ?
     Simple_Prn_Buf[4] = '';
     Dark_Fill_String(); 
 }
 ?
 int xprintf(char *fmt, ...)
 {
     char *Str;
     int  Int_Data;
     uchar Fill_Flag = 0;
 ?
     va_list ap;
     va_start(ap, fmt);
 ?
     while(*fmt)
     {
         if ((*fmt != '%') && (Fill_Flag == 0))
         {
             Push_To_TX_Buffer(*fmt++);
             continue;
         }
 ?
         if (*fmt == '%')
         {
             fmt++;
             Align_Bit = 0;
             Fill_Flag = 1;
         }
         
         switch(*fmt)
         {
             case 's':
                  Str = va_arg(ap, char *);
                  for (; *Str; Str++)
                     Push_To_TX_Buffer(*Str);
                  Fill_Flag = 0;
                  Align_Bit = 0;
                  break;
 ?
             case 'd':
                  Int_Data = va_arg(ap, int);
                  IntToStr(Int_Data);
                  for (Str=Simple_Prn_Buf; *Str; Str++) {
                     Push_To_TX_Buffer(*Str);
                  }
                  Fill_Flag = 0;
                  Align_Bit = 0;
                  break;
 ?
             case 'x':
                  Int_Data = va_arg(ap, int);
                  HexToStr(Int_Data, 0); //小寫(xiě)
                  for (Str=Simple_Prn_Buf; *Str; Str++) {
                     Push_To_TX_Buffer(*Str);
                  }
                  Fill_Flag = 0;
                  Align_Bit = 0;
                  break;
 ?
             case 'X':
                  Int_Data = va_arg(ap, int);
                  HexToStr(Int_Data, 1); //大寫(xiě)
                  for (Str=Simple_Prn_Buf; *Str; Str++) {
                     Push_To_TX_Buffer(*Str);
                  }
                  Fill_Flag = 0;
                  Align_Bit = 0;
                  break;
 ?
             default:
                  //Push_To_TX_Buffer(*fmt);
                  Align_Bit = *fmt - '0';
                  if (Align_Bit > 9)
                     Align_Bit = 9;
                  break;
         }
         fmt++;
     }
     va_end(ap);
 ?
     return 0;
 }
 ?

3 源碼測(cè)試

簡(jiǎn)單的測(cè)試代碼如下:

#include 
 #include 
 #include 
 ?
 extern int xprintf(const char* format, ...);
 ?
 #define LOG(fmt, arg...)xprintf(fmt, ##arg)
 ?
 int main(int argc, const char *argv[])
 {
 //uart_init();
     
 #if 1
 puts("Hello World

");/*
 unsigned int size1 = sizeof(char *);
 unsigned int size2 = sizeof(int *);
 unsigned int size3 = sizeof(int);
 unsigned int size4 = sizeof(short int);
 size = sizeof(int);
 printf("sizeof int = %d
", size);
 size = sizeof(short int);
 printf("sizeof short int = %d
", size);*/
 uart2_send_string("Hello World

");
 uart1_send_string("



");
 uart1_send_string("



");
 LOG("1Test log

");
 LOG("2Test log %c

", '=');
 LOG("3Test log %s %s

", "123", "098");
 LOG("4--Test log %d

", -456);
 LOG("4Test log %d

", 456);
 LOG("5Test log %u

", 789);
 LOG("6Test log %x

", 0x12);
 LOG("6Test log %x

", 0x1A);
 LOG("6Test log %x

", 0x1A);
 LOG("6Test log %x

", 0x1B);
 LOG("6Test log %x

", 0xab);
 LOG("6Test log %x

", 0xAB);
 LOG("6Test log %x

", 0x01);
 LOG("6Test log %2x

", 0x01);
 LOG("6Test log %x

", 0x00);
 LOG("6Test log %2x

", 0x00);
 #endif
 ?
 return 0;
 }

感興趣的朋友可以把這段測(cè)試代碼,在C51平臺(tái)上編譯運(yùn)行下,相信它會(huì)給你驚喜的!

4 小小總結(jié)

printf函數(shù)看似很常用,但是真正到了要自己去實(shí)現(xiàn)它的時(shí)候,你又會(huì)發(fā)現(xiàn)其實(shí)還是蠻多東西需要考慮的。

同時(shí),即便是本文中的實(shí)現(xiàn),還是有些類(lèi)型的數(shù)據(jù)是不支持輸出的,比如 long int 類(lèi)型這種,就比較難輸出;還有 float類(lèi)型這種數(shù)據(jù),也是沒(méi)法輸出的。

看到這里,你是否還有更好的實(shí)現(xiàn)方案呢?

5 更多分享

[架構(gòu)師李肯]

架構(gòu)師李肯全網(wǎng)同名 ),一個(gè)專(zhuān)注于嵌入式IoT領(lǐng)域的架構(gòu)師。有著近10年的嵌入式一線(xiàn)開(kāi)發(fā)經(jīng)驗(yàn),深耕IoT領(lǐng)域多年,熟知IoT領(lǐng)域的業(yè)務(wù)發(fā)展,深度掌握IoT領(lǐng)域的相關(guān)技術(shù)棧,包括但不限于主流RTOS內(nèi)核的實(shí)現(xiàn)及其移植、硬件驅(qū)動(dòng)移植開(kāi)發(fā)、網(wǎng)絡(luò)通訊協(xié)議開(kāi)發(fā)、編譯構(gòu)建原理及其實(shí)現(xiàn)、底層匯編及編譯原理、編譯優(yōu)化及代碼重構(gòu)、主流IoT云平臺(tái)的對(duì)接、嵌入式IoT系統(tǒng)的架構(gòu)設(shè)計(jì)等等。擁有多項(xiàng)IoT領(lǐng)域的發(fā)明專(zhuān)利,熱衷于技術(shù)分享,有多年撰寫(xiě)技術(shù)博客的經(jīng)驗(yàn)積累,連續(xù)多月獲得RT-Thread官方技術(shù)社區(qū)原創(chuàng)技術(shù)博文優(yōu)秀獎(jiǎng),榮獲[CSDN博客專(zhuān)家]、[CSDN物聯(lián)網(wǎng)領(lǐng)域優(yōu)質(zhì)創(chuàng)作者]、[2021年度CSDN&RT-Thread技術(shù)社區(qū)之星]、[2022年RT-Thread全球技術(shù)大會(huì)講師]、[RT-Thread官方嵌入式開(kāi)源社區(qū)認(rèn)證專(zhuān)家]、[RT-Thread 2021年度論壇之星TOP4]、[華為云云享專(zhuān)家(嵌入式物聯(lián)網(wǎng)架構(gòu)設(shè)計(jì)師)]等榮譽(yù)。堅(jiān)信【知識(shí)改變命運(yùn),技術(shù)改變世界】!

審核編輯:湯梓紅

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

    關(guān)注

    6037

    文章

    44558

    瀏覽量

    635298
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4331

    瀏覽量

    62618
  • Printf
    +關(guān)注

    關(guān)注

    0

    文章

    83

    瀏覽量

    13660
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    有哪幾種辦法可實(shí)現(xiàn)單片機(jī)像在pc終端一樣打印log

    有哪幾種辦法可實(shí)現(xiàn)單片機(jī)像在pc終端一樣打印log呢?stm32實(shí)現(xiàn)printf打印log的辦法
    發(fā)表于 12-01 06:39

    單片機(jī)如何控制調(diào)試信息輸出

    單片機(jī)調(diào)試log信息輸出控制方法因子最近在研發(fā)公司項(xiàng)目:基于無(wú)線(xiàn)通信的****物聯(lián)網(wǎng)應(yīng)用。過(guò)程涉及到了多個(gè)程序模塊,包括MQTT、JSON解析、二維碼生成等。在
    發(fā)表于 01-27 07:18

    基于STM8L15x單片機(jī)的串口printf輸出程序分享

    本文主要詳細(xì)介紹了基于STM8L15x單片機(jī)的串口printf輸出,具體的跟隨小編一起來(lái)了解一下。
    的頭像 發(fā)表于 09-24 09:44 ?5395次閱讀

    如何使用單片機(jī)printf

    1. 如c語(yǔ)言同:printf(“”);在控制臺(tái)就會(huì)輸出“”的內(nèi)容; 2. 通過(guò)串口輸出:只需要在初始化串口后,直接使用printf
    發(fā)表于 10-29 15:48 ?3269次閱讀
    如何使用<b class='flag-5'>單片機(jī)</b><b class='flag-5'>中</b><b class='flag-5'>printf</b>

    如何在Keil中使用51單片機(jī)進(jìn)行printf串口輸出

    最近有同學(xué)在51單片機(jī)的學(xué)習(xí)過(guò)程困擾如何使用單片機(jī)串口在上位機(jī)串口助手上輸出顯示的問(wèn)題,其實(shí)很多開(kāi)發(fā)環(huán)境都支持使用C語(yǔ)言里面最常用的
    發(fā)表于 08-13 17:32 ?14次下載
    如何在Keil中使用51<b class='flag-5'>單片機(jī)</b>進(jìn)行<b class='flag-5'>printf</b>串口<b class='flag-5'>輸出</b>

    如何使用單片機(jī)系統(tǒng)重寫(xiě)printf函數(shù)

    本文檔的主要內(nèi)容詳細(xì)介紹的是如何使用單片機(jī)系統(tǒng)重寫(xiě)printf函數(shù)。
    發(fā)表于 07-23 17:37 ?1次下載
    如何使用<b class='flag-5'>單片機(jī)</b>系統(tǒng)重寫(xiě)<b class='flag-5'>printf</b>函數(shù)

    單片機(jī)printf的移植過(guò)程資料免費(fèi)下載

    大都是51單片機(jī)的,說(shuō)的是在51單片機(jī)編譯軟件庫(kù)中有自帶printf函數(shù),也有自己實(shí)現(xiàn)一個(gè)自己的printf函數(shù)的,但是講的不詳細(xì),看了好幾
    發(fā)表于 07-19 17:37 ?2次下載
    <b class='flag-5'>單片機(jī)</b><b class='flag-5'>printf</b>的移植過(guò)程資料免費(fèi)下載

    單片機(jī)printf重定向的函數(shù)免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是單片機(jī)printf重定向的函數(shù)免費(fèi)下載。
    發(fā)表于 07-03 17:42 ?0次下載
    <b class='flag-5'>單片機(jī)</b><b class='flag-5'>printf</b>重定向的函數(shù)免費(fèi)下載

    AVR單片機(jī)使用printf的方法

    Pro2、程序編寫(xiě)要想在AVR單片機(jī)中使用printf函數(shù),首先得包含頭文件<stdio.h>,其次,得在函數(shù)定義put...
    發(fā)表于 11-14 20:36 ?8次下載
    AVR<b class='flag-5'>單片機(jī)</b>使用<b class='flag-5'>printf</b>的方法

    單片機(jī)printf函數(shù)的重映射

    單片機(jī)printf函數(shù)的重映射一、源自于:大俠有話(huà)說(shuō)1.如果你在學(xué)習(xí)單片機(jī)之前學(xué)過(guò)C語(yǔ)言,那么一定知道printf這個(gè)函數(shù).它最最好用的功
    發(fā)表于 11-15 20:51 ?11次下載
    <b class='flag-5'>單片機(jī)</b><b class='flag-5'>中</b><b class='flag-5'>printf</b>函數(shù)的重映射

    51單片機(jī)串口通信調(diào)試printf函數(shù)重定向輸出打印

    51單片機(jī)串口通信以及printf調(diào)試串行通信1.串口初始化串口工作方式波特率設(shè)置通過(guò)軟件直接生成串口初始化代碼2.輸出到串口3.發(fā)送字符串到串口4.printf重定向到串口5.補(bǔ)充
    發(fā)表于 11-20 16:36 ?16次下載
    51<b class='flag-5'>單片機(jī)</b>串口通信調(diào)試<b class='flag-5'>printf</b>函數(shù)重定向<b class='flag-5'>輸出</b>打印

    單片機(jī)控制調(diào)試信息輸出的方法

    單片機(jī)調(diào)試log信息輸出控制方法因子最近在研發(fā)公司項(xiàng)目:基于無(wú)線(xiàn)通信的****物聯(lián)網(wǎng)應(yīng)用。過(guò)程涉及到了多個(gè)程序模塊,包括MQTT、JSON解析、二維碼生成等。在
    發(fā)表于 12-03 12:06 ?0次下載
    <b class='flag-5'>單片機(jī)</b>控制調(diào)試信息<b class='flag-5'>輸出</b>的方法

    單片機(jī)實(shí)現(xiàn) printf 打印輸出,和電腦端一樣用

    在學(xué)C語(yǔ)言時(shí) printf 很好用,到了單片機(jī)時(shí)卻不能用,那因?yàn)?printf 在庫(kù)驅(qū)動(dòng)是答應(yīng)到顯示屏的,所用我們把驅(qū)動(dòng)重新定向打印到串口就可以在
    發(fā)表于 12-17 18:32 ?1次下載
    <b class='flag-5'>單片機(jī)</b><b class='flag-5'>實(shí)現(xiàn)</b> <b class='flag-5'>printf</b> 打印<b class='flag-5'>輸出</b>,和電腦端一樣用

    stm32單片機(jī)串口使用printf及u3_printf

    外部設(shè)備與單片機(jī)連接的時(shí)候使用的是串口(通常物聯(lián)網(wǎng)用到的ESP8266,SIM9600等都是通過(guò)串口發(fā)送AT指令進(jìn)行模式的配置的),但是printf函數(shù)卻只有一個(gè)。在單片機(jī)
    發(fā)表于 12-27 19:24 ?1次下載
    stm32<b class='flag-5'>單片機(jī)</b>串口使用<b class='flag-5'>printf</b>及u3_<b class='flag-5'>printf</b>

    51單片機(jī)為什么很少出現(xiàn)printf的身影

    51單片機(jī)為什么很少出現(xiàn) printf 的身影?是用不了嗎? 不是的,51單片機(jī)可以用 printf,只是不建議使用。 平時(shí)我們?cè)诓僮飨到y(tǒng)
    的頭像 發(fā)表于 12-03 10:46 ?295次閱讀
    51<b class='flag-5'>單片機(jī)</b><b class='flag-5'>中</b>為什么很少出現(xiàn)<b class='flag-5'>printf</b>的身影