WS2812B灯带驱动实验

这篇具有很好参考价值的文章主要介绍了WS2812B灯带驱动实验。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

实验环境:

KEIL5、正点原子阿波罗STM32F767开发板

一、灯带介绍

过多介绍我这里不赘述了,想了解详情的可以看看手册,直接开干。

1.1、灯带连接方式

我们只要控制DIN端就好了。
WS2812B灯带驱动实验

1.2、传输数据方式

简单理解就是单总线发了一串数据,第一个灯拿了第一个字节的数据,第二个灯拿个第二个字节的数据,以此类推。
WS2812B灯带驱动实验

1.3、控制时序

代码就照这个时序写,因为例程中没有没有纳秒级别的延迟函数,所以我们要根据自己芯片去写。
WS2812B灯带驱动实验
我用的晶振是216M,一个 __nop() 计算方式为:1 / 216MHz ≈ 0.0046us = 4.6ns 。
根据这个就可以写纳秒(ns)级别的函数了。

二、程序介绍

2.1、WC2812B.c

/************************************************************
@Description: WS2812B全彩LED灯驱动
***********************************************************/
#include "WS2812B.h"
#include "delay.h"

Color_TypeDef PixelBuf[PIXEL_NUM]; //像数数据
uint8_t flag;
Color_TypeDef	Color_Prar;	
//晶振216M,1/216≈0.004629us=4.6ns
#define delay_4_6ns		__nop()							//1个nop是4.6ns
#define	delay_23ns		delay_4_6ns;delay_4_6ns;delay_4_6ns;delay_4_6ns;delay_4_6ns
#define delay_115ns		delay_23ns;delay_23ns;delay_23ns;delay_23ns;delay_23ns
//T0H
#define delay_391ns		delay_115ns;delay_115ns;delay_115ns;delay_23ns;delay_23ns
//T0L
#define delay_851ns		delay_805ns;delay_23ns;delay_23ns
//T1L
#define delay_460ns		delay_115ns;delay_115ns;delay_115ns;delay_115ns
//T1H
#define delay_805ns		delay_460ns;delay_115ns;delay_115ns;delay_115ns

/*---------------------------------------------------------------------------
@Function   :WS2812B_Init
@Description:初始化
----------------------------------------------------------------------------*/
void WS2812B_Init(void)
{
	GPIO_InitTypeDef GPIO_Initure;
	__HAL_RCC_GPIOB_CLK_ENABLE();           //开启GPIOA时钟
	GPIO_Initure.Pin=WS2812B_PIN;           //PB1
	GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  //推挽输入
	GPIO_Initure.Pull=GPIO_PULLUP;        	//上拉
	GPIO_Initure.Speed=GPIO_SPEED_HIGH;     //高速

	HAL_GPIO_Init(WS2812B_PORT,&GPIO_Initure);
	HAL_GPIO_WritePin(WS2812B_PORT,WS2812B_PIN,GPIO_PIN_SET);	//PB1置1 
}
/*---------------------------------------------------------------------------
@Function   :WS2812B_Reset
@Description:复位
----------------------------------------------------------------------------*/
void WS2812B_Reset(void)          //复位函数
{
	WS2812B_Low();
	delay_us(300);
}

/*---------------------------------------------------------------------------
@Function   :WS2812B_WriteByte
@Description:写一个字节
----------------------------------------------------------------------------*/
void WS2812B_WriteByte(uint8_t dat)
{
	u8 i;
	for (i=0;i<8;i++)
	{
		//先发送高位
		if (dat & 0x80) //1
		{
			WS2812B_Hi();
			delay_805ns; 	//T1H
			WS2812B_Low();	
			delay_460ns; //T1L
		}
		else	//0
		{
			WS2812B_Hi();
			delay_391ns; //T0H
			WS2812B_Low();	
			delay_851ns; //T0L
		}
		dat<<=1;
	}
}

