日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

hal库开启中断关中断_[STM32]HAL库下GPIO按键中断与去抖问题分析(分析源码解决问题)...

發(fā)布時(shí)間:2025/5/22 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 hal库开启中断关中断_[STM32]HAL库下GPIO按键中断与去抖问题分析(分析源码解决问题)... 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
自上篇文章STM32 非阻塞HAL_UART_ReceiveIT解析與實(shí)際應(yīng)用,具體總結(jié)了HAL庫下套娃函數(shù)中如何看清庫函數(shù)的脈絡(luò),更細(xì)致的認(rèn)識調(diào)用的過程,以解決潛在的問題。又又又遇到了新的問題(GPIO按鍵中斷),感覺網(wǎng)絡(luò)上和各種資料都沒解釋清楚的情況下。我又去扒了扒HAL庫函數(shù)源碼,提供不一樣解決按鍵抖動(dòng)的問題(個(gè)人認(rèn)為除了那些通過配置具體寄存器的外;是從HAL庫提供函數(shù)的基礎(chǔ)上解決的)有別于那種在Callback返回函數(shù)中添加延遲和判斷具體是否按下按鍵的方法(個(gè)人實(shí)際操作感覺這種方法效果也不好)。而是在HAL_GPIO庫函數(shù)上的HAL_GPIO_EXTI_IRQHandler處理中斷函數(shù)解決按鍵抖動(dòng)帶來的問題,是更根上解決問題的方法。

前言

Yume-知乎文章?www.zhihu.com

在這里,還是以我一貫的風(fēng)格——不重復(fù)造輪子。具體如何配置STM32CubeMX初始化、生成工程目錄之類的問題。包括關(guān)于STM32的Cortex-M3處理器的中斷細(xì)節(jié)都不會在本文章中贅述,想了解的朋友可以自行去翻看“Cortex-M3 權(quán)威指南”、“Cortex-M3 技術(shù)手冊”等相關(guān)技術(shù)文檔,都有中文的翻譯版本。本文的目的只在如何具體分析問題,解決問題。

1 STM32CubeMX中GPIO配置(基于正點(diǎn)原子的Stm32F1-Nano板)

像如何配置RCC、配置相關(guān)的時(shí)鐘樹、配置中斷NVIC、配置中斷輸入等基礎(chǔ)配置,生成工程文件的問題。這里就省略了,有需要的朋友可以參考其他網(wǎng)絡(luò)上資料。重點(diǎn)就看看關(guān)于GPIO配置,便于后面分析講解代碼。

其中,PC0、PC1、PC2為LED燈,當(dāng)按鍵觸發(fā)中斷時(shí)反轉(zhuǎn)。PC8、PC9、PD2為共地按鍵(低電平有效),所以設(shè)置GPIO為Pull-up。按鍵的GPIO mode有兩個(gè)為上升沿觸發(fā)(Rising edge)和一個(gè)下降沿觸發(fā)(Falling edge),這里其實(shí)上升沿或下降沿都沒啥特別大的關(guān)系。

2 HAL庫的GPIO中斷響應(yīng)過程

在初始化相關(guān)中斷響應(yīng)函數(shù)后,HAL庫是如何進(jìn)行中斷響應(yīng)的。其實(shí)和上篇文章

Yume:STM32 非阻塞HAL_UART_Receive_IT解析與實(shí)際應(yīng)用?zhuanlan.zhihu.com

有很多相似的地方,可以借助上篇文章來理解。

同樣的,GPIO的入口函數(shù)是什么呢?這里先引用“Cortex-M3權(quán)威指南”的一張圖來簡單說明Cortex-M3處理器的中斷問題

可以看出Cortex-M3處理器有16個(gè)外部I/O中斷,分別對應(yīng)[0:15]端口上。也就是說每個(gè)中斷端口號(0-15)可以在任一Port(A-G)上,然后通過選擇器去決定中斷端口采用哪個(gè)Port。當(dāng)然這部分在STM32CubeMX上很容易就能配置并初始化好。自然就會有對應(yīng)的Handler函數(shù)。那具體是啥,我們看看生成的工程文件中“Src”文件夾里的“stm32f1xx_it.c”中斷文件中有這么一段注釋

