STM32外部中断(总结了易出现的BUG)

news2024/11/15 19:42:33

本文主要讲述了,本人在使用STM32F103C8T6做项目时,使用到按键触发外部中断时,发现无法触发外部中断。通过查看寄存器找出问题的过程,并总结了出现该问题的原因。

出现的问题

在使用STM32F103C8T6做一个矩阵键盘任务时,发现了不规范使用标准库导致外部中断无法触发。
下面是实验时的部分原理图:
矩阵键盘原理图在这里插入图片描述

代码思路:让IO口PB12、PB13、PB14、PB15输出低电平,IO口PB8、PB9、PB10、PB11外部中断下降沿触发,检测按键是否按下。如果外部中断触发成功,LED指示灯将会被点亮。但是实际现象是怎么按按键,指示灯也不亮。并且使用在线仿真在外部中断处打断点也无法进入中断。(这段代码是之前成功案例复制过来的,只是进行了适当修改)
下面是有问题的代码:

在这里插入代码片
int main(void)
{	
	LED_Init();						//LED函数初始化(LED函数在HARDWARE文件夹中)
	LED_OFF();                      //关闭LED指示灯
	delay_init();
	Key_Exti_init();
	while(1)							//死循环,使得LED一直亮
	{                                   //将4个IO口输出低,确保随机按下哪个按钮,入IO口都能拉低,方便测试外部中断是否有用
     GPIO_ResetBits(GPIOB,GPIO_Pin_15);
     GPIO_ResetBits(GPIOB,GPIO_Pin_14);
     GPIO_ResetBits(GPIOB,GPIO_Pin_13);
     GPIO_ResetBits(GPIOB,GPIO_Pin_12);
	}	
}
//按键初始化函数
void KEY_Init(void) //IO初始化
{ 
 	GPIO_InitTypeDef GPIO_InitStructure;
 
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);//使能GPIOB时钟
    //输出口
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置推挽输出
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOE2,3,4

    //输入口
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;   //上拉输入
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOA.0

}
void Key_Exti_init(void)
{
	EXTI_InitTypeDef EXTI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    KEY_Init();
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource8|GPIO_PinSource9|GPIO_PinSource10|GPIO_PinSource11);
	
	EXTI_InitStructure.EXTI_Line=EXTI_Line8|EXTI_Line9|EXTI_Line10|EXTI_Line11;
	EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;
	EXTI_InitStructure.EXTI_LineCmd=ENABLE;
	EXTI_Init(&EXTI_InitStructure);
	
	NVIC_InitStructure.NVIC_IRQChannel=EXTI9_5_IRQn|EXTI15_10_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
	NVIC_Init(&NVIC_InitStructure);
}
void EXTI9_5_IRQHandler(void)
{
	  LED_ON();                     //当触发外部中断,指示灯点亮
	delay_ms(10);
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_8)==RESET && EXTI_GetITStatus(EXTI_Line8)==SET)
	{
	   
	}
	
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_9)==RESET && EXTI_GetITStatus(EXTI_Line9)==SET)
	{
			
	}
	EXTI_ClearITPendingBit(EXTI_Line8);
	EXTI_ClearITPendingBit(EXTI_Line9);	
}
void EXTI15_10_IRQHandler(void)
{
	LED_ON();
	delay_ms(10);
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)==RESET && EXTI_GetITStatus(EXTI_Line10)==SET)
	{
		
	}
	
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)==RESET && EXTI_GetITStatus(EXTI_Line11)==SET)
	{
		
	}
	EXTI_ClearITPendingBit(EXTI_Line10);
	EXTI_ClearITPendingBit(EXTI_Line11);
	
}

问题分析过程和解决过程

通过对数据手册外部中断、AFIO寄存器、NVIC寄存器章节进一步阅读,并通过在线仿真DUG查看寄存器是否置位,最终发现问题所在。
DUG时发现AFIO寄存器和NVIC控制外部中断的寄存器没有置位。具体看下图。
图2-1 EXTI寄存器
如图2-1可看出该寄存器已经被设置了,没有问题。
图2-1 AFIO寄存器
根据数据手册的描述当使用这些口做外部中断时EXTI8、EXTI9、 EXTI10 、EXTI11寄存器需要都赋值为0X01。与图2-1对比发现寄存器值不对,因此这个寄存器设置出现了 问题。
图2-3 NVIC寄存器
根据数据手册图2-3的寄存器设置也出现了问题。

结果

最终通过排查发现是下面使用代码使用不规范导致的错误:

GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource8|GPIO_PinSource9|GPIO_PinSource10|GPIO_PinSource11);

NVIC_InitStructure.NVIC_IRQChannel=EXTI9_5_IRQn|EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
NVIC_Init(&NVIC_InitStructure);

将上面代码段改成下面代码段就可以解决BUG:

GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource8);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource9);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource10);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource11);

NVIC_InitStructure.NVIC_IRQChannel=EXTI9_5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
NVIC_Init(&NVIC_InitStructure);
	
NVIC_InitStructure.NVIC_IRQChannel=EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
NVIC_Init(&NVIC_InitStructure);