/*---------------------------------------------------------------------------
@Function   :RGB_LED_Write_24Bits
@Description:写入1个24bit颜色数据
----------------------------------------------------------------------------*/
void RGB_LED_Write_24Bits(uint8_t green, uint8_t red, uint8_t blue)
{
    WS2812B_WriteByte(green);
    WS2812B_WriteByte(red);
    WS2812B_WriteByte(blue);
    WS2812B_Reset();
}

/*---------------------------------------------------------------------------
@Function   :RGB_LED_Red
@Description:写入1红色数据
@Input      :无
@Retrun     :无
@Others     :
----------------------------------------------------------------------------*/
void RGB_LED_Red(void)
{
    uint8_t i;
    for (i = 0; i < 1; i++)
    {
        RGB_LED_Write_24Bits(0, 0xff, 0);
    }
}


/*---------------------------------------------------------------------------
@Function   :RGB_LED_Green
@Description:写入1绿色数据
----------------------------------------------------------------------------*/
void RGB_LED_Green(void)
{
    uint8_t i;
    for (i = 0; i < 1; i++)
    {
        RGB_LED_Write_24Bits(0xff, 0, 0);
    }
}

/*---------------------------------------------------------------------------
@Function   :RGB_LED_Blue
@Description:写入1蓝色数据
----------------------------------------------------------------------------*/
void RGB_LED_Blue(void)
{
    uint8_t i;
    for (i = 0; i < 1; i++)
    {
        RGB_LED_Write_24Bits(0, 0, 0xff);
    }
}

/*---------------------------------------------------------------------------
@Function   :WS2812B_WriteColor
@Description:写入1个24bit颜色数据
----------------------------------------------------------------------------*/
void WS2812B_WriteColor(Color_TypeDef *pColor)
{
	WS2812B_WriteByte(pColor->G);
	WS2812B_WriteByte(pColor->R);
	WS2812B_WriteByte(pColor->B);
}

/*---------------------------------------------------------------------------
@Function   :WS2812B_RefreshPixel
@Description:更新显示
@Input      :无
@Retrun     :无
@Others     :
----------------------------------------------------------------------------*/
void WS2812B_RefreshPixel(void)
{
	u8 i;

	for(i=0;i<PIXEL_NUM;i++)
	{
		WS2812B_WriteColor(&PixelBuf[i]);
	}
}
//============================================================================
void Copy_Color(Color_TypeDef *pDst,Color_TypeDef *pScr)
{
	pDst->R = pScr->R;
	pDst->G = pScr->G;
	pDst->B = pScr->B;
}

/*---------------------------------------------------------------------------
@Function   :WS2812B_FillColor
@Description:填充颜色
@Input      :start:开始位置;end:结束信置;pColor:颜色值
@Retrun     :无
@Others     :
----------------------------------------------------------------------------*/
void WS2812B_FillColor(u16 start,u16 end,Color_TypeDef *pColor)
{
	if (start > end) //交换位置
	{
		u16 temp;
		temp = start;
		start = end;
		end = temp;
	}

	if (start >= PIXEL_NUM)return; //超出范围
	if (end >= PIXEL_NUM)end = PIXEL_NUM-1;

	//填充颜色值
	while(start <= end)
	{
		Copy_Color(&PixelBuf[start],pColor);
		start++;
	}
}

/*---------------------------------------------------------------------------
@Function   :WS2812B_All_Blue
@Description:点亮全部灯带显示为蓝色
----------------------------------------------------------------------------*/
void WS2812B_All_Blue(u8 num)
{
	Color_Prar.G = 0x00;
	Color_Prar.R = 0x00;
	Color_Prar.B = 0xff;
	WS2812B_FillColor(0,num,&Color_Prar);	
}
void WS2812B_All_Red(u8 num)	//全红
{
	Color_Prar.G = 0x00;
	Color_Prar.R = 0xff;
	Color_Prar.B = 0x00;
	WS2812B_FillColor(0,num,&Color_Prar);	
}
void WS2812B_All_Green(u8 num)	//全绿
{
	Color_Prar.G = 0xff;
	Color_Prar.R = 0x00;
	Color_Prar.B = 0x00;
	WS2812B_FillColor(0,num,&Color_Prar);	
}

