STM32定时器程序,包含基本定时、PWM输出、输入捕获、编码器接口和高级定时器应用。
一、定时器基础配置
1.1 定时器核心定义
c
/* 定时器核心数据结构定义 */
#include "stm32f10x.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "misc.h"
#include <stdio.h>
// 定时器选择
#define USE_TIM1 0
#define USE_TIM2 1
#define USE_TIM3 1
#define USE_TIM4 0
// 定时器模式定义
typedef enum {
TIM_MODE_BASIC, // 基本定时模式
TIM_MODE_PWM_OUTPUT, // PWM输出模式
TIM_MODE_INPUT_CAPTURE, // 输入捕获模式
TIM_MODE_OUTPUT_COMPARE,// 输出比较模式
TIM_MODE_ENCODER, // 编码器接口模式
TIM_MODE_ONE_PULSE // 单脉冲模式
} TIM_Mode;
// 定时器通道定义
#define TIM_CHANNEL_1 TIM_Channel_1
#define TIM_CHANNEL_2 TIM_Channel_2
#define TIM_CHANNEL_3 TIM_Channel_3
#define TIM_CHANNEL_4 TIM_Channel_4
// 全局变量
volatile uint32_t tim2_counter = 0;
volatile uint32_t tim3_counter = 0;
volatile uint8_t tim2_update_flag = 0;
volatile uint8_t tim3_update_flag = 0;
1.2 定时器时钟配置
c
/* 定时器时钟使能 */
void TIM_CLK_Init(void) {
#if USE_TIM1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
#endif
#if USE_TIM2
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
#endif
#if USE_TIM3
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
#endif
#if USE_TIM4
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
#endif
printf("Timer clocks initialized\n");
}
二、基本定时功能
2.1 定时器基础初始化
c
/* 基本定时器初始化 */
void TIM_Basic_Init(TIM_TypeDef* TIMx, uint16_t prescaler, uint16_t period) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 定时器基础配置
TIM_TimeBaseStructure.TIM_Period = period; // 自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler = prescaler; // 预分频器
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数
TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);
// 使能更新中断
TIM_ITConfig(TIMx, TIM_IT_Update, ENABLE);
// 配置NVIC中断
if (TIMx == TIM2) {
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
} else if (TIMx == TIM3) {
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
} else if (TIMx == TIM4) {
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
}
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 使能定时器
TIM_Cmd(TIMx, ENABLE);
printf("Timer basic init complete\n");
}
/* 定时器2初始化 - 1ms定时 */
void TIM2_Init_1ms(void) {
// 72MHz时钟,预分频72,计数周期1000,得到1ms中断
TIM_Basic_Init(TIM2, 72-1, 1000-1);
printf("TIM2: 1ms interval initialized\n");
}
/* 定时器3初始化 - 1s定时 */
void TIM3_Init_1s(void) {
// 72MHz时钟,预分频7200,计数周期10000,得到1s中断
TIM_Basic_Init(TIM3, 7200-1, 10000-1);
printf("TIM3: 1s interval initialized\n");
}
2.2 定时器中断服务函数
c
/* 定时器2中断服务函数 */
void TIM2_IRQHandler(void) {
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
tim2_counter++;
tim2_update_flag = 1;
// 清除中断标志
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
/* 定时器3中断服务函数 */
void TIM3_IRQHandler(void) {
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) {
tim3_counter++;
tim3_update_flag = 1;
// 清除中断标志
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
}
}
/* 获取定时器计数值 */
uint32_t TIM_GetCounterValue(TIM_TypeDef* TIMx) {
return TIM_GetCounter(TIMx);
}
/* 延时函数(基于定时器) */
void TIM_Delay_ms(uint32_t ms) {
uint32_t start = tim2_counter;
while ((tim2_counter - start) < ms);
}
三、PWM输出功能
3.1 PWM初始化
c
/* PWM输出初始化 */
void TIM_PWM_Init(TIM_TypeDef* TIMx, uint16_t channel, uint16_t prescaler,
uint16_t period, uint16_t pulse) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
// 使能GPIO时钟
if (TIMx == TIM2) {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
} else if (TIMx == TIM3) {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
}
// 配置GPIO引脚
if (TIMx == TIM2) {
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; // TIM2_CH1 -> PA0
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
} else if (TIMx == TIM3) {
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; // TIM3_CH1 -> PA6
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
// 定时器基础配置
TIM_TimeBaseStructure.TIM_Period = period;
TIM_TimeBaseStructure.TIM_Prescaler = prescaler;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);
// PWM模式配置
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = pulse;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
// 配置通道
if (channel == TIM_CHANNEL_1) {
TIM_OC1Init(TIMx, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIMx, TIM_OCPreload_Enable);
} else if (channel == TIM_CHANNEL_2) {
TIM_OC2Init(TIMx, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIMx, TIM_OCPreload_Enable);
} else if (channel == TIM_CHANNEL_3) {
TIM_OC3Init(TIMx, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIMx, TIM_OCPreload_Enable);
} else if (channel == TIM_CHANNEL_4) {
TIM_OC4Init(TIMx, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIMx, TIM_OCPreload_Enable);
}
// 使能定时器
TIM_Cmd(TIMx, ENABLE);
TIM_ARRPreloadConfig(TIMx, ENABLE);
printf("PWM initialized on TIM%d Channel %d\n",
(TIMx == TIM2) ? 2 : 3, channel);
}
/* 设置PWM占空比 */
void TIM_PWM_SetDuty(TIM_TypeDef* TIMx, uint16_t channel, uint16_t duty) {
uint16_t pulse = (TIMx->ARR * duty) / 100;
if (channel == TIM_CHANNEL_1) {
TIM_SetCompare1(TIMx, pulse);
} else if (channel == TIM_CHANNEL_2) {
TIM_SetCompare2(TIMx, pulse);
} else if (channel == TIM_CHANNEL_3) {
TIM_SetCompare3(TIMx, pulse);
} else if (channel == TIM_CHANNEL_4) {
TIM_SetCompare4(TIMx, pulse);
}
}
/* 呼吸灯效果 */
void TIM_BreathingLED(TIM_TypeDef* TIMx, uint16_t channel) {
static uint8_t direction = 0;
static uint16_t duty = 0;
if (direction == 0) {
duty++;
if (duty >= 100) {
direction = 1;
}
} else {
duty--;
if (duty == 0) {
direction = 0;
}
}
TIM_PWM_SetDuty(TIMx, channel, duty);
}
3.2 高级PWM应用
c
/* 互补PWM输出(高级定时器TIM1/TIM8) */
void TIM_ComplementaryPWM_Init(void) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
// 使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOA, ENABLE);
// 配置GPIO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_7; // TIM1_CH1, TIM1_CH1N
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 定时器基础配置
TIM_TimeBaseStructure.TIM_Period = 1000-1; // 1kHz PWM
TIM_TimeBaseStructure.TIM_Prescaler = 72-1; // 72MHz/72 = 1MHz
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
// PWM配置
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_Pulse = 500; // 50%占空比
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
// 死区配置
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
TIM_BDTRInitStructure.TIM_DeadTime = 100; // 死区时间
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
// 使能定时器
TIM_Cmd(TIM1, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE); // 必须使能主输出
printf("Complementary PWM initialized\n");
}
四、输入捕获功能
4.1 输入捕获初始化
c
/* 输入捕获初始化 */
void TIM_InputCapture_Init(TIM_TypeDef* TIMx, uint16_t channel) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 使能时钟
if (TIMx == TIM2) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
} else if (TIMx == TIM3) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
}
// 配置GPIO
if (TIMx == TIM2 && channel == TIM_CHANNEL_1) {
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; // TIM2_CH1 -> PA0
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
} else if (TIMx == TIM3 && channel == TIM_CHANNEL_1) {
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; // TIM3_CH1 -> PA6
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
// 定时器基础配置
TIM_TimeBaseStructure.TIM_Period = 0xFFFF; // 最大计数值
TIM_TimeBaseStructure.TIM_Prescaler = 72-1; // 1MHz计数频率
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);
// 输入捕获配置
TIM_ICInitStructure.TIM_Channel = channel;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; // 上升沿捕获
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0; // 无滤波
TIM_ICInit(TIMx, &TIM_ICInitStructure);
// 使能捕获中断
TIM_ITConfig(TIMx, TIM_IT_CC1, ENABLE);
// 配置NVIC
if (TIMx == TIM2) {
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
} else if (TIMx == TIM3) {
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
}
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 使能定时器
TIM_Cmd(TIMx, ENABLE);
printf("Input capture initialized on TIM%d Channel %d\n",
(TIMx == TIM2) ? 2 : 3, channel);
}
/* 测量PWM频率和占空比 */
typedef struct {
uint8_t first_edge_captured;
uint32_t rising_edge_value;
uint32_t falling_edge_value;
uint32_t period;
uint32_t pulse_width;
float frequency;
float duty_cycle;
} PWM_Measurement;
PWM_Measurement pwm_measure = {0};
/* 输入捕获中断处理 */
void TIM_InputCapture_Handler(TIM_TypeDef* TIMx, uint16_t channel) {
static uint32_t last_capture = 0;
if (TIM_GetITStatus(TIMx, TIM_IT_CC1) != RESET) {
uint32_t current_capture = TIM_GetCapture1(TIMx);
if (pwm_measure.first_edge_captured == 0) {
// 第一次捕获(上升沿)
pwm_measure.rising_edge_value = current_capture;
pwm_measure.first_edge_captured = 1;
// 改为下降沿捕获
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel = channel;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIMx, &TIM_ICInitStructure);
} else {
// 第二次捕获(下降沿)
pwm_measure.falling_edge_value = current_capture;
// 计算脉宽
if (pwm_measure.falling_edge_value > pwm_measure.rising_edge_value) {
pwm_measure.pulse_width = pwm_measure.falling_edge_value -
pwm_measure.rising_edge_value;
} else {
pwm_measure.pulse_width = (0xFFFF - pwm_measure.rising_edge_value) +
pwm_measure.falling_edge_value;
}
// 改为上升沿捕获
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel = channel;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIMx, &TIM_ICInitStructure);
pwm_measure.first_edge_captured = 0;
}
// 计算频率(假设1MHz计数频率)
if (current_capture > last_capture) {
pwm_measure.period = current_capture - last_capture;
} else {
pwm_measure.period = (0xFFFF - last_capture) + current_capture;
}
pwm_measure.frequency = 1000000.0 / pwm_measure.period; // 1MHz / 周期
pwm_measure.duty_cycle = (float)pwm_measure.pulse_width / pwm_measure.period * 100.0;
last_capture = current_capture;
// 清除中断标志
TIM_ClearITPendingBit(TIMx, TIM_IT_CC1);
}
}
五、编码器接口
5.1 编码器接口初始化
c
/* 编码器接口初始化 */
void TIM_Encoder_Init(TIM_TypeDef* TIMx) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
// 使能时钟
if (TIMx == TIM2) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
} else if (TIMx == TIM3) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
}
// 配置GPIO(编码器A、B相)
if (TIMx == TIM2) {
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; // TIM2_CH1, CH2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
} else if (TIMx == TIM3) {
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; // TIM3_CH1, CH2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
// 定时器基础配置
TIM_TimeBaseStructure.TIM_Period = 0xFFFF; // 最大计数值
TIM_TimeBaseStructure.TIM_Prescaler = 0; // 无预分频
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);
// 编码器接口配置
TIM_EncoderInterfaceConfig(TIMx, TIM_EncoderMode_TI12,
TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
// 输入捕获配置
TIM_ICStructInit(&TIM_ICInitStructure);
TIM_ICInitStructure.TIM_ICFilter = 6; // 滤波器
TIM_ICInit(TIMx, &TIM_ICInitStructure);
// 清零计数器
TIM_SetCounter(TIMx, 0);
// 使能定时器
TIM_Cmd(TIMx, ENABLE);
printf("Encoder interface initialized on TIM%d\n",
(TIMx == TIM2) ? 2 : 3);
}
/* 读取编码器计数值 */
int32_t TIM_Encoder_Read(TIM_TypeDef* TIMx) {
return (int32_t)TIM_GetCounter(TIMx);
}
/* 计算编码器转速 */
float TIM_Encoder_CalculateSpeed(TIM_TypeDef* TIMx, uint16_t ppr, float sample_time) {
static int32_t last_count = 0;
static uint32_t last_time = 0;
int32_t current_count = TIM_Encoder_Read(TIMx);
uint32_t current_time = TIM_GetCounter(TIM2); // 使用TIM2作为时间基准
// 计算转速(RPM)
float rpm = 0;
if (current_time > last_time) {
float delta_time = (current_time - last_time) / 1000.0; // 转换为秒
int32_t delta_count = current_count - last_count;
// RPM = (脉冲数/时间) * (60秒/分钟) / PPR
rpm = (delta_count / delta_time) * 60.0 / ppr;
}
last_count = current_count;
last_time = current_time;
return rpm;
}
六、定时器同步与级联
6.1 定时器同步配置
c
/* 定时器同步配置 */
void TIM_Synchronization_Init(void) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// 使能时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB1Periph_TIM3, ENABLE);
// 配置TIM2为主定时器
TIM_TimeBaseStructure.TIM_Period = 1000-1;
TIM_TimeBaseStructure.TIM_Prescaler = 72-1;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// 配置TIM3为从定时器
TIM_TimeBaseStructure.TIM_Period = 500-1;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
// 配置TIM2触发输出
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
// 配置TIM3从模式
TIM_SelectInputTrigger(TIM3, TIM_TS_ITR1); // TIM2作为触发源
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
// 使能定时器
TIM_Cmd(TIM2, ENABLE);
TIM_Cmd(TIM3, ENABLE);
printf("Timer synchronization configured\n");
}
/* 定时器级联PWM */
void TIM_Cascade_PWM_Init(void) {
// TIM2作为主定时器,产生PWM
TIM_PWM_Init(TIM2, TIM_CHANNEL_1, 72-1, 1000-1, 500);
// TIM3作为从定时器,由TIM2触发
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseStructure.TIM_Period = 500-1;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
// PWM配置
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 250;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
// 配置从模式
TIM_SelectInputTrigger(TIM3, TIM_TS_ITR1); // TIM2触发
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
TIM_Cmd(TIM3, ENABLE);
printf("Cascade PWM configured\n");
}
参考代码 STM32 定时器程序 www.youwenfan.com/contentcst/133657.html
七、定时器应用示例
7.1 综合应用示例
c
/* 主程序示例 */
#include "stm32f10x.h"
#include "system_stm32f10x.h"
// 系统滴答定时器
volatile uint32_t system_tick = 0;
void SysTick_Init(void) {
SysTick_Config(SystemCoreClock / 1000); // 1ms中断
}
void SysTick_Handler(void) {
system_tick++;
}
uint32_t Get_SystemTick(void) {
return system_tick;
}
int main(void) {
// 系统初始化
SystemInit();
SysTick_Init();
// 初始化串口(用于printf)
USART_Init();
printf("\r\n=== STM32 Timer Demo ===\r\n");
// 1. 初始化定时器时钟
TIM_CLK_Init();
// 2. 基本定时功能
printf("\r\n1. Basic Timer Functions\r\n");
TIM2_Init_1ms();
TIM3_Init_1s();
// 3. PWM输出功能
printf("\r\n2. PWM Output Functions\r\n");
TIM_PWM_Init(TIM2, TIM_CHANNEL_1, 72-1, 1000-1, 250); // 25%占空比
TIM_PWM_Init(TIM3, TIM_CHANNEL_1, 72-1, 1000-1, 750); // 75%占空比
// 4. 输入捕获功能
printf("\r\n3. Input Capture Functions\r\n");
TIM_InputCapture_Init(TIM2, TIM_CHANNEL_1);
// 5. 编码器接口
printf("\r\n4. Encoder Interface\r\n");
TIM_Encoder_Init(TIM2);
// 6. 定时器同步
printf("\r\n5. Timer Synchronization\r\n");
TIM_Synchronization_Init();
printf("\r\n=== All Timer Functions Initialized ===\r\n");
// 主循环
while (1) {
// 1ms定时任务
if (tim2_update_flag) {
tim2_update_flag = 0;
// 在这里执行1ms任务
}
// 1s定时任务
if (tim3_update_flag) {
tim3_update_flag = 0;
printf("1 second elapsed, TIM2 counter: %lu\r\n",
TIM_GetCounterValue(TIM2));
// 呼吸灯效果
TIM_BreathingLED(TIM2, TIM_CHANNEL_1);
// 读取编码器值
int32_t encoder_value = TIM_Encoder_Read(TIM2);
printf("Encoder value: %ld\r\n", encoder_value);
// 计算编码器转速
float rpm = TIM_Encoder_CalculateSpeed(TIM2, 1000, 1.0); // 1000PPR
printf("Encoder speed: %.2f RPM\r\n", rpm);
}
// 输入捕获数据显示
if (pwm_measure.frequency > 0) {
printf("PWM Frequency: %.2f Hz, Duty Cycle: %.2f%%\r\n",
pwm_measure.frequency, pwm_measure.duty_cycle);
}
// 延时
for (volatile uint32_t i = 0; i < 10000; i++);
}
}
八、定时器调试与优化
8.1 调试函数
c
/* 定时器调试函数 */
void TIM_Debug_Info(TIM_TypeDef* TIMx) {
printf("=== Timer %s Debug Info ===\r\n",
(TIMx == TIM1) ? "1" :
(TIMx == TIM2) ? "2" :
(TIMx == TIM3) ? "3" : "4");
printf("CR1: 0x%08lX\r\n", TIMx->CR1);
printf("CR2: 0x%08lX\r\n", TIMx->CR2);
printf("SMCR: 0x%08lX\r\n", TIMx->SMCR);
printf("DIER: 0x%08lX\r\n", TIMx->DIER);
printf("SR: 0x%08lX\r\n", TIMx->SR);
printf("EGR: 0x%08lX\r\n", TIMx->EGR);
printf("CCMR1:0x%08lX\r\n", TIMx->CCMR1);
printf("CCMR2:0x%08lX\r\n", TIMx->CCMR2);
printf("CCER: 0x%08lX\r\n", TIMx->CCER);
printf("CNT: 0x%08lX\r\n", TIMx->CNT);
printf("PSC: 0x%08lX\r\n", TIMx->PSC);
printf("ARR: 0x%08lX\r\n", TIMx->ARR);
printf("CCR1: 0x%08lX\r\n", TIMx->CCR1);
printf("CCR2: 0x%08lX\r\n", TIMx->CCR2);
printf("CCR3: 0x%08lX\r\n", TIMx->CCR3);
printf("CCR4: 0x%08lX\r\n", TIMx->CCR4);
printf("DCR: 0x%08lX\r\n", TIMx->DCR);
printf("DMAR: 0x%08lX\r\n", TIMx->DMAR);
printf("===========================\r\n");
}
/* 定时器性能测试 */
void TIM_Performance_Test(void) {
uint32_t start_time, end_time;
uint32_t iterations = 1000000;
printf("=== Timer Performance Test ===\r\n");
// 测试TIM_GetCounter性能
start_time = Get_SystemTick();
for (uint32_t i = 0; i < iterations; i++) {
volatile uint32_t counter = TIM_GetCounter(TIM2);
}
end_time = Get_SystemTick();
printf("TIM_GetCounter calls: %lu\r\n", iterations);
printf("Elapsed time: %lu ms\r\n", end_time - start_time);
printf("Calls per second: %lu\r\n", iterations * 1000 / (end_time - start_time));
// 测试TIM_SetCompare性能
start_time = Get_SystemTick();
for (uint32_t i = 0; i < iterations; i++) {
TIM_SetCompare1(TIM2, i % 1000);
}
end_time = Get_SystemTick();
printf("\nTIM_SetCompare calls: %lu\r\n", iterations);
printf("Elapsed time: %lu ms\r\n", end_time - start_time);
printf("Calls per second: %lu\r\n", iterations * 1000 / (end_time - start_time));
printf("============================\r\n");
}
8.2 定时器优化建议
c
/* 定时器优化配置 */
void TIM_Optimization_Tips(void) {
printf("Timer Optimization Tips:\r\n");
printf("1. Use appropriate prescaler for desired resolution\r\n");
printf("2. Enable preload register for smooth PWM updates\r\n");
printf("3. Use input capture filter for noisy signals\r\n");
printf("4. Configure proper dead-time for complementary PWM\r\n");
printf("5. Use timer synchronization for complex timing\r\n");
printf("6. Enable interrupt only when necessary\r\n");
printf("7. Clear interrupt flags promptly in ISR\r\n");
printf("8. Use DMA for high-speed data transfer\r\n");
printf("9. Consider using advanced timers for motor control\r\n");
printf("10. Use encoder interface for position feedback\r\n");
}
/* 低功耗定时器配置 */
void TIM_LowPower_Config(TIM_TypeDef* TIMx) {
// 配置定时器在低功耗模式下运行
TIM_Cmd(TIMx, DISABLE);
// 降低预分频器以节省功耗
TIM_PrescalerConfig(TIMx, 7200-1, TIM_PSCReloadMode_Immediate);
// 禁用不需要的中断
TIM_ITConfig(TIMx, TIM_IT_Update, DISABLE);
// 重新使能定时器
TIM_Cmd(TIMx, ENABLE);
printf("Timer configured for low power mode\r\n");
}
九、高级应用案例
9.1 步进电机控制
c
/* 步进电机控制 */
typedef struct {
TIM_TypeDef* tim;
uint16_t step_pin;
uint16_t dir_pin;
uint16_t enable_pin;
uint32_t steps_per_revolution;
float current_position;
float target_position;
uint8_t is_moving;
} StepperMotor;
StepperMotor motor1;
void StepperMotor_Init(StepperMotor* motor, TIM_TypeDef* tim) {
motor->tim = tim;
motor->steps_per_revolution = 200; // 200步/圈
motor->current_position = 0;
motor->target_position = 0;
motor->is_moving = 0;
// 初始化定时器为PWM输出
TIM_PWM_Init(tim, TIM_CHANNEL_1, 72-1, 1000-1, 500);
printf("Stepper motor initialized\r\n");
}
void StepperMotor_MoveTo(StepperMotor* motor, float position) {
motor->target_position = position;
motor->is_moving = 1;
// 计算需要的步数
int32_t steps_needed = (position - motor->current_position) * motor->steps_per_revolution;
if (steps_needed > 0) {
// 正转
GPIO_SetBits(GPIOA, motor->dir_pin);
} else {
// 反转
GPIO_ResetBits(GPIOA, motor->dir_pin);
steps_needed = -steps_needed;
}
// 设置PWM频率对应步进速度
uint16_t pwm_period = 1000; // 1kHz步进频率
TIM_SetAutoreload(motor->tim, pwm_period - 1);
printf("Moving to position %.2f, steps: %ld\r\n", position, steps_needed);
}
void StepperMotor_Update(StepperMotor* motor) {
if (motor->is_moving) {
// 更新当前位置
if (motor->target_position > motor->current_position) {
motor->current_position += 1.0 / motor->steps_per_revolution;
if (motor->current_position >= motor->target_position) {
motor->is_moving = 0;
TIM_Cmd(motor->tim, DISABLE); // 停止PWM
printf("Movement completed\r\n");
}
} else {
motor->current_position -= 1.0 / motor->steps_per_revolution;
if (motor->current_position <= motor->target_position) {
motor->is_moving = 0;
TIM_Cmd(motor->tim, DISABLE);
printf("Movement completed\r\n");
}
}
}
}
十、总结
这个完整的STM32定时器程序实现了以下功能:
核心功能:
- 基本定时:1ms、1s定时中断
- PWM输出:可调占空比、呼吸灯效果
- 输入捕获:测量PWM频率和占空比
- 编码器接口:读取旋转位置和速度
- 定时器同步:主从定时器级联
高级特性:
- 互补PWM:带死区控制的电机驱动
- 步进电机控制:精确定位控制
- 性能优化:高效的中断处理和资源管理
- 调试工具:详细的寄存器信息和性能测试
应用场景:
- 电机控制:直流电机、步进电机、伺服电机
- 信号测量:频率、占空比、脉冲宽度测量
- 位置反馈:编码器接口、旋转位置检测
- 定时任务:精确的周期性任务调度
- PWM调光:LED亮度控制、电机速度控制
- 触发系统:定时器同步、级联触发
使用建议:
- 根据应用需求选择合适的定时器资源
- 合理配置预分频器和自动重装载值
- 注意中断优先级和中断处理时间
- 使用DMA减轻CPU负担
- 定期校准定时器精度
这个程序可以直接用于STM32F10x系列项目,通过修改定时器编号和引脚配置,可以适配其他STM32系列。