跳到主要内容

STM32 定时器中断

介绍

STM32微控制器中的定时器(Timer)是一个强大的外设,用于生成精确的时间延迟、测量时间间隔或生成PWM信号。定时器中断是定时器的一个重要功能,它允许在定时器达到特定条件(如计数器溢出或比较匹配)时触发中断,从而执行特定的任务。

在本教程中,我们将学习如何配置STM32的定时器中断,并通过一个简单的示例来演示如何使用定时器中断实现LED的闪烁。

定时器中断的基本概念

定时器中断的核心思想是:当定时器的计数器达到某个特定值时,触发一个中断请求(IRQ),然后执行相应的中断服务程序(ISR)。STM32的定时器通常有以下几种中断源:

  • 更新中断(Update Interrupt):当计数器溢出或下溢时触发。
  • 捕获/比较中断(Capture/Compare Interrupt):当计数器值与捕获/比较寄存器的值匹配时触发。

通过配置这些中断源,我们可以实现各种时间相关的功能。

配置STM32定时器中断

1. 选择定时器

STM32系列微控制器通常有多个定时器(如TIM2、TIM3等)。我们需要根据需求选择一个合适的定时器。

2. 配置定时器

配置定时器包括设置预分频器(Prescaler)和自动重装载寄存器(Auto-reload Register)。预分频器用于降低定时器的时钟频率,而自动重装载寄存器决定了计数器的最大值。

c
// 示例:配置TIM2定时器
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = 9999; // 自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler = 7199; // 预分频器
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

3. 使能定时器中断

接下来,我们需要使能定时器的更新中断,并配置NVIC(嵌套向量中断控制器)以处理中断。

c
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

4. 编写中断服务程序

在中断服务程序中,我们可以执行特定的任务。例如,下面的代码在每次定时器中断时切换LED的状态。

c
void TIM2_IRQHandler(void) {
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
GPIO_ToggleBits(GPIOC, GPIO_Pin_13); // 切换LED状态
}
}

5. 启动定时器

最后,启动定时器以开始计数。

c
TIM_Cmd(TIM2, ENABLE);

实际应用案例:LED闪烁

假设我们使用STM32F103C8T6微控制器,并且连接了一个LED到GPIOC的Pin 13。我们可以使用TIM2定时器中断来实现LED的闪烁。

c
#include "stm32f10x.h"

void TIM2_IRQHandler(void) {
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
GPIO_ToggleBits(GPIOC, GPIO_Pin_13); // 切换LED状态
}
}

int main(void) {
// 初始化GPIOC的Pin 13为输出
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);

// 配置TIM2定时器
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = 9999; // 自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler = 7199; // 预分频器
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

// 使能定时器中断
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

// 启动定时器
TIM_Cmd(TIM2, ENABLE);

while (1) {
// 主循环
}
}
提示

提示:在实际应用中,定时器中断可以用于各种任务,如控制电机速度、测量传感器数据、生成PWM信号等。

总结

在本教程中,我们学习了如何配置STM32的定时器中断,并通过一个简单的LED闪烁示例演示了定时器中断的使用。定时器中断是STM32微控制器中非常重要的功能,掌握它可以帮助我们实现各种时间相关的任务。

附加资源与练习

  • 练习1:修改代码,使LED以不同的频率闪烁。
  • 练习2:尝试使用其他定时器(如TIM3)来实现相同的功能。
  • 参考文档:STM32参考手册中的定时器章节,了解更多关于定时器的配置和使用方法。

通过不断练习和探索,你将能够熟练使用STM32的定时器中断功能,并将其应用到更复杂的项目中。