void WS2812B_All_Yellow(u8 num)	//全黄
{
	Color_Prar.G = 0xff;
	Color_Prar.R = 0xff;
	Color_Prar.B = 0x00;
	WS2812B_FillColor(0,num,&Color_Prar);	
}

2.2、WS2812.h

/************************************************************
@Description: WS2812B全彩LED灯驱动
***********************************************************/
#ifndef __WS2812B_H
#define	__WS2812B_H
#include "sys.h"

//WS2812B IO 定义  注意初始化APB时钟也要修改
#define WS2812B_PORT		GPIOB
#define WS2812B_PIN			GPIO_PIN_1
#define WS2812B_RCC_AHB		__HAL_RCC_GPIOB_CLK_ENABLE()           //开启GPIOB时钟

#define WS2812B_Hi()	HAL_GPIO_WritePin(WS2812B_PORT,WS2812B_PIN,GPIO_PIN_SET)	
#define WS2812B_Low()	HAL_GPIO_WritePin(WS2812B_PORT,WS2812B_PIN,GPIO_PIN_RESET)	
//颜色
typedef struct color{
	u8 G;
	u8 R;
	u8 B;
}Color_TypeDef;

//------------------------
#define PIXEL_NUM	60	//LED灯的个数

void WS2812B_Init(void);
void WS2812B_Reset(void);
void WS2812B_WriteColor(Color_TypeDef *pColor);

void RGB_LED_Write_24Bits(uint8_t green, uint8_t red, uint8_t blue);
void RGB_LED_Red(void);
void RGB_LED_Green(void);
void RGB_LED_Blue(void);

void WS2812B_RefreshPixel(void);
void WS2812B_FillColor(u16 start,u16 end,Color_TypeDef *pColor);

void WS2812B_All_Blue(u8 num);
void WS2812B_All_Red(u8 num);
void WS2812B_All_Green(u8 num);
void WS2812B_All_Yellow(u8 num);
#endif 

2.3、KEY.c

#include "key.h"
#include "delay.h"
#include "WS2812B.h"

//按键初始化函数
void KEY_Init(void)
{
    GPIO_InitTypeDef GPIO_Initure;
    
    __HAL_RCC_GPIOA_CLK_ENABLE();           //开启GPIOA时钟
    __HAL_RCC_GPIOC_CLK_ENABLE();           //开启GPIOC时钟
    __HAL_RCC_GPIOH_CLK_ENABLE();           //开启GPIOH时钟
    
    GPIO_Initure.Pin=GPIO_PIN_0;            //PA0
    GPIO_Initure.Mode=GPIO_MODE_INPUT;      //输入
    GPIO_Initure.Pull=GPIO_PULLDOWN;        //下拉
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;     //高速
    HAL_GPIO_Init(GPIOA,&GPIO_Initure);
    
    GPIO_Initure.Pin=GPIO_PIN_13;           //PC13
    GPIO_Initure.Mode=GPIO_MODE_INPUT;      //输入
    GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;     //高速
    HAL_GPIO_Init(GPIOC,&GPIO_Initure);
    
    GPIO_Initure.Pin=GPIO_PIN_2|GPIO_PIN_3; //PH2,3
    HAL_GPIO_Init(GPIOH,&GPIO_Initure);
}

//按键处理函数
//返回按键值
//mode:0,不支持连续按;1,支持连续按;
//0,没有任何按键按下
//1,WKUP按下 WK_UP
//注意此函数有响应优先级,KEY0>KEY1>KEY2>WK_UP!!
u8 KEY_Scan(u8 mode)
{
    static u8 key_up=1;     //按键松开标志
    if(mode==1)key_up=1;    //支持连按
    if(key_up&&(KEY0==0||KEY1==0||KEY2==0||WK_UP==1))
    {
        delay_ms(10);
        key_up=0;
        if(KEY0==0)       return KEY0_PRES;
        else if(KEY1==0)  return KEY1_PRES;
        else if(KEY2==0)  return KEY2_PRES;
        else if(WK_UP==1) return WKUP_PRES;          
    }else if(KEY0==1&&KEY1==1&&KEY2==1&&WK_UP==0)key_up=1;
    return 0;   //无按键按下
}


