当前位置:网站首页>stm32-WS2812 PWM+DMA(自己写库函数)
stm32-WS2812 PWM+DMA(自己写库函数)
2022-08-11 05:24:00 【McuBoy~C】
stm32-WS2812 HAL PWM+DMA库函数
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
边栏推荐
- Introduction of safety helmet wearing recognition system
- mAPH - Waymo dataset
- GBase 8a MPP Cluster产品支撑的平台
- AI智能图像识别的工作原理及行业应用
- Safety helmet identification system - escort for safe production
- CVPR2022——A VERSATILE MULTI-VIEW FRAMEWORK
- >>数据管理:DAMA简介
- 【转载】图表:数读2022年上半年国民经济
- 安全帽识别
- AI-based intelligent image recognition: 4 different industry applications
猜你喜欢
【转载】图表:数读2022年上半年国民经济
Pay “Attention” to Adverse Weather
Redis分布式锁
Waymo数据集使用介绍(waymo-open-dataset)
梅科尔工作室-深度学习第二讲 BP神经网络
CVPR2022——A VERSATILE MULTI-VIEW FRAMEWORK
LiDAR Snowfall Simulation for Robust 3D Object Detection
Wisdom construction site safety helmet identification system
Joint 3D Instance Segmentation and Object Detection for Autonomous Driving
智慧工地 安全帽识别系统
随机推荐
The kernel communicates with user space through character devices
安全帽识别系统-为安全生产保驾护航
websocket聊天通讯(全局封装)
Toward a Unified Model
Toolbar 和 DrawerLayout 滑动菜单
Hardhat Recognition System - Solving Regulatory Conundrums
TAMNet: A loss-balanced multi-task model for simultaneous detection and segmentation
梅科尔工作室-DjangoWeb 应用框架+MySQL数据库第五次培训
GBase 8a MPP Cluster产品高级特性
The latest safety helmet wearing recognition system in 2022
CVPR2022——Not All Points Are Equal : IA-SSD
关于安全帽识别系统,你需要知道的选择要点
AIDL 简介以及使用
安全帽识别
Thread Handler
GBase 8s中IO读写方法
梅科尔工作室-HarmonyOS应用开发第三次培训
Zhejiang University School of Software 2020 Guarantee Research Computer Real Question Practice
浙江大学软件学院2020年保研上机真题练习
AI-based intelligent image recognition: 4 different industry applications