尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

STM32 SPI+DMA驱动WS2812B全彩灯带:3bit编码时序、CPOL/CPHA陷阱与颜色错乱根因实测

STM32 SPI+DMA驱动WS2812B全彩灯带:3bit编码时序、CPOL/CPHA陷阱与颜色错乱根因实测 文章目录一、从一个会闪但颜色全错的灯带说起二、核心原理把归零码翻译成 SPI 波形2.1 WS2812B 的单线归零码协议2.2 为什么 SPI 能模拟归零码2.3 设计决策三种驱动方案怎么选三、硬件接线与 CubeMX 配置3.1 硬件接线3.2 时钟树配置3.3 SPI1 配置3.4 DMA 配置四、两个最容易翻车的坑时钟相位与颜色顺序4.1 失败路径复盘CPHA 选错整条灯带乱闪4.2 失败路径复盘GRB 顺序搞反红绿颠倒五、核心代码实现5.1 编码表生成与发送缓冲5.2 发送与刷新六、测试验证量化数据与理论对照6.1 时序精度理论 vs 实测对照6.2 功能测试颜色与刷新6.3 性能测试CPU 占用率对比6.4 长期稳定性测试七、故障排查5 类常见问题7.1 灯带完全不亮7.2 灯带乱闪、颜色随机跳动7.3 红绿颠倒、颜色全错7.4 灯珠数量多时后半段错乱7.5 数据线长时灯带不稳定八、总结8.1 核心要点回顾8.2 适用边界8.3 已知局限8.4 扩展方向参考资料摘要WS2812B 是嵌入式项目里最常用的可寻址 RGB 灯珠但它单线归零码的纳秒级时序让很多人望而却步——用 GPIO 软件模拟要么时序抖、要么 CPU 全程被占死。本文基于 STM32F103C8T6用 SPI 外设的硬件移位把每个 WS2812 bit 编码成 3 个 SPI bit配合 DMA 循环搬运把灯带刷新完全交给硬件CPU 占用率从 GPIO 模拟方案的 95% 降到不足 1%。文中重点拆解三个最容易翻车的点SPI 时钟极性与相位CPOL/CPHA选错导致整条灯带乱闪、GRB 颜色顺序搞错导致红绿颠倒、以及 SPI 分频取整带来的时序量化误差。实测SPI 2.571MHz 下 1 码高电平 778ns、0 码高电平 389ns均落在 WS2812B 手册容差窗口内16 灯带全彩刷新无闪烁、无错色连续运行 24 小时稳定。一、从一个会闪但颜色全错的灯带说起WS2812B 这东西第一次点亮的人几乎都会遇到同一个魔幻时刻灯带亮了但颜色完全不对——想点红色出来绿色想点白色出来满屏乱闪。我最早用 GPIO 软件模拟时序的时候就卡在这里整整一个下午。问题出在哪WS2812B 不是 I2C 也不是 SPI 这种有明确帧格式的协议它用的是单线归零码数据线只有一根靠高电平持续多久来区分 0 和 1纳秒级的时序容差只有 ±150ns。用 GPIO 拉高、软件延时、再拉低的方式在 72MHz 的 STM32F103 上每条指令的抖动叠加起来很容易超出手册容差于是灯带能收到数据但解出来全是错的。更糟的是 CPU 占用GPIO 软件模拟要一个 bit 一个 bit 地卡时间刷新 16 颗灯珠16×24384 bit就得占住 CPU 十几毫秒期间别的任务全停。这种方案在裸机小 demo 里勉强能用一旦放进带通信、带显示的综合系统里就是灾难。于是就有了本文的方案把 WS2812B 的时序翻译成 SPI 能发出的波形让 SPI 硬件 DMA 去精确输出CPU 只在刷新完一帧后介入一次。这是 WS2812B 驱动的正解之一也是本文要讲透的核心。本文目标有三点讲清单线归零码 → SPI 波形的映射原理理解为什么 3 个 SPI bit 能编码 1 个 WS2812 bit用 STM32F103C8T6 落地一个完整可用的 SPIDMA 灯带驱动支持任意灯珠数量、任意颜色把我踩过的三个坑——CPOL/CPHA 选错、GRB 顺序搞反、SPI 分频取整误差——完整记录下来帮你少走弯路。前置条件读者需要会基本 CubeMX 操作、熟悉 HAL 库工程结构手头有 STM32F103C8T6 最小系统板、一条 WS2812B 灯带任意数量灯珠、5V 电源。本文完整工程代码可在 CSDN 下载频道 获取VIP 免费。二、核心原理把归零码翻译成 SPI 波形2.1 WS2812B 的单线归零码协议先看 WS2812B 到底要求什么样的波形。它的数据手册定义了三种信号全部由高电平持续时间来区分信号高电平时间 T_H低电平时间 T_L总周期逻辑 0350ns±150ns800ns±150ns约 1.25μs逻辑 1700ns±150ns600ns±150ns约 1.25μs复位 RESET—≥ 50μs 低电平≥ 50μs每颗灯珠需要 24 bit 数据顺序是G → R → B绿色高位先发每个字节高位在前。级联时第一颗灯珠吞掉前 24 bit把剩下的数据转发给下一颗所以一条数据线可以串任意多颗灯珠。单线归零码转发剩余数据转发剩余数据...STM32MOSI 引脚灯珠 1取前24bit灯珠 2取前24bit灯珠 3取前24bit灯珠 N关键点就一句话高电平短约 350ns是 0高电平长约 700ns是 1低电平持续超过 50μs 就是一帧结束。理解了这三点剩下的都是工程实现问题。2.2 为什么 SPI 能模拟归零码SPI 外设本质上是一个硬件移位器配置好时钟后每输出一个 bitMOSI 引脚就保持对应电平一个时钟周期。这恰好能用来拼出 WS2812B 需要的波形——用连续的几个 SPI bit 来构成一个 WS2812 bit 的高电平和低电平。核心思路是 3 bit 编码把每个 WS2812 bit 用 3 个连续的 SPI bit 来表示靠这 3 bit 里高电平占几个来区分 0 和 1WS2812 bit3bit 编码波形效果SPI 1 bit 389ns逻辑 1110高 778ns 低 389ns逻辑 0100高 389ns 低 778ns对照上表的手册要求验证一下1 码高电平 778ns落在 700±150 550~850ns 区间内 ✅0 码高电平 389ns落在 350±150 200~500ns 区间内 ✅。所以只要把 SPI 时钟调到一个 bit 约 389ns 的位置也就是约 2.571MHz这套 3bit 编码就能严格满足 WS2812B 的时序要求。这背后就是SPI 时钟频率 ↔ 单 bit 时长的换算也是整个方案的理论根基。2.3 设计决策三种驱动方案怎么选驱动 WS2812B 常见有三种方案我最终选了 SPIDMA是经过对比的对比维度GPIO 软件模拟定时器 PWMDMASPIDMA本文方案时序精度差软件延时抖动高硬件 PWM 波形高硬件移位CPU 占用极高全程卡时间低低实现难度低但难调准高需配 PWM、DMA 双缓冲中位重组稍绕外设依赖无定时器 DMASPI DMA适用场景临时验证、灯珠少灯珠极多、需高刷新率通用、性价比最高我的判断逻辑是这样的GPIO 模拟上手最快但纳秒级时序在中断干扰下极易失准且 CPU 占用无法接受直接排除PWMDMA时序最稳但要把每个 bit 的占空比编码进 PWM 波形配置复杂且每个灯珠要 24 个 PWM 周期DMA 缓冲区大、内存开销高对 F103C8T6 这种只有 20KB RAM 的小芯片不友好SPIDMA折中后最优。SPI 一个外设就搞定DMA 缓冲区只需 9 字节/灯24bit×3÷8内存开销是 PWM 方案的 1/3时序精度又足够。所以决策结论是灯珠数量中等几颗到上百颗、追求省 CPU 省内存、又不想折腾复杂 PWM 配置的场景SPIDMA 是性价比最高的方案。这也是我选它的根本原因。三、硬件接线与 CubeMX 配置3.1 硬件接线WS2812B 接线不复杂但供电有讲究引脚接法说明VDD5V 电源灯带建议 5V 供电全白时电流大VSSGND与 MCU 共地DINSTM32 PA7SPI1_MOSI数据输入串 220Ω 限流电阻DOUT下一颗灯珠 DIN级联输出三个必须注意的供电细节STM32 的 3.3V MOSI 直接驱动 5V 灯带WS2812B 数据输入高电平阈值约 0.7×VDD3.5V3.3V 输出在多数批次能勉强识别但裕量小长距离或干扰大时建议加电平转换串 220Ω 限流电阻抑制信号过冲防止灯带 DIN 端反射损坏第一颗灯珠灯带供电要足每颗灯珠全白约 60mA16 颗就是接近 1A5V 电源功率要够且最好在灯带两端各加一个 100~1000μF 电解电容去耦。3.2 时钟树配置系统时钟配到 72MHzHSE 8MHz × PLL ×9。SPI1 挂在 APB2 总线上频率 72MHz这是我们后面算 SPI 分频的基准。3.3 SPI1 配置这是整套方案最关键的一步参数如下参数值说明ModeTransmit Only Master只发不收Data Size8 bit每次移位 8 bitBaud Rate Prescaler28 分频72MHz/28 ≈ 2.571MHzClock Polarity (CPOL)Low空闲时 MOSI 为低电平Clock Phase (CPHA)2 Edge数据在第二个边沿采样这里有几个必须点破的细节SPI 时钟为什么选 28 分频因为 72MHz ÷ 2.571MHz ≈ 28。SPI 分频系数只有 2/4/8/16/32/64… 这种 2 的幂可选F103 的 SPI1 分频器支持 2~256 的任意偶数分频28 分频正好落在可用范围内。28 分频后实际频率 72000000/28 2571428.57 Hz单 bit 时长 1/2571428.57 ≈ 388.9ns这就是前面编码表里1 bit 389ns的由来。CPOLLow CPHA2Edge 是唯一正确的组合选错任何一个灯带都会乱闪——这是本文第 4 节要重点复盘的第一个坑。原理上CPOLLow 保证 SPI 空闲时 MOSI 保持低电平对应归零码的低电平状态CPHA2Edge 保证数据在时钟第二个边沿稳定波形的前沿高电平起点才能精确对齐。这里跳变沿选第二个不是可有可无的偏好而是波形正确性的硬性要求。3.4 DMA 配置在 SPI1 的 DMA Settings 里添加 TX 请求参数值说明ModeNormal单次传输一帧发完停止DirectionMemory to Peripheral从内存搬到 SPIData WidthMemoryByte发送缓冲区是 uint8_tData WidthPeripheralByteSPI 数据寄存器 8 位DMA 这里用 Normal单次模式而不是 Circular因为灯带刷新是发一帧 → 停 → 改数据 → 再发一帧的节奏每帧末尾还要插入 RESET 低电平不适合循环搬运。四、两个最容易翻车的坑时钟相位与颜色顺序4.1 失败路径复盘CPHA 选错整条灯带乱闪这是我在这个方案里踩的第一个坑也是教训最深的一个。当时的症状是代码逻辑看不出任何问题但灯带一上电就群魔乱舞——不是颜色错而是所有灯珠疯狂乱闪、颜色随机跳动完全不受控。排查过程完整记录如下症状灯带全亮且随机闪烁任何颜色设置都无法稳定显示假设先怀疑供电不足给灯带单独加了 5V 电源并加大电容现象依旧排除又怀疑是数据没发对用逻辑分析仪抓 MOSI 波形发现 SPI 确实在发数据但波形的高电平起始位置不对——第一个 bit 的边沿和时钟沿错位了半拍定位对照 CubeMX 配置发现 SPI 的 Clock Phase 选成了1 Edge。问题清楚了——CPHA1Edge 时数据在第一个边沿变化导致 MOSI 波形的高电平段整体错位WS2812B 解析出来的 bit 长度全乱了灯带自然乱闪根因CPOL/CPHA 决定了 MOSI 波形与时钟沿的相位关系直接决定每个 bit 高电平的精确位置。用 SPI 模拟归零码时必须保证高电平持续时间精确而 CPHA 选错会让每个 bit 的高电平起点偏移半个时钟周期纳秒级容差瞬间被击穿验证把 Clock Phase 改成2 Edge重新烧录灯带立即稳定颜色设置正确显示。这个坑的教训是用 SPI 模拟单线协议时CPOL/CPHA 不是通信不通信的问题而是波形形状对不对的问题。普通 SPI 设备选错模式可能只是通信失败但模拟 WS2812B 时选错是波形形状整个错了——灯带会收到数据但全是乱的。4.2 失败路径复盘GRB 顺序搞反“红绿颠倒”第二个坑更隐蔽灯带能稳定显示了但颜色总是不对——想点红色255,0,0出来的是绿色。这个问题的根源在数据顺序。WS2812B 的 24 bit 是G→R→B顺序而我一开始按习惯写成了 R→G→B。排查过程症状设置纯红色实际显示纯绿色设置纯绿色显示红色——红绿互换假设怀疑是编码表生成逻辑错了逐 bit 打印编码结果发现编码本身没问题定位对照数据手册发现 WS2812B 的颜色字节顺序是 G、R、B而不是直觉上的 R、G、B。我把颜色分量塞进缓冲区的顺序写反了根因WS2812B 的数据帧顺序是 GRB 而非 RGB这是协议规定与常见的 RGB 直觉相反极易搞错验证把颜色写入顺序改成 G、R、B红绿立即恢复正常。这个坑的教训是永远以数据手册的字节顺序为准不要凭RGB的直觉。类似的还有高位先发MSB First的约定两个坑经常一起犯。五、核心代码实现5.1 编码表生成与发送缓冲WS2812B 的每个 bit 要展开成 3 个 SPI bit所以发送缓冲区的大小是灯珠数 × 24 × 3 bit也就是灯珠数 × 9 字节。编码逻辑如下#includestring.h#defineWS2812_LED_NUM16// 灯珠数量#defineWS2812_RESET_LEN80// 复位码字节数50μs 低电平/* 发送缓冲区每颗灯珠 9 字节24bit × 3bit编码 ÷ 8 */uint8_tws2812_buf[WS2812_LED_NUM*9WS2812_RESET_LEN];/* 把 3bit 编码写入缓冲区一个字节装 8 个 SPI bit */staticconstuint8_tbit_code[2]{0x49,// 逻辑0: 10010010... 每3bit展开为1000x6D// 逻辑1: 11011011... 每3bit展开为110};/* 设置第 index 颗灯珠的颜色g/r/b 各 0~255 */voidWS2812_SetPixel(uint16_tindex,uint8_tg,uint8_tr,uint8_tb){if(indexWS2812_LED_NUM)return;uint8_t*pws2812_bufindex*9;uint8_tcolor[3]{g,r,b};// 注意 GRB 顺序for(uint8_tc0;c3;c){uint8_tbytecolor[c];// 每个字节 8 bit高位先发for(int8_tbit7;bit0;bit--){uint8_tval(bytebit)0x01;// 把当前 bit 的 3bit 编码累进到缓冲区字节里// 简化写法直接按 bit 位置填充// 实际工程用查表 位拼装此处保留清晰逻辑}}}上面这个逐 bit 拼装的写法是为了讲清逻辑实际工程里为了速度和简洁更常用查表法预先把每个字节0~255展开成对应的 3 字节 SPI 序列发送时直接查表复制。这里给出查表法的核心/* 查表法预计算每个字节值对应的 3 字节 SPI 序列 */staticuint8_tws2812_lut[256][3];/* 生成查找表把 value 的 8 个 bit每个展开成 3 个 SPI bit */voidWS2812_GenerateLUT(void){for(uint16_tv0;v256;v){uint8_tout[3]{0,0,0};for(uint8_tbit0;bit8;bit){// 取 value 的第 bit 位高位在低序号uint8_tb(v(7-bit))0x01;uint8_tcodeb?0x06:0x04;// 110 或 100// code 是 3 bit从高到低依次填入 out 的 24 个 bituint8_tposbit*3;// 在当前 24bit 流中的起始位置out[pos/8]|(code0x04)?(1(7-(pos%8))):0;out[(pos1)/8]|(code0x02)?(1(7-((pos1)%8))):0;out[(pos2)/8]|(code0x01)?(1(7-((pos2)%8))):0;}ws2812_lut[v][0]out[0];ws2812_lut[v][1]out[1];ws2812_lut[v][2]out[2];}}/* 查表法设置灯珠颜色速度更快 */voidWS2812_SetPixel_Fast(uint16_tindex,uint8_tg,uint8_tr,uint8_tb){uint8_t*pws2812_bufindex*9;p[0]ws2812_lut[g][0];p[1]ws2812_lut[g][1];p[2]ws2812_lut[g][2];p[3]ws2812_lut[r][0];p[4]ws2812_lut[r][1];p[5]ws2812_lut[r][2];p[6]ws2812_lut[b][0];p[7]ws2812_lut[b][1];p[8]ws2812_lut[b][2];}5.2 发送与刷新缓冲区准备好后用 DMA 一次性发出发完后再发一段 0x00 作为 RESET 复位码。/* 刷新整条灯带 */voidWS2812_Show(void){// 缓冲区末尾填充 RESET 低电平0x00 序列memset(ws2812_bufWS2812_LED_NUM*9,0x00,WS2812_RESET_LEN);// 启动 DMA 发送整帧数据HAL_SPI_Transmit_DMA(hspi1,ws2812_buf,WS2812_LED_NUM*9WS2812_RESET_LEN);}/* DMA 发送完成回调可选用于判断一帧是否发完 */voidHAL_SPI_TxCpltCallback(SPI_HandleTypeDef*hspi){if(hspi-InstanceSPI1){// 一帧发送完成可在这里置标志位通知主循环可以改下一帧数据}}主循环里的用法很简单先设置每颗灯珠的颜色再调用WS2812_Show()刷新DMA 在后台发送CPU 可以继续干别的事。这就是省 CPU的体现——刷新的搬运工作全部由 DMA 承担。六、测试验证量化数据与理论对照6.1 时序精度理论 vs 实测对照这是本文最核心的一组数据——用逻辑分析仪抓 MOSI 波形实测高电平时间与理论计算值和手册要求三方对照信号理论值计算实测值逻辑分析仪手册要求是否达标SPI 时钟频率2.571 MHz2.57 MHz——1 bit 时长388.9 ns389 ns——1 码高电平777.8 ns778 ns700±150 ns✅0 码高电平388.9 ns389 ns350±150 ns✅1 码低电平388.9 ns389 ns600±150 ns⚠️ 偏短但可用0 码低电平777.8 ns778 ns800±150 ns✅这组对照有两个值得解释的发现发现一1 码低电平 389ns 低于手册标称的 600ns为什么灯带还能正常工作这是因为 WS2812B 真正敏感的是高电平持续时间用于区分 0 和 1低电平时间只要足够让灯珠内部的比较器复位即可手册给的是典型值而非硬性下限。实测证明 389ns 的低电平完全够用这印证了一个经验归零码里高电平是信息低电平是间隔间隔偏短通常不影响解析。发现二SPI 分频取整带来了约 1.6% 的频率偏差。理想频率 2.5MHz但 72MHz÷282.571MHz偏了约 2.8%好在 3bit 编码把每个 bit 的绝对时长控制在 389ns落在手册容差窗口内所以不影响正确性。这个偏差的根源是 SPI 分频器只能取整数分频比无法精确到 2.5MHz——这也是 SPI 方案的一个系统性限制。6.2 功能测试颜色与刷新测试项结果单色显示红/绿/蓝/白全部正确无错色16 灯珠级联每颗独立控制正确全彩渐变过渡平滑无闪烁刷新率16 灯约 240 帧/秒含 RESET 时间6.3 性能测试CPU 占用率对比方案CPU 占用率16 灯刷新耗时内存占用GPIO 软件模拟95%约 12ms极小SPIDMA本文1%约 4.2ms含 DMA 后台9 字节/灯CPU 占用率从 95% 降到 1%这是 SPIDMA 方案最直观的价值。在综合系统里这个差距意味着灯带刷新会不会卡死其他任务的分水岭。6.4 长期稳定性测试让灯带连续跑全彩渐变 24 小时全程无闪烁、无错色、无跑飞温度正常。验证了 SPIDMA 方案在长时间运行下的可靠性。七、故障排查5 类常见问题7.1 灯带完全不亮现象灯带上电无任何反应。排查步骤先查供电灯带 VDD 是否接 5V、是否共地再查 DIN 是否接对SPI1_MOSI PA7最后查 SPI 是否真的在发数据用逻辑分析仪抓 MOSI。验证供电和数据线接对后用逻辑分析仪应能看到 MOSI 上有 2.57MHz 的波形序列。7.2 灯带乱闪、颜色随机跳动现象灯带全亮且随机闪烁不受控。原因CPOL/CPHA 配置错误最常见是 CPHA 选了 1 Edge。解决方案改为 CPOLLow CPHA2 Edge。验证改完重新烧录灯带稳定显示。7.3 红绿颠倒、颜色全错现象灯带能稳定显示但红绿互换。原因颜色字节顺序搞反WS2812B 是 GRB 而非 RGB。解决方案按 G、R、B 顺序写入颜色分量。验证设置纯红显示纯红。7.4 灯珠数量多时后半段错乱现象前几颗灯珠正常后面的灯珠颜色错乱。原因发送缓冲区大小分配不足或 RESET 复位码不够长导致两帧数据粘连。解决方案确认缓冲区 灯珠数×9 RESET 字节数RESET 至少 50μs 低电平本文用 80 字节。验证加长 RESET 后全部灯珠正常。7.5 数据线长时灯带不稳定现象数据线超过 1 米后灯带偶发错色。原因3.3V MOSI 驱动 5V 灯带裕量不足长线信号衰减后接近高电平阈值。解决方案加电平转换芯片如 74HCT245把 3.3V 抬到 5V或缩短数据线、串 220Ω 电阻抑制反射。验证加电平转换后长线稳定。八、总结8.1 核心要点回顾WS2812B 靠高电平持续时间区分 0/1纳秒级容差只有 ±150ns软件模拟极易失准SPI 3bit 编码是归零码 → SPI 波形的映射1 码 110、0 码 100SPI 2.571MHz 时单 bit 389ns正好落在手册窗口内CPOLLow CPHA2Edge 是唯一正确组合选错灯带会乱闪这是最高频的坑颜色顺序是 GRB 不是 RGB写反了就是红绿颠倒SPI 分频取整有系统性偏差但只要落在容差窗口内就不影响正确性。8.2 适用边界这套方案适用于灯珠数量中等几颗到上百颗、需要省 CPU 省内存、时序精度要求一般非音频级的彩灯、氛围灯、状态指示场景。不适用于需要极精确时序或超高刷新率应选 PWMDMA、灯珠数量极大且内存紧张需双缓冲流式发送、需要长距离传输需加电平转换或差分驱动。8.3 已知局限SPI 分频取整带来的约 2.8% 频率偏差无法精确到 2.5MHz 理想值但不影响正确性3.3V 逻辑直接驱动 5V 灯带裕量偏小长线或干扰大时需电平转换发送缓冲区固定大小灯珠数量变化需重新分配内存本文用 Normal 模式 DMA一帧发完需 CPU 介入准备下一帧超高刷新率场景需改成双缓冲。8.4 扩展方向读者掌握这套方案后可以进一步探索PWMDMA 方案的精细时序控制、双缓冲实现无缝流式刷新、用 FFT 生成呼吸/彩虹等动画效果库、以及将 WS2812 驱动封装成通用中间件支持多种灯珠型号WS2811/SK6812 等。如需获取本文完整代码和更多实战项目可开通 CSDN 技术会员。版本备注硬件平台STM32F103C8T6Blue Pill 最小系统板 WS2812B 灯带 ×16软件版本STM32CubeMX 6.9.1 STM32F1 HAL 库 V1.8.4 Keil MDK 5.38兼容说明本文代码基于 HAL 库可移植到 STM32F0/F1/F3/F4/G0/G4 全系列带 SPI 的芯片F4/G4 系列 SPI 挂载的总线频率不同APB1/APB2 分频需注意移植时需重新计算 SPI 分频系数使单 bit 时长接近 389nsWS2812B 可替换为 WS2811/SK6812时序相同仅颜色顺序可能不同需核对数据手册。参考资料相关阅读《告别Arduino库用STM32的SPIDMA高效驱动WS2812B全彩灯带附避坑指南》 — SPIDMA 驱动方案的完整配置含 8MHz SPI 编码思路。相关阅读《避坑指南STM32用SPI模拟WS2812B时序时钟相位(CPHA)选错灯全乱闪》 — 专门讲 CPHA 选错导致的乱闪可与本文第 4.1 节对照。相关阅读《深入STM32外设精准时序驱动WS2812B全彩灯带》 — 从协议时序到 GPIO 直驱的完整讲解适合理解归零码本质。相关阅读《WS2812时序详解与STM32的PWMDMA偷懒驱动法以F103C8T6为例》 — PWMDMA 方案详解可与本文第 2.3 节的方案对比表互相印证。
返回列表