大致意思就是:STM32F1xx外部中斷處理(Handlers)在“stratup file”中提及到了。有了這信息,再去看看在工程文件的根目錄中“startup_stm32f103xb.s”文件(基于Nano版上的處理器)雖然里面是匯編語言,但通過查找“IRQHandler”可以看到

這7個(gè)就是外部I/O中斷的入口函數(shù)(可以看出[0:4]端口是獨(dú)立的入口,而[5:9]、[10-15]分別共用一個(gè)入口)。再看看“stm32f1xx_it.c”文件也能看到對應(yīng)的函數(shù)定義

可以看到進(jìn)入對應(yīng)的I/O中斷入口函數(shù)后就會傳輸GPIO_Pin口(用戶配置的中斷端口[0:15])到“HAL_GPIO_EXTI_IRQHandler()”中。那我們再看看這個(gè)IRQHandle函數(shù)

描述也很清晰地表明了這個(gè)函數(shù)功能是EXTI中斷回應(yīng)。那具體發(fā)生了什么呢?在函數(shù)里調(diào)用了“__HAL_GPIO_EXTI_GET_IT()”和“__HAL_GPIO_EXTI_CLEAR_IT()”后就調(diào)用“HAL_GPIO_EXTI_Callback”用戶處理函數(shù),有了解上篇文章

Yume:STM32 非阻塞HAL_UART_Receive_IT解析與實(shí)際應(yīng)用

,應(yīng)該已經(jīng)清楚怎么回事了,這里就不贅述了。但關(guān)鍵問題是前面兩個(gè)調(diào)用又是什么?

可以看到,這兩并不是函數(shù),而是一個(gè)宏。是干嘛的呢?大概可以看出是檢查到底是哪個(gè)I/O端口觸發(fā)中斷的。所以這里就可以理解為啥[5:9]和[10:15]可以共用入口函數(shù)也不會出問題了。原因就在這里可以檢查。

那再細(xì)致點(diǎn)的去看這兩個(gè)宏定義,不難發(fā)現(xiàn)第一個(gè)是獲取中斷的標(biāo)志位和確認(rèn)中斷是否產(chǎn)生,由誰產(chǎn)生。第二個(gè)則是清除標(biāo)志位。通過查看“Cortex-M3 技術(shù)文檔”的相關(guān)寄存器,也能更好地理解上面說的過程。

那現(xiàn)在應(yīng)該很清楚發(fā)生了什么事了。發(fā)生中斷響應(yīng)時(shí),通過入口函數(shù)“EXITx_IRQHandler”進(jìn)入到“HAL_GPIO_EXTI_IRQHandler()”確認(rèn)中斷端口后,重置對應(yīng)中斷的標(biāo)志位,進(jìn)入到“HAL_GPIO_EXTI_Callback”用戶處理函數(shù)中去。那我們只需要在用戶處理函數(shù)中用switch語句選擇不同I/O中斷端口GPIO_Pin([0:15])對應(yīng)不同中斷處理任務(wù)就行了。例:

3 按鍵抖動(dòng)問題分析與解決方案

那如果單純在用戶函數(shù)中類似上例中這么寫,肯定會發(fā)現(xiàn)很嚴(yán)重的問題。發(fā)現(xiàn)按下去觸發(fā)中斷時(shí)可能會產(chǎn)生兩次任務(wù)(預(yù)期是按下去就觸發(fā)一次任務(wù))。因?yàn)榘存I時(shí)會有抖動(dòng)的,導(dǎo)致進(jìn)入了兩次中斷,相信這不用我來解釋為何按鍵抖動(dòng)會引發(fā)這類的問題。

