從keil的幫助文檔裏我們可以看到,printf
是基於putchar
實現的,所以我們只要重新實現putchar
,就可以實現printf
的重定向,即可以將printf
用在其他串口上。
putchar
的函數實現在…/C51/LIB下可以找到。
#include <reg51.h>
#define XON 0x11
#define XOFF 0x13
/*
* putchar (full version): expands '\n' into CR LF and handles
* XON/XOFF (Ctrl+S/Ctrl+Q) protocol
*/
char putchar (char c) {
if (c == '\n') {
if (RI) {
if (SBUF == XOFF) {
do {
RI = 0;
while (!RI);
}
while (SBUF != XON);
RI = 0;
}
}
while (!TI);
TI = 0;
SBUF = 0x0d; /* output CR */
}
if (RI) {
if (SBUF == XOFF) {
do {
RI = 0;
while (!RI);
}
while (SBUF != XON);
RI = 0;
}
}
while (!TI);
TI = 0;
return (SBUF = c);
}
我們來分析一下代碼,首先我們先不管那兩個if
判斷,putchar
函數總是要執行的語句其實只有三句,首先先等待上一個數據發送完畢,將標誌位置零以後,再發送下一個數據。這也解釋了爲什麼我們在第一次調用printf
函數時要先把TI
置1,因爲STC單片機復位以後TI
的值爲0,直接調用printf
函數就會一直卡死在while(!TI)
裏面了。
while(!TI);
TI = 0;
return (SBUF = c);
if(c == '\n')
部分是判斷是否接收到換行符,如果接收到換行符以後,就會輸出CR+LF。SBUF = 0X0d
是在輸出CR,推測LF是在putchar
函數之外輸出的。
最後if(RI)
部分是軟件流控制。當接收端數據緩存區滿了以後,就會向發送端發送XOFF
標誌,發送端接收到XOFF
以後停止發送數據。接收端處理完數據以後,會向發送端發送XON
標誌,表示可以繼續發送數據。
使用流控制可以有效的防止數據傳輸過程中的丟失情況。
分析完官方的putchar
函數以後,我們需要自己寫一個putchar
函數來調用串口3,這裏要說明一下,如果我們的工程中包含了putchar
函數,編譯器會優先使用我們所定義的函數,而不會去使用…/C51/LIB下的putchar
函數。
下面是我寫的putchar
函數,因爲沒有那麼高的要求,所以我並沒有使用流控制,其次我的代碼是先發送數據,再檢測標誌位,我認爲這樣做更符合我們平時的使用習慣。
char putchar(char c)
{
if (c == '\n')
{
S3BUF = 0x0d;
while (!(S3CON & S3TI)); //等待發送成功
S3CON &= ~S3TI;
/* output CR */
}
S3BUF = c;
while (!(S3CON & S3TI)); //等待發送成功
S3CON &= ~S3TI; //清除發送中斷標誌
return c;
}
我們只需要將這個putchar
函數包含在工程中,然後初始化串口3,便可以利用printf
打印串口了。