今天周六,寫點輕松一點的內容,相信很多朋友都有使用宏定義的經歷。宏定義寫得好,你的代碼修改、調試、移植等都方便;相反,寫的不好,可能你的頭腦會炸掉。
1問題來源
我前面移植一部分代碼,忽略了一些細節問題,直接測試,一有數據(正常應該是進入中斷),程序就掛了,進入了“B .”處,如下圖:
這代表什么意思呢?網上一搜B .的意思就知道,程序運行到這個地方,在這里死循環了。
2問題跟蹤,并解決
遇到上面問題,于是我就開始了在線調試查找問題。果然,在線調試一眼就看出了問題,中斷函數體沒有被觸發,先看下圖:
看上圖,經常調試的人就知道,前面沒有灰色的標記代表程序不會運行到這個位置。
上面那個DEBUG_COM_IRQHandler函數,我使用的是宏定義:
那么,問題來了,我使用了宏定義中斷函數接口,為什么沒有進入中斷函數?
問題就出在宏定義和被定義函數體的包含關系,簡單說就是:stm32f4xx_it.c文件里面應該添加#include "bsp_usart.h"這行代碼。
不添加包含宏定義的文件,編譯時就會把DEBUG_COM_IRQHandler當做成一個普通函數,也不會出錯。此時,中斷函數其實是沒有定義的,那么,程序運行中斷函數時,沒有定義函數體,自然就會跳轉到B .處去。
解決的辦法就如上所說:stm32f4xx_it.c文件添加添加#include "bsp_usart.h"即可。
3總結
針對以上問題,拓展并總結幾點內容:
1.宏定義注意事項
宏定義與源代碼最好要高度一致,就拿USART時鐘的宏定義來說,如下這種方式就容易出錯。
宏定義:
#define DEBUG_COM_CLK RCC_APB2Periph_USART1
調用方式:
RCC_APB2PeriphClockCmd(DEBUG_COM_CLK, ENABLE);
假如我修改時鐘:
RCC_APB2Periph_USART1改為RCC_APB1Periph_USART2
發現問題沒有:
APB2和APB1混亂調用了。
2.B .含義
這里提出來,是讓有些初學者順便了解一下(其實網上一搜就明白)。這是一個匯編指令,“B”代表不返回的跳轉,比如跳到某個標號處。“.”是指定當前的地址,B .這條指令,其實就是死循環。
3.在線調試代碼覆蓋
經常有朋友問題:我在線調試,為什么有些地方不能打斷點?處理需要配置輸出調試信息之外,就是這里說的代碼覆蓋問題。
看見我上面有兩個中斷函數那張圖沒有,里面我有文字說明:前面有灰色標記的代碼,代表程序可執行(已覆蓋)。相反,則沒有被覆蓋。
4.中斷函數接口宏定義
一般很多初學者不知道函數接口可以使用宏定義。其實,有很多地方,包括一些標準的代碼都有用到使用宏定義函數接口。拿我們比較熟悉的FreeRTOS來說,為了移植方便,使用宏定義三個中斷函數,如下圖:
這里需要注意的就如上面分析的,包含關系需加上。
-
源代碼
+關注
關注
96文章
2945瀏覽量
66747 -
USART
+關注
關注
1文章
195瀏覽量
30857 -
宏定義
+關注
關注
0文章
50瀏覽量
9012
發布評論請先 登錄
相關推薦
評論