这个实验要用到外部中断,我们简单了解了下系统中断:
NVIC用于是在内核里的,不需要开时钟,它是用来根据中断优先级分配终中断顺序的 。
中断优先级的分组如上图所示,相同优先级的中断先后顺序由中断号决定。
先来看下EXTI(外部中断)引起的中断,先了解下EXTI:
值得注意的是,相同号的GPIO_Pin引脚只有一个能接到EXTI对应号的通道上,因为AFIO只能在相同号的GPIO_Pin引脚选择一个,比如GPIOA_Pin_0,GPIOB_Pin_0,GPIOC_Pin_0 这三个只能选一个。
可以看到有20条输出到了其他外设,这个就是出发事件响应的。
以上我们只会用到AFIO的中断引脚选择的功能,他还有一个功能,就是复用功能引脚重映射。
中断信号从AFIO出来后就进入到EXTI 了,先看下EXTI内部电路的概形:
触发信号从输入线进入,我们可以配置上触发升沿或下降沿触发寄存器来检测 输入的信号,符合条件后输出,来到和软件中断事件寄存器一起进入或门,或门输出的触发信号兵分两路,分为触发中断的信号和触发事件的信号,请求挂起寄存器检测到中断信号会挂起标志位,可以通过读取该寄存器判断哪个通道发生的中断,中断屏蔽寄存器和事件屏蔽寄存器相当于输出中断信号和中断事件发生的开关。
以上EXTI通道的中断介绍到此为止,接下来将完成对射式红外传感器计次,线上接线图:
跳过了OLED的介绍,因为OLED现只用于简单的显示,不做多赘述,注意接线。
根据接线图,我们需要将GPIO_Pin_14配置为外部中断引脚,根据此图,我们一步步对外设进行配置,先是开引脚时钟,然后是AFIO时钟,然后是引脚初始化,接着AFIO选择引脚,然后到EXTI,进行中断触发配置,最后到NVIC,主要进行优先级配置,如下:
#include "stm32f10x.h" // Device header
uint8_t count=0;
void Redlay_Sensor_Init()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启AFIO的时钟
GPIO_InitTypeDef Redlay_Sensor_InitStructure;
Redlay_Sensor_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
Redlay_Sensor_InitStructure.GPIO_Pin=GPIO_Pin_11;
Redlay_Sensor_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&Redlay_Sensor_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource11);//AFIO配置
EXTI_InitTypeDef EXTI_InitStruture;
EXTI_InitStruture.EXTI_Line=EXTI_Line11;
EXTI_InitStruture.EXTI_LineCmd=ENABLE;
EXTI_InitStruture.EXTI_Mode=EXTI_Mode_Interrupt;//配置中断模式
EXTI_InitStruture.EXTI_Trigger=EXTI_Trigger_Rising;//上升沿触发
EXTI_Init(&EXTI_InitStruture);//EXTI配置
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置优先级组合
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=EXTI15_10_IRQn;//中断线
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//优先级等级
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);//NVIC配置
}
uint8_t GetCount()
{
return count;
}
void EXTI15_10_IRQHandler()//中断函数,可在start文件夹的md.s后缀文件里找到函数名
{
if(EXTI_GetITStatus(EXTI_Line11)==1)
EXTI_ClearITPendingBit(EXTI_Line11);
count++;
}
OLED代码省略。。。。。。
配置完EXTI中断后,终端就可以被触发了,触发外部中断后,中断函数被调用,我们就可以在库函数头文件EXTI里找到函数EXTI_GetITStatus()用于检测中断标志位是否被挂起,如果挂起就再用找到的EXTI_ClearITPendingBit()函数清零,为下一次中断做准备。
主函数代码就随便写下吧:
#include "stm32f10x.h"// Device header
#include "OLED.H"
#include "Redlay_Sensor.h"
int main()
{
uint8_t count=0;
OLED_Init();
Redlay_Sensor_Init();
OLED_ShowString(1,3,"Count:");
while(1)
{
count=GetCount();
OLED_ShowNum(1,9,count,4);
}
}
以上内容仅供参考,谢谢!