STM32的外部中斷
你好,這裏是月魂離人本小白的博客,本人最近在學習stm32(基於cubemx),寫下這篇博客希望自己能養成做筆記的習慣,同時也是鍛鍊自己寫博客的能力,希望大家不吝賜教,大佬們指出我的問題,hhhhh。本篇博客最後寫到了怎麼用jlink調試stm32以及其中的坑,希望能幫到需要的朋友。大家一起沖沖衝,我們開始吧!
外部中斷EXTI是STM32微處理器實時處理外部事件的一種機制,由於中斷請求主要來自GPIO端口的引腳,所以稱爲外部中斷。
STM32F013微處理器有19個能產生事件/中斷請求的邊沿檢測器,每個輸入線可以獨立地配置成輸入類型(脈衝或掛起)和對應的觸發事件(上升沿、下降沿或雙邊沿觸發),也可以獨立地屏蔽。
EXTI0~EXTI15:GPIO端口引腳。
EXTI16:PVD輸出,可編程電壓監測。
EXTI17:RTC鬧鐘。
EXTI18:USB喚醒。
EXIT0的連接引腳是: PA0~PG0,即每個端口組的0號引腳
NVIC
NVIC全稱Nested vectored interrupt controller,即嵌套向量中斷控制器,用來決定中斷的優先級。
NVIC在 ARM Conrtex-M 內核中,用一個 8 位的寄存器來配置,總共可以配置28=25628=256 2^8=25628=256級中斷,但是 ST 公司在生產 STM32 的時候,發現一個小小的單片機根本用不了這麼多,純屬浪費,所以將該寄存器的低 4 位全部置0,只使用高 4 位來配置,這樣一來 STM32 就只有24=1624=16 2^4=1624=16級中斷啦。
簡化爲16級中斷後,ST發現 STM32 內部這麼豐富的外設,還是不方便配置,乾脆人工給這4位來個分組,劃分出了5個分組:
優先級分組 | 搶佔優先級佔的位數 | 子優先級佔的位數 |
---|---|---|
NVIC_PriorityGroup_0 | 0 bit | 4 bit |
NVIC_PriorityGroup_1 | 1 bit | 3 bit |
NVIC_PriorityGroup_2 | 2 bit | 2 bit |
NVIC_PriorityGroup_3 | 3 bit | 1 bit |
NVIC_PriorityGroup_4 | 4 bit | 0 bit |
再次強調一下,這5種中斷分組規則是人爲的,用哪種規則,之後設置具體的優先級時對應就行,STM32默認使用的規則是 NVIC_PriorityGroup_0 。
STM32 的CPU判斷優先級的方法如下:
先判斷搶佔優先級,數字越小,優先級越高;
若搶佔優先級相同,判斷子優先級,同樣,數字越小,優先級越高
基於STM32CubeMX的外部中斷設計步驟
-
在STM32CubeMX中指定引腳,配置中斷初始化參數, 選擇GPIO引腳的功能,設置中斷信號觸發條件,使能NVIC對應的中斷通道。
-
重寫該I/O引腳對應的中斷回調函數。
具體實現步驟:
-
新建工程
- 搜索芯片型號
- 選擇芯片
- 創建工程
-
設置RCC
- 1點擊RCC
- 2高速時鐘(HSE)選擇外部晶振
- 3軟件自動配置管腳
-
GPIO初始化
LED :GPIO_OUTPUT(輸出模式)
按鍵 :GPIO_EXITx(外部中斷模式)
- 點擊對應管腳
- 設置對應模式
GPIO的各種模式設置
-
+ GPIO output level 引腳電平設置 高/低
+ GPIO mode GPIO模式 推輓輸出/開漏輸出
+ GPIO Pull-up/Pull-dowm 上拉下拉電阻 上拉電阻/下拉電阻/無上拉或下拉
+ Maxinum output speed 引腳速度設置 低速/中速/高速
+ User Label 用戶標籤 給引腳設置名稱 如LED0
==GPIO_EXIT的六種模式==
-
設置NVIC(嵌套向量中斷控制器)
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳
- 1點擊NVIC2 勾選EXIT Line
- 2 interrupt 和 EXIT Line[15:12] interrupt 使能中斷)
-
時鐘源設置
- 1選擇外部時鐘HSE 8MHz
- 2PLL鎖相環倍頻9倍
- 3系統時鐘來源選擇爲PLL
- 4設置APB1分頻器爲 /2
-
項目文件設置
MDK外部中斷的設置
-
隨後我們可以在stm32f1xx_it.c中看到我們所配置的中斷服務函數 並且可以看到gpio的初始化分到了gpio.c裏面,並且裏面有一個函數
-
HAL_GPIO_EXTI_IRQHandler(); void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin) { /* EXTI line interrupt detected */ if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET) { __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin); HAL_GPIO_EXTI_Callback(GPIO_Pin); } }
-
上述代碼中可以看到,在該函數中首先讀取了一下中斷寄存器,確認該中斷是否發生,確認之後又調用了一個函數,並將接收到的參數
GPIO_Pin
繼續傳給該函數 -
HAL_GPIO_EXTI_Callback()
-
該函數稱爲EXIT中斷的回調函數,用來處理所有發生的EXIT中斷事件
-
往下看這個回調函數定義的時候使用了__weak修飾符,使用
_weak
進行了弱定義,所以用戶可以再次定義該函數,並且這個note寫的非常清楚:這個函數不應該被改變,如果需要使用回調函數,請重新在用戶文件中實現該函數。我們需要重新定義這個函數。編輯在gpio.c(或者main.c也可以)
使用JLINK調試STM32
- 左邊第一個按鍵時進入調試
- 第二個是設置斷點
如圖所示,在中斷進入函數設置一個斷點
先選擇JATG模式進行調試,頻率爲5Mhz,後面設置斷點後進入調試,點擊RUN(F5),則會出現如圖所示的BUG
這是因爲在使用cubemx時沒有設置SYS導致的,SYS默認是(No Debug模式)
將其設置爲Serial Wire模式然後生成工程,進入調試後仍發現上述錯誤存在,我在網上查找後發現是在stm32f1xx_hal_msp.c第79行代碼,此代碼的存在禁用了jtag,將其註釋掉
切記註釋後將程序再次燒錄進板子裏(重新編譯就不用我說了吧)
😄
再次RUN,就沒有發現錯誤了,程序直接到了斷點處(這裏我是比較疑惑的。因爲我還沒有按下按鍵,結果直接就到了,小白不知道是什麼情況hhhhh等大佬解釋)
然後後面就是一步步調試
我們再次點擊DEBUG
設置爲SW模式,頻率爲10Mhz
重複上述步驟,發現只有當按下按鍵後程序纔會跑到斷點處,最終我決定在調試時選擇SW模式
重複上述步驟,發現只有當按下按鍵後程序纔會跑到斷點處,最終我決定在調試時選擇SW模式