首页 > 编程语言 >关于 STM32 在使用 C++ 进行编程时无法进行中断(触发中断就死循环)的问题

关于 STM32 在使用 C++ 进行编程时无法进行中断(触发中断就死循环)的问题

时间:2023-08-18 21:44:06浏览次数:35  
标签:IRQHandler 函数 中断 C++ STM32 extern GPIO

他妈的!!!就因为这破事导致我浪费了两天的时间!!!

都是基础不扎实的锅,导致我没能第一时间想到问题的关键

好了,平复一下心情,快速的写一篇博客来记录这个叼问题

解决方法

先把结论放在这里:用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 语言的标准编译,就可以正确的被中断调用到了

标签:IRQHandler,函数,中断,C++,STM32,extern,GPIO
From: https://www.cnblogs.com/Starsdust/p/17641685.html

相关文章

  • C++11新特性——1.4-1.5 final和override
    1.4final原文:https://subingwen.cn/cpp/final/总结:1.final限制某个类不能被继承,或限制某个虚函数不能被重写2.final修饰虚函数或者类3.final关键字写到虚函数或类后面classBase{public:virtualvoidtest(){cout<<"Baseclass.........
  • c++ 常用的 STL
    c++中常用的STLvector//vector变长数组倍增的思想(倍增:系统为每一个程序分配空间的时候,所需要的时间和空间大小无关,与请求次数相关)尽量减少请求的次数/*返回元素的个数size()判断是否为空empty()清空clear()front()返回第一个数back()返回最后一个数push......
  • [AT_ABC106_C]题解(C++)
    PartIPreface原题目\(\text{(Luogu)}\)原题目\(\text{(AtCoder)}\)PartIISketch给定一个字符串\(s\)以及一个整数\(k\)。该字符串为纯数字串。其中的数字\(x\)会在\(k\)天后变为\(x^{k-1}\)个\(x\)。求出\(10^{15}\)天后,串\(s\)的第\(k\)位是什么......
  • [AT_ABC106_D]题解(C++)
    PartIPreface原题目\(\text{(Luogu)}\)原题目\(\text{(AtCoder)}\)PartIISketch给定正整数\(n,m,q\)。接下来给定\(m\)组\(x_i,y_i\),表示一列列车的起始站和终点站。在接下来给定\(q\)组\(l_i,r_i\)。对于每组询问,回答有多少\(x_i\geql_i\operatorna......
  • [AT_ABC106_B]题解(C++)
    PartIPreface原题目\(\text{(Luogu)}\)原题目\(\text{(AtCoder)}\)PartIISketch给定一个正整数\(N\)。求出\(1\simN\)所有因数个数为\(8\)的数的个数。PartIIIAnalysis先输入\(N\)。遍历\(1\simN\)的每个数,记录每个数的因数个数。若因数个数等于\(8\)......
  • [AT_ABC106_A]题解(C++)
    PartIPreface原题目$\text{(Luogu)}$原题目$\text{(AtCoder)}$PartIISketch给定整数$a,b$,输出$(a-1)\times(b-1)$。$2\leqa,b\leq100$。PartIIIAnalysis运用小学知识,进行平移,把几块地拼接在一起。不难看出长为$a-1$,宽为$b-1$,面积为$(a-1)\tim......
  • c++ 占位符和序列化
    1#include<nlohmann/json.hpp>2#include<iostream>3#include<iomanip>45usingjson=nlohmann::json;67intmain()8{9std::cout<<std::setw(4)<<json::meta()<<std::endl;10}https://json.n......
  • C++快速入门 第四十二讲:链接和作用域
    与作用域有关的另一个概念是链接,当同时编译多个文件时,每个源文件被称为一个翻译单元,在某一个翻译单元里定义的东西在另一个翻译单元里使用正是链接发挥作用的地方。存储类(storageclass):每个变量都有一个存储类,它决定着程序将把变量的值储存在计算机的什么地方、如何存储、以及变......
  • C++快速入门 第四十三讲:链接和作用域2
    1header.h文件23#ifndefHEADER_H4#defineHEADER_H56unsignedlongreturnFactorial(unsignedshortnum);7staticconstunsignedshortheaderNum=5;//定义静态恒定值的全局变量89#endif1011that.cpp文件:1213#include"header.h"14uns......
  • C++快速入门 第四十五讲:类模板
    类模板与函数模板非常相似,同样是先由你编写一个类的模板,再由编译器在你第一次使用这个模板时生成的实际代码。实例:栈的出入栈1#include<iostream>2#include<string>34template<classT>5classStack//栈类6{7public:8Stack(unsignedintsize=......