作为一名嵌入式开发工程师,我深知STM32的定时器模块在实际项目中的重要性。今天,我将结合自己多年的开发经验,为大家带来STM32F10x_TIM.C文件的全面解析和实战应用指南。
STM32F10x系列提供了8个定时器,分为三类:
重要提示:不同定时器的时钟源不同,配置时需特别注意。APB1总线最大时钟为36MHz,APB2为72MHz。
理解定时器时钟是正确配置的基础:
stm32f10x_tim.c文件约2000行代码,主要包含以下部分:
c复制#define CR1_CEN_Set ((uint16_t)0x0001) // 计数器使能位
#define CR1_CEN_Reset ((uint16_t)0x03FE) // 计数器禁用掩码
这些宏定义了寄存器位的操作掩码,用于精确控制特定寄存器位而不影响其他位。
c复制static void TI1_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity,
uint16_t TIM_ICSelection, uint16_t TIM_ICFilter);
这些内部函数处理输入捕获通道的底层配置,开发者通常不需要直接调用。
预分频器将定时器时钟分频后提供给计数器:
ARR决定了计数器的计数范围:
定时时间计算公式:
T = (PSC + 1) × (ARR + 1) / Tclk
其中:
c复制void TIM3_Init_1ms(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
// 使能TIM3时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
// 配置时基参数
TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);
TIM_TimeBaseInitStruct.TIM_Prescaler = 71; // 72MHz/72=1MHz
TIM_TimeBaseInitStruct.TIM_Period = 999; // 1000个计数=1ms
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);
// 使能中断
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
// 使能定时器
TIM_Cmd(TIM3, ENABLE);
}
c复制void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
// 处理定时中断
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
}
}
c复制void TIM2_PWM_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_OCInitTypeDef TIM_OCInitStruct;
// 使能时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// 配置时基
TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);
TIM_TimeBaseInitStruct.TIM_Prescaler = 71; // 1MHz
TIM_TimeBaseInitStruct.TIM_Period = 999; // 1kHz PWM
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
// 配置PWM模式
TIM_OCStructInit(&TIM_OCInitStruct);
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStruct.TIM_Pulse = 500; // 初始占空比50%
TIM_OC1Init(TIM2, &TIM_OCInitStruct);
// 使能预装载
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM2, ENABLE);
// 使能定时器
TIM_Cmd(TIM2, ENABLE);
}
c复制// 设置占空比(0-1000对应0%-100%)
TIM_SetCompare1(TIM2, 750); // 75%占空比
c复制void TIM3_IC_Init(void)
{
TIM_ICInitTypeDef TIM_ICInitStruct;
// 使能时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
// 配置输入捕获
TIM_ICStructInit(&TIM_ICInitStruct);
TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;
TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInit(TIM3, &TIM_ICInitStruct);
// 使能捕获中断
TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);
// 使能定时器
TIM_Cmd(TIM3, ENABLE);
}
c复制void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
{
uint16_t capture = TIM_GetCapture1(TIM3);
// 处理捕获值
TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);
}
}
高级定时器(TIM1/TIM8)需要额外配置:
c复制// 使能PWM主输出
TIM_CtrlPWMOutputs(TIM1, ENABLE);
掌握STM32定时器的使用是嵌入式开发的基础技能,希望本文能帮助开发者更好地理解和应用这一重要外设。在实际项目中,建议结合具体需求选择合适的定时器和工作模式,并充分利用STM32标准库提供的丰富函数简化开发流程。