【經(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ù)改變世界】!
審核編輯:湯梓紅
-
單片機(jī)
+關(guān)注
關(guān)注
6037文章
44558瀏覽量
635298 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4331瀏覽量
62618 -
Printf
+關(guān)注
關(guān)注
0文章
83瀏覽量
13660
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論