void KEY_LED_Control(void)
{
	switch(KEY_Scan(0))
	{
		case KEY0_PRES:
		{
			WS2812B_All_Blue(30);
			delay_ms(100);
			WS2812B_RefreshPixel();		//更新显示
		}break;
		case KEY1_PRES:
		{
			WS2812B_All_Red(30);
			delay_ms(100);	
			WS2812B_RefreshPixel();		//更新显示
		}break;
		case KEY2_PRES:
		{
			WS2812B_All_Green(30);
			delay_ms(100);
			WS2812B_RefreshPixel();		//更新显示
		}break;
		case WKUP_PRES:
		{
			WS2812B_All_Yellow(30);
			delay_ms(100);
			WS2812B_RefreshPixel();		//更新显示
		}break;
	}
}

2.4、KEY.h

#ifndef _KEY_H
#define _KEY_H
#include "sys.h"

#define KEY0        HAL_GPIO_ReadPin(GPIOH,GPIO_PIN_3)  //KEY0按键PH3
#define KEY1        HAL_GPIO_ReadPin(GPIOH,GPIO_PIN_2)  //KEY1按键PH2
#define KEY2        HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13) //KEY2按键PC13
#define WK_UP       HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)  //WKUP按键PA0

#define KEY0_PRES 	1
#define KEY1_PRES	2
#define KEY2_PRES	3
#define WKUP_PRES   4

void KEY_Init(void);
u8 KEY_Scan(u8 mode);
void KEY_LED_Control(void);

#endif

2.5、main.c

#include "sys.h"
#include "delay.h"
#include "key.h"
#include "WS2812B.h"

int main(void)
{
    Cache_Enable();                 //打开L1-Cache
    HAL_Init();				        //初始化HAL库
    Stm32_Clock_Init(432,25,2,9);   //设置时钟,216Mhz 
    delay_init(216);                //延时初始化
	KEY_Init();						//按键初始化
	WS2812B_Init();					//灯带控制IO口初始化

    while(1)
    {		
		KEY_LED_Control();	//由此按钮函数控制切换红、绿、蓝、黄四种颜色
	}
}

遇到的问题

灯带是点亮了,也能控制切换,但是,灯带受外部干扰也很强,不控制的情况下,也可能会不受控制的点亮。

文章参考:

闲来无事,搞了条WS2812B全彩灯带玩一下,驱动程序借助以下两篇文章的大佬的程序修改。
https://blog.csdn.net/Lennon8_8/article/details/108980808
https://blog.csdn.net/weixin_53411486/article/details/127246513
做实验前结合这两位仁兄的贴子,感谢两位大佬。

附带代码连接

有遇到相同实验环境的情况的伙伴,也可以直接使用这份代码实验一下。
https://download.csdn.net/download/weixin_41569625/87452923文章来源地址https://www.toymoban.com/news/detail-480018.html

