STM32HAL库+SPI+DMA驱动SW2812

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_R7654321
19
20
0
SW2812_SPI_buff1*01*01*01*01*01*01*01*0
SW2812_SPI_buff23222120191817161514131211109876543210
初始化值0X240X490X92

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

最后一个效果图

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_43175613

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值