Files
ESHL/Driver/ws2812b.c
2025-07-22 22:23:55 +08:00

131 lines
3.6 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//
// Created by E_LJF on 25-7-10.
//
#include "ws2812b.h"
#include <stdlib.h>
#include "string.h"
#define DATA_LEN 24 // WS2812数据长度单个需要24个字节
/**
* 函数WS2812单灯设置函数
* 参数which:灯的位置R、G、B分别为三个颜色通道的亮度最大值为255
* 作用单独设置每一个WS2812的颜色
***/
void WS2812_Set(WS2812B_OBJ_T* ws2812b,uint16_t which,uint8_t R,uint8_t G,uint8_t B)
{
which = (which > ws2812b->num) ? ws2812b->num : which;
uint32_t indexx=(which *DATA_LEN);
for (uint8_t i = 0;i < 8;i++)
{
//填充数组
ws2812b->rgb_buff[indexx+i] = (G << i) & (0x80)?WS_H:WS_L;
ws2812b->rgb_buff[indexx+i + 8] = (R << i) & (0x80)?WS_H:WS_L;
ws2812b->rgb_buff[indexx+i + 16] = (B << i) & (0x80)?WS_H:WS_L;
}
}
//WS2812初始化函数
//返回 0 初始化成功
//返回 1 初始化失败
uint8_t WS2812_Init(
WS2812B_OBJ_T* ws2812b, //WS2812B对象
TIM_HandleTypeDef *htim,//使用的定时器
uint32_t Channel, //定时器通道
uint16_t num //灯珠数量
)
{
uint8_t retn = 1;
ws2812b->htim = htim;
ws2812b->Channel = Channel;
ws2812b->num = num;
ws2812b->rgb_buff = (uint16_t*)malloc((ws2812b->num*DATA_LEN+WS2812_RST_NUM) * sizeof(uint16_t) );
if (ws2812b->rgb_buff != NULL) {
retn = 0;
//清空显存
memset(ws2812b->rgb_buff,0,(ws2812b->num*DATA_LEN+WS2812_RST_NUM) * sizeof(uint16_t));
//设置关闭所有灯
for(int i=0;i<8;i++)
{
WS2812_Set(ws2812b,i, 0, 0, 0);
}
//作用调用DMA将显存中的内容实时搬运至定时器的比较寄存器
HAL_TIM_PWM_Start_DMA(ws2812b->htim,ws2812b->Channel,(uint32_t *)ws2812b->rgb_buff,(ws2812b->num*DATA_LEN+WS2812_RST_NUM));
}
return retn;
}
//删除WS2812b对象
void WS2812_OBJ_DEL(WS2812B_OBJ_T* ws2812b) {
WS2812_SetAll(ws2812b,0,0,0);
free(ws2812b->rgb_buff);
}
//关闭WS2812b对象
void WS2812_DISABLE(WS2812B_OBJ_T* ws2812b) {
WS2812_SetAll(ws2812b,0,0,0);
HAL_TIM_PWM_Stop_DMA(ws2812b->htim,ws2812b->Channel);
}
//重新开启WS2812b对象
void WS2812_ENABLE(WS2812B_OBJ_T* ws2812b) {
HAL_TIM_PWM_Start(ws2812b->htim,ws2812b->Channel);
}
//设置所有灯珠颜色
//R,G,B为对应的RGB通道值
void WS2812_SetAll(WS2812B_OBJ_T* ws2812b,uint8_t R,uint8_t G,uint8_t B) {
for (uint16_t j = 0;j < ws2812b->num;j++) {
uint32_t indx = j * DATA_LEN;
for (uint8_t i = 0;i < 8;i++)
{
//填充数组
ws2812b->rgb_buff[indx+i] = (G << i) & (0x80)?WS_H:WS_L;
ws2812b->rgb_buff[indx+i + 8] = (R << i) & (0x80)?WS_H:WS_L;
ws2812b->rgb_buff[indx+i + 16] = (B << i) & (0x80)?WS_H:WS_L;
}
}
}
//点亮指定片段的灯珠
//from 起始位置
//to 末位置
//rgb_arr[] RGB数组,数组内容为[R1,G1,B1 , R2,G2,B2......]
void WS2812_SetFromTo(WS2812B_OBJ_T* ws2812b,uint16_t from,uint16_t to,uint8_t rgb_arr[]) {
if (from > to) {
uint16_t buff = from;
from = to;
to = buff;
}
to = (to > ws2812b->num) ? ws2812b->num : to;
uint16_t num = 0;
for (uint16_t j = from;j < (to + 1);j++) {
uint32_t indx = j * DATA_LEN;
for (uint8_t i = 0;i < 8;i++)
{
//填充数组
ws2812b->rgb_buff[indx+i] = (rgb_arr[num + 1] << i) & (0x80)?WS_H:WS_L;
ws2812b->rgb_buff[indx+i + 8] = (rgb_arr[num] << i) & (0x80)?WS_H:WS_L;
ws2812b->rgb_buff[indx+i + 16] = (rgb_arr[num + 2] << i) & (0x80)?WS_H:WS_L;
}
num += 3;
}
}