流程图
┌─────────────────────┐
│ ws2812_buf[][] │ ← 用户设置的 LED 颜色缓存 (GRB)
│ 每个 LED 3 个字节 │
└─────────┬───────────┘
│ 遍历每个 LED、每个颜色字节
▼
┌─────────────────────┐
│ 拆字节成 bit │
│ for bit = 7..0 │
└─────────┬───────────┘
│ 转换成 PWM 高低电平占空比
▼
┌─────────────────────┐
│ ws2812_dma_buf[] │ ← DMA 缓冲区
│ 每个 bit 对应一个 │
│ PWM 高低电平值 │
└─────────┬───────────┘
│ 填充 Reset 信号 (0)
▼
┌─────────────────────┐
│ DMA 控制器 │
│ DMA_SetCurrDataCounter(idx) │
│ DMA_Cmd(ENABLE) │
└─────────┬───────────┘
│ 通过定时器 TIM 输出 PWM
▼
┌─────────────────────┐
│ WS2812 LED 灯带 │
│ 每个 LED 接收 24 bit│
│ 更新颜色显示 │
└─────────────────────┘PWM配置
pwm的本质是CNT和CCR进行比较,当CNT<CCR时输出高电平,当CNT>CCR时输出低电平。从在一整个周期内,获得高电平和低电平的不同的占比。
定时器计数器 CNT 的计数
- 假设你用的是
72MHz的时钟,分频器PSC=0。 - 那么 CNT 每 1/72 MHz = 13.9ns 增加 1。
ARR=89(周期寄存器),所以 CNT 会从0 → 89,再回到0,形成一个周期。- 这个过程需要 90 个时钟周期,所以整个 PWM 周期就是
90 / 72MHz ≈ 1.25µs,刚好是 WS2812 协议的一个 bit 时间。
比较过程
PWM 模式 1 的规则:
- 如果
CNT < CCRn→ 输出高电平(有效电平)。 - 如果
CNT ≥ CCRn→ 输出低电平(无效电平)。
举例:
ARR=89- 若
CCR=60:- 当 CNT 从
0 → 59时,高电平。 - 当 CNT 从
60 → 89时,低电平。 → 占空比 = 60/90 ≈ 66%。
- 当 CNT 从
- 若
CCR=30:- 当 CNT 从
0 → 29时,高电平。 - 当 CNT 从
30 → 89时,低电平。 → 占空比 = 30/90 ≈ 33%。
- 当 CNT 从
DMA配置
DMA把ws2812_dma_buf的数据转运到TIM3 的 CCR3 寄存器,去生成PWM波形