在使用IAR開發STM32項目時,使用串口或者是虛擬終端來輸出我們想看的信息是一個非常好而且簡便的方式。
首先來看看串口怎么實現信息輸出。簡單來說串口輸出信息就是將標准輸出重定向到串口,在上位機的超級終端或者串口助手等工具中查看結果。
在使用串口之前要配置串口,這一點是串口應用的基本知識,如果要通過串口輸入參數可能還需要使用中斷。關於串口配置和終端配置,應根據具體是用來實現。這里主要說一下標准輸出的重定向。
標准庫中的printf函數實際調用了int fputc(int ch, FILE *f)函數,所以我們要重載這個函數,實現從串口輸出數據。
int fputc(int ch, FILE *f) { while (USART_GetFlagStatus(USARTn, USART_FLAG_TC) == RESET) {} USART_SendData(USARTn, (uint8_t) ch); return ch; }
當然,如果想通過串口輸入參數還需要從在標准輸入函數,如:
int GetKey (void) { while (!(USARTn->SR & USART_FLAG_RXNE)); return ((int)( USARTn->DR & 0x1FF)); }
完成以上重載后,在程序中使用printf函數打印信息時,就會從串口輸出信息。接到上位軟件的畫就可以在上位機看到這些信息,便於查看調試。
接下來我們看一看在IAR虛擬終端中查看輸出結果,這個相對要簡單得多。只需要做一些必要的設置即可將標准輸出重定向到IAR虛擬終端中。
在開始之前,必須在使用printf函數的的文件中引用stdio.h。這一點毋庸置疑,與任何外部函數的調用是一樣的。然后開始設置:
右鍵點擊項目名稱並在彈出菜單中點擊“Options”或者在軟件“Project”菜單中點擊“Options”。
彈出Options界面后在左側列表框中選擇“General Options”,在右側的Tab界面中選擇“Library Configuration”標簽,如下圖紅框所示:
在“Library Configuration”標簽下,將Library改為全庫“Full”,將“stdout/stderr”改為“Via SWO”,如下圖紅框所示。
在完成上述設置后如果沒有其他的輸出設置,當在線調試時,打開View菜單中的“Terminal IO”(如下圖紅框所示),就可在IAR中顯示輸出了,當然也可以輸入數據。
如果在使用IAR虛擬終端時重載了輸入輸出函數,則不會從IAR虛擬終端輸出,每次修改很麻煩,我們可以寫一個源文件通過條件編譯來實現我們想要的輸出方式。
定義兩個宏來控制我們要要的方式:
/*啟用調試使用功能代碼*/ #ifndef DEBUG_CODE_ENABLE #define DEBUG_CODE_ENABLE (1) #endif
在調試時,將DEBUG_CODE_ENABLE設為1,方便查看,在項目正式發布時則可將DEBUG_CODE_ENABLE設為0將這段代碼屏蔽。
/*定義開關串口打印的宏,當為1時使用串口輸出,當為0時使用IAR虛擬終端*/ #ifndef USART_PRINT_ENABLE #define USART_PRINT_ENABLE (0) #endif
而在使用時,如果輸出的內容數量和種類比較多的話,實現起來比較亂而且可能破環其他部分代碼的整體性和可讀性。我們可以使用函數指針來集中操作,這樣無論是代碼還是輸出信息的完整性都可以保證,而且實現條件編譯也變得更簡潔。
先定義一個打印對象類型的枚舉類型和一個打印對象的結構體,如下:
/*定義一個打印對象數據類型的枚舉,有新類型是在此添加即可*/ typedef enum{ pChar, pInt8, pInt16, pInt32, pFloat, pString }PrintType; /*定義一個答應對象的結構體類型*/ typedef struct{ PrintType printType; void * objValue; }PrintObject;
再定義一個函數指針數組用於存放打印函數的指針:
int (*ObjPrintf[])(void *objValue)={CharPrintf,Int8Printf,Int16Printf,Int32Printf,FloatPrintf,StringPrintf};
並定義一個調用打印的函數:
/*調試時批量打印輸出函數*/
void DebugOutput(PrintObject * printObject,uint16_t amount);
對於具體的實現函數根據自己的要求實現就可以了。
在調用時只需要定義一個要輸出的對象數組並將其作為參數傳遞給DebugOutput汗數據可以了。
/*啟用調試輔助代碼時,初始化顯影的參數*/ #if DEBUG_CODE_ENABLE > (0) char title[]="\nThe result is:"; PrintObject printObject[]={{pString,title},{pFloat,&o2Concentration},{pFloat,&h2Concentration},{pFloat,&ch4Concentration}}; /*如果啟用了串口打印輸出功能,則初始化串口配置*/ #if USART_PRINT_ENABLE > (0) PrintUsartConfiguration(); #endif #endif /*用於測試*/ #if DEBUG_CODE_ENABLE > (0) DebugOutput(printObject,sizeof(printObject)/sizeof(PrintObject)); #endif
如此就可以非常方便的輸出信息、並可根據自己的需要控制是否輸出調試信息,采用何種信息輸出方式了,對調試來說非常有幫助。