SPI+DMA驱动和控制WS2812彩色RGB灯

简介: SPI+DMA驱动和控制WS2812彩色RGB灯

SPI+DMA驱动和控制WS2812彩色RGB灯

SPI+DMA驱动WS2812

比赛的能量机关,官方的灯条是SK6812灯珠,每米144个灯珠,但是真的贵(

最后还是选用了WS2811灯珠。

很恶心的一点是,WS2811的逻辑0和1表达示方式这部分,网上好多图都是不对的,一定要以数据手册为准... 如果逻辑0和逻辑1的发送时序不对,那么整个灯条的颜色都是乱的甚至根本不会亮

ws28121

ws28122

ws28123

先放一段QA吧

Q1: 像这种一根信号线输出控制的逻辑电平一般都要求5V及以上,需要3.3V升5V吗

A1: STM32虽然只能输出3.3V,但是控WS2811是可以的。另外3.3V升到5V,三极管或是MOS管的信号上升时间相对而言太长了,跟不上控制信号的变化,导致几乎输不出信号

Q2: 直接用IO口翻转可以控制吗

A2: 不太行。用封装库函数翻转IO的执行速度,很难满足几百ns到1us级别的时间要求,虽然可以直接操作寄存器,但即使是对着示波器一点点测试NOP空指令的个数,也只是一种时序近似。随着灯条长度的加长和信号发送时间的推移,总会出现逻辑0和1的误识别的情况

Q3: FreeRTOS 会影响控制的时序吗

A3: 配上稍高一些的任务优先级,使用SPI+DMA不会影响

Q4: 一条总线能控多少灯

A4: 测试一条SPI+DMA控了1920个灯珠也依旧能正常控制,更多的灯珠没设备了也就没测。只要时序对了理论上是能控制无限个的

控制方式

单总线,通过总线上高低电平时间长短的不同来区分0和1。

WS2811的工作频率为800KHz,如果将SPI的频率设置为6.4MHz,正好是灯条IC芯片的8倍,那么每一个字节(8位)正好对应一个逻辑位,也就是11110000代表逻辑1,11000000代表逻辑0

不过协议也有150ns的兼容性。比如SPI设置为5.25MBits/s(Mbps)(84MHz时钟线16分频据线是8Bits),一Bit的发送时间为1/5.25=190ns一个字节约1.52us。所以可以通过SPI的MOSI输出信号线发送一个字节Byte(8Bits)的数据模拟 WS2812的一个位。所以发送一个uint8字节0xF8(11111000),高电平时间为5x190=950ns在580ns-1us范围之间,代表逻辑1;0x80(10000000),高电平时间为190ns接近220ns-380ns范围,代表逻辑0

CubeMX 配置

  • 开启 SPI1,因为只用到了MOSI输出信号线,所以模式选择Transmit Only Master 仅发送主模式 就可以。

    • Data Size 设置为 8 Bits。理由是因为上面的控制方式
    • CPHA 设置为 2 Edge。跳变沿为1时,MOSI空闲电平为高电平。跳变沿设置为2时,会延续上次发送的最后电平,因为发送数据的末尾都是低电平,这样 WS2812 不会误判
    • CPOL 设置为 High。总线空闲时SCK的时钟状态为高电平
  • 开启 DMA。Mode设置为Normal,由程序触发DMA发送即可。

程序

#define LED_NUM 64    // LED灯珠个数

// 模拟bit码: 0x80为逻辑0, 0xF8为逻辑1
const uint8_t code[]={0x80,0xF8};

typedef struct {
  uint8_t R;
  uint8_t G;
  uint8_t B;
}RGBColor_TypeDef;    //颜色结构体

// 常见颜色定义
const RGBColor_TypeDef RED = {255, 0, 0};
const RGBColor_TypeDef BLUE = {0, 0, 255};

// 灯颜色缓存
RGBColor_TypeDef RGB_Data[LED_NUM] = {0};

/**
  * @brief            设置灯带颜色发送缓存
  * @param[in]        ID 颜色
  */
void Set_LEDColor(uint16_t LedId, RGBColor_TypeDef Color)
{
    RGB_Data[LedId].G = Color.G;
    RGB_Data[LedId].R = Color.R;
    RGB_Data[LedId].B = Color.B;
}

/**
  * @brief            SPI发送控制ws2812
  * @param[in]        待发送缓存
  */
static void SPI_Send_WS2812(uint8_t *SPI_RGB_BUFFER)
{
    // 判断上次DMA有没有传输完成
    while(HAL_DMA_GetState(&hdma_spi1_tx) != HAL_DMA_STATE_READY);
    // 发送一个24bit的RGB数据
    HAL_SPI_Transmit_DMA(&hspi1, SPI_RGB_BUFFER, 24);
}

/**
  * @brief            控制WS2812
  * @param[in]        待发送缓存
  */
void RGB_Reflash(void)
{
    static uint8_t RGB_BUFFER[24]={0};
    uint8_t dat_b,dat_r,dat_g;
    // 将数组颜色转化为24个要发送的字节数据
    for (uint16_t i = 0; i < LED_NUM; i++) {
        dat_g = RGB_DAT[i].G;
        dat_r = RGB_DAT[i].R;
        dat_b = RGB_DAT[i].B;
        for (uint16_t j = 0; j < 8; j++) {
            RGB_BUFFER[7-j] =code[dat_g & 0x01];
            RGB_BUFFER[15-j]=code[dat_r & 0x01];
            RGB_BUFFER[23-j]=code[dat_b & 0x01];
            dat_g >>=1;
            dat_r >>=1;
            dat_b >>=1;
        }
        SPI_Send_WS2812(RGB_BUFFER);
    }
}
目录
相关文章
|
Linux 网络安全 开发工具
python更换版本
python更换版本
763 1
|
JavaScript Linux
linux安装pm2全过程
你要在linux上安装pm2有很多方法,但我是用node的工具npm来完成安装的,所以在安装pm2之前需要先安装node
5073 1
|
7月前
|
芯片
基于模拟I2C协议驱动SD3078时钟芯片
基于模拟I2C协议驱动SD3078时钟芯片
|
Linux 网络安全 开发工具
【开发工具】【windows】Visual Studio Code(VS Code)远程Linux服务器环境搭建——SFTP篇
【开发工具】【windows】Visual Studio Code(VS Code)远程Linux服务器环境搭建——SFTP篇
1879 0
【开发工具】【windows】Visual Studio Code(VS Code)远程Linux服务器环境搭建——SFTP篇
|
9月前
|
Ubuntu 安全 Linux
Ubuntu 24.04.1版全新安装与初体验揭秘
那么,这样的更替,是否意味着未来的Ubuntu会更加人性化?我们在科技发展的同时,也许更向往的是那份纯粹与简约。或许,许多人期待着新版本都是为了体验更好的性能和更为简洁的界面,但最终,我们都会发现,真正触动我们心灵的,仍然是那份简单易用的初心。就像诗人所说,“生活的精髓在于细节”,而这些细节,就藏在你我日常使用中。
|
移动开发 网络协议 数据格式
【VOFA+速成】半小时入门VOFA+简明教程之基础认识(一)
【VOFA+速成】半小时入门VOFA+简明教程(一)
5736 1
|
自然语言处理 数据挖掘 API
淘宝直播间弹幕 API 接口(淘宝 API 系列)
淘宝直播间弹幕API助力电商直播数据分析与优化。通过实时获取弹幕信息(昵称、内容、时间、类型),商家可精准把握消费者需求,优化直播内容;开发者可构建数据分析工具和智能客服系统。接口采用WebSocket协议,支持全双工通信,确保数据实时性。请求需包含直播间ID(room_id),并遵循平台使用规范。示例代码展示了Python调用方法,需安装`websocket-client`库并处理重连与异常。
1058 6
|
存储 Java 开发者
HashSet和TreeSet教你重新认识Java集合的无序与有序
【10月更文挑战第14天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了它们分别实现无序和有序存储的机制。通过理解HashSet基于哈希表的无序特性和TreeSet利用红黑树实现的有序性,帮助开发者更好地选择合适的集合类型以满足不同的应用场景。
405 2
|
存储 安全
电脑怎么格式化清除所有数据
在出售、捐赠或维修电脑之前或需要处理敏感数据时,格式化硬盘并彻底清除所有数据还是很有必要的。本篇文章将详细介绍如何安全、彻底地格式化你的电脑。
电脑怎么格式化清除所有数据
|
消息中间件 算法 调度
FreeRTOS 任务调度和任务的状态
FreeRTOS 任务调度和任务的状态
FreeRTOS 任务调度和任务的状态