到了这里,关于WS2812B灯带驱动实验的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Nano Framework ESP32篇】WS2812 彩色灯带实验

    地球人皆知,许多物联网教程作者的心中都深爱着一灯大师,所以第一个例程总喜欢点灯,高级一点的会来个“一闪一闪亮晶晶”。老周今天要扯的也是和灯有关的,但不单纯地点个灯,那样实在不好玩,缺乏乐趣。老周打算舞个龙灯,哦不,是用 LED 彩色灯带给伙伴们整点

    2024年04月17日
    浏览(29)
  • 【花雕动手做】ASRPRO语音识别(33)--语音驱动8位 WS2812B直条

    WS2812B芯片 是一个集控制电路与发光电路于一体的智能外控LED光源。其外型与一个5050LED灯珠相同,每个元件即为一个像素点。像素点内部包含了智能数字接口数据锁存信号整形放大驱动电路,还包含有高精度的内部振荡器和12V高压可编程定电流控制部分,有效保证了像素点光

    2024年01月17日
    浏览(21)
  • STM32 HAL库 PWM+DMA 驱动WS2812B彩灯(STM32F030F4P6)

    博主使用STM32驱动WS2812B主要参考了这位佬的文章,因为需求问题,采用了Cortex-M0的stm32f030f4p6(16k的flash,4k的sram)来驱动,原文中写的是stm32f103c8t6,个人认为其实区别并不是很大,需要修改部分参数即可移植(cv战士申请出战)。 上图是我的一圈灯,一共8个,第一个LED的数

    2024年02月06日
    浏览(34)
  • GPIO模拟时序控制外设1——WS2812B

    上一篇文章中介绍了整个板子的最基本功能模块——使用GPIO的通用输入输出实现简单的按键输入以及推挽输出控制的功能。本文深入一步,在只使用GPIO的输入输出功能的基础上,通过查看对应模块的芯片手册,模拟其对应的通信时序来驱动对应的模块。 首先来个网红模块—

    2024年02月12日
    浏览(16)
  • 【Arduino】ESP8266&WS2812S灯带控制

    前言   关于WS2812S灯带的驱动控制时序,网上已经有很多文章介绍过,这里就不在介绍了。这里只是为有WS2812S灯带的时候,能快速应用起来。直接举例代码案例,适合个人笔记用。 目录 下载文件 代码案例 下载文件   左上角点击 工具 ,在下拉的选项中,选 管理库 ,搜

    2024年02月13日
    浏览(16)
  • 【ESP32 IDF】用RMT控制 WS2812 彩色灯带

    在上一篇中,老周用 .NET Nano Framework 给大伙伴们演示了 WS2812 灯带的控制,包括用 SPI 和 红外RMT 的方式。利用 RMT 是一个很机灵的方案,不过,可能很多大伙伴对 ESP32 的 RMT 不是很熟悉。除了乐鑫自己的文档,没几个人写过相关的水文,可见这里头空白的水市场很充足,老周

    2024年04月22日
    浏览(28)
  • STM32例程分享-05-WS2812B灯带(单线归零码)

    例程运行结果:    WS2812B是一款全彩LED控制IC,单总线控制, 灯带上的每一位灯珠都可用编程控制全彩显示,通过单片机,我们可以实现任意数量任意颜色任意组合效果的炫彩灯光显示效果。    数据协议采用单线归零码的通讯方式,像素点在上电复位以后,DIN端接受从控制

    2024年02月11日
    浏览(15)
  • WS2812B彩灯 STM32HAL库开发:PWM+DMA(stm32f103c8t6)

    目录 一、摘要 二、WS2812B介绍 三、CUBEMX配置 四、程序介绍(KEIL编译器) 五、数据手册         1、本文使用示例单片机型号为 stm32f103c8t6 ,RGB型号为 WS2812B ;          2、主要实现功能是实现用 PWM+DMA 使RGB_LED亮起不同颜色的灯光;         3、目的:简单调通该型号

    2024年02月03日
    浏览(19)
  • 【正点原子】STM32F103Core Board系列小实验从零开始(一)安装并激活Keil5、安装芯片支持包

    本文涉及到的所有软件的都在这个百度云链接里面: 链接:https://pan.baidu.com/s/1h-G50SPYcHnRnXnn3dDl-A?pwd=v0a3 提取码:v0a3 右键以 管理员身份 运行mdk514.exe,选择 是 Next 勾选agree,Next 选择安装位置,建议不要安装在C盘,Next 随便乱填,Next 稍等一会 可能会弹出如图的安装界面,选

    2024年02月16日
    浏览(18)
  • 软件STM32cubeIDE下STM32F1xx使用定时器(TIM8)+DMA+PWM点亮灯带WS2812-基础样例

    好长时间不调试灯带ws2812了,最近项目上,要在STM32F1上进行点灯带ws2812,虽然自己之前做了很多了,但是人有个性质,一旦某个事情做完了,你不在去惦记它了,基本会完全抛在脑后。所以才体现记录的重要性,本次在做STM32F1上验证时,即使之前有经验的情况下,还是掉坑

    2024年02月01日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包