发新帖本帖赏金 20.00元(功能说明)我要提问
1234下一页
返回列表
打印
[蓝牙芯片]

【WS2812驱动ch582版】基于CH582使用IO模拟时序驱动WS2812

[复制链接]
4646|69
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 lilijin1995 于 2022-9-17 17:54 编辑

#申请原创#  @21小跑堂
---------------------
【WS2812驱动ch582板】基于CH582使用IO模拟时序驱动WS2812,实现红绿蓝切换

1.背景

选择IO口驱动WS2812实属无奈,事情是这样的,本来想使用TIM PWM+DMA的方式,但是画板子的时候选择了CH582的第14pin,即PB7 PWM9模式,按理说PWM模式没有DMA问题也不大嘛,但是事情不是这样的,因为这个PWM模式,他的周期只能选择如下几种;

typedef enum
{
     PWMX_Cycle_256 = 0, // 256 个PWMX周期
     PWMX_Cycle_255,     // 255 个PWMX周期
     PWMX_Cycle_128,     // 128 个PWMX周期
     PWMX_Cycle_127,     // 127 个PWMX周期
     PWMX_Cycle_64,      // 64 个PWMX周期
     PWMX_Cycle_63,      // 63 个PWMX周期
     PWMX_Cycle_32,      // 32 个PWMX周期
     PWMX_Cycle_31,      // 31 个PWMX周期
} PWMX_CycleTypeDef;



并且我们的主频是60M,选择分频系数为1不分频,最后算出来1码没有达到800K,尝试了好几种配置,能点亮红色,绿色,蓝色不亮;

2. WS2812B驱动原理

通过阅读规格书,如下图所示,可以知道WS2812B的数据刷新率为800K,

再有时序定义如下:0码由T0H和T0L组成,1码也差不多,RESET码是断帧码,断帧就是第几个灯珠停止,点亮几颗灯的意思;

最后是数据结构,如下,一个灯珠的数据由24bit的GRB组成,N个24bit的GRB点亮N个灯珠,最后Reset断帧,其中1个bit如果是二进制的1,那么时序对应的是1码,反之是0码;

3. 代码实现:

这里我们直接上代码,其中Set0Code和Set1Code是基于1码和0码的时序用示波器调出来的,这里就介绍方法不介绍过程了;方法是直接调用SendOneFrame(0xFF);全发1码驱动1码,确定0码是发SendOneFrame(0x00),看高低电平即可;

/********************************** (C) COPYRIGHT *******************************
  * File Name          : Main.c
  * Author             : Li
  * Version            : V1.0
  * Date               : 2022/09/07
  * Description         : IO驱动WS281X彩灯功能演示
  * Copyright (c) 2022 Guangzhou Liandun Electronic Technology Co., LTD.
  * SPDX-License-Identifier: Apache-2.0
  *******************************************************************************/

#include "CH58x_common.h"

#define SNUM       1//灯珠数量

//缓存区
unsigned char buf[SNUM][3]={
0
};
//发0码
void Set0Code(void) {
     GPIOB_SetBits(GPIO_Pin_7);
     __nop();
     __nop();
     GPIOB_ResetBits(GPIO_Pin_7);
     //       NOP();
}
//发1码
void Set1Code(void) {
     GPIOB_SetBits(GPIO_Pin_7);
     __nop();
     __nop();
     __nop();
     __nop();
     __nop();
     __nop();
     __nop();
     __nop();
     GPIOB_ResetBits(GPIO_Pin_7);
}
//发一个像素
void SendOnePix(unsigned char *ptr) {
     unsigned char i, j;
     unsigned char temp;

     for (j = 0; j < 3; j++) {
         temp = ptr[j];
         for (i = 0; i < 8; i++) {
             if (temp & 0x80)        //从高位开始发送
                     {
                 Set1Code();
             } else                //发送“0”码
             {
                 Set0Code();
             }
             temp = (temp << 1);      //左移位
         }
     }
}
//发一帧数据
void SendOneFrame(unsigned char *ptr) {
     uint16_t k;

     //  PWM_RGB=0;//发送帧复位信号
     //  DelayMs(1);

     for (k = 0; k < SNUM; k++)              //发送一帧数据,SNUM是板子LED的个数
             {
         SendOnePix(&ptr[(3 * k)]);
     }

     GPIOB_ResetBits(GPIO_Pin_7);              //发送帧复位信号

}

/*********************************************************************
  * @fn      main
  *
  * [url=home.php?mod=space&uid=247401]@brief[/url]   主函数
  *
  * [url=home.php?mod=space&uid=266161]@return[/url]  none
  */
