STM32学习-NVIC、EXTI、SysTick

文章介绍了STM32微控制器中的中断系统,包括NVIC(嵌套向量中断控制器)的优先级分组和中断编程方法,EXTI(外部中断事件控制器)的功能和配置,以及SysTick系统定时器的使用和配置。NVIC控制中断处理,EXTI管理外部输入信号的中断,而SysTick则提供了一个可配置的系统定时器中断。
摘要由CSDN通过智能技术生成

1. NVIC

NVIC 是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。但是各个芯片厂商在设

计芯片的时候会对 Cortex-M4 内核里面的 NVIC 进行裁剪,把不需要的部分去掉,所以说 STM32的 NVIC 是 Cortex-M4 的 NVIC 的一个子集。

优先级分组

image-20230223133450312

优先级设置

image-20230223133526364

中断编程

​ 1. 使能外设某个中断,这个具体由每个外设的相关中断使能位控制。比如串口有发送完成中断,接收完成中断,这两个中断都由串口控制寄存器的相关中断使能位控制。

  1. 初始化 NVIC_InitTypeDef 结构体,配置中断优先级分组,设置抢占优先级和子优先级,使能

中断请求。

typedef struct {
    uint8_t NVIC_IRQChannel; // 中断源 用来设置中断源,不同的中断中断源不一样具体参考stm32f4xx.h typedef enum IRQn
    uint8_t NVIC_IRQChannelPreemptionPriority; // 抢占优先级
    uint8_t NVIC_IRQChannelSubPriority; // 子优先级

    FunctionalState NVIC_IRQChannelCmd; // 中断使能或者失能
} NVIC_InitTypeDef;

NVIC_PriorityGroupConfifig 是整个程序中只需要设置一次

示例程序

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);
}

2. EXTI 外部中断事件控制器

外部中断/事件控制器 (EXTI) 管理了控制器的 23 个中断/事件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。EXTI 可以实现对每个中断/事件线进行单独配置,可以单独配置为中断或者事件,以及触发事件的属性。

功能框图

image-20230223134146927

红色线产生中断,绿色线产生事件

中断:

  • 1是输入线,有23根,除了每个GPIO的十六根以外,还有7根用于控制其他事件image-20230223135150431

    SYSCFG 外部中断配置寄存器 1(SYSCFG_EXTICR1) 的 EXTI0[3:0] 位选择配置为 PA0、PB0、PC0、PD0、PE0、PF0、PG0、PH0 或者 PI0

    image-20230223135255088

  • 2是边沿检测电路,配置为上升沿触发或者下降沿触发,也可以同时触发

  • 3是或门,提供了软件中断事件寄存器也可以触发中断的功能

  • 4是与门,当中断屏蔽寄存器为0时可以屏蔽中断

  • 5是将EXTI_PR寄存器内容给NVIC

事件:

  • 6的作用与4相同,用于选择屏蔽事件
  • 编号 7 是一个脉冲发生器电路,当它的输入端,即编号 6 电路的输出端,是一个有效信号 1 时就会产生一个脉冲;如果输入端是无效信号就不会输出脉冲。
  • 编号 8 是一个脉冲信号,就是产生事件的线路最终的产物,这个脉冲信号可以给其他外设电路使用,比如定时器 TIM、模拟数字转换器 ADC 等等。

EXTI初始化结构体

