用STM32实现中断控制LED灯亮灭时,出现“按这个键,那个灯却亮了”情况后的反思

  今天在写利用中断实现控制LED灯亮灭程序时,我遇到了一个尴尬的问题。

灯值表
  本来是想实现绿色标识的对应控制,即

K_UP控制LED1亮,K_DOWN控制LED2亮,
K_LEFT控制LED3亮,K_RIGHT控制LED4亮。

  但结果很遗憾,出现了红色标识对应的情况,各按钮与LED灯的对应情况不符。我原始的代码如下:(仅用于记录错误代码,若无兴趣可以直接跳至中断服务函数

#include "exti.h"

void My_EXTI_Init(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	EXTI_InitTypeDef  EXTI_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //中断优先级分组 分2组
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource2);//选择GPIO管脚用作外部中断线路
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource3);//选择GPIO管脚用作外部中断线路
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource4);//选择GPIO管脚用作外部中断线路
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);//选择GPIO管脚用作外部中断线路
	
	…………//NVIC配置的代码略	
	
	EXTI_InitStructure.EXTI_Line=EXTI_Line0;
	EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;
	EXTI_InitStructure.EXTI_LineCmd=ENABLE;
	EXTI_Init(&EXTI_InitStructure);
	
	EXTI_InitStructure.EXTI_Line=EXTI_Line2|EXTI_Line3|EXTI_Line4; 
	EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;
	EXTI_InitStructure.EXTI_LineCmd=ENABLE;
	EXTI_Init(&EXTI_InitStructure);
}

void EXTI0_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line0)==1)
	{
		delay_ms(10);
		if(K_UP==1)
		{
			LED1_ON;
		}	
	}
	EXTI_ClearITPendingBit(EXTI_Line0);
}


void EXTI2_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line2)==1)
	{
		delay_ms(10);
		if(K_DOWN==1)
		{
			LED2_ON;
		}	
	}
	EXTI_ClearITPendingBit(EXTI_Line2);
}


void EXTI3_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line3)==1)
	{
		delay_ms(10);
		if(K_LEFT==1) 
		{
			LED3_ON;
		}	
	}
	EXTI_ClearITPendingBit(EXTI_Line3);
}


void EXTI4_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line4)==1)
	{
		delay_ms(10);
		if(K_RIGHT==0) 
		{
			LED4_ON;
		}	
	}
	EXTI_ClearITPendingBit(EXTI_Line4);
}

  既然从灯值表能看出K_UP和K_RIGHT与灯的对应关系是正确的,那么问题是出在了K_DOWNK_LEFT上。在仔细复盘查找ledkeyexti的问题之后,我最终把焦点锁定在了中断服务函数上。

  原来,我的代码的问题出现在了中断服务函数与中断线的对应上。什么意思呢?我做了一张表格来表明我的中断对应关系,如下:

中断服务函数与中断线的对应
  乍一看其实没有什么问题的,也是符合中断定义规则的。但联系到笔记开头的灯值表的第一列,就能发现问题了。中断对应其中,绿色代表预想的配置关系,红色代表错误配置关系。

  显然,在中断复用IO后:
  K_DOWN按键(PEin(3))应该对应EXTI3,却被误设置为对应EXTI2
  K_LEFT按键PEin(2))应该对应EXTI2,却被误设置为对应EXTI3

  这也就是为什么出现了“按这个键,那个灯却亮了”的原因。而为什么会出现明明应该是“K_DOWN== 0”和“K_LEFT== 0”(因为按照我在key.h里的宏定义,“==0”代表了低电平,而硬件设计则表示低电平代表开关打开),却在设置“K_DOWN ==1”时灯才会亮呢?

  可以这么理解:由于
  EXTI_InitStructure.EXTI_Line=EXTI_Line2|EXTI_Line3|EXTI_Line4;
  EXTI_EXTI_Trigger=EXTI_Trigger_Falling;
  故EXTI2和EXTI3都被配置成了下降沿触发(0到1时触发)。

//以EXTI2为例说明,EXTI3同
void EXTI2_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line2)==1)
	{		
		delay_ms(10);		if(K_DOWN==1)	{	LED2_ON;	}
	}
	EXTI_ClearITPendingBit(EXTI_Line2);
}

  当按下按键K_LEFT时,EXTI2的中断服务函数启动,此时:

若设置为if(K_DOWN==0)(代表K_DOWN按下)那么显然if不成立,LED2不亮;
若设置为if(K_DOWN==1)(代表K_DOWN未按下)因为我按下的是K_LEFT按键,那么此时if条件是成立的,LED2亮。

  按照此思路一一对应过去就会发现与文章最开头的灯值表是情况一致的。

  那么其实要修改为正确程序,只需要将两个中断服务函数的if条件对换位置即可:

//以EXTI2为例说明,EXTI3同
void EXTI2_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line2)==1)
	{
		delay_ms(10);		if(K_LEFT==0)	{	LED3_ON;	}	
	}
	EXTI_ClearITPendingBit(EXTI_Line2);
}
总结

  由于对外部中断的理解不够深入,导致编程时出现了一些制杖的问题。

  但从中我也学习到了:在中断里的if函数代表了先满足中断条件后,后进行判断。也就是说如果要执行中断函数里的if函数的内容,要满足两个条件:1、能中断2、满足1的前提下同时满足if函数的条件

  中断充当了一个连接硬件层面条件和软件层面条件的桥梁,当硬件层面条件(上升沿、下降沿)被满足时,中断服务函数启动,若中断服务函数内还有条件判断语句,则软件层面条件(if语句等)开始执行判断。

  另外,这也告诉我:只有当在编写软件层面程序的同时,对硬件层面也要有深刻地理解,这样才能实现精准而无bug的控制。

附言

  完整程序文件见附件,我使用的开发板是普中PZ6806L型开发板,所以对应IO是以它的IO为设置的。

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
STM32是一款基于ARM Cortex-M系列内核的32位微控制器,可用于开发嵌入式系统。按中断LED灯亮灭是嵌入式系统中非常常见的功能,下面我将用300字回答如何使用STM32的按中断控制LED灭。 首先,我们需要连接一个按和一个LEDSTM32控制器的相应引脚上。假设按连接到PA0引脚,LED连接到PC13引脚。 接下来,我们需要配置STM32的GPIO外设来控制这些引脚。首先,开启相关引脚的时钟。然后,将PA0引脚配置为输入模式,PC13引脚配置为输出模式。可以使用STM32的寄存器或者开发环境提供的库函数来完成这些配置。 然后,我们需要配置外部中断。配置PA0引脚所对应的外部中断线,使其可以检测到按的状态变化。可以使用STM32的寄存器或者库函数来完成这个配置。 紧接着,我们编写中断处理函数。当按状态发生变化,中断触发时,中断处理函数被调用。在该函数中,我们可以读取按引脚的状态,如果按被按下,我们将PC13引脚设置为高电平,LED灯亮起;如果按被释放,我们将PC13引脚设置为低电平,LED熄灭。 最后,我们需要在主函数中启用中断。启用中断后,当按状态发生变化时,中断处理函数将被调用。 以上就是使用STM32的按中断控制LED灯亮灭的步骤。通过配置GPIO外设和外部中断,编写中断处理函数,我们能够实现按下按时,LED灯亮起;释放按时,LED熄灭的功能。这样就完成了按中断控制LED灯亮灭的任务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值