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_R; SW2812_RGB[number*3+1]=RGB_G; 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_R; SW2812_RGB[number*3+1]=color->RGB_G; 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
最后一个效果图