解決方案大家應(yīng)該也清楚,要么通過計(jì)算添加合適大小電容消除抖動(dòng)產(chǎn)生的影響,那另一種方案,也是最常見的方案就是添加去抖延遲。在網(wǎng)上也有很多類似的教程,甚至也是針對STM32的。會發(fā)現(xiàn),他們都是在用戶處理函數(shù)“HAL_GPIO_EXTI_Callback”中添加延遲,然后讀取確認(rèn)按鍵。那問題來了,通過上面一步一步分析HAL庫的I/O中斷處理過程,就知道在用戶處理函數(shù)之前的“HAL_GPIO_EXTI_IRQHandler()”確認(rèn)中斷端口中就已經(jīng)將中斷標(biāo)志位消除了(在用戶處理函數(shù)之前),意味著抖動(dòng)仍然能觸發(fā)中斷。然后再通過閱讀相關(guān)文檔,發(fā)現(xiàn)STM32中斷是依靠向量表機(jī)制,也就是說只要觸發(fā)了中斷,一般情況下總是要去響應(yīng)和清除相應(yīng)的中斷標(biāo)志位。所以我認(rèn)為在用戶處理函數(shù)這么做可能可以解決問題,但以我個(gè)人經(jīng)驗(yàn),效果并不是很好,原因就是解決問題的方法不太對。

個(gè)人認(rèn)為更正確的做法是在清除標(biāo)志位之前延遲等待抖動(dòng)消失,防止因抖動(dòng)在此將中斷標(biāo)志位置為有效。即需要修改HAL庫(Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c)中的“HAL_GPIO_EXTI_IRQHandler”函數(shù)。如圖,在“__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);”之前添加延遲“HAL_Delay((uint32_t)20);”

然后再用戶處理函數(shù)中返回前添加延遲。就能比較好的解決按鍵抖動(dòng)帶來可能重復(fù)進(jìn)入中斷的問題。(雖然在我摧殘下,還是有可能出現(xiàn)問題,但感覺基本上是能達(dá)到預(yù)期的,畢竟鼠標(biāo)都可能因?yàn)槲?dòng)問題出現(xiàn)雙擊呢)


想說的話

網(wǎng)絡(luò)上有人批判HAL庫效率、為非EE專業(yè)設(shè)計(jì)的,將所有東西都抽象了等一系列問題。但我想說的是,對于大多數(shù)普通用戶或相關(guān)工作者。處理效率固然重要,但開發(fā)效率、移植效率也是需要實(shí)際考察的。會想起剛接觸C51用匯編操作寄存器能時(shí),我也會有點(diǎn)批判高級程序語言的效率各種不如匯編,不如匯編一步一步清晰。但問題是現(xiàn)在微處理器計(jì)算性能、寄存器數(shù)量也是遠(yuǎn)遠(yuǎn)超過以前。面對復(fù)雜的項(xiàng)目時(shí),需要操作32位甚至64位總線寬度時(shí),你還能處理各種復(fù)雜的關(guān)系么。

雖然我有時(shí)也覺得怎么一個(gè)中斷都能套娃般弄得如此復(fù)雜,明明感覺有更簡便的方法。但也意識到,之所以會弄這么復(fù)雜,一方面是為了提高開發(fā)者的開發(fā)效率,方便移植,另一方面也減少因?yàn)槭终`配置錯(cuò)寄存器,導(dǎo)致不可預(yù)知的后果。隨著項(xiàng)目復(fù)雜度的上升,人為出錯(cuò)的概率也會上升,而用庫相比去配置寄存器,出錯(cuò)的概率我認(rèn)為是更低的。更別說在抽象后高層級的去思考能更好的完成某件任務(wù)的邏輯,而不是苦與寄存器相互如何作用的問題發(fā)愁。

總的來說,如果認(rèn)為HAL庫犧牲效率,甚至出現(xiàn)感覺不符合預(yù)期的Bug出現(xiàn)時(shí)無法像配置寄存器類似的方法排錯(cuò)。那我感覺可能就只是片面的去看HAL庫函數(shù)就是黑盒,實(shí)際上這些函數(shù)都是能去追溯到具體的寄存器,在追溯的過程中慢慢的可能也能找到Bug的原因,在針對實(shí)際場景做修改也不是不可以的。

也許很多地方我表達(dá)的不專業(yè),還請多多包涵。


Yume:STM32 非阻塞HAL_UART_Receive_IT解析與實(shí)際應(yīng)用?zhuanlan.zhihu.com

總結(jié)

以上是生活随笔為你收集整理的hal库开启中断关中断_[STM32]HAL库下GPIO按键中断与去抖问题分析(分析源码解决问题)...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。