【經驗分享】C51單片機中如何實現printf輸出log?
你在真實的項目工程開發中,有考慮過在類似C51單片機中實現printf輸出log嗎?本文給出一種參考實現。
1 需求說明2 源碼實現2.1 函數申明2.2 功能實現3 源碼測試4 小小總結5 更多分享
1 需求說明
這個需求比較簡單,就是要在C51單片機中實現printf函數,并使用它來打印輸出常用的幾種類型的數據,比如整型數據,字符串數據等等。
2 源碼實現
2.1 函數申明
通過查看man幫助,我們可以知道printf函數的功能及其簡要申明。
?
2.2 功能實現
以下是我的一個簡單實現源碼,僅供參考:
?
#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 小小總結
printf函數看似很常用,但是真正到了要自己去實現它的時候,你又會發現其實還是蠻多東西需要考慮的。
同時,即便是本文中的實現,還是有些類型的數據是不支持輸出的,比如 long int 類型這種,就比較難輸出;還有 float類型這種數據,也是沒法輸出的。
看到這里,你是否還有更好的實現方案呢?
5 更多分享
[架構師李肯]
架構師李肯 ( 全網同名 ),一個專注于嵌入式IoT領域的架構師。有著近10年的嵌入式一線開發經驗,深耕IoT領域多年,熟知IoT領域的業務發展,深度掌握IoT領域的相關技術棧,包括但不限于主流RTOS內核的實現及其移植、硬件驅動移植開發、網絡通訊協議開發、編譯構建原理及其實現、底層匯編及編譯原理、編譯優化及代碼重構、主流IoT云平臺的對接、嵌入式IoT系統的架構設計等等。擁有多項IoT領域的發明專利,熱衷于技術分享,有多年撰寫技術博客的經驗積累,連續多月獲得RT-Thread官方技術社區原創技術博文優秀獎,榮獲[CSDN博客專家]、[CSDN物聯網領域優質創作者]、[2021年度CSDN&RT-Thread技術社區之星]、[2022年RT-Thread全球技術大會講師]、[RT-Thread官方嵌入式開源社區認證專家]、[RT-Thread 2021年度論壇之星TOP4]、[華為云云享專家(嵌入式物聯網架構設計師)]等榮譽。堅信【知識改變命運,技術改變世界】!
審核編輯:湯梓紅
-
單片機
+關注
關注
6052文章
44764瀏覽量
642750 -
函數
+關注
關注
3文章
4359瀏覽量
63486 -
Printf
+關注
關注
0文章
83瀏覽量
13912
發布評論請先 登錄
相關推薦
單片機如何控制調試信息輸出
基于STM8L15x單片機的串口printf輸出程序分享
如何使用單片機中printf

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

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

AVR單片機使用printf的方法

單片機中printf函數的重映射

51單片機串口通信調試printf函數重定向輸出打印

單片機控制調試信息輸出的方法

單片機實現 printf 打印輸出,和電腦端一樣用

stm32單片機串口使用printf及u3_printf

評論