前言
上一节中没有使用中断,这小节将使用中断,按键按下,触发中断,中断事情在中断服务函数中处理
一、NVIC 嵌套向量中断控制器
NVIC是嵌套向量中断控制器,控制着整个芯片中中断相关功能,是内核里面的一个外设。
手册中的中断向量:分为系统中断和外设中断。红框框出来的是系统中断,有10个。外设中断比较多有60个,图片仅显示一小部分。
优先级定义:
原则上每个外部中断可配置的优先级为0~255,数值越小,优先级越高。优先级被分组成抢占优先级和子优先级。如果多个中断同时相应,抢占优先级会先执行。如果抢占优先级相同,再比较子优先级,如果子优先级相同在比较硬件的中断号,就是上图中Pritorty编号,编号越小优先级越高。
优先级分组如下:
固件库中NVIC相关的函数
//设置分组优先级
void NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
//获取分组优先级
uint32_t NVIC_GetPriorityGrouping(void)
//中断使能
void NVIC_EnableIRQ(IRQn_Type IRQn)
//中断失效
void NVIC_DisableIRQ(IRQn_Type IRQn)
//获取中断
uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
//设置中断
void NVIC_SetPendingIRQ(IRQn_Type IRQn)
//清除中断
void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
//设置中断优先级
void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
//获取中断优先级
uint32_t NVIC_GetPriority(IRQn_Type IRQn)
中断编程步骤:
1)设置外设中断,比如串口收发中断;
2)初始化NVIC_InitTypeDef结构体;
typedef struct
{
uint8_t NVIC_IRQChannel;//中断源,参考IRQn_Type
uint8_t NVIC_IRQChannelPreemptionPriority; //中断优先级 参考NVIC_Priority_Table
uint8_t NVIC_IRQChannelSubPriority;//中断子优先级NVIC_Priority_Table
FunctionalState NVIC_IRQChannelCmd; //This parameter can be set either to ENABLE or DISABLE
} NVIC_InitTypeDef;
3)中断服务函数
二、EXIT 外部中断控制器
EXIT(External interrupt/event controller)外部中断/事件控制器。每个中断/事件线都对应一个边沿检测器,可以实现输入信号的上升沿检测和下降沿检测。输入线一般是存在电平变化的信号。EXIT可分为两类,一类是产生中断,另一类是产生事件。中断直接给NVIC,进一步实现中断。中断事件输送给外设电路使用,比如ADC,定时器TIM。
EXTI 有 20 个中断/事件线,每个 GPIO 都可以被设置为输入线,占用 EXTI0 至EXTI15,还有另外七根用于特定的外设事件。输入源与中断/事件的关系如下
通过AFIO_EXTICRx配置GPIO线上的外部中断/事件
EXIT结构体:
typedef struct
{
uint32_t EXTI_Line; /* 中断/事件线,EXTI0-EXTI19 combination of @ref EXTI_Lines */
EXTIMode_TypeDef EXTI_Mode;/* 模式选择@ref EXTIMode_TypeDef */
EXTITrigger_TypeDef EXTI_Trigger; /* 触发选择,上升沿,下降沿,上升沿和下降沿 @ref EXTIMode_TypeDef */
FunctionalState EXTI_LineCmd; /* 是否使能ENABLE or DISABLE */
}EXTI_InitTypeDef;
三 、外部中断实验
使用外接的按键来作为触发源,使得控制器产生中断,并在中断服务函数中实现控制点灯的任务。按键KEY1对应的GPIO为使用PA0,EXTI对应于EXTI0中断线;NVIC对应于EXTI0_IRQn中断源。
1) 初始化用来产生中断的GPIO
2)初始化EXTI
3)配置NVIC
4)编写中断服务函数
头文件
#include "stm32f10x.h"
#define KEY1_INT_GPIO_PORT GPIOA//组 PA
#define KEY1_INT_GPIO_CLK (RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO)//时钟需要开启AFIO 配置中断 APB2
#define KEY1_INT_GPIO_PIN GPIO_Pin_0//引脚
#define KEY1_INT_EXTI_PORTSOURCE GPIO_PortSourceGPIOA//端口
#define KEY1_INT_EXTI_PINSOURCE GPIO_PinSource0//引脚
#define KEY1_INT_EXTI_LINE EXTI_Line0//中断线
#define KEY1_INT_EXTI_IRQ EXTI0_IRQn//中断源中断/事件
#define KEY1_IRQHandler EXTI0_IRQHandler//中断服务函数
配置EXTI, 产生中断的GPIO
void EXTI_Key_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
/*时钟设置*/
RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE);
/* NVIC中断*/
NVIC_Configuration();
/*按键使用的GPIO*/
GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN;
/* 浮空 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure);
/* 选择EXTI信号源 Selects the GPIO pin used as EXTI Line */
GPIO_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, KEY1_INT_EXTI_PINSOURCE);
/*中断事件*/
EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE;
/* 中断模式*/
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
/* 触发模式,上升沿*/
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
/* 使能 */
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
外部中断寄存器的配置 GPIO_EXTILineConfig 函数用来指定中断/事件线的输入源,它实际是设定外部中断配置寄存器的 AFIO_EXTICRx 值,该函数接收两个参数,第一个参数指定 GPIO 端口源,第二个参数为选择对应 GPIO 引脚源编号.
配置NVIC
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/*优先级选择,组1 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/* 中断源 */
NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;
/* 主优先级*/
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
/*子优先级*/
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
/*使能中断*/
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//初始化
NVIC_Init(&NVIC_InitStructure);
}
中断服务函数
void KEY1_IRQHandler(void)
{
//获取中断线EXTI line状态
if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET)
{
//翻转LED灯
LED1_TOGGLE;
EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);
}
}
评论(0)
您还未登录,请登录后发表或查看评论