当前位置:网站首页>stm32-WS2812 PWM+DMA(自己写库函数)

stm32-WS2812 PWM+DMA(自己写库函数)

2022-08-11 05:24:00 McuBoy~C

stm32-WS2812 HAL PWM+DMA库函数

查看Github项目

CubeMx配置如下:

1、选择72M时钟

2、选择外部晶振

3、选择调试方式

4、选择定时器3 PWM 通道1输出 (记住接线:PA6--->WS2812_DATA_IN)DMA配置:内存到外设,内存地址自增加,(数据为Byte)

5、根据上面选择进行修改配置头文件:

文件:mylib_ws28xx.h

#ifndef MYLIB_WS28XX
#define MYLIB_WS28XX

/****************************************
*Include
****************************************/
#include "tim.h"			//定时器句柄
//如果需要移植,更改这个 __show() 驱动以及对应的数据结构即可

/****************************************
*Config
****************************************/
#define BIT_1                   61 			//1比较值为61-->850us
#define BIT_0                   28 			//0比较值为28-->400us

#define PIXEL_SIZE							6
#define WS28xx_PWM_hTIMER				htim3
#define WS28xx_PWM_Chaneel      TIM_CHANNEL_1		


/****************************************
*数据结构
****************************************/

#define HSV_H_MAX 				360
#define HSV_H_MIN 				1

#define HSV_S_MAX 				1
#define HSV_S_MIN 				0.6				//0.6保证能显示基本颜色(而不会变白色失真)

#define HSV_V_MAX 				1
#define HSV_V_MIN 				0.005
//整个WS28xx_DataTypeStruct结构体将被以PWM方式发送
typedef struct
{
						//3个0等待PWM稳定
	unsigned char ColorStartData[3];
						//实际GRB数据(已经转换为PWM对应的值)
	unsigned char ColorRealData[24*PIXEL_SIZE*8];
						//结束位为0
	unsigned char ColorEndData;
}WS28xx_DataTypeStruct;

/****************************************
*对象化编程
****************************************/
typedef struct 
{
	//实际发送的数据
	WS28xx_DataTypeStruct WS28xx_Data;
	//灯数量
	unsigned short int Pixel_size;
	
	
//单独设置index的RGB颜色
void (*SetPixelColor_RGB)(unsigned short int index,unsigned char r,unsigned char g,unsigned char b);
//从RGB数据读出:设置index的RGB颜色
void (*SetPixelColor_From_RGB_Buffer)( unsigned short int pixelIndex,unsigned char pRGB_Buffer[][3],unsigned short int DataCount);
//设置所有为RGB颜色
void (*SetALLColor_RGB)(unsigned char r,unsigned char g,unsigned char b);
//获取某个位置的RGB
void (*GetPixelColor_RGB)(unsigned short int index,unsigned char *r,unsigned char *g,unsigned char *b);
	

	
// **************************************** HSV空间设置 ****************************************
//单独设置index的HSV颜色																									--->>改变HSV
void (*SetPixelColor_HSV)(unsigned short int index,unsigned short int h,float s,float v);
	
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!以下操作在原来颜色基础上做改变
//设置某个位置的HSV色相(Hue)(1~~360)																		--->>也就是颜色(逆时针)
//SetPixelColor_HSV_H注意该函数,如果一开始
void (*SetPixelColor_HSV_H)(unsigned short int pixelIndex,unsigned short int light);
//设置某个位置的HSV饱和度(Saturation)(0.6~~1)													--->>色彩纯净度
void (*SetPixelColor_HSV_S)(unsigned short int pixelIndex,float light);
//设置某个位置的HSV明度(Value)(0.005~~1)																--->>也就是亮度
void (*SetPixelColor_HSV_V)(unsigned short int pixelIndex,float light);

//设置所有HSV色相(1~~360)			       																			--->>也就是颜色(逆时针)
void (*SetALLColor_HSV_H)(unsigned short int setH);
//设置所有HSV饱和度(0.01~~1)																			   			--->>色彩纯净度
void (*SetALLColor_HSV_S)(float setS);
//设置所有明度/亮度(0.01~~1)																							--->>也就是亮度
void (*SetALLColor_HSV_V)(float setV);
//显示(发出数据)
void (*show)(void);
}WS28xx_TypeStruct;