int main() {
     SetSysClock(CLK_SOURCE_PLL_60MHz);

     /* 配置GPIO */
     GPIOB_ModeCfg(GPIO_Pin_7, GPIO_ModeOut_PP_20mA);  // PB7 - PWM9


     while(1)
     {
         //Red
         buf[0][0]=0xFF;
         buf[0][1]=0x00;
         buf[0][2]=0x00;
         SendOneFrame(buf);
         DelayMs(1000);
         //Green
         buf[0][0]=0x00;
         buf[0][1]=0xFF;
         buf[0][2]=0x00;
         SendOneFrame(buf);
         DelayMs(1000);
         //Blue
         buf[0][0]=0x00;
         buf[0][1]=0x00;
         buf[0][2]=0xFF;
         SendOneFrame(buf);
         DelayMs(1000);
     }
}

4.下载验证:

可以看到RGB大约1ms切换;


附件是源码


EXAM.rar

309.39 KB

使用特权

评论回复

打赏榜单

21小跑堂 打赏了 20.00 元 2022-09-08
理由:恭喜通过原创文章审核!请多多加油哦!

评论
21小跑堂 2022-9-8 16:43 回复TA
硬件随意,软件哭泣,虽说你错过了硬件驱动,但是软件模拟却可以任意移植,也是一个不错的选择哦 
沙发
kiwis66| | 2022-9-12 10:14 | 只看该作者
硬件随意,软件哭泣
这是神总结啊

使用特权

评论回复
板凳
guijial511| | 2022-9-12 14:14 | 只看该作者
哈哈,总结到位。

使用特权

评论回复
地板
abotomson| | 2022-10-5 16:37 | 只看该作者
这个真的可以吗              

使用特权

评论回复
5
dzfansman| | 2022-10-5 16:58 | 只看该作者
怎么操作WS2812B彩灯模块  

使用特权

评论回复
6
wengh2016| | 2022-10-5 17:28 | 只看该作者
ws2812和ws2812b能混用吗  

使用特权

评论回复
7
htmlme| | 2022-10-5 17:56 | 只看该作者
CH582能不能使用定时器实现延时呢

使用特权

评论回复
8
typeof| | 2022-10-5 18:31 | 只看该作者
延时的代码是怎么调整的      

使用特权

评论回复
9
iamaiqiyi| | 2022-10-5 19:21 | 只看该作者
之前使用stm32模拟过,不是很稳定,数据显示有问题

使用特权

评论回复
10
alvpeg| | 2022-10-5 20:12 | 只看该作者
看的出来WS2812对时序还是要求比较严格的  

使用特权

评论回复
11
lilijin1995|  楼主 | 2022-10-7 09:44 | 只看该作者

我是蓝牙模式指示,只试过1颗灯珠

使用特权

评论回复
12
lilijin1995|  楼主 | 2022-10-7 09:45 | 只看该作者
dzfansman 发表于 2022-10-5 16:58
怎么操作WS2812B彩灯模块

IO模拟2812时序

使用特权

评论回复
13
lilijin1995|  楼主 | 2022-10-7 09:46 | 只看该作者
wengh2016 发表于 2022-10-5 17:28
ws2812和ws2812b能混用吗

可以先看一下规格书中的时序,有些不一样,大部分一样

使用特权

评论回复
14
lilijin1995|  楼主 | 2022-10-7 09:47 | 只看该作者
htmlme 发表于 2022-10-5 17:56
CH582能不能使用定时器实现延时呢

定时器可以直接PWM控制,有DMA会更好

使用特权

评论回复
15
lilijin1995|  楼主 | 2022-10-7 09:48 | 只看该作者
htmlme 发表于 2022-10-5 17:56
CH582能不能使用定时器实现延时呢

看错了,可以的,控制寄存器实现即可

使用特权

评论回复
16
lilijin1995|  楼主 | 2022-10-7 09:49 | 只看该作者
typeof 发表于 2022-10-5 18:31
延时的代码是怎么调整的

IO口调整时序,我是加NOP

使用特权

评论回复
17
lilijin1995|  楼主 | 2022-10-7 09:51 | 只看该作者
iamaiqiyi 发表于 2022-10-5 19:21
之前使用stm32模拟过,不是很稳定,数据显示有问题

我在HK32F030M试过也是不稳定,在辉芒微内存较低的型号也会,一般1K以上的SRAM会好很多,我驱动灯带可以,但饱和度不够

使用特权

评论回复
18
lilijin1995|  楼主 | 2022-10-7 09:52 | 只看该作者
alvpeg 发表于 2022-10-5 20:12
看的出来WS2812对时序还是要求比较严格的

是啊,最好频率高点MCU

使用特权

评论回复
19
chenqianqian| | 2022-10-8 20:53 | 只看该作者
用PWM效率最高,最方便。

使用特权

评论回复
20
tpgf| | 2022-10-9 12:01 | 只看该作者
一般情况下可以使用什么驱动WS2812呢

使用特权

评论回复
发新帖 本帖赏金 20.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

54

主题

162

帖子

7

粉丝