下面三张图片是解决BUG后寄存器的值
在这里插入图片描述
在这里插入图片描述

)在这里插入图片描述

最终修改后的代码如下

int main(void)
{	
	LED_Init();						//LED函数初始化(LED函数在HARDWARE文件夹中)
	LED_OFF();                      //关闭LED指示灯
	delay_init();
	Key_Exti_init();
	while(1)							//死循环,使得LED一直亮
	{                                   //将4个IO口输出低,确保随机按下哪个按钮,入IO口都能拉低,方便测试外部中断是否有用
     GPIO_ResetBits(GPIOB,GPIO_Pin_15);
     GPIO_ResetBits(GPIOB,GPIO_Pin_14);
     GPIO_ResetBits(GPIOB,GPIO_Pin_13);
     GPIO_ResetBits(GPIOB,GPIO_Pin_12);
	}	
}
//按键初始化函数
void KEY_Init(void) //IO初始化
{ 
 	GPIO_InitTypeDef GPIO_InitStructure;
 
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);//使能GPIOB时钟
    //输出口
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置推挽输出
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOE2,3,4

    //输入口
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;   //上拉输入
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOA.0

}
void Key_Exti_init(void)
{
	EXTI_InitTypeDef EXTI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    KEY_Init();
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource8);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource9);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource10);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource11);
	
	EXTI_InitStructure.EXTI_Line=EXTI_Line8|EXTI_Line9|EXTI_Line10|EXTI_Line11;
	EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;
	EXTI_InitStructure.EXTI_LineCmd=ENABLE;
	EXTI_Init(&EXTI_InitStructure);
	
	NVIC_InitStructure.NVIC_IRQChannel=EXTI9_5_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
	NVIC_Init(&NVIC_InitStructure);
	
	NVIC_InitStructure.NVIC_IRQChannel=EXTI15_10_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
	NVIC_Init(&NVIC_InitStructure);
}
void EXTI9_5_IRQHandler(void)
{
	  LED_ON();                     //当触发外部中断,指示灯点亮
	delay_ms(10);
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_8)==RESET && EXTI_GetITStatus(EXTI_Line8)==SET)
	{
	   
	}
	
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_9)==RESET && EXTI_GetITStatus(EXTI_Line9)==SET)
	{
			
	}
	EXTI_ClearITPendingBit(EXTI_Line8);
	EXTI_ClearITPendingBit(EXTI_Line9);	
}
void EXTI15_10_IRQHandler(void)
{
	LED_ON();
	delay_ms(10);
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)==RESET && EXTI_GetITStatus(EXTI_Line10)==SET)
	{
		
	}
	
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)==RESET && EXTI_GetITStatus(EXTI_Line11)==SET)
	{
		
	}
	EXTI_ClearITPendingBit(EXTI_Line10);
	EXTI_ClearITPendingBit(EXTI_Line11);
	
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2095950.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【学习笔记】卫星通信NTN 3GPP标准化进展分析(五)- 3GPP Release19 研究计划

