目录
0????????前言
1????????必要的概念介绍
(1)中断源及其中断向量
(2)外部中断系统结构
(3)中断优先级控制
2? ? ? ? 外部中断使用流程配置
(1)NVIC设置
(2)中断端口的配置
(3)中断处理?
3? ? ? ?程序的实现?
?bsp_exti
?bsp_led
中断服务及其返回
主函数
代码资源包 (下载)
0????????前言
? ? ? ? STM32F10x最多有84个中断,包括16个内核中断和68个可屏蔽中断,具有16个可屏蔽中断优先级。
? ? ? ? 下文我所用的STM32F103系列具有60个可屏蔽中断。
1????????必要的概念介绍
(1)中断源及其中断向量
????????? STM32F103中断系统提供10个系统异常和60个可屏蔽中断,具有16个可屏蔽中断优先级。
????????? 可屏蔽中断源包括外部中断、定时器中断、串口中断、直接内存访问中断(DMA)、模数转换中断(A/D)、集成电路总线中断、串口外设接口中断等。
????????其中,本帖子用到的外部中断由嵌套向量中断控制器NVIC和外部中断/事件控制器EXTI来控制。
(2)外部中断系统结构
????????中断/事件请求可以来源于芯片引脚输入的外部中断/事件,也可以通过软件在软件中断寄存器写1,来产生一个中断/事件请求。(对应上图3号或门)
?????????外部中断/事件信号从芯片引脚输入,经过边沿检测电路处理后,与软件中断事件寄存器通过或门进入。然后进入挂起请求寄存器,最后与中断屏蔽寄存器相与输出到嵌套向量中断控制器NVIC。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
????????从GPIO端口与外部中断/事件的映射关系来看,每一组相同编号的GPIO端口都被映射到同一个外部中断/事件寄存器中。
(3)中断优先级控制
?????????STM32的中断向量有两个属性,抢占属性和响应属性(属性编号越小,优先级越高),其优先级由中断优先级寄存器IPR控制
0组对应的是0位抢占优先级(父优先级),4位响应优先级(子优先级)。那么无抢占优先级,响应优先级可以设置为0-15级的任意一种
1组对应的是1位抢占优先级(父优先级),2位响应优先级(子优先级)。那么抢占优先级设置为0与1级的任意一种,响应优先级可以设置为0-7级的任意一种.
以此类推
当然,我们判断的时候先看抢占优先级,如果抢占优先级相同再看响应优先级的高低,如果再相同就看中断通道的向量地址。
2? ? ? ? 外部中断使用流程配置
(1)NVIC设置
????????首先对中断优先级进行分组,确定父子优先级的个数?
????????选择中断通道(不同的优先级对应不同的中断通道,在stm32f10x.h头文件中定义了中断通道结构体IRQn_Type)
????????根据系统要求设置中断父子优先级
????????使能相应的中断,完成NVIC配置
????????????????????????
?
(2)中断端口的配置
?????????首先进行GPIO配置
?????????然后对外部中断方式进行配置(包括中断线路配置、中断或事件的选择、触发方式的设置、使能中断线)
(3)中断处理?
?????????1 中断请求
?????????2 中断响应
?????????3 中断服务程序
?????????4??中断返回
void EXTI0_IRQHandler(void)
{
if(RESET != EXTI_GetFlagStatus(EXTI_Line0)) //判断中断标志位
{
LED_G_TOGGLE;//中断服务内容
EXTI_ClearFlag(EXTI_Line0); //清除
}
}
3? ? ? ? 程序的实现?
?????????首先我实现的是用按键控制LED灯的翻转,我的板子上面有两个按键,我也就写了两个按键
? ? ? ? ?bsp_exti
? ? ? ? ? ? ? ? 头文件?
#ifndef __BSP_EXTI_H
#define __BSP_EXTI_H
#include "stm32f10x.h"
#define KEY1_INT_GPIO_PIN GPIO_Pin_0
#define KEY1_INT_GPIO_PORT GPIOA
#define KEY1_INT_GPIO_CLK RCC_APB2Periph_GPIOA
#define KEY2_INT_GPIO_PIN GPIO_Pin_13
#define KEY2_INT_GPIO_PORT GPIOC
#define KEY2_INT_GPIO_CLK RCC_APB2Periph_GPIOC
#endif /*__BSP_EXTI_H*/
?bsp_exti函数
#include "bsp_exti.h"
/*============NVIC设置===================
============中断端口配置================
============中毒那处理==================*/
static void EXTI_NVIC_Config()
{
/*====3====初始化NVIC处理中断*/
NVIC_InitTypeDef NVIC_Initstruct; //声明NVIC初始化结构体
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //选择中断分组
NVIC_Initstruct.NVIC_IRQChannel = EXTI0_IRQn; //选择中断通道
NVIC_Initstruct.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级(父优先级)
NVIC_Initstruct.NVIC_IRQChannelSubPriority = 1; //响应优先级 (子优先级)
NVIC_Initstruct.NVIC_IRQChannelCmd = ENABLE; //使能
NVIC_Init(&NVIC_Initstruct); //调用初始化函数完成配置
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_Initstruct.NVIC_IRQChannel = EXTI15_10_IRQn; //选择中断通道
NVIC_Initstruct.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级(父优先级)
NVIC_Initstruct.NVIC_IRQChannelSubPriority = 2; //响应优先级 (子优先级)
NVIC_Initstruct.NVIC_IRQChannelCmd = ENABLE; //使能
NVIC_Init(&NVIC_Initstruct); //调用初始化函数完成配置
}
void EXTI_Key_Config()
{
GPIO_InitTypeDef GPIOI_Initstruct; //声明GPIO初始化结构体
EXTI_InitTypeDef EXTI_Initstruct; //声明EXTI初始化结构体
//配置终端优先级
EXTI_NVIC_Config();
/*====1=====初始化GPIO*/
RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE); //开时钟
GPIOI_Initstruct.GPIO_Pin = KEY1_INT_GPIO_PIN; //选择GPIO引脚
GPIOI_Initstruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; //模式为浮空输入(按键)
GPIO_Init(KEY1_INT_GPIO_PORT, &GPIOI_Initstruct); //GPIO初始化函数
RCC_APB2PeriphClockCmd(KEY2_INT_GPIO_CLK,ENABLE); //开时钟
GPIOI_Initstruct.GPIO_Pin = KEY2_INT_GPIO_PIN; //选择GPIO引脚
GPIOI_Initstruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; //模式为浮空输入(按键)
GPIO_Init(KEY2_INT_GPIO_PORT, &GPIOI_Initstruct); //GPIO初始化函数
/*====2====初始化EXTI产生中断*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //开时钟
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); //选择中断输入线(中断引脚)
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource13); //选择中断输入线(中断引脚)
EXTI_Initstruct.EXTI_Line = EXTI_Line0 | EXTI_Line13; //产生中断线路
EXTI_Initstruct.EXTI_Mode = EXTI_Mode_Interrupt; //选择中断模式
EXTI_Initstruct.EXTI_Trigger = EXTI_Trigger_Falling; //触发方式------上升沿
EXTI_Initstruct.EXTI_LineCmd = ENABLE; //使能
EXTI_Init(&EXTI_Initstruct); //exti初始化函数
}
? ? ? ? ? ? ? ? bsp_led
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 头文件?
#ifndef __BSP_LED_H
#define __BSP_LED_H
#include "stm32f10x.h"
#define LED_G_GPIO_PIN GPIO_Pin_0
#define LED_B_GPIO_PIN GPIO_Pin_1
#define LED_R_GPIO_PIN GPIO_Pin_5
#define LED_G_GPIO_PORT GPIOB
#define LED_R_GPIO_PORT GPIOB
#define LED_G_TOGGLE {LED_G_GPIO_PORT->ODR ^= LED_G_GPIO_PIN;}
#define LED_R_TOGGLE {LED_R_GPIO_PORT->ODR ^= LED_R_GPIO_PIN;}
void LED_GPIO_Config(void);
#endif /*__BSP_LED_H*/
?函数
#include "bsp_led.h"
void LED_GPIO_Config(void)
{
GPIO_InitTypeDef GPIOI_Initstruct; //初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //打开ABP2时钟
GPIOI_Initstruct.GPIO_Pin=LED_G_GPIO_PIN; //选PIN绿led
GPIOI_Initstruct.GPIO_Mode=GPIO_Mode_Out_PP; //模式为推挽输出
GPIOI_Initstruct.GPIO_Speed=GPIO_Speed_50MHz; //速度50MHZ
GPIO_Init(GPIOB, &GPIOI_Initstruct); //GPIO初始化函数
GPIOI_Initstruct.GPIO_Pin=LED_R_GPIO_PIN; //选PIN R led
GPIOI_Initstruct.GPIO_Mode=GPIO_Mode_Out_PP; //模式为推挽输出
GPIOI_Initstruct.GPIO_Speed=GPIO_Speed_50MHz; //速度50MHZ
GPIO_Init(GPIOB, &GPIOI_Initstruct); //GPIO初始化函数
LED_R(OFF);LED_G(OFF);
}
中断服务及其返回
void EXTI0_IRQHandler(void)
{
if(RESET != EXTI_GetFlagStatus(EXTI_Line0)) //判断中断标志位
{
LED_G_TOGGLE;//中断服务内容
EXTI_ClearFlag(EXTI_Line0); //清除
}
}
主函数
#include "stm32f10x.h" //相当于51的 #include<reg52.h>
#include "bsp_led.h"
#include "bsp_exti.h"
void delay(uint32_t count)
{
for(;count!=0;count--);
}
int main(void)
{
//在这里系统的函数已经被配置成72M
LED_GPIO_Config();
EXTI_Key_Config();
while(1)
{
}
}
代码资源包 (下载)
https://download.csdn.net/download/m0_58193842/86627026
? ? ? ? ? ? ? ??
??????????????????????????
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
|