stm32 中断

来源:互联网 发布:各种网络协议 编辑:程序博客网 时间:2024/05/17 08:07

中断编程

在配置每个中断的时候一般有三个编程要点:

1、使能外设某个中断,这个具体由每个外设的相关中断使能控制。比如串口发送完成中断接收完成中断,这两个中断都由串口控制寄存器相关中断使能位控制。
2、初始化NVIC_IntTypedef结构体,配置中断优先级分组,设置抢断优先级和子优先级,使能中断请求。NVIC_IntTypeDef结构体在库文件misc.h中定义。

typedef struct { uint8_t NVIC_IRQChannel; // 中断源 uint8_t NVIC_IRQChannelPreemptionPriority; // 抢占优先级 uint8_t NVIC_IRQChannelSubPriority; // 子优先级 FunctionalState NVIC_IRQChannelCmd; // 中断使能或者失能 } NVIC_InitTypeDef;

EXIT初始化结构体

typedef struct{    uint32_t EXTI_Line;//中断/事件线    EXTIMode_TypeDef EXTI_Mode;//EXTI模式    EXTITrigger_TypeDef EXTI_Trigger;//触发类型    FunctionalState EXTI_LineCmd;//EXTI使能}EXTI_InitTypeDef;

编程要点
1)初始化用来产生中断的GPIO;
2)初始化EXTI;
3)配置NVIC;
4)编写中断服务函数;

引脚定义

 #define KEY1_INT_GPIO_PORT GPIOA #define KEY1_INT_GPIO_CLK (RCC_APB2Periph_GPIOA\ RCC_APB2Periph_AFIO) #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 #define KEY2_INT_GPIO_PORT GPIOC #define KEY2_INT_GPIO_CLK (RCC_APB2Periph_GPIOC\ RCC_APB2Periph_AFIO) #define KEY2_INT_GPIO_PIN GPIO_Pin_13 #define KEY2_INT_EXTI_PORTSOURCE GPIO_PortSourceGPIOC #define KEY2_INT_EXTI_PINSOURCE GPIO_PinSource13 #define KEY2_INT_EXTI_LINE EXTI_Line13 #define KEY2_INT_EXTI_IRQ EXTI15_10_IRQn

在上面的宏定义中,我们除了开GPIO的端口时钟外,我们还打开了AFIO的时钟,这是因为等下配置EXTI信号源的时候需要用到AFIO中断控制寄存器AFIO_EXTICRx,
具体见具体见《 STM32F10X-中文参考手册》 8.4 章节 AFIO 寄存器描述。

嵌套向量中断控制寄存器NVIC配置

static void NVIC_Configuration(void){ NVIC_InitTypeDef NVIC_InitStructure; /* 配置 NVIC 为优先级组 1 */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); /* 配置中断源:按键 1 */ NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ; /* 配置抢占优先级: 1 */ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; /* 配置子优先级: 1 */ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; /* 使能中断通道 */ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* 配置中断源:按键 2,其他使用上面相关配置 */ NVIC_InitStructure.NVIC_IRQChannel = KEY2_INT_EXTI_IRQ; NVIC_Init(&NVIC_InitStructure); }

EXTI中断配置

 void EXTI_Key_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure;/*开启按键 GPIO 口的时钟*/ RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE); /* 配置 NVIC 中断*/ NVIC_Configuration(); /*--------------------------KEY1 配置---------------------*/ /* 选择按键用到的 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 的信号源 */ GPIO_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, \ KEY1_INT_EXTI_PINSOURCE); EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE; /* EXTI 为中断模式 */  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; /* 上升沿中断 */ EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; /* 使能中断 */ EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); /*--------------------------KEY2 配置------------------*/ /* 选择按键用到的 GPIO */ GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN; /* 配置为浮空输入 */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure); /* 选择 EXTI 的信号源 */ GPIO_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE, \ KEY2_INT_EXTI_PINSOURCE); EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE; /* EXTI 为中断模式 */ EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; /* 下降沿中断 */ EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; /* 使能中断 */ EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); }

EXTI中断服务函数

void KEY1_IRQHandler(void) { //确保是否产生了 EXTI Line 中断 if (EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) { // LED1 取反 LED1_TOGGLE; //清除中断标志位 EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE); } } void KEY2_IRQHandler(void) {//确保是否产生了 EXTI Line 中断 if (EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET) { // LED2 取反 LED2_TOGGLE; //清除中断标志位 EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE); } }

EXTI_GetITStatus 函数用来获取 EXTI 的中断标志位状态,如果 EXTI 线有中断发生函数返回“SET”否则返回“RESET”。实际上, EXTI_GetITStatus 函数是通过读取EXTI_PR 寄存器值来判断 EXTI 线状态的。按键 1 的中断服务函数我们让 LED1 翻转其状态,按键 2 的中断服务函数我们让 LED2翻转其状态。执行任务后需要调用 EXTI_ClearITPendingBit 函数清除 EXTI 线的中断标志位。

主函数

 int main(void) { /* LED 端口初始化 */ LED_GPIO_Config(); /* 初始化 EXTI 中断,按下按键会触发中断, * 触发中断会进入 stm32f4xx_it.c 文件中的函数 * KEY1_IRQHandler 和 KEY2_IRQHandler,处理中断,反转 LED 灯。 */ EXTI_Key_Config(); /* 等待中断,由于使用中断方式, CPU 不用轮询按键 */ while (1) {  } }
原创粉丝点击