extern WS28xx_TypeStruct WS28xx;


void	WS28xx_TypeStructInit(void);


/*
*工具函数
*/
#define LIMIT(x,max,min) ((x<max )? ((x>min )? x:min):max)
#define MAX(a,b,c) (a>b?a:b>c?b:c)
#define MIN(a,b,c) (a<b?a:b<c?b:c)
void RGB2HSV(unsigned char r, unsigned char g, unsigned char b, float *h, float *s, float *v);
void HSV2RGB(float h, float s, float v, unsigned char *r, unsigned char *g, unsigned char *b);
#endif

文件:mylib_ws28xx.c

#include "../Inc/mylib_ws28xx.h"

WS28xx_TypeStruct WS28xx;
//如果需要移植官方库函数,更改这个 __show() 驱动即可
void __show()
{
	HAL_TIM_PWM_Start_DMA(&WS28xx_PWM_hTIMER,WS28xx_PWM_Chaneel,(uint32_t *)(&WS28xx.WS28xx_Data),sizeof(WS28xx.WS28xx_Data));
}

		
//设置index的颜色
void __SetPixelColor_RGB(unsigned short int index,unsigned char r,unsigned char g,unsigned char b)
{
	unsigned char j;
	if(index > WS28xx.Pixel_size)
		return;
	for(j = 0; j < 8; j++)
	{
		//G
		WS28xx.WS28xx_Data.ColorRealData [24 * index + j]     = (g & (0x80 >> j)) ? BIT_1 : BIT_0; //将高位先发
		//R
		WS28xx.WS28xx_Data.ColorRealData [24 * index + j + 8]     = (r & (0x80 >> j)) ? BIT_1 : BIT_0; //将高位先发
		//B
		WS28xx.WS28xx_Data.ColorRealData [24 * index + j + 16]     = (b & (0x80 >> j)) ? BIT_1 : BIT_0; //将高位先发
	}
}
//获取某个位置的RGB
void __GetPixelColor_RGB(unsigned short int index,unsigned char *r,unsigned char *g,unsigned char *b)
{
	unsigned char j;
	*r=0;
	*g=0;
	*b=0;
	if(index > WS28xx.Pixel_size)
		return;
	for(j = 0; j <8; j++)
	{
		//G
		(*g)|=((WS28xx.WS28xx_Data.ColorRealData [24 * index + j] >=BIT_1)?  0x80>>j:0);
		//R
		(*r)|=((WS28xx.WS28xx_Data.ColorRealData [24 * index + j + 8] >=BIT_1)? 0x80>>j:0);
		//B
		(*b)|=((WS28xx.WS28xx_Data.ColorRealData [24 * index + j + 16] >=BIT_1)? 0x80>>j:0);
	}
}
//读取RGB缓存数据,并且设置颜色例如下面数据
/*unsigned char RGB[x][3]={
{r1,g1,b2},
{r1,g1,b2},
{r1,g1,b2}};
*/
void __SetPixelColor_From_RGB_Buffer( unsigned short int pixelIndex,unsigned char pRGB_Buffer[][3],unsigned short int DataCount)
{
	unsigned short int Index,j=0;
	for(Index=pixelIndex;Index < WS28xx.Pixel_size; Index++)
	{
			WS28xx.SetPixelColor_RGB(Index,pRGB_Buffer[j][0],pRGB_Buffer[j][1],pRGB_Buffer[j][2]);
			j++;
			if(j>DataCount)
				return;
	}
}

//设置所有颜色
void __SetALLColor_RGB(unsigned char r,unsigned char g,unsigned char b)
{
	unsigned short int Index;
	for(Index=0;Index < WS28xx.Pixel_size; Index++)
	{
		WS28xx.SetPixelColor_RGB(Index,r,g,b);
	}
}

