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

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

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

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

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

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

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

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

1 需求說明

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

2 源碼實現(xiàn)

2.1 函數(shù)申明

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

?

2.2 功能實現(xiàn)

以下是我的一個簡單實現(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); //小寫
                  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); //大寫
                  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 源碼測試

簡單的測試代碼如下:

#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;
 }

感興趣的朋友可以把這段測試代碼,在C51平臺上編譯運行下,相信它會給你驚喜的!

4 小小總結(jié)

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

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

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

5 更多分享

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

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

審核編輯:湯梓紅

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

    關(guān)注

    6023

    文章

    44376

    瀏覽量

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

    關(guān)注

    3

    文章

    4237

    瀏覽量

    61969
  • Printf
    +關(guān)注

    關(guān)注

    0

    文章

    81

    瀏覽量

    13564
收藏 人收藏

    評論

    相關(guān)推薦

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

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

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

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

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

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

    如何使用單片機printf

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

    51單片機串口通訊需要注意的寄存器及51單片機使用PRINTF的示例程序

    本文檔的主要內(nèi)容詳細介紹的是51單片機進行串口通訊需要注意的寄存器及51單片機使用PRINTF的示例程序的詳細資料概述。
    發(fā)表于 08-14 17:32 ?2次下載
    51<b class='flag-5'>單片機</b>串口通訊需要注意的寄存器及51<b class='flag-5'>單片機</b>使用<b class='flag-5'>PRINTF</b>的示例程序

    如何在Keil中使用51單片機進行printf串口輸出

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

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

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

    單片機printf的移植過程資料免費下載

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

    單片機printf重定向的函數(shù)免費下載

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

    AVR單片機使用printf的方法

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

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

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

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

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

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

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

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

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

    stm32單片機串口使用printf及u3_printf

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