在網上看到有人在微控制器上使用printf函式,心癢癢,也想用,看了網上的一些方法,
大都是51微控制器的,說的是在51微控制器編譯軟體庫中有自帶printf函式,也有自己實現
乙個自己的printf函式的,但是講的不詳細,看了好幾個部落格,東拼西湊,也在自己的
微控制器上弄出來了。
1,先進行用到的知識講解:
巨集va_start(ap,fmt) 、 va_end(ap) 、va_arg(a,t) 以及型別定義va_list 主要用於獲取 printf() 的引數,因為 printf() 引數數量可變,
// 參考
在我的編譯器安裝路徑中找到檔案 stdarg.h, 裡面有如下定義:
#define va_arg(ap, t)
\((ap) += _bnd(t, _aupbnd), *(t __near *)((ap) - _bnd(t, _adnbnd)))
#define va_end(ap)
(void)0
#define va_start(ap, a)
\(void)((ap) = (char __near *)&(a) + _bnd(a, _aupbnd))
#define _bnd(x, bnd)
(sizeof (x) + (bnd) & ~(bnd))
在另一檔案yvals.h 中找到 #define _aupbnd 1u // 1u 即 1,後面的u是 unsigned 的意思
因此,可以得到 #define va_arg(ap, t) ((ap) += sizeof(t), *(t*)((ap) - sizeof(t))
((ap) += sizeof(t), *(t*)((ap) - sizeof(t)) 是乙個逗號表示式,功能是先將指標 ap 指向下乙個引數,然後取出當前的引數資料。
#define va_start(ap, a)
(void)((ap) = (char *)&a + sizeof(a)) 功能是將 ap 指向第二個引數,例如 printf("%s\n", "hello world"); 第乙個引數"%s\n", 第二個引數"hello world"
2,下面貼出**。(只需要確定存在檔案stdarg.h ,實現針對特定晶元的函式 void uart1writebyte(unsigned char databyte),下面的**即可直接使用)
主要參考;
/** stdarg.h 針對特定晶元定義的標頭檔案,主要定義了va_start(ap,fmt); va_end(ap); va_arg(a,t);
* 特定晶元是因為有的晶元棧是自下而上,有的相反
*/#include
typedef char *va_list;
/** 將整形數字轉換成字元,如 0 轉換成 '0'
*/char number2char(int num)
return ch;}/*
* 將整數 ch 按照十進位制/十六進製制轉換成字元, 因為我的微控制器8bit夠用了,所以使用unsigned char ch
*/char * convert_func(char *str, unsigned char ch, int num)
return pstr;}/*
* 將 const char *fmt 和 va_list args 轉換成乙個字串,指標 buf 指向該字串
* 例如 printf("hello %s\n", "world"); 此函式將 "hello %s\n" 和 "world" 組合成 "hello world\r\n"
* 此函式參考 刪減改寫而成
*/int my_vsprintf(char *buf, const char *fmt, va_list args)
if (*fmt != '%') // 如果不是'%',儲存進str,如果不是,越過取下乙個字元,見switch (*fmt)
fmt++;
switch (*fmt) // 這樣只能解析%c, %s, %x, %x, %d. 像 %02d 這種可以自己擴充套件
}*str = '\0';
return str-buf;}/*
* 將字串 unsigned char *string 逐個通過串列埠輸出
* 參考:
*/void sendstring(unsigned char *string)
} /** printf函式,例如:uart_printf("hello %s\n", "world");
* 參考:
*/void uart_printf(char *fmt,...)
參考:1,
2,3,
4,5,
6,
微控制器移植 UCOS移植 (函式詳解)
1.系統滴答定時器systick static void systickconfig void configure the systick handler priority nvic setpriority systick irqn,0x0 定時器中斷,1ms中斷一次 void systick ha...
微控制器printf的換行問題
因為串列埠軟體是在windows系統中的,而printf是在微控制器中執行的,所以我們平時所認為的換行,是需要 r n兩個符號的連用 r 是回車 return 返回到一行的頭部 和home鍵的效果相同 n是換行 newline 跳到下一行,列位置不變 r n連用,可達到跳到下一行行首的位置 wind...
51微控制器上移植C語言的printf
移植了c語言的printf 函式到51微控制器上,實現了在51微控制器的串列埠類pc端的printf 輸出。在專案工程中新增xxprintf.h和xxprintf.c檔案 在專案中需要使用xxprintf 函式的地方引入標頭檔案xxprintf.h,在xxprintf.h中引入微控制器相關標頭檔案 ...