void RGB2HSV(unsigned char r, unsigned char g, unsigned char b, float *h, float *s, float *v)
{
  float red, green ,blue;
  float cmax, cmin, delta;
  
  red = (float)r / 255;
  green = (float)g / 255;
  blue = (float)b / 255;
  
  cmax = MAX(red, green, blue);
  cmin = MIN(red, green, blue);
  delta = cmax - cmin;

  /* H */
  if(delta != 0)
  {
    if(cmax == red)
    {
			*h= green >= blue ? 60 * ((green - blue) / delta): 60 * ((green - blue) / delta) + 360;
    }
    else if(cmax == green)
    {
      *h = 60 * ((blue - red) / delta + 2);
    }
    else if(cmax == blue) 
    {
      *h = 60 * ((red - green) / delta + 4);
    }
  }else
  {
    *h = 0;
  }
  /* S */
	*s=cmax?delta / cmax:0;
  /* V */
  *v = cmax;
}
  
void HSV2RGB(float h, float s, float v, unsigned char *r, unsigned char *g, unsigned char *b)
{
    int hi = ((int)h / 60) % 6;
    float f = h * 1.0 / 60 - hi;
    float p = v * (1 - s);
    float q = v * (1 - f * s);
    float t = v * (1- (1 - f) * s);
    switch (hi){
        case 0:
            *r = 255 * v;
            *g = 255 * t;
            *b = 255 * p;
            break;
        case 1:
            *r = 255 * q;
            *g = 255 * v;
            *b = 255 * p;
            break;
        case 2:
            *r = 255 * p;
            *g = 255 * v;
            *b = 255 * t;
            break;
        case 3:
            *r = 255 * p;
            *g = 255 * q;
            *b = 255 * v;
            break;
        case 4:
            *r = 255 * t;
            *g = 255 * p;
            *b = 255 * v;
            break;
        case 5:
            *r = 255 * v;
            *g = 255 * p;
            *b = 255 * q;
            break;
    }
}
//单独设置index的RGB颜色
void __SetPixelColor_HSV(unsigned short int pixelIndex,unsigned short int h,float s,float v)
{
	unsigned char r,g,b;
	h = LIMIT(h,HSV_H_MAX,HSV_H_MIN);
	s = LIMIT(s,HSV_S_MAX,HSV_S_MIN);
	v = LIMIT(v,HSV_V_MAX,HSV_V_MIN);
	HSV2RGB(h, s, v, &r, &g, &b);
	WS28xx.SetPixelColor_RGB(pixelIndex,r,g,b);
}
void __SetPixelColor_HSV_H(unsigned short int pixelIndex,unsigned short int setH)
{
	unsigned char r,g,b;
	float h,s,v;
	WS28xx.GetPixelColor_RGB(pixelIndex,&r,&g,&b);
	RGB2HSV(r,g,b, &h, &s, &v);
	h = LIMIT(setH,HSV_H_MAX,HSV_H_MIN);
	s = LIMIT(s,HSV_S_MAX,HSV_S_MIN);
	v = LIMIT(v,HSV_V_MAX,HSV_V_MIN);
	HSV2RGB(h, s, v, &r, &g, &b);
	WS28xx.SetPixelColor_RGB(pixelIndex,r,g,b);
}


void __SetPixelColor_HSV_S(unsigned short int pixelIndex,float setS)
{
	unsigned char r,g,b;
	float h,s,v;
	WS28xx.GetPixelColor_RGB(pixelIndex,&r,&g,&b);
	RGB2HSV(r,g,b, &h, &s, &v);
	h = LIMIT(h,HSV_H_MAX,HSV_H_MIN);
	s = LIMIT(setS,HSV_S_MAX,HSV_S_MIN);
	v = LIMIT(v,HSV_V_MAX,HSV_V_MIN);
	HSV2RGB(h, s, v, &r, &g, &b);
	WS28xx.SetPixelColor_RGB(pixelIndex,r,g,b);
}
void __SetPixelColor_HSV_V(unsigned short int pixelIndex,float setV)
{
	unsigned char r,g,b;
	float h,s,v;
	WS28xx.GetPixelColor_RGB(pixelIndex,&r,&g,&b);
	RGB2HSV(r,g,b, &h, &s, &v);
	h = LIMIT(h,HSV_H_MAX,HSV_H_MIN);
	s = LIMIT(s,HSV_S_MAX,HSV_S_MIN);
	v = LIMIT(setV,HSV_V_MAX,HSV_V_MIN);
	HSV2RGB(h, s, v, &r, &g, &b);
	WS28xx.SetPixelColor_RGB(pixelIndex,r,g,b);
}


