lilijin1995 发表于 2022-9-7 11:48

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

本帖最后由 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={
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;
         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
*
* @brief   主函数
*
* @returnnone
*/
int main() {
   SetSysClock(CLK_SOURCE_PLL_60MHz);

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


   while(1)
   {
         //Red
         buf=0xFF;
         buf=0x00;
         buf=0x00;
         SendOneFrame(buf);
         DelayMs(1000);
         //Green
         buf=0x00;
         buf=0xFF;
         buf=0x00;
         SendOneFrame(buf);
         DelayMs(1000);
         //Blue
         buf=0x00;
         buf=0x00;
         buf=0xFF;
         SendOneFrame(buf);
         DelayMs(1000);
   }
}
​4.下载验证:可以看到RGB大约1ms切换;https://www.bilibili.com/video/BV1kV4y1u785/
附件是源码


kiwis66 发表于 2022-9-12 10:14

硬件随意,软件哭泣
这是神总结啊

guijial511 发表于 2022-9-12 14:14

哈哈,总结到位。

abotomson 发表于 2022-10-5 16:37

这个真的可以吗            

dzfansman 发表于 2022-10-5 16:58

怎么操作WS2812B彩灯模块

wengh2016 发表于 2022-10-5 17:28

ws2812和ws2812b能混用吗

htmlme 发表于 2022-10-5 17:56

CH582能不能使用定时器实现延时呢

typeof 发表于 2022-10-5 18:31

延时的代码是怎么调整的      

iamaiqiyi 发表于 2022-10-5 19:21

之前使用stm32模拟过,不是很稳定,数据显示有问题

alvpeg 发表于 2022-10-5 20:12

看的出来WS2812对时序还是要求比较严格的

lilijin1995 发表于 2022-10-7 09:44

abotomson 发表于 2022-10-5 16:37
这个真的可以吗

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

lilijin1995 发表于 2022-10-7 09:45

dzfansman 发表于 2022-10-5 16:58
怎么操作WS2812B彩灯模块

IO模拟2812时序

lilijin1995 发表于 2022-10-7 09:46

wengh2016 发表于 2022-10-5 17:28
ws2812和ws2812b能混用吗

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

lilijin1995 发表于 2022-10-7 09:47

htmlme 发表于 2022-10-5 17:56
CH582能不能使用定时器实现延时呢

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

lilijin1995 发表于 2022-10-7 09:48

htmlme 发表于 2022-10-5 17:56
CH582能不能使用定时器实现延时呢

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

lilijin1995 发表于 2022-10-7 09:49

typeof 发表于 2022-10-5 18:31
延时的代码是怎么调整的

IO口调整时序,我是加NOP

lilijin1995 发表于 2022-10-7 09:51

iamaiqiyi 发表于 2022-10-5 19:21
之前使用stm32模拟过,不是很稳定,数据显示有问题

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

lilijin1995 发表于 2022-10-7 09:52

alvpeg 发表于 2022-10-5 20:12
看的出来WS2812对时序还是要求比较严格的

是啊,最好频率高点MCU

chenqianqian 发表于 2022-10-8 20:53

用PWM效率最高,最方便。

tpgf 发表于 2022-10-9 12:01

一般情况下可以使用什么驱动WS2812呢
页: [1] 2 3 4
查看完整版本: 【WS2812驱动ch582版】基于CH582使用IO模拟时序驱动WS2812