1.5 PWM呼吸灯 - 实验篇

这个实验中我们将实现呼吸灯


硬件电路连接

Pasted image 20260701004853

  • 我们使用TIM3 CH1 (channel 1)来输出 PWM 波
  • 单片机的最高输出电压是 3.3v
  • LED 正常降压 1.5v 以上, 电流约 5mA

经过算计, 电阻两端电压约为 1.8v, 我们需要 360Ω左右的电阻(上下不超过 5 倍都行, 即 180 - 1800Ω)

电阻色环: 4 色环颜色 220Ω = 红红棕金,330Ω = 橙橙棕金,1kΩ = 棕黑红金Pasted image 20260701015055 多色环:Pasted image 20260701015141 其实我自己实验的时候没有电阻也成功了…


CubeMX的配置

还是老样子, 配置出一个 cmake 工程

  • 在 TIM3 中勾选使用内部时钟, 并且使能 CH1Pasted image 20260701005801

  • 将 TIM3 时钟如图配置Pasted image 20260701010718

配置项 含义 说明
Prescaler (PSC) 预分频值 就是公式里的 PSC。填 7199 = 输入时钟 ÷ 1000
Counter Mode 计数模式 Up = 向上计数
Counter Period (ARR) 自动装载值 就是公式里的 ARR。填 99 = 数100 个后溢出(10ms)
Internal Clock Division (CKD) 内部时钟分频 用于输入滤波等高级场景,初学保持 No Division 即可
auto-reload preload ARR 预装载 随意
Trigger Output (TRGO) Parameters Trigger Output (TRGO) 参数 保持默认即可, 这组参数是用来定时器之间联动
PWM mode 分为 mode1 和 mode2 mode 1:CNT < CCR 输出有效电平,CNT ≥ CCR 输出无效电平
mode2 相反
Pulse (16 bits value) CCR 的初值 CCR(比较寄存器)的初值, 真正调整亮度时再用__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, value) 写就行
Output compare preload(OCxPE) 和上面那个auto-reload preload 一样, 是CCR 版的 ARPE Enable 时你写进 CCR 的新值不会立刻生效,而是先缓存,等下一次 Update(溢出)事件才整体载入
Fast Mode 快速模式 选择 Disable
正常时 CNT 命中 CCR 到输出翻转有几个时钟延迟; Fast Mode 在某些触发场景让输出立即翻转
CH Polarity 有效电平的极性 Hige 说敏有效电平是高(是 PWMmode 那个有效电平); Low = 有效是低

代码

Step 1 - 声明 CCR 变量

1
2
3
/* USER CODE BEGIN PV */  
uint16_t ccrVal = 0;
/* USER CODE END PV */

Step 2 - 使能定时器的 PWM 输出通道

1
2
3
/* USER CODE BEGIN 2 */  
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
/* USER CODE END 2 */

Step 3 - 主函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
while (ccrVal < 100)
{
ccrVal++;
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, ccrVal);
HAL_Delay(10);
}
while (ccrVal > 0)
{
ccrVal--;
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, ccrVal);
HAL_Delay(10);
}
HAL_Delay(200);
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */}
/* USER CODE END 3 */

函数__HAL_TIM_SET_COMPARE

它的作用是代码运行时更改占空比, 具体来说是把一个值写进通道对应的比较寄存器 CCRx

本质上约等于:

1
TIM3->CCR1 = ccrVal;   

流程分析

TIM3 的计数器以每秒数一万个的速度向前数数(PSC), 数到 100 的时候就停下从 0 重新数(ARR), 我们确定一条线, 数字低于这条线灯就亮(ccrVal). 一开始这条线是 0(Pulse), 这就导致灯没有机会亮, 占空比为 0%. 随后这条线慢慢变高, 灯越来越亮…

呼吸灯就实现了!