typedef struct {
    uint32_t EXTI_Line; // 中断/事件线
    EXTIMode_TypeDef EXTI_Mode; // EXTI 模式
    EXTITrigger_TypeDef EXTI_Trigger; // 触发事件
    FunctionalState EXTI_LineCmd; // EXTI 控制
} EXTI_InitTypeDef;
  • EXTI_Line:EXTI中断/事件选择,EXTI0-EXTI22
  • EXTI 模式选择,可选为产生中断 (EXTI_Mode_Interrupt) 或者产生事件(EXTI_Mode_Event)。
  • EXTI_Trigger:EXTI 边沿触发事件,可选上升沿触发 (EXTI_Trigger_Rising)、下降沿触发 (EXTI_Trigger_Falling) 或者上升沿和下降沿都触发 ( EXTI_Trigger_Rising_Falling)。
  • EXTI_LineCmd:控制是否使能 EXTI 线,可选使能 EXTI 线 (ENABLE) 或禁用 (DISABLE)
  1. 初始化 RGB 彩灯的 GPIO;
  1. 开启按键 GPIO 时钟和 SYSCFG 时钟;

    /* 使能 SYSCFG 时钟 ,使用 GPIO 外部中断时必须使能 SYSCFG 时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
    
  2. 配置 NVIC;

  3. 配置按键 GPIO 为输入模式;

  4. 将按键 GPIO 连接到 EXTI 源输入;

    SYSCFG_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE,KEY1_INT_EXTI_PINSOURCE);
    
  5. 配置按键 EXTI 中断/事件线;

  6. 编写 EXTI 中断服务函数

void EXTI_Key_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    EXTI_InitTypeDef EXTI_InitStructure;

    /* 开启按键 GPIO 口的时钟 */
    RCC_AHB1PeriphClockCmd(KEY1_INT_GPIO_CLK|KEY2_INT_GPIO_CLK ,ENABLE);

    /* 使能 SYSCFG 时钟 ,使用 GPIO 外部中断时必须使能 SYSCFG 时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

    /* 配置 NVIC */
    NVIC_Configuration();

    /* 选择按键 的引脚 */
    GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN;
    /* 设置引脚为输入模式 */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
    /* 设置引脚不上拉也不下拉 */
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    /* 使用上面的结构体初始化按键 */
    GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure);

    /* 连接 EXTI 中断源 到 key引脚 */
    SYSCFG_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE,
    KEY1_INT_EXTI_PINSOURCE);

    /* 选择 EXTI 中断源 */
    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_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN;
    /* 其他配置与上面相同 */
    GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure);

    /* 连接 EXTI 中断源 到 key引脚 */
    SYSCFG_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE,
    KEY2_INT_EXTI_PINSOURCE);

    /* 选择 EXTI 中断源 */
    EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    /* 上升沿触发 */
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);
}

3. SysTick系统定时器

SysTick—系统定时器是属于 CM4 内核中的一个外设,内嵌在 NVIC 中。系统定时器是一个 24bit的向下递减的计数器,计数器每计数次的时间为 1/SYSCLK,一般我们设置系统时钟 SYSCLK等于 180M。当重装载数值寄存器的值递减到 0 的时候,系统定时器就产生一次中断,以此循环往复。

因为 SysTick 是属于 CM4 内核的外设,所以所有基于 CM4 内核的单片机都具有这个系统定时器,使得软件在 CM4 单片机中可以很容易的移植。系统定时器一般用于操作系统,用于产生时基,维持操作系统的心跳。

SysTick配置函数在core_cm4.h中实现,只需要调用即可。

__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)

形参 ticks 用来设置重装载寄存器的值,最大不能超过重装载寄存器的值 2 24,当重装载寄存器的值递减到 0 的时候产生中断,然后重装载寄存器的值又重新装载往下递减计数,以此循环往复。紧随其后设置好中断优先级,最后配置系统定时器的时钟为 168M,使能定时器和定时器中断,这样系统定时器就配置好了

SysTick初始化函数,SysTick初始化函数由我们自己编写

/**
* @brief 启动系统滴答定时器 SysTick
* @param 无
* @retval 无

*/
void SysTick_Init(void)
{
    /* SystemFrequency / 1000 1ms 中断一次
    * SystemFrequency / 100000 10us 中断一次
    * SystemFrequency / 1000000 1us 中断一次
    */
    if (SysTick_Config(SystemCoreClock / 100000)) {
    /* Capture error */
    while (1);
	}
}

SysTick中断时间计算

SystemFrequency为168M/100000是1680,SysTick是自上往下递减的,计数一次时间T = 1/CLKAHB,AHB为168M,1680/168M=10us,因此10us中断一次

示例程序:通过SysTick实现延时

static uint32_t TimingDelay = 0;
void SysTick_Handler(void)//SysTick中断服务函数
{
    if (TimingDelay != 0x00) 
        TimingDelay--;
}
void Delay(__IO uint32_t nTime)
{
    TimeingDelay = nTime;
    while(TimingDelay != 0);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

指针到处飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值