一 什么是中断
:
轮询机制
:顾名思义,就是每轮都询问一次。比如
while
循环的每一次,就会执
行检查,
1.
此处串口是否有数据到来。
2.
每次都检测一下引脚状态
,
是否为低电
平。
本质是
while
循环每一次都把数据获取的函数或者寄存器执行一次,看看数据是
否发生变化。
中断机制:中断也是一种对于数据获取的调度方式。通过中断源来提醒
CPU
,数
据已经更新,可以读取新数据。
从上图可以观察到
NVIC
的有一部分是接到了
EXTI
的器件,
EXTI
,中文名称
外
部中断
/
事件控制器
。这个器件有
16
根线路连接到了不同的引脚上。比如
PAO,PA1
等等。我们板子所有的
GPIO
引脚都连接着各自相应的 外部中断控制
器。
二,什么是外部中断
凡是要经过
EXTI
到达
NVIC
的中断,都叫做
“
外部中断
”
。内部中断不经过
EXTI
。
外部中断与内部中断路线示意如下
上图紫色线路为轮询机制。黑色线路部分为内部中断。红色线路部分为外部中断
思考:为什么要
EXTI
这个结构。引脚线路为什么不直接见到
NVIC
上去
原因1:因为
NVIC
处理的是中断信号,不是电平信号。
usart
,
TIM
,
IIC
这些芯片
内部器件本身就可以产生中断信号,因此就可以直接与NVIC
连接。但是,光突
突的
GPIO
本身就是一根电线,肯定不具备产生中断信号的功能。因此连接
EXTI
,依靠
EXTI
产生中断信号。
原因
2
:中断通达数量比较少,
EXTI
的多路复选的功能扩充了接口。一个
EXTI
可
以接
16
个
GPIO
引脚呢。
三,外部中断的使用
3.1
他是什么样子
着重注意
**
:
EXTI0
的
16
根引脚接的是
GPIO
所有组的第
0
个成员。
EXTI1
管着所
有
GPIO
组的第
1
个成员。。。。。。
EXTI16
管着所有
GPIO
组的第
16
个成员
.
因此:我们希望红外传感器(我接在
PF13
上)对人的感知,采用中断形式上
报。过程如下;
红外传感器数据传输到引脚
PF13
。所以,该引脚硬件连接在
EXTI13
上。
EXTI13
发送数据到
NVIC
上,
core
内核调用相应中断服务函数。
3.2
外部中断如何使用。
3.2.1
任务分配
3.2.2
任务分配
pir
代码检查
void pir_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_Init(GPIOF, &GPIO_InitStructure);
}
void pir_run()
{
if(PFin(13) == 1)
{
printf("有人靠近\n");
}
else
{
printf("周边没人\n");
}
}
3.2.3
确认引脚
从代码去人引脚
PF13
,
GPIO
的
F
组的第
13
个成员。
组号:
GPIOF
成员号:
GPIO_Pin_13
3.2.4
工程添加文件
点击位置
3.2.5
代码编写流程图
3.2.5.1
连接
PF13
与
EXTI13
函数解释:告诉程序你要用哪一个
EXTI
,并用哪一根引脚。
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOx, EXTI_PinSourcex)
参数
1
:
EXTI_PortSourceGPIOx
,第几组。
参数
2
:
EXTI_PinSourcex
,第几根。
3.2.5.2EXTI
参数配置
函数解释:告诉程序让哪一个
EXTI
以什么形式工作。
EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct)
;
结构体名字
.EXTI_Line =
到底是哪一个
EXTI.EXTI_Line2/EXTI_Line3;
结构体名字
.EXTI_LineCmd =
是否开始工作。
结构体名字
.EXTI_Mode =
检测中断呢还是事件
;
结构体名字
.EXTI_Trigger =
何种电平信号为依据
;
3.2.5.3
优先级分组
NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
;
函数解释:对于四个比特位进行划分为两个数据段。不同的划分行为影响流程图
第四步的优先级配置。
参数
1
:
NVIC_PriorityGroup
,这里模仿了
IP
地址子网划分的思想,进行分组。
NVIC_PriorityGroup_0\NVIC_PriorityGroup_1\NVIC_PriorityGroup_2\NVIC_Pri
orityGroup_3\NVIC_PriorityGroup_4
3.2.5.4NVIC
参数配置
NVIC_Init(&NVIC_InitStruct);
函数解释:告诉
NVIC
检测拿一根电线(中断通道),以什么样子的
“
优先级
别
”
来处理
参数
1
:第几根中断通道,以第几组优先级别(抢占优先级),第几成员优先级
别(响应优先级)来处理,
NVIC_InitStruct.NVIC_IRQChannel = 中断通道;
NVIC_InitStruct.NVIC_IRQChannelCmd = 开始工作;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority =抢占优先
级;
NVIC_InitStruct.NVIC_IRQChannelSubPriority =相应优先级
3.2.5.4
中断服务函数
void EXTI15_10_IRQHandler()
{
}
函数解释:中断出发后会调用这个函数。其中内容标准写法如下。
1.
查看标记位,确认中断。
2.
执行想要执行的内容。
3.
清楚标记位,并退出。
3.2.6
代码验证和代码整理
void pir_interrupt_init()
{
//exti13与F13连接
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOF,EXTI_PinSource13
);
//配置EXTI
EXTI_InitTypeDef EXTI_InitStruct;
EXTI_InitStruct.EXTI_Line = EXTI_Line13;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
EXTI_Init(&EXTI_InitStruct);
//分组模式
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority =2;
NVIC_InitStruct.NVIC_IRQChannelSubPriority =2;
NVIC_Init(&NVIC_InitStruct);
}
中断服务函数展示如下:
static uint32_t i = 0;
void EXTI15_10_IRQHandler()
{
if(EXTI_GetITStatus(EXTI_Line13) != RESET)//确认中断事件
{
i++;
if(i%2 == 0)
{
printf("有人靠近\n");
}
else
{
printf("有人离开\n");
}
EXTI_ClearITPendingBit(EXTI_Line13);//清除挂起中断标志位
}
}
四,总结原理深化
中断根据中断信号来源不同,分为内部中断和外部中断。
外部中断:中断信号来自
“EXTI”,
信号经过
EXTI
的,都是外部中断。否则都是内
部中断。
常见的外部中断:
KEY
开关,触发类的传感器(
PIR
),警报设备和诱捕设备。
内部中断:不经过
EXTI
的就是内部中断,常见的内部中断有,定时器
TIM
,串口
usart
,主要是通信类的接口。