本篇文章主要介紹STM32的調試利器,串口printf打印輸出,希望能給人以收獲。
1.開發環境
軟件環境
使用MDK5.25版本,芯片包為STM32F4系列。
硬件環境
開發板:STM32F407VGT6開發板,是一款大容量芯片,最高能跑168MHz。
燒錄器:STlink或者Jlink。
2.工程搭建
直接復制上一篇代碼,在工程欄加入/LIB/src文件夾下的串口庫函數文件stm32f4xx_usart.c,在/APP文件夾下加入usart.c和usart.h文件並添加到MDK工程欄。
開始編寫串口初始化函數和重定義printf打印函數。
在usart.c文件中添加串口初始化函數,F407和F103有些區別,1是串口掛載的時鍾總線,2是F103對於串口TX和RX是分別初始化為復用推挽輸出和上拉輸入的。
/*
*********************************************************************************************************
* 函 數 名: uart1_Init
* 功能說明: 串口1初始化函數
* 形 參: 1.bound(串口波特率)
* 返 回 值: 無
*********************************************************************************************************
*/
void uart1_Init(u32 bound)
{
//GPIO端口設置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA時鍾
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1時鍾
//串口1對應引腳復用映射
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9復用為USART1
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10復用為USART1
//USART1端口配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9與GPIOA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//復用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽復用輸出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10
//USART1 初始化設置
USART_InitStructure.USART_BaudRate = bound;//波特率設置
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字長為8位數據格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一個停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//無奇偶校驗位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無硬件數據流控制
USART_InitStructure.USART_Mode = USART_Mode_Tx; //收發模式
USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_Cmd(USART1, ENABLE); //使能串口1
//USART_ClearFlag(USART1, USART_FLAG_TC); //解決第一個字節丟失問題,如果第一個字節丟失可以加上這行
}
對於重定義printf函數有兩種方法,一種是使用微庫,一種是不是用微庫(正點原子)使用的方法。
1.使用微庫重定義printf函數
注意:printf函數依賴於"stdio.h",在使用的時候記得添加上"stdio.h"。
如果是C++文件則修改成
2.不使用微庫重定義printf函數
在原來的fputc函數的基礎上再加入避免使用半主機模式的一些代碼(參考正點原子)。
可以參考這篇對於半主機模式的理解
小結:所謂重定義就是修改fputc函數的底層代碼,修改成運行一次串口發送一個字節的數據。
3.測試
3.打印方案
編寫打印代碼
於我而言,我個人把打印分成兩種,一種是錯誤打印(一般用於else的后面,或者校驗失敗的地方),另一種就是常規打印,這些打印還可能遇到一些場景,例如我的單片機資源比較少,我就寫程序的時候用一下,或者我想控制我的打印輸出等等。
直接上代碼開講
USER_DEBUG是程序控制的開關,用於單片機資源比較少的時候,我們調試的時候用一下。
Print_Switch是一個接口控制的開關,可用於遠程網絡或者本地串口修改,來開啟或者關閉打印。
當然,我們還可以分很多級別的打印,希望各位舉一反三。
測試
4.總結
這個宏定義最好放在.h頭文件中,方便其他.c文件,后續我會加在Dbg.c和Dbg.h中,對於邏輯復雜的狀態機,用打印的方法是一個很好的調試手段,當然如果遇到死機,那得用仿真器Debug了。
代碼已全部上傳到gitee,希望各位小伙伴們在下載的同時不忘點擊Star,地址:https://gitee.com/Notmi/stm32-standard-peripheral-libraries。