STM32F103 TIM3四路PWM独立控制实战:驱动舵机、LED调光与电机调速(附完整工程)
STM32F103 TIM3四路PWM独立控制实战驱动舵机、LED调光与电机调速在嵌入式开发中PWM脉冲宽度调制技术堪称瑞士军刀般的存在。从精确控制舵机角度到平滑调节LED亮度再到电机调速PWM都能完美胜任。STM32F103的TIM3定时器提供了四个独立的PWM输出通道CH1-CH4但如何让这四个通道同时输出不同频率和占空比的信号这正是本文要解决的核心问题。想象一个智能小车项目需要同时控制转向舵机50Hz PWM、车头LED亮度500Hz PWM、驱动电机转速5kHz PWM和状态指示灯1Hz闪烁。传统做法是使用多个定时器但通过本文的配置技巧仅用TIM3就能实现所有功能。我们将从寄存器配置底层原理讲起逐步构建可复用的工程框架最终实现三种典型外设的协同控制。1. PWM基础与TIM3核心配置1.1 关键参数解析PWM控制的本质是对三个寄存器的精确操控ARRAuto-Reload Register决定PWM周期// 计算公式PWM频率 定时器时钟 / [(ARR 1) * (PSC 1)] // 例72MHz时钟ARR7199PSC0 → 72MHz/(7200*1)10kHzPSCPrescaler时钟预分频系数// 有效分频值 PSC 1 // PSC1表示2分频PSC71表示72分频CCRxCapture/Compare Register控制占空比// 占空比 CCRx / (ARR 1) // ARR999时CCR1300表示30%占空比1.2 TIM3多通道配置技巧TIM3的四个通道共享ARR和PSC寄存器但每个通道有独立的CCRx寄存器。这意味着频率必须相同所有通道的PWM频率由ARR和PSC共同决定占空比可独立设置通过CCR1-CCR4分别控制四个通道重要提示虽然频率必须一致但通过软件技巧可以实现伪独立频率具体方法在第3章详解。配置流程示例void TIM3_Config(uint32_t arr, uint16_t psc) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseStructure.TIM_Period arr; TIM_TimeBaseStructure.TIM_Prescaler psc; TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, TIM_TimeBaseStructure); // 通道1-4的OCInit结构体配置... TIM_Cmd(TIM3, ENABLE); }2. 硬件连接与工程架构设计2.1 引脚分配方案TIM3四路PWM的完全重映射配置使用GPIOC通道引脚推荐外设典型参数CH1PC6舵机控制50Hz, 0.5-2.5ms脉宽CH2PC7LED调光500Hz, 0-100%占空比CH3PC8电机调速5kHz, 20-80%占空比CH4PC9状态指示灯1Hz, 50%占空比硬件连接注意事项舵机信号线需串联220Ω电阻保护驱动电机建议使用MOSFET隔离高亮度LED需加限流电阻2.2 软件架构设计采用分层架构实现参数独立控制工程目录结构 ├── Drivers │ ├── PWM │ │ ├── pwm.h // 抽象接口 │ │ └── tim3_pwm.c // TIM3具体实现 ├── Applications │ ├── servo_ctrl.c // 舵机控制 │ ├── led_ctrl.c // LED控制 │ └── motor_ctrl.c // 电机控制 └── main.c // 调度逻辑关键接口设计// pwm.h typedef enum { PWM_CH1 0, PWM_CH2, PWM_CH3, PWM_CH4 } PWM_Channel; void PWM_Init(uint32_t freq_hz); // 初始化TIM3 void PWM_SetDuty(PWM_Channel ch, float duty); // 设置占空比(0.0-1.0) void PWM_SetPulseWidth(PWM_Channel ch, uint32_t width_us); // 设置脉宽(us)3. 多外设协同控制实战3.1 舵机精确角度控制标准舵机控制参数频率50Hz周期20ms脉宽0.5ms0°- 2.5ms180°实现代码// servo_ctrl.c void Servo_SetAngle(PWM_Channel ch, float angle) { // 将角度转换为脉宽(us) uint32_t pulse_width 500 angle * (2000 / 180.0); PWM_SetPulseWidth(ch, pulse_width); } // 初始化示例 PWM_Init(50); // 50Hz Servo_SetAngle(PWM_CH1, 90.0); // 中位90度3.2 LED无闪烁调光技术避免LED闪烁的关键频率≥200Hz人眼视觉暂留使用gamma校正使亮度变化更自然// led_ctrl.c const uint8_t gamma_table[256] {0,0,1,...255}; // gamma校正表 void LED_SetBrightness(PWM_Channel ch, uint8_t level) { float duty gamma_table[level] / 255.0; PWM_SetDuty(ch, duty); } // 呼吸灯效果实现 void LED_Breathing(PWM_Channel ch, uint32_t period_ms) { static uint32_t tick 0; uint8_t level (sin(2*PI*tick/period_ms) 1) * 127.5; LED_SetBrightness(ch, level); tick; }3.3 电机调速与制动控制直流电机控制要点频率选择5-20kHz避免可闻噪声死区时间配置H桥驱动时// motor_ctrl.c void Motor_SetSpeed(PWM_Channel ch, int8_t percent) { percent constrain(percent, -100, 100); if(percent 0) { // 正转 PWM_SetDuty(ch, percent / 100.0); BRAKE_GPIO 0; } else { // 制动 PWM_SetDuty(ch, 0); BRAKE_GPIO 1; } }4. 高级技巧与性能优化4.1 动态频率调整方案虽然TIM3各通道必须共享频率但可通过以下方法实现伪独立频率基准频率选择最小公倍数// 需要50Hz(舵机)和1Hz(指示灯) // 选择50Hz为基准指示灯每50周期翻转一次软件定时器辅助// 在中断中手动翻转GPIO void TIM3_IRQHandler() { static uint16_t counter 0; if(TIM_GetITStatus(TIM3, TIM_IT_Update)) { counter; if(counter 50) { // 实现1Hz GPIO_ToggleBits(GPIOC, GPIO_Pin_9); counter 0; } TIM_ClearITPendingBit(TIM3, TIM_IT_Update); } }4.2 占空比动态平滑调整避免突变的占空比变化void PWM_SmoothTransition(PWM_Channel ch, float target_duty, uint32_t duration_ms) { float current PWM_GetDuty(ch); uint32_t steps duration_ms / 10; float delta (target_duty - current) / steps; for(uint32_t i0; isteps; i) { current delta; PWM_SetDuty(ch, current); Delay_ms(10); } }4.3 资源消耗优化对比不同实现方式资源占用对比方法CPU占用内存占用精度实现复杂度硬件PWM低低高低软件模拟高中中高定时器中断GPIO翻转中低低中工程实践中发现当系统中有USB或无线通信等实时性要求高的任务时应优先使用硬件PWM。某四轴飞行器项目中使用本文的配置方法TIM3控制四个电调PWM同时利用空闲通道驱动状态LEDCPU占用率仅增加2%。