void __SetALLColor_HSV_H(unsigned short int setH)
{
	unsigned short int Index;
	for(Index=0;Index < WS28xx.Pixel_size; Index++)
	{
		WS28xx.SetPixelColor_HSV_H(Index,setH);
	}
}
void __SetALLColor_HSV_S(float setS)
{
	unsigned short int Index;
	for(Index=0;Index < WS28xx.Pixel_size; Index++)
	{
		WS28xx.SetPixelColor_HSV_S(Index,setS);
	}
}
void __SetALLColor_HSV_V(float setV)
{
	unsigned short int Index;
	for(Index=0;Index < WS28xx.Pixel_size; Index++)
	{
		WS28xx.SetPixelColor_HSV_V(Index,setV);
	}
}

void	WS28xx_TypeStructInit()
{
	WS28xx.Pixel_size=PIXEL_SIZE;
	WS28xx.GetPixelColor_RGB=__GetPixelColor_RGB;
	WS28xx.SetPixelColor_From_RGB_Buffer=__SetPixelColor_From_RGB_Buffer;
	WS28xx.SetPixelColor_RGB=__SetPixelColor_RGB;
	WS28xx.SetALLColor_RGB=__SetALLColor_RGB;
	//HSV空间设置
	WS28xx.SetPixelColor_HSV=__SetPixelColor_HSV;
	WS28xx.SetPixelColor_HSV_H=__SetPixelColor_HSV_H;
	WS28xx.SetPixelColor_HSV_S=__SetPixelColor_HSV_S;
	WS28xx.SetPixelColor_HSV_V=__SetPixelColor_HSV_V;
	WS28xx.SetALLColor_HSV_H=__SetALLColor_HSV_H;
	WS28xx.SetALLColor_HSV_S=__SetALLColor_HSV_S;
	WS28xx.SetALLColor_HSV_V=__SetALLColor_HSV_V;
	WS28xx.show=__show;
}

引入头文件:

#include "../mylib/Inc/mylib_ws28xx.h"

在main初始化调用:

#include "../Inc/mylib_ws28xx_test.h"

void read_RGB_Buffer()
{
	uint8_t rgb[][3]={
	{0xFF,0,0},
	{0,0xFF,0},
	{0,0,0xFF},
	{0,0,0xFF},
	{0,0xFF,0},
	{0xFF,0,0},
	};
	uint8_t r,g,b;
	WS28xx.SetPixelColor_From_RGB_Buffer(0,rgb,6);
	WS28xx.show();
	HAL_Delay(500);
	WS28xx.GetPixelColor_RGB(1,&r,&g,&b);
	WS28xx.SetPixelColor_RGB(3,r,g,b);
	WS28xx.show();
	HAL_Delay(500);
}
void HSV_test()
{
	uint16_t h=0,index=0;
	float v=0,s=0;
	
	WS28xx.SetALLColor_HSV_V(0.4);
	for(h=0;h<360;h+=20)
	{
		WS28xx.SetPixelColor_HSV_H(index++%WS28xx.Pixel_size,h);
		WS28xx.show();
		HAL_Delay(300);
	}
	
	for(s=0.6;s<1;s+=0.05)
	{
		WS28xx.SetALLColor_HSV_S(s);
		WS28xx.show();
		HAL_Delay(200);
	}
	for(v=0;v<1;v+=0.05)
	{
		WS28xx.SetALLColor_HSV_V(v);
		WS28xx.show();
		HAL_Delay(200);
	}
}

void WS2812_test()
{
	read_RGB_Buffer();
	HSV_test();
}
int main(void)
{
  /* USER CODE BEGIN 1 */
  /* USER CODE END 1 */
  

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_TIM3_Init();
  /* USER CODE BEGIN 2 */
	WS28xx_TypeStructInit();//初始化

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  { 
     WS2812_test();
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

最终目录文件:

效果图如下:


GitHub项目链接:https://github.com/Jim-Chenming/stm32-WB2812

 

 

 

 

原网站

版权声明
本文为[McuBoy~C]所创,转载请带上原文链接,感谢
https://blog.csdn.net/cjmsd/article/details/114102222