前言
上一节中没有使用中断,这小节将使用中断,按键按下,触发中断,中断事情在中断服务函数中处理
一、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); } }
前言
上一节中没有使用中断,这小节将使用中断,按键按下,触发中断,中断事情在中断服务函数中处理
一、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); } }
举报