打印
[应用相关]

STM32标准库中断配置

[复制链接]
237|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
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

使用特权

评论回复
沙发
734774645| | 2025-1-2 17:49 | 只看该作者
同一个组内还有优先级顺序吗?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

16

帖子

0

粉丝