他媽的!!!就因為這破事導致我浪費了兩天的時間!!! 都是基礎不扎實的鍋,導致我沒能第一時間想到問題的關鍵 好了,平復一下心情,快速的寫一篇博客來記錄這個叼問題 ## 解決方法 先把結論放在這裡:用`extern "C" {}`把中斷函數包起來 ```C++ // 就像這樣 extern "C" { ...
他媽的!!!就因為這破事導致我浪費了兩天的時間!!!
都是基礎不扎實的鍋,導致我沒能第一時間想到問題的關鍵
好了,平復一下心情,快速的寫一篇博客來記錄這個叼問題
解決方法
先把結論放在這裡:用extern "C" {}
把中斷函數包起來
// 就像這樣
extern "C" {
void EXTI4_IRQHandler() {
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_4);
}
}
問題解決,現在來講述一下過程
開端
本來我是想寫一個 RS485 通信模塊的,但是寫好之後發現發送正常,但是接收的時候沒有反應
在主程式加上 LED 閃爍以後,我發現每次發送數據,單片機都是直接卡死
然後我想了個招,使用調試器在程式運行的時候進行暫停,發現它卡在了Default_Handler
之中,而這是個死迴圈
考慮到 .s 文件中,如果找不到同名函數,就直接進入Default_Handler
好了,現在程式卡死的原因找到了,可又是什麼導致了這個現象呢?我陷入了迷惘
折磨
找不到同名函數就卡死?我看了看我寫在 main 文件裡面的函數,確定了不是名字打錯了
也不是函數名的問題,事情逐漸變得棘手
我抱著僥幸心態在 .h 文件加上了中斷函數的定義,毫無疑問沒有任何用
由於我用的 platformio + Clion 來編寫的程式,我想著或許是編譯器的問題。因為這在我用 Keil 的時候是沒有發生過的
或許是 sdcc 的bug?但是不管怎麼搜都搜不到相關的資料
事情到此進入了僵局
解決
我不死心,去運行了正點原子的示例,不出我所料,它非常正常的運行了
於是我靈光一現,將所有相關文件扔到了 CLion 裡面,改好了 include 的路徑,一運行,嗨,成了!
直接給我震驚到了,這說明肯定是我的代碼哪裡有問題!
但是我對自己的代碼質量還是有點信心的,我左看看,右看看,一眼瞧到了複製來文件上面大大的 .c 尾碼名!
我感覺自己把握到了關鍵點,直接就把所有的 .c 全改成了 .cpp
再一試,壞了,好了!問題找到了!
我直接打開我的項目工程,啪啪啪把extern "C"
敲了上去,果然好了!
我直接仰天長嘯:我!好!菜!啊!
原因分析
其實這個問題說透了也很簡單,就是因為 C++ 和 C 語言編譯結果不同導致的
因為 C++ 是允許同名函數的,也就是通過不同的參數進行重載,這就會導致函數名稱和編譯後的不相同
比如EXTI4_IRQHandler()
這個函數,放在 C++ 裡面編譯後指不定就變成了EXTI4_IRQHandler_void
這跟 .s 文件裡面預先聲明的函數不能說一點不相干,只能說完全不一樣
加上extern "C"
以後,編譯器就會按照 C 語言的標準編譯,就可以正確的被中斷調用到了