【STM32学习】外部中断学习记录——F407

1:外部中断原理分析

1.1定义

        中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。 

        比如:我正在煮面(事件1),门外有人敲门,我去开门(事件2),开门后继续回去煮面(事件1);

这就是中断的通俗理解,我正在持续不断的做事件1,但是被事件2打断,此时我停下事件1,去做事件2,做完回来继续事件1。

那么当多件事情一起来打断怎么办?是随心想做什么就做什么,还是又逻辑性的有顺序的完成?

1.2解析

        参考《STM32F4XX中文参考手册》第10章中断和事件,中的外部中断/事件控制(EXTI)理解。EXTI(External interrupt)

1.2.1EXTI功能框图解析

/23表示支持23个软件事件/中断事件。

本次实验使用到的是NVIC中断控制器方式,通过板载的按键。控制LED或者蜂鸣器发声。

下面是映射关系:

可以看到硬件连接是PE2/3/4和PA0,所以在选择中断线的时候是EXTI2/3/4/0四条,如果选择的时候是同一个数字如PE2和PA2,需要配置EXTI[3:0]的相关寄存器。

1.2.2代码解析

//初始化 PE2~4,PA0 为中断输入.
void EXTIX_Init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;

KEY_Init(); //按键对应的 IO 口初始化

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能 SYSCFG 时钟

SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource2);//PE2 连接线 2
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource3);//PE3 连接线 3
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource4);//PE4 连接线 4
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);//PA0 连接线 0

/* 配置 EXTI_Line0 */
 EXTI_InitStructure.EXTI_Line = EXTI_Line0;//LINE0
 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件
 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发
 EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能 LINE0
 EXTI_Init(&EXTI_InitStructure);/

/* 配置 EXTI_Line2,3,4 */
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);//配置

NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//外部中断 0
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;//抢占优先级 0
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//响应优先级 2
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
 NVIC_Init(&NVIC_InitStructure);//配置 NVIC

NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;//外部中断 2
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x03;//抢占优先级 3
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//响应优先级 2
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
 NVIC_Init(&NVIC_InitStructure);//配置 NVIC

NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;//外部中断 3
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;//抢占优先级 2
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//响应优先级 2
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
 NVIC_Init(&NVIC_InitStructure);//配置 NVIC

NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;//外部中断 4
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;//抢占优先级 1
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//响应优先级 2
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
 NVIC_Init(&NVIC_InitStructure);//配置 NVIC 
}

 1:GPIO初始化

在KEY_Init();函数中已经对GPIO的时钟和输入输出初始化完成。

2:配置中断线

SYSCFG_EXTILineConfig();

void SYSCFG_EXTILineConfig(uint8_t EXTI_PortSourceGPIOx, uint8_t EXTI_PinSourcex)
{
  uint32_t tmp = 0x00;

  /* Check the parameters */
  assert_param(IS_EXTI_PORT_SOURCE(EXTI_PortSourceGPIOx));//检查定义
  assert_param(IS_EXTI_PIN_SOURCE(EXTI_PinSourcex));//检查定义

  tmp = ((uint32_t)0x0F) << (0x04 * (EXTI_PinSourcex & (uint8_t)0x03));
  SYSCFG->EXTICR[EXTI_PinSourcex >> 0x02] &= ~tmp;
  SYSCFG->EXTICR[EXTI_PinSourcex >> 0x02] |= (((uint32_t)EXTI_PortSourceGPIOx) << (0x04 * (EXTI_PinSourcex & (uint8_t)0x03)));
}



1.2.2.1SYSCFG_EXTILineConfig函数解析

选择一个中断线简单的解析
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource3);//PE3 连接到中断线3
解析这一段代码,库函数是如何运行的;

tmp = ((uint32_t)0x0F) << (0x04 * (EXTI_PinSourcex & (uint8_t)0x03));

EXTI_PinSourcex ,我们使用的是 EXTI_PinSource3;
查找头文件发现:#define EXTI_PinSource3           ((uint8_t)0x03)

                            #define EXTI_PortSourceGPIOE       ((uint8_t)0x04)   

tmp = (0X0F)<<(0X04*(0X03&0X03))=0X0F<<(0X03*0X02)=0X0F<<0X06=0X3C0;

SYSCFG->EXTICR[EXTI_PinSourcex >> 0x02] &= ~tmp;

SYSCFG->EXTICR[0X3>> 0x02] &= ~3C0;

SYSCFG->EXTICR[0] &= FC3F = 0;

SYSCFG->EXTICR[0]数组的第0位,所以这里使用的是SYSCFG 外部中断配置寄存器 1 (SYSCFG_EXTICR1);

SYSCFG->EXTICR[EXTI_PinSourcex >> 0x02] |= (((uint32_t)EXTI_PortSourceGPIOx) << (0x04 * (EXTI_PinSourcex & (uint8_t)0x03)));

SYSCFG->EXTICR[0x03>> 0x02] |= ((0X04) << (0x04 * (0X03 & (uint8_t)0x03)));

SYSCFG->EXTICR[0] |= 0X04<<C;

SYSCFG->EXTICR[0] |= 4000;

SYSCFG->EXTICR[0] = 4000;第14位置高。

查看寄存器SYSCFG->EXTICR[0],即SYSCFG_EXTICR1;

可以看出第14位置高,是EXTI3的,也就是PE[x],所以配置的确实是PE3引脚。作为EXTI3外部中断的源输入;

以此类推;

其他的就是简单的结构体配置,明白定义即可,暂时不去理解用的什么寄存器(主要是太多了,还有还多没学,后面再说吧),里面大概就是框图中的每个必要点拉高;

//外部中断 0 服务程序
void EXTI0_IRQHandler(void)
{ 
delay_ms(10); //消抖
if(WK_UP==1)
{ BEEP=!BEEP; //蜂鸣器翻转
}
EXTI_ClearITPendingBit(EXTI_Line0); //清除 LINE0 上的中断标志位
}
//外部中断 2 服务程序
void EXTI2_IRQHandler(void)
{ 
delay_ms(10); //消抖
if(KEY2==0) 
{ LED0=!LED0; 
}
EXTI_ClearITPendingBit(EXTI_Line2);//清除 LINE2 上的中断标志位
}
//外部中断 3 服务程序
void EXTI3_IRQHandler(void)
{ 
delay_ms(10); //消抖
if(KEY1==0)
{ LED1=!LED1;
}
EXTI_ClearITPendingBit(EXTI_Line3); //清除 LINE3 上的中断标志位 
}
//外部中断 4 服务程序
void EXTI4_IRQHandler(void)
{ 
delay_ms(10); //消抖
if(KEY0==0)
{ LED0=!LED0;
LED1=!LED1;
}
EXTI_ClearITPendingBit(EXTI_Line4);//清除 LINE4 上的中断标志位 
} 
//外部中断初始化程序

这里我还是比较奇怪为什么,中断服务程序是可以直接进入的,不用和之前一样判断触发条件寄存器,而是直接使用的KEY=XX,也就是直接判断GPIO口的上升下降沿触发。

查找下来在启动程序中发现了这些定义:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值