一、引言: 本文来自3GPP Joern Krause, 3GPP MCC (May 14,2024) Non-Terrestrial Networks (NTN) (3gpp.org) 本文总结了NTN标准化进程以及后续的研究计划,是学习NTN协议的入门。 【学习笔记】卫星通信NTN 3GPP标准化进展分析(一&#xff…

R语言报错 | object ‘integral‘ not found whilst loading name

1、报错背景 Registered S3 method overwritten by htmlwidgets:method from print.htmlwidget tools:rstudio Error: package or namespace load failed for ‘Seurat’:object integral not found whilst loading namespace spatstat.core 当我想library&…

RabbitMQ~架构、能力、AMQP、工作模式、高可用、死信队列了、事务机制了解

RabbitMQ RabbitMQ是使用Erlang编写的一个开源的消息中间件。它实现了AMQP(高级消息队列协议),并支持其他消息传递协议:例如STOMP(简单文本定向消息协议)和MQTT(物联网协议)。 支持多种客户端如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、…

4-7 使用bios 中断 读取磁盘

1 首先是逻辑。 首先来看一下 他的编译代码的逻辑。 可以看到我 生成的 实际上是 Boot.bin , 这个文件可不止一个扇区, 然后将这个文件写入到了, disk1.img 这里加载了 disk1.img , disk2.img 我不太理解。 但是可以跑通, 暂时先不管了。…

How can I change from OpenAI to ChatOpenAI in langchain and Flask?

题意:“在 LangChain 和 Flask 中,如何将 OpenAI 更改为 ChatOpenAI?” 问题背景: This is an implementation based on langchain and flask and refers to an implementation to be able to stream responses from the OpenAI …

力扣763-划分字母区间(Java详细题解)

题目链接:763. 划分字母区间 - 力扣(LeetCode) 前情提要: 因为本人最近都来刷贪心类的题目所以该题就默认用贪心方法来做。 贪心方法:局部最优推出全局最优。 如果一个题你觉得可以用局部最优推出全局最优&#xf…

云服务器系统盘存储空间不够用怎么办?解决方法:扩容或挂载数据盘

云服务器系统盘满了不够用怎么办?服务器百科:可以系统盘扩容,也可以通过挂载数据盘来增大存储空间。 1、系统盘扩容教程:使用云服务器系统盘空间不足时,可以在ECS控制台上扩容云盘的容量以增加存储空间。阿里云支持云…

MCU3.电平等一些名词

1.电平的简单定义 计算机由各种硬件组成,只认识0和1,可以通过改变电压来向计算机输入数据(0和1) 例如:最大电压为3.3V 电压范围是0~3.3V,可以定义0~1V较低的电压表示0,定义2~3.3V较高的电压表…

领域驱动设计——大型结构(Large-Scale Structure)的综合运用

在一个大的、复杂的系统中,可能需要在一个设计中综合运用几种策略。那么,大型结构如何与CONTEXT MAP共存?应该把构造块放到哪里?第一步先做什么?第二步和第三步呢?如何设计你的战略? 把大型结构与BOUNDED CONTEXT结合起来使用 战略设计的3个基本原…

SpringBoot中@Value获取值和@ConfigurationProperties获取值用法及比较

SpringBoot中Value获取值和ConfigurationProperties获取值用法及比较 更新时间:2024年08月08日 09:41:48 作者:岳轩子 在Spring Boot中,Value注解是一个非常有用的特性,它允许我们将外部的配置注入到我们的Bean中,ConfigurationProperties用于将配置文件…

理解调试和组织 CSS——WEB开发系列26

CSS(层叠样式表)不仅是为网页提供样式的关键工具,也是调试和优化网页表现的重要部分。无论是调整网页布局,还是确保样式的一致性,掌握调试和组织 CSS 的技巧都是至关重要的。 一、使用浏览器开发者工具 浏览器开发者工…

【国外比较权威的免费的卫星数据网站——Sentinel Open Access Hub】

Sentinel Open Access Hub 网址:https://scihub.copernicus.eu/dhus/#/home简介:哨兵系列卫星科研数据中心(Sentinel Open Access Hub)是欧洲航天局(ESA)提供卫星数据的官方网站。该网站提供哨兵系列卫星的…

八、2 DMA数据转运 DMA函数介绍

把数组定义在Flash中,可以节省SRAM的空间 去掉const不会影响程序运行,但会占用SRAM的空间 1、步骤 (1)RCC开启DMAD的时钟 (2)调用DMA_Init,初始化参数 (3)调用DMA_Cmd…

Java的动态代理(实际案例秒懂!)

在看动态代理解决两个案例之前,请先看链接VCR 《java代理》2分钟动画_哔哩哔哩_bilibili 一.动态代理-精致小案例 需求分析 传统方法 就是定义一个接口,然后实现类去实现规定的run方法 缺点:代码很冗余,有一些运行前和运行后…

C++ | Leetcode C++题解之第385题迷你语法分析器

题目: 题解: class Solution { public:int index 0;NestedInteger deserialize(string s) {if (s[index] [) {index;NestedInteger ni;while (s[index] ! ]) {ni.add(deserialize(s));if (s[index] ,) {index;}}index;return ni;} else {bool negati…

超实用!如何用搜索引擎提升你的工作效率

平常用的Google浏览器比较多,所以分享下Google Chrome一些能提高工作效率的配置和操作以及如何巧妙利用Google搜索技巧快速找我们想要的数据 1. 浏览器设置 1. 搜索引擎快速切换 使用效果: 2. 历史记录快速打开 效果展示: 3. 隐藏显示书…

线性约束最小方差准则(LCMV)波束形成算法及MATLAB深入仿真分析

阵列信号处理——线性约束最小方差准则(LCMV)波束形成算法及MATLAB深入仿真分析 目录 前言 一、LCMV算法 二、仿真参数设置 三、抗干扰权值计算仿真 四、不同干扰方位下抗干扰性能仿真 五、不同信噪比和干噪比下抗干扰性能仿真 总结 前言 在信号处理模块中,通…

Vue——认识day06_class与style绑定

在Vue中,可以使用v-bind指令来将CSS样式动态地绑定到HTML元素上。有两种方式可以实现CSS与style的绑定: 对象语法:可以将一个包含CSS属性和值的对象传递给v-bind,将对象的属性与HTML元素的style属性进行绑定。例如: …

使用 Docker 搭建企业级私有仓库HARBOR

目录 1 HARBOR 的获取 1.1 下载软件包地址 1.2 HARBOR 的介绍 2 部署harbor 2.1 仓库端操作 2.1.1 修改harbor配置文件 2.1.2 生成服务端的证书与秘钥 2.1.3 管理HARBOR 2.1.4 查看是否运行 2.2 客户端操作 2.2.1 证书拷贝给客户端 2.2.2 环境配置 2.2.3 批量读取本地镜像 2.2…

Transformer面试真题详解——覆盖99%的Transformer面试问题(建议收藏)

文章目录 1. 请简述一下Transformer的基本结构和原理2. Transformer为什么使用多头注意力机制3. Transformer计算attention为什么选择点乘而不是加法?两个计算复杂度和效果上有什么区别?4. 为什么在softmax之后要对attention进行scaled(为什么…