第27章 通用定时器-定时
第二十七章 通用定时器-定时
1. 硬件设计
TIM输入stm32内部资源无需硬件设计,led电路我们也已经分析过了
2. 软件设计
- TIM相关参数宏定义
#define GENERAL_TIM TIM2 // 选择使用的定时器--TIM2
#define GENERAL_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd // 选择挂载的定时器时钟--RCC_APB1Periph_TIM2
#define GENERAL_TIM_CLK RCC_APB1Periph_TIM2 // 选择使用的定时器时钟--RCC_APB1Periph_TIM2
#define GENERAL_TIM_Period (1000-1) // 定时器周期--1000-1
#define GENERAL_TIM_Prescaler 71 // 定时器分频系数--71
#define GENERAL_TIM_IRQ TIM2_IRQn // 选择使用的定时器中断--TIM2_IRQn
#define GENERAL_TIM_IRQHandler TIM2_IRQHandler // 选择使用的定时器中断处理函数--TIM2_IRQHandler
- 配置中断
// NVIC中断优先级配置
static void GENERAL_TIM_NVIC_Config(void)
{
// 1.定义NVIC_InitTypeDef结构体
NVIC_InitTypeDef NVIC_InitStructure;
// 2.设置中断组为0
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
// 3.设置中断来源
NVIC_InitStructure.NVIC_IRQChannel = GENERAL_TIM_IRQ ;
// 4.设置主优先级为 0
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
// 5.设置抢占优先级为3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
// 6.使能中断
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// 7.初始化NVIC
NVIC_Init(&NVIC_InitStructure);
}
中断配置,我们已经见到很多了,不必解释
- 配置定时器模式
// 定时器模式配置
static void GENERAL_TIM_Mode_Config(void)
{
// 1.定义TIM_TimeBaseInitTypeDef结构体
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// 2.开启定时器时钟,即内部时钟CK_INT=72M
GENERAL_TIM_APBxClock_FUN(GENERAL_TIM_CLK, ENABLE);
// 3.自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
TIM_TimeBaseStructure.TIM_Period = GENERAL_TIM_Period;
// 4.时钟预分频数
TIM_TimeBaseStructure.TIM_Prescaler = GENERAL_TIM_Prescaler;
// 5.时钟分频因子 ,没用到不用管
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
// 6.计数器计数模式,设置为向上计数
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
// 7.重复计数器的值,没用到不用管
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
// 8.初始化定时器
TIM_TimeBaseInit(GENERAL_TIM, &TIM_TimeBaseStructure);
// 9.清除计数器中断标志位
TIM_ClearFlag(GENERAL_TIM, TIM_FLAG_Update);
// 10.开启计数器中断
TIM_ITConfig(GENERAL_TIM, TIM_IT_Update, ENABLE);
// 11.使能计数器
TIM_Cmd(GENERAL_TIM, ENABLE);
}
对定时器的配置简要说明如下:
- 定义结构体:定义用于定时器基础配置的结构体
TIM_TimeBaseInitTypeDef
。 - 开启时钟:启用定时器的时钟。这里假设
GENERAL_TIM_APBxClock_FUN
是一个宏或函数,用于使能定时器时钟。 - 自动重装载寄存器:设置定时器的自动重装载寄存器的值,这决定了定时器的溢出周期。
- 时钟预分频:设置时钟预分频数,影响定时器的计数频率。
- 时钟分频因子:设置时钟分频因子(未用到可以保持默认值)。
- 计数模式:设置计数模式为向上计数。
- 重复计数器:设置重复计数器的值(未用到可以保持默认值)。
- 初始化定时器:根据配置初始化定时器。
- 清除中断标志:清除定时器更新中断标志位,确保中断不会立即触发。
- 开启中断:启用定时器更新中断。
- 使能计数器:启动计数器,使定时器开始计数。
- 定时器初始化
void GENERAL_TIM_Init(void)
{
GENERAL_TIM_NVIC_Config();
GENERAL_TIM_Mode_Config();
}
定时器初始化即中断配置和定时器配置
- 主函数
// 通用定时器TIMx,x[2,3,4,5]定时应用
#include "stm32f10x.h"
#include "bsp_led.h"
#include "bsp_GENERALTim.h"
uint32_t time = 0; // ms 计时变量
int main(void)
{
// led 端口配置
LED_GPIO_Config();
// TIM初始化
GENERAL_TIM_Init();
while(1)
{
if(time == 1000) // 1000 * 1 ms = 1s 时间到
{
time = 0; // 计数器清零
// LED1 取反
LED1_TOGGLE;
}
}
}
这个程序应该比较简单了,就是利用定时器进行定时,到达一秒后,定时器更新,LED状态取反
3. 小结
照例,我们还是来回顾一下基本流程,尽管这个实验很简单:
1. 配置系统时钟
首先确保系统时钟配置正确。通常,这在启动文件或者系统初始化代码中已经完成。
2. 启用定时器时钟
启用TIM2时钟。这里假设你正在使用STM32标准外设库,RCC_APB1PeriphClockCmd
函数用于启用外设时钟。
3. 配置定时器基础设置
配置定时器的基础参数,包括自动重装载寄存器值、预分频器等。
4. 使能定时器中断(如果需要)
配置定时器中断并设置优先级。
5. 启动定时器
使能定时器,开始计数。
6. 示范代码
#include "stm32f0xx.h" // 包含STM32F0系列的头文件
void TIM2_IRQHandler(void); // 定义定时器中断处理函数原型
void TIM2_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 1. 启用TIM2时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// 2. 配置TIM2的基础设置
TIM_TimeBaseStructure.TIM_Period = 7999; // 定时器周期
TIM_TimeBaseStructure.TIM_Prescaler = 999; // 时钟预分频
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
// 初始化定时器
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// 3. 清除TIM2更新中断标志
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
// 4. 使能TIM2更新中断
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
// 5. 配置定时器中断优先级
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 6. 启动TIM2
TIM_Cmd(TIM2, ENABLE);
}
// 定时器中断处理函数
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
// 处理定时器中断
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
// 在这里执行你的定时任务
}
}
int main(void)
{
// 系统初始化代码
SystemInit();
// 配置TIM2
TIM2_Config();
while (1)
{
// 主循环中可以执行其他任务
}
}
2024.9.12 第一次修订,后期不再维护