STM32 PWM呼吸灯实现详解(附完整工程代码)

STM32 PWM呼吸灯实现详解(附完整工程代码)

摘要:本文基于STM32的PWM技术实现LED呼吸灯效果,通过动态调节占空比控制LED亮度渐变。使用STM32CubeMX配置定时器TIM2,结合HAL库开发,完整解析硬件设计、软件实现及参数计算过程。

目录

硬件设计原理软件实现关键代码

系统时钟配置TIM2初始化GPIO配置主程序逻辑 关键参数计算实验现象分析问题与优化方案总结与源码获取

一、硬件设计原理

核心器件

主控芯片:STM32F103C8T6(Cortex-M3内核,72MHz主频)LED电路:PA0(TIM2_CH1)驱动LED,串联220Ω限流电阻时钟系统:8MHz外部晶振(HSE)通过PLL倍频 PWM呼吸灯原理 利用脉冲宽度调制改变LED有效电压:

V

e

f

f

=

T

o

n

T

×

V

c

c

V_{eff} = \frac{T_{on}}{T} \times V_{cc}

Veff​=TTon​​×Vcc​ 占空比从0%→100%→0%循环变化,实现LED渐亮渐灭的"呼吸"效果。

二、软件实现关键代码

1. 系统时钟配置(72MHz)

// main.c 中 SystemClock_Config()

RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; // HSE(8MHz)*9=72MHz

RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; // APB1时钟36MHz

2. TIM2初始化(100Hz PWM)

// tim.c 中 MX_TIM2_Init()

htim2.Init.Prescaler = 360-1; // 预分频360

htim2.Init.Period = 2000-1; // 自动重载值2000

// PWM频率 = 72MHz / (360*2000) = 100Hz

sConfigOC.Pulse = 200; // 通道1初始占空比10%

sConfigOC.Pulse = 600; // 通道2初始占空比30%

3. GPIO配置(PWM输出模式)

// tim.c 中 HAL_TIM_MspPostInit()

GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1; // PA0(通道1), PA1(通道2)

GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 复用推挽输出

HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

4. 主程序动态调节占空比

// main.c 中主循环

while (1) {

HAL_Delay(100); // 每100ms更新一次

pwm_value += step; // 步进值±100

if(pwm_value==0) step = 100; // 到达最小值反转

if(pwm_value==2000) step = -100; // 到达最大值反转

user_pwm_setvalue(pwm_value); // 更新占空比

}

// PWM设置函数

void user_pwm_setvalue(uint16_t value) {

sConfigOC.Pulse = value; // 设置新占空比

HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);

HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); // 需重启通道生效

}

三、关键参数计算

PWM周期计算:

T

=

(

P

r

e

s

c

a

l

e

r

+

1

)

×

(

P

e

r

i

o

d

+

1

)

S

Y

S

C

L

K

=

360

×

2000

72

×

10

6

=

0.01

s

=

10

m

s

T = \frac{(Prescaler+1) \times (Period+1)}{SYSCLK} = \frac{360 \times 2000}{72 \times 10^6} = 0.01s = 10ms

T=SYSCLK(Prescaler+1)×(Period+1)​=72×106360×2000​=0.01s=10ms

占空比调节特性:

参数值说明周期2000计数器最大值最小步进100占空比变化分辨率5%亮度变化周期4秒0→2000→0共40步

四、实验现象分析

通道1(PA0)呼吸效果:

上电初始亮度10%每100ms亮度增加5%,2秒达最亮每100ms亮度减少5%,2秒回最暗循环周期4秒 通道2(PA1)状态:

保持初始化30%占空比常亮因未在循环中更新,亮度恒定

五、问题与优化方案

1. 现存问题

通道2不受控:主循环仅更新通道1占空比效率问题:每次更新都调用ConfigChannel+Start导致资源浪费通道干扰:修改通道1配置时通道2参数被重置

2. 优化方案

// 优化后的PWM设置函数

void user_pwm_setvalue(uint16_t ch1_val, uint16_t ch2_val) {

// 直接修改CCR寄存器避免重新配置

TIM2->CCR1 = ch1_val; // 通道1捕获比较值

TIM2->CCR2 = ch2_val; // 通道2捕获比较值

}

// 主循环调整

pwm_value += step;

user_pwm_setvalue(pwm_value, 600); // 通道2固定30%

3. 参数改进建议

// 更平滑的呼吸效果

#define PWM_MAX 2000 // 最大计数值

#define PWM_STEP 20 // 步进值减至1%变化率

HAL_Delay(20); // 更新间隔缩短至20ms

六、总结

实现要点总结

时钟配置:HSE→PLL倍频→72MHz系统时钟定时器设置:

预分频器:360-1自动重载值:2000-1PWM模式1,高电平有效 动态调光算法:线性增减CCR值实现渐变

知识延伸

可扩展多路PWM控制RGB彩灯加入ADC采集实现光强反馈控制使用DMA自动更新PWM参数

完整工程源码 GitHub仓库链接 包含STM32CubeMX配置文件和Keil工程

参考文献 [1] STM32F10xxx参考手册(RM0008) [2] STM32CubeMX用户手册 [3] 野火《STM32库开发实战指南》

如何使用电卷发棒
雨刮器多少钱一副