- 使用標準庫實現本次功能的源代碼已上傳:
- https://github.com/yzmj0986/STM32_Std.lib_USART_Printf.git
TIPS:作爲一隻新手,從標準庫轉到HAL庫確實很不習慣,這個程序配置很簡單但是代碼也是糾結了很久,最終參考了官方的USART_Printf例程,下載見:STM32Cube官方例程學習指南。
MCU:STM32F103ZET6
IDE: MDK-ARM V5 +STM32CubeMX5.0.0
串口調試助手:SSCOM3.2
功能描述:USART1收到PC機發來的數據後原封不動的返回給PC機顯示,但是C語言中printf函數默認輸出設備是顯示器,要使用printf輸出到串口,需要將fputc裏面的輸出指向串口,這一過程就叫重定向。
需要配置的只有USART1,配置過程非常簡單。
一. 在 Pinout&Configuration---System Core中:
- 1. 首先設置時鐘RCC的HSE(外部高速時鐘)爲晶振模式:Crystal/ceramic Resonator
- 2. 設置系統SYS的Debug爲Serial Wire:
二. 在 Pinout&Configuration---Connectivity中:
- 1. 打開USART1,並設置模式爲異步收發模式Asynchronous:
- 2. 設置USART1的參數,通用的“96-N-8-1”模式,即波特率9600,N校驗位(無校驗),數據位數爲8,停止位爲1位:
- 3. 串口通信方式有:查詢、中斷、DMA三種,因此要使能USART1的中斷,在NVIC使能選項中打鉤:
三.在 Clock Configuration中:
配置時鐘爲72 Mhz。
四.在 Project Manager---Project中:
- 1.設置項目的名稱以及保存的位置,選擇Toolchain/IDE爲MDK-ARM V5,
Tips:最好把Linker Settings中的Minimum Heap Size設置爲0x600。
- 2.在Code Generator選項中如下勾選:
最後點Generate Code生成代碼,並選擇“Open Project”:
五.代碼分析與改寫:
將printf()函數的輸出功能映射到串口上:
- 1. 首先在main.c中進行宏定義:
/* Private function prototypes -----------------------------------------------*/
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
- 2. 對於MDK-ARM編譯器,在main.c中加入重定向函數:(此處與官方例程中不同,將&UartHandle改爲&huart1)
/* USER CODE BEGIN 0 */
int fputc(int ch,FILE *f)
{
HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF);
return ch;
}
/* USER CODE END 0 */
此處附上標準庫實現的printf重定向代碼供參考:(僅供參考,無需添加)
int fputc(int ch,FILE *p) //Printf重定向
{
USART_SendData(USART1,(u8)ch);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
return ch;
}
- 3. 在main.c的while(1)循環中添加輸出內容:
/* USER CODE BEGIN 3 */
printf("zytjasper blog printf function USART1 output \r\n");
HAL_Delay(1000);
如果不想一直輸出,只輸出一次就將輸出內容放在循環外:
/* USER CODE BEGIN 2 */
printf("\n\r zytjasper blog \n\r");
/* USER CODE END 2 */
至此,編譯後無錯並下載到開發板中,就完成了通過STM32CubeMX調用HAL庫實現printf函數串口通信的效果程序,實驗結果如下:
這次只是按照官方例程實現了這個功能,但感覺理解USART還比較吃力,尤其是對中斷方式串口通信還不是很清楚,Mark一下,以後學習懂了回頭再討論。