当前位置: 首页 > news >正文

CH5xx TMR PWM DMA驱动WS2812

CH5xx TMR PWM DMA驱动WS2812

本文以CH592测试,使用TMR的PWM功能驱动WS2812,这种方法相对于SPI DMA驱动的方式有点时节省IO资源,但是RAM消耗会比SPI方式大四倍。

下面贴出程序:

1.pwm_ws2812.c文件:

#include "pwm_ws2812.h"/*** @brief  初始化WS2812缓冲区(填充前后复位信号)*/
void ws2812_buf_init(uint32_t *buf)
{uint16_t i;// 前导复位信号(低电平)for(i = 0; i < WS2812_RESET_CYCLES; i++){buf[i] = 0; // 占空比0%(低电平)
    }// 后导复位信号(确保数据发送完成后复位)uint16_t data_end = WS2812_RESET_CYCLES + WS2812_LED_NUM * 24;for(i = data_end; i < WS2812_BUF_LEN; i++){buf[i] = 0;}
}/*** @brief  内部函数:填充单个LED的24bit数据*/
static void ws2812_set_rgb_bits(uint32_t *buf, uint8_t g, uint8_t r, uint8_t b)
{uint8_t i;// 绿色分量(8bit,先低后高)for(i = 0; i < 8; i++){buf[i] = (g & 0x01) ? WS2812_T1H : WS2812_T0H;g >>= 1;}// 红色分量(8bit,先低后高)for(i = 0; i < 8; i++){buf[i + 8] = (r & 0x01) ? WS2812_T1H : WS2812_T0H;r >>= 1;}// 蓝色分量(8bit,先低后高)for(i = 0; i < 8; i++){buf[i + 16] = (b & 0x01) ? WS2812_T1H : WS2812_T0H;b >>= 1;}
}/*** @brief  设置单个LED的颜色*/
void ws2812_set_single(uint32_t *buf, uint8_t led_idx, uint8_t g, uint8_t r, uint8_t b)
{if(led_idx >= WS2812_LED_NUM) return; // 索引越界检查// 计算当前LED在缓冲区中的起始位置uint32_t *led_buf = buf + WS2812_RESET_CYCLES + led_idx * 24;ws2812_set_rgb_bits(led_buf, g, r, b);
}/*** @brief  填充所有LED为同一颜色*/
void ws2812_fill_all(uint32_t *buf, uint8_t g, uint8_t r, uint8_t b)
{for(uint8_t i = 0; i < WS2812_LED_NUM; i++){ws2812_set_single(buf, i, g, r, b);}
}/*** @brief  发送WS2812数据*/
void ws2812_send(uint32_t *buf)
{// 配置DMA传输范围
    TMR2_DMACfg(ENABLE,(uint16_t)(uint32_t)buf,(uint16_t)(uint32_t)(buf + WS2812_BUF_LEN ),Mode_Single);// 启动PWM(低电平起始,单次传输)//TMR2_PWMInit(Low_Level, PWM_Times_1);
    TMR2_PWMEnable();TMR2_Enable();}/*** @brief  初始化WS2812硬件(定时器2+GPIO)*/
void ws2812_hw_init(void)
{// 配置GPIO(PB11,推挽输出)
    GPIOA_ModeCfg(GPIO_Pin_11, GPIO_ModeOut_PP_5mA);//    GPIOB_ModeCfg(GPIO_Pin_11, GPIO_ModeOut_PP_5mA);
//    GPIOPinRemap(ENABLE, RB_PIN_TMR2); // 映射定时器2到PB11// 配置定时器2 PWM周期TMR2_PWMCycleCfg(WS2812_BIT_CYCLE); // 单bit周期
    TMR2_PWMInit(High_Level, PWM_Times_1);}

2.pwm_ws2812.h文件:

#ifndef __PWM_WS2812_H
#define __PWM_WS2812_H#include "CH59x_common.h"// WS2812 配置参数(根据实际需求修改)
#define WS2812_LED_NUM      10      // LED数量
#define WS2812_CLK_FREQ     60      // 系统时钟频率(MHz),需与实际时钟一致
#define WS2812_RESET_US     50      // 复位信号最小时间(us)// 时序参数(单位:系统时钟周期,自动计算)
#define WS2812_T0H          (uint32_t)(0.4 * WS2812_CLK_FREQ)  // 0码高电平(≈0.4us)
#define WS2812_T1H          (uint32_t)(0.8 * WS2812_CLK_FREQ)  // 1码高电平(≈0.8us)
#define WS2812_BIT_CYCLE    (uint32_t)(1.25 * WS2812_CLK_FREQ) // 单bit总周期(≈1.25us)
#define WS2812_T0L          (WS2812_BIT_CYCLE - WS2812_T0H)    // 0码低电平
#define WS2812_T1L          (WS2812_BIT_CYCLE - WS2812_T1H)    // 1码低电平
#define WS2812_RESET_CYCLES (uint32_t)((WS2812_RESET_US * WS2812_CLK_FREQ) / 1000) // 复位周期数// 缓冲区长度计算(前导复位+数据+后导复位)
#define WS2812_BUF_LEN      (WS2812_RESET_CYCLES + WS2812_LED_NUM * 24 + WS2812_RESET_CYCLES/2)/*** @brief  初始化WS2812缓冲区(填充复位信号)* @param  buf: 缓冲区指针(需提前定义为WS2812_BUF_LEN长度)*/
void ws2812_buf_init(uint32_t *buf);/*** @brief  设置单个LED的RGB颜色* @param  buf: 缓冲区指针* @param  led_idx: LED索引(0~WS2812_LED_NUM-1)* @param  g: 绿色分量(0-255)* @param  r: 红色分量(0-255)* @param  b: 蓝色分量(0-255)*/
void ws2812_set_single(uint32_t *buf, uint8_t led_idx, uint8_t g, uint8_t r, uint8_t b);/*** @brief  填充所有LED为同一颜色* @param  buf: 缓冲区指针* @param  g: 绿色分量(0-255)* @param  r: 红色分量(0-255)* @param  b: 蓝色分量(0-255)*/
void ws2812_fill_all(uint32_t *buf, uint8_t g, uint8_t r, uint8_t b);/*** @brief  发送WS2812数据(启动DMA和PWM)* @param  buf: 缓冲区指针*/
void ws2812_send(uint32_t *buf);/*** @brief  初始化WS2812硬件(定时器+GPIO)*/
void ws2812_hw_init(void);#endif

3.main函数:

#include "CH59x_common.h"#include "pwm_ws2812.h"// 定义WS2812缓冲区(按宏定义长度分配)
__attribute__((aligned(4))) uint32_t PwmBuf[WS2812_BUF_LEN];void DebugInit(void)
{GPIOA_SetBits(GPIO_Pin_9);GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU);GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA);UART1_DefInit();
}int main()
{SetSysClock(CLK_SOURCE_PLL_60MHz);DebugInit();PRINT("WS2812 Test @ChipID=%02X\n", R8_CHIP_ID);// 初始化WS2812硬件和缓冲区
    ws2812_hw_init();ws2812_buf_init(PwmBuf);
PRINT("WS2812_BUF_LEN=%d\n",WS2812_BUF_LEN);// 测试流程:依次显示黄→青→紫→逐个点亮ws2812_fill_all(PwmBuf, 0xFF, 0xFF, 0x00); // 黄色for(uint16_t i=0;i<WS2812_BUF_LEN;i++){PRINT("%d ",PwmBuf[i]);}PRINT("\n");ws2812_send(PwmBuf);DelayMs(1000);ws2812_fill_all(PwmBuf, 0xFF, 0x00, 0xFF); // 青色
    ws2812_send(PwmBuf);DelayMs(1000);ws2812_fill_all(PwmBuf, 0x00, 0xFF, 0xFF); // 紫色
    ws2812_send(PwmBuf);DelayMs(1000);while(1) // 无限循环,持续律动
    {// 1. 从左到右:目标色依次点亮,背景色保持不变for(uint8_t j = 0; j < WS2812_LED_NUM; j++){// 每次循环先重置所有LED为背景色(避免残留之前的目标色)ws2812_fill_all(PwmBuf, 0x55, 0xAA, 0xFF);// 将当前位置j的LED设为目标色ws2812_set_single(PwmBuf, j, 0xAA, 0x55, 0x00);// 发送数据,更新LED显示
            ws2812_send(PwmBuf);// 控制律动速度,数值越小越快(可根据需求调整,如300ms)DelayMs(300);}// 2. 从右到左:目标色依次熄灭(恢复背景色),模拟“往回走”for(int8_t j = WS2812_LED_NUM - 2; j >= 0; j--) // 从倒数第二个开始(最后一个已点亮,无需重复)
        {// 重置所有LED为背景色ws2812_fill_all(PwmBuf, 0x55, 0xAA, 0xFF);// 将当前位置j的LED设为目标色ws2812_set_single(PwmBuf, j, 0xAA, 0x55, 0x00);// 发送数据,更新LED显示
            ws2812_send(PwmBuf);// 保持与“从左到右”相同的速度,确保律动流畅DelayMs(300);}}
}

 

http://www.jsqmd.com/news/307693/

相关文章:

  • springboot多商家美食商城网站系统39949-vue
  • springboot电影院售票网站vue
  • 2026年江西好用的数字孪生园区平台推荐,选购时要注意什么
  • springboot的学生选课考勤签到请假销假管理系统_zyoqy-vue
  • springboot二手书籍二手影音商品交易平台vue
  • 通过feing 调用的微服务,怎么暴露给外部通过postman 调用
  • 机器人信息|基于Springboot的机器人门户展示架构设计与建立(源码+数据库+文档)
  • 2026年长沙心理咨询机构哪家专业?这份机构指南请关注
  • 新手学古筝必看:2026年值得入手的品牌推荐,瑶鸾古筝/瑶鸾古筝Y103系列(梦蝶),古筝源头厂家口碑推荐
  • C++ 并发编程进阶:线程同步、原子操作与死锁规避实战 - 教程
  • 闲置沃尔玛购物卡回收变现攻略 三步轻松兑现金
  • 2026年小面积施工用地坪漆品牌推荐:从适配性到性价比的专业选型指南
  • 大模型如何突破“认知茧房”?RAG+MCP构建外部脑接口​
  • 南京top10研究生留学机构,资质正规,助力留学成功之路
  • Spring Boot 性能优化:启动时间从 5s 到 1s 的全链路实战指南
  • 泉州研究生留学机构口碑排名出炉!录取案例多,助力学子成功
  • 导师推荐10个AI论文平台,助你搞定研究生论文格式规范!
  • 深度剖析广州研究生留学机构口碑排名,申请成功率高成重要参考!
  • 苏州硕士留学机构top10如何选?学员满意度高给出关键指标
  • Linux中收集【系统】和【硬件】信息的30个常用命令总结
  • Agent Skills 傻瓜式教程,26 年最火 AI 技术就这?
  • 一文给傻子讲清各个网络协议名词 MQTT TCP/IP TCP/UDP WEBSOCKET的区别
  • {“message“:“User login“,“context“:{“user_id“:123},“extra“:{“request_id“:“abc123“}}的庖丁解牛
  • 零基础从零到一暴露 /metrics 端点(内网访问)的庖丁解牛
  • PHP 可观测性的庖丁解牛
  • 雅思提分不走弯路|2026 网上雅思培训学校优选推荐 个性化方案解析
  • 千匠网络:值得信赖的大宗电商系统服务商
  • 2026 上海专业找猫全指南:凭借高找回率、标准化服务树立行业壁垒
  • 2026年权威测评:雅思线上培训平台深度横评与选择指南,揭秘高分提分高效路径
  • 2026年检测试剂盒源头厂家有哪些?这些企业不容错过,羊试剂盒/试剂盒elisa,检测试剂盒公司怎么选择