1、CubeMx配置,时钟部分设置72M 硬件SPI配置为32分频,一个时钟脉冲0.444us,至于其他配置选项随意选 都无所谓 配置DMA传输
根据SW2812的通讯0:高0.4us+低0.85us 1:高0.8us+0.45us 还有150ns允许误差可以理解为:
高0.4us+数据0.4us+低0.45us
SW2812的1bit位对应SPI的3个时钟脉冲,高位在前
发0:数据设置为100
发1:数据设置为110
这样通讯总线直接连接到SPI的MOSI引脚上就行了
对应复位脉冲有的数据手册写的大于50us 有的是大于80us 还有280us 的 我都晕了
实现方法也很简单就是在发送完数据后,SPI再连续发送 复位脉冲**us/0.444us的bit位0数据就行了,因为总线空闲状态为低电平,最一个刷新周期后SPI最后传输的数据位要为0
这样RGB的数据共24位需要缓冲区24bit*3=72bit=9byte
SW2812_RGB_to_buff();这个函数就是将24位颜色按1bit对应3个数据bit写入DMA缓冲区,注意是高位优先传送但是DMA传输是配置的按字节,做好对应关系
下面列出其中的R数据对应关系
SW2812_RGB.RGB_R | 7 | 6 | 5 | 4 | 3 | 2 | 1 19 20 | 0 | ||||||||||||||||
SW2812_SPI_buff | 1 | * | 0 | 1 | * | 0 | 1 | * | 0 | 1 | * | 0 | 1 | * | 0 | 1 | * | 0 | 1 | * | 0 | 1 | * | 0 |
SW2812_SPI_buff | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
初始化值 | 0X24 | 0X49 | 0X92 |
DMA配置循环传输 程序中只需要启动一次就行了 可以选择normal模式 手动启动传输
.h文件代码
#ifndef __SW2812_H
#define __SW2812_H
#include "main.h"
#define SW2812_NUM 16 //配置SW2812的个数
//配置复位脉冲时间长度=1秒/ 2.25Mbits/s * 80byte *8bit=284.44us
//根据数据手册复位脉冲时间可以更改此数据实测最小15运行正常 看来复位脉冲最小是50us
#define RST_Byte 80
//定义颜色RGB结构体
typedef struct
{
uint8_t RGB_R;
uint8_t RGB_G;
uint8_t RGB_B;
}type_color;
void SW2812_Send_Start(void);//启动DMA传输
void SW2812_RGB_to_buff(void);//将RGB数据转换为DMA缓冲区1byte颜色对应3byte数据
void SW2812_Set_color(uint16_t number,uint8_t RGB_R,uint8_t RGB_G,uint8_t RGB_B);//设置颜
void SW2812_Set_TypeDef(uint16_t number ,const type_color * color);//按结构体设置颜色
void SW2812_Display(uint8_t choice);//主函数调用 形参为模式选择
.C 文件代码
#include "main.h"
#include "SPI.h"
#include "RGB_Normal.h"
#include "sw2812.h"
uint8_t SW2812_RGB[SW2812_NUM*3];
uint8_t SW2812_SPI_buff[SW2812_NUM*3*3+RST_Byte];
void SW2812_Send_Start(void)
{
//空闲状态是低电平
HAL_SPI_Transmit_DMA ( &hspi1 ,SW2812_SPI_buff, SW2812_NUM*3*3+RST_Byte);
}
void SW2812_RGB_to_buff(void)
{
uint16_t i;
for(i=0;i<SW2812_NUM*3;i++)
{
SW2812_SPI_buff[i*3] =0x92;//默认SPI输出为0
SW2812_SPI_buff[i*3+1] =0x49;//默认SPI输出为0
SW2812_SPI_buff[i*3+2] =0x24;//默认SPI输出为0
if( (SW2812_RGB[i]&0x01)==0x01) //第0位
SW2812_SPI_buff[i*3+2]|=0x02;
if( (SW2812_RGB[i]&0x02)==0x02) //第1位
SW2812_SPI_buff[i*3+2]|=0x10;
if( (SW2812_RGB[i]&0x04)==0x04) //第2位
{SW2812_SPI_buff[i*3+2]|=0x80;}
if( (SW2812_RGB[i]&0x08)==0x08) //第3位
{SW2812_SPI_buff[i*3+1]|=0x04;}
if( (SW2812_RGB[i]&0x10)==0x10) //第4位
{SW2812_SPI_buff[i*3+1]|=0x20;}
if( (SW2812_RGB[i]&0x20)==0x20) //第5位
{SW2812_SPI_buff[i*3]|=0x01;}
if( (SW2812_RGB[i]&0x40)==0x40) //第6位
{SW2812_SPI_buff[i*3]|=0x08;}
if( (SW2812_RGB[i]&0x80)==0x80) //第7位
{SW2812_SPI_buff[i*3]|=0x40;}
}
}
void SW2812_Set_color(uint16_t number,uint8_t RGB_R,uint8_t RGB_G,uint8_t RGB_B)
{
SW2812_RGB[number*3+0]=RGB_G;
SW2812_RGB[number*3+1]=RGB_R;
SW2812_RGB[number*3+2]=RGB_B;
}
void SW2812_Set_TypeDef(uint16_t number ,const type_color * color)
{
SW2812_RGB[number*3+0]=color->RGB_G;
SW2812_RGB[number*3+1]=color->RGB_R;
SW2812_RGB[number*3+2]=color->RGB_B;
}
void SW2812_Display(uint8_t choice)
{
switch(choice)
{
case 0:{
uint8_t i;
static uint8_t j;
j++;
for(i=0;i<16;i++)
SW2812_Set_TypeDef(i,&RGB_normal[(i+j)%SW2812_NUM]);
}break;
case 1:{
uint8_t i;
static uint8_t j;
j++;
for(i=0;i<16;i++)
SW2812_Set_TypeDef(i,&RGB_NO_light[(i+j)%SW2812_NUM]);
}break;
}
SW2812_RGB_to_buff();//更新到SPI——DMA的缓冲区
}
RGB颜色定义结构体常亮.h文件
#ifndef __RGB_Normal_H
#define __RGB_Normal_H
#include "SW2812.h"
const type_color RGB_normal[]={
{255,0,0}, //0 red,
{255,255,0}, //1 yellow,
{0,255,0}, //2 green,
{0,255,255}, //3 cyan,
{0,0,255}, //4 blue,
{255,0,255}, //5 Brilliant_purple,
{128,0,0}, //6 maroon,
{128,128,0}, //7 olive,
{0,128,0}, //8 Dark_green,
{0,128,128}, //9 turquoise,
{0,0,128}, //10 Dark_blue,
{128,0,128}, //11 purple,
{255,255,255}, //12 white,
{192,192,192}, //13 silver,
{128,128,128}, //14 gray,
{000,128,255}, //16
{000,255,128}, //17
{128,000,255}, //18
{128,128,000}, //19
{0,0,0}, //15 black,
};
const type_color RGB_NO_light[]={
{1,0,0},
{0,1,0},
{1,1,0},
{0,0,1},
{1,0,1},
{0,1,1},
{1,1,1},
{1,0,0},
{0,1,0},
{1,1,0},
{0,0,1},
{1,0,1},
{0,1,1},
{1,1,1},
{1,0,0},
{0,1,0},
{1,1,0},
{0,0,1},
};
#endif
最后一个效果图