STM32 定时器程序(标准外设库版本)

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定时器程序实现了以下功能:

核心功能:

  1. 基本定时:1ms、1s定时中断
  2. PWM输出:可调占空比、呼吸灯效果
  3. 输入捕获:测量PWM频率和占空比
  4. 编码器接口:读取旋转位置和速度
  5. 定时器同步:主从定时器级联

高级特性:

  1. 互补PWM:带死区控制的电机驱动
  2. 步进电机控制:精确定位控制
  3. 性能优化:高效的中断处理和资源管理
  4. 调试工具:详细的寄存器信息和性能测试

应用场景:

  • 电机控制:直流电机、步进电机、伺服电机
  • 信号测量:频率、占空比、脉冲宽度测量
  • 位置反馈:编码器接口、旋转位置检测
  • 定时任务:精确的周期性任务调度
  • PWM调光:LED亮度控制、电机速度控制
  • 触发系统:定时器同步、级联触发

使用建议:

  1. 根据应用需求选择合适的定时器资源
  2. 合理配置预分频器和自动重装载值
  3. 注意中断优先级和中断处理时间
  4. 使用DMA减轻CPU负担
  5. 定期校准定时器精度

这个程序可以直接用于STM32F10x系列项目,通过修改定时器编号和引脚配置,可以适配其他STM32系列。

相关推荐
振南的单片机世界1 小时前
高阻态:GPIO输入的“不打扰”哲学
stm32·单片机·嵌入式硬件
LCG元2 小时前
STM32实战:基于STM32F103的FatFs文件系统移植(SD卡读写)
stm32·单片机·嵌入式硬件
minji...2 小时前
Linux 网络套接字编程(二)从 0 到 1 实现 UDP 回声服务器,recvfrom,sendto
linux·运维·网络·单片机·udp
rit84324992 小时前
基于STM32的RTC(实时时钟)程序设计与实现
stm32·嵌入式硬件·实时音视频
九鼎创展科技2 小时前
联发科 MT8883 核心优势深度解析:对比 MT8385/MT8788/MT8183
人工智能·科技·嵌入式硬件·边缘计算
zmj32032415 小时前
单片机串口收发数据不可靠--用做指令会执行错误动作
单片机·嵌入式硬件·串口
yuan1999715 小时前
STM32 驱动 RC522(MFRC522)实现方案
单片机·嵌入式硬件
踏着七彩祥云的小丑16 小时前
嵌入式——认识电子元器件——电容系列
单片机·嵌入式硬件
Sean_VIP17 小时前
SeanLib系列函数库-MyList
stm32