他妈的!!!就因为这破事导致我浪费了两天的时间!!!
都是基础不扎实的锅,导致我没能第一时间想到问题的关键
好了,平复一下心情,快速的写一篇博客来记录这个叼问题
解决方法
先把结论放在这里:用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 语言的标准编译,就可以正确的被中断调用到了