通过SPI+DMA控制WS2812

文章详细介绍了如何使用STM32CubeMX配置SPI和DMA来控制WS2812灯珠,包括选择芯片型号、配置时钟、设置SPI和DMA参数,以及计算合适的SPI频率。同时,文章给出了C代码示例,展示了如何设置单个LED颜色、SPI_DMA发送和不同颜色显示功能,并提供了渐变色彩的实现方法。
摘要由CSDN通过智能技术生成

通过SPI+DMA控制WS2812

一、STM32CubeMX配置

1、在Clion 中新建项目并,并给其项目命名,然后选中STM32CubeMX,最后点击Create

0

2、打开STM32CuMX搜索其对应的芯片型号

1

3、选择HSE使用外部晶振

3

4、打开SYS选择SW

在这里插入图片描述

5、打开Clock Configuration进行配置

在这里插入图片描述

6、给工程命名,(注使用Clion的朋友们,这个工程名一定要和最开始在Clion中创建的要一致,并且在Toolchain/IDE中选择STM32CubeIDE,最后要注意工程位置),而使用KEIL的朋友在Toolchain/IDE中选择MDK-ARM即可

在这里插入图片描述

7、在Code Generator勾上第一个,这样使得各个部分的初始化生成在对于的.c和.h文件,否则会将其初始化全部生成在main.c文件中

7

8、配置SPI,具体如图,频率选择看SPI频率选择

在这里插入图片描述

9、配置DMA,具体如图

在这里插入图片描述

10、最后点击GENERATE COOD

在这里插入图片描述

二、SPI频率选择

0码和1码

T0H0码,高电平时间0.40us 加减150ns
T1H1码,高电平时间0.85us 加减150ns
T0L0码,低电平时间0.85us 加减150ns
T1L1码,低电平时间0.40us 加减150ns
RES帧单位,低电平时间50us以上

不管是 0 码 还是 1 码 ,其时间都约等于1.25u(0.40us.+0.85=1.25us),我们选择SPI发生8位,则1.25u / 8=0.15625us,即每一位等于0.15625us

频率=1/周期

频率=1/0.15625us=6.4M

即SPI频率设置为6.4M,

但是0.4us和0.85us都可以加减0.15us

故频率可以在1/[(1.25-0.3)/8]=8.4M,1/[(1.25+0.3)/8]=5.2M之间都可以,当然越接近6.4越好

因此我们在时钟树选择48MHz,得到SPI发送频率为6M,比较接近6.4M

三、程序设计

1、c文件代码如下

#include "ws2812.h"

#define    LED_NUMS   56//灯的数量

#define CODE1  0xf0//1码
#define CODE0  0xc0//0码

uint8_t BLACK[3] = { 0,0,0};
uint8_t RED[3]   = {30,0,0};
uint8_t GREEN[3] = {0,30,0};
uint8_t BLUE[3]  = {0,0,30};
uint8_t LED_BUFFER[24*LED_NUMS + 10];

extern SPI_HandleTypeDef hspi1;

//单个LED颜色设置,即将单个灯的颜色转换成对应的0码和1码
void RGB_Set_Color(uint8_t ID,uint8_t color[3])
{
    int i=0;
    for (i = 0; i < 8; i++) { //green
        LED_BUFFER[ID*24+i] = ((color[1] << i) & 0x80) ? CODE1 : CODE0;
    }
    for (i = 0; i < 8; i++) { //red
        LED_BUFFER[ID*24+8+i] = ((color[0] << i) & 0x80) ? CODE1 : CODE0;
    }
    for (i = 0; i < 8; i++) { //blue
        LED_BUFFER[ID*24+16+i] = ((color[2] << i) & 0x80) ? CODE1 : CODE0;
    }
}

//SPI_DMA发送
void RGB_Reflash(uint8_t reflash_num)
{
    HAL_SPI_Transmit_DMA(&hspi1, LED_BUFFER, 24*reflash_num);
}

//全部黑色,可用于初始化将其所有灯熄灭
void RGB_BLACK(uint8_t RGB_LEN)
{
    for(int i=0;i<RGB_LEN;i++)
    {
        RGB_Set_Color(i,BLACK);
        RGB_Reflash(RGB_LEN);
    }
}
//全部红色
void RGB_RED(uint8_t RGB_LEN)
{
    for(int i=0;i<RGB_LEN;i++)
    {
        RGB_Set_Color(i,RED);
        RGB_Reflash(RGB_LEN);
    }
}
//全部绿色
void RGB_GREEN(uint8_t RGB_LEN)
{
    for(int i=0;i<RGB_LEN;i++)
    {
        RGB_Set_Color(i,GREEN);
        RGB_Reflash(RGB_LEN);
    }
}
//全部蓝色
void RGB_BLUE(uint8_t RGB_LEN)
{
    for(int i=0;i<RGB_LEN;i++)
    {
        RGB_Set_Color(i,BLUE);
        RGB_Reflash(RGB_LEN);
    }
}

//渐变
void ws2812_1(uint16_t RGB_LEN,int speed,float light)
{
    if(light==0)
        light=1;
    for(int j=0;j<12;j++)//A
    {
        uint8_t My_color[3]={32/light ,3*j/light  ,  0};
        RGB_Set_Color(j,My_color);
    }

    for(int j=12;j<20;j++)//B
    {
        uint8_t My_color[3]={(32-4*(j-12))/light ,32/light  ,  0};
        RGB_Set_Color(j,My_color);
    }

    for(int j=20;j<28;j++)//C
    {
        uint8_t My_color[3]={0 ,32/light  ,  4*(j-20)/light};
        RGB_Set_Color(j,My_color);
    }

    for(int j=28;j<36;j++)//D
    {
        uint8_t My_color[3]={0 ,(32-4*(j-28))/light  ,  32/light};
        RGB_Set_Color(j,My_color);
    }

    for(int j=36;j<46;j++)//E
    {
        uint8_t My_color[3]={3*(j-36)/light ,0  ,  30/light};
        RGB_Set_Color(j,My_color);
    }

    for(int j=46;j<56;j++)//F
    {
        uint8_t My_color[3]={30/light ,0  ,  30-3*(j-46)/light};
        RGB_Set_Color(j,My_color);
    }
    uint8_t My_color[3]={ 0 ,30/light  , 0 };
    RGB_Set_Color(LED_NUMS,My_color);
    RGB_Reflash(RGB_LEN);
    HAL_Delay (speed);
}

2、h文件代码如下

#ifndef __WS2812_H__
#define __WS2812_H__
#include "spi.h"

#ifdef __cplusplus
extern "C" {
#endif
//单个LED颜色设置,即将单个灯的颜色转换成对应的0码和1码
void RGB_Set_Color(uint8_t ID,uint8_t color[3]);
    
void RGB_Reflash(uint8_t reflash_num);//SPI_DMA发送

void RGB_BLACK(uint8_t RGB_LEN);//全部黑色,可用于初始化将其全部熄灭
void RGB_RED(uint8_t RGB_LEN);  //全部红色
void RGB_GREEN(uint8_t RGB_LEN);//全部绿色
void RGB_BLUE(uint8_t RGB_LEN); //全部蓝色

//渐变light=[0.12,8]  light通过比例来调节亮度
void ws2812_1(uint16_t RGB_LEN, int speed,float light);

3、在main中调用函数 ws2812_1(56,100,1);即可,最终效果如图
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值