1.配置STM32微控制器的中断优先级管理。
对STM32芯片的嵌套向量中断控制器(NVIC)进行设置,确保系统在中断发生时,能按预定优先级处理不同中断,避免重要中断被延迟或打断,保证系统稳定、高效运行。
1.1打开复用时钟
打开使能APB2总线上的AFIO(复用时钟)。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
RCC_APB2PeriphClockCmd 函数用于控制APB2(Advanced Peripheral Bus 2)总线上外设时钟的开启或关闭。APB2总线连接着STM32微控制器的高速外设。
RCC_APB2Periph_AFIO:AFIO(Alternate Function I/O)即复用功能I/O,用于将一些GPIO引脚配置为特殊功能,如定时器、串口等功能的引脚复用。开启该时钟意味着后续可以对AFIO相关功能进行配置。
ENABLE:这是一个枚举值,用于表示使能(开启)指定的外设时钟。与之对应的还有DISABLE,用于关闭外设时钟。
1.2 设置优先级分组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
这段代码是将NVIC优先级分组设为第4组,此分组把所有优先级位都分给抢占优先级,共16级 ,无子优先级。
这个函数的参数一共有四个,分别是:
1.3 配置NVIC结构体
NVIC_InitTypeDef 是定义在相关头文件中的结构体类型,用于配置嵌套向量中断控制器(NVIC)。
初始化所有成员为0,能确保各配置参数从确定的初始状态开始,避免因未初始化而产生不可预测值,影响NVIC配置。例如,结构体可能包含中断通道、抢占优先级、子优先级及中断使能等成员。若不初始化,这些成员值随机,可能导致中断配置出错,系统运行异常。 后续可按需对 nvic_initstruct 的成员赋值,再传入 NVIC_Init 函数来配置NVIC 。
NVIC_InitTypeDef nvic_initstruct = {0};
nvic_initstruct.NVIC_IRQChannel = EXTI0_IRQn;
nvic_initstruct.NVIC_IRQChannelPreemptionPriority = 1;
nvic_initstruct.NVIC_IRQChannelSubPriority = 0;
nvic_initstruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_initstruct);
将NVIC_IRQChannel成员设置为EXTI0_IRQn,这指定了要配置的中断通道为EXTI0中断。
设置抢占优先级为1。抢占优先级决定了在多个中断同时发生时,哪个中断会优先得到响应。数值越小,优先级越高。
设置抢占优先级为0。抢占优先级决定了在多个中断同时发生时,哪个中断会优先得到响应。数值越小,优先级越高。
将NVIC_IRQChannelCmd设置为ENABLE,表示使能EXTI0中断。如果设置为DISABLE,则会禁止该中断。
调用NVIC_Init函数,并将配置好的结构体nvic_initstruct的地址作为参数传递进去。该函数会根据结构体中的配置信息,对NVIC进行相应的设置,使前面设置的中断配置生效。
2.配置外部中断源
1.1打开复用时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
1.2 配置EXTI结构体
创建一个用于配置外部中断的结构体变量 exti_initstruct ,并对其各个成员进行赋值,以指定要配置的中断线,工作模式,触发方式,且使能该中断线。然后调用 EXTI_Init 函数,按照结构体中设置的参数完成对外部中断的初始化,使得当 配置的线 上的输入信号出现下降沿时,能够触发中断并执行相应的中断服务程序。
EXTI_InitTypeDef exti_initstruct = {0};
exti_initstruct.EXTI_Line = EXTI_Line0;
exti_initstruct.EXTI_Mode = EXTI_Mode_Interrupt;
exti_initstruct.EXTI_Trigger = EXTI_Trigger_Falling;
exti_initstruct.EXTI_LineCmd = ENABLE;
EXTI_Init(&exti_initstruct);
exti_initstruct.EXTI_Line = EXTI_Line0; 这里指定了要配置的外部中断线为 EXTI_Line0 。不同的芯片可能支持多条外部中断线,通过设置这个成员来选择具体要操作的那一条。
exti_initstruct.EXTI_Mode = EXTI_Mode_Interrupt; 这表明将外部中断的工作模式设置为中断模式。通常还有事件模式等其他可选模式,中断模式意味着当相应的触发条件发生时,会执行中断服务程序。
exti_initstruct.EXTI_Trigger = EXTI_Trigger_Falling; 此语句设定了中断的触发方式为下降沿触发。也就是说,当对应的输入信号从高电平变为低电平时,会产生中断。也可以选择上升沿触发(EXTI_Trigger_Rising)或者上升沿和下降沿都触发(EXTI_Trigger_Rising_Falling)。
exti_initstruct.EXTI_LineCmd = ENABLE; 这最后一步将这条中断线使能,使其处于有效状态,这样当中断触发条件满足时,系统才会响应中断。
通过调用 EXTI_Init(&exti_initstruct); 函数,将上述设置好的结构体参数传递进去,完成对外部中断的初始化配置工作。
1.3 配置中断处理函数
找到自己环境中的STM32f10x_it.c文件
滑到最下面,找到示范函数
将他复制一份改个名字,改成你自己所配置的中断函数的名字。
这里面就是当程序运行的过程中如果触发了中断就会调用此函数,它是跟你配置的NVIC中的NVIC_IRQChannel属性联系上的。
3.代码:
此处我们用普通的延时函数来模拟程序的堵塞。我们用摁键KEY1作为中断触发源,摁下KEY1就会执行EXTI0_IRQHandler中断函数中,点亮我们的LED灯。直接上代码:
main.c
#include "stm32f10x.h"
#include "LED/led.h"
#include "DELAY/delay.h"
void Init()
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
NVIC_InitTypeDef nvic_initstruct = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOA,ENABLE);
nvic_initstruct.NVIC_IRQChannel = EXTI0_IRQn;
nvic_initstruct.NVIC_IRQChannelPreemptionPriority = 1;
nvic_initstruct.NVIC_IRQChannelSubPriority = 0;
nvic_initstruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_initstruct);
GPIO_InitTypeDef gpio_initstruct = {0};
GPIO_SetBits(GPIOA,GPIO_Pin_0);
gpio_initstruct.GPIO_Pin = GPIO_Pin_0;
gpio_initstruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
gpio_initstruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&gpio_initstruct);
EXTI_InitTypeDef exti_initstruct = {0};
exti_initstruct.EXTI_Line = EXTI_Line0;
exti_initstruct.EXTI_Mode = EXTI_Mode_Interrupt;
exti_initstruct.EXTI_Trigger = EXTI_Trigger_Falling;
exti_initstruct.EXTI_LineCmd = ENABLE;
EXTI_Init(&exti_initstruct);
}
int main()
{
Init();
LED_Init();
while(1)
{
NOP_Delay_S(1);
}
}
LED/led.h
#ifndef __LED_H__
#define __LED_H__
#include "stm32f10x.h"
void LED_Init(void); //LED初始化
#define LED_ALL_LIGHT GPIO_ResetBits(GPIOA,GPIO_Pin_1); \
GPIO_ResetBits(GPIOA,GPIO_Pin_2); \
GPIO_ResetBits(GPIOA,GPIO_Pin_3); //LED灯全亮
#define LED_ALL_CLOSE GPIO_SetBits(GPIOA,GPIO_Pin_1); \
GPIO_SetBits(GPIOA,GPIO_Pin_2); \
GPIO_SetBits(GPIOA,GPIO_Pin_3); //LED灯全灭
#endif /*__LED_H__*/
DELAY/delay.h
延时函数
#ifndef __DELAY_H
#define __DELAY_H
#define TIME __nop()
void NOP_Delay(unsigned int num);
void NOP_Delay_Us(unsigned int time);
void NOP_Delay_Ms(unsigned int time);
void NOP_Delay_S(unsigned int time);
#endif /* __DELAY_H*/
stm32f10x_it.c
中断函数(补充)
#include "LED/led.h"
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0) == SET)
{
LED_ALL_LIGHT;
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_71828548/article/details/144778772
|