本帖最后由 eew_cT3H5d 于 2024-7-23 23:58 编辑
先看效果:
WS2812B-5050是一个集控制电路与发光电路于一体的智能外控LED光源;其外型采用最新的molding封装工艺,将IC与发光芯片封装在一个5050的封装尺寸中,每个元件即为一个像素点;像素点内部包含了智能数字接口数据锁存信号整形放大驱动电路,还包含有高精度的内部振荡器和可编程定电流控制部分,有效保证了像素点光的颜色高度一致。
它能显示RGB三原色组合成的颜色显示灯,封装为5050,有四个引脚,分别是VCC、VSS、DIN、DOUT . 它的控制协议非常简单,通过一根信号线就可以进行串行异步信号发送
WS2812的级联控制协议是非常简单的。在串行通讯中使用不同高低电平脉冲表示数据0,1编码。通过发送三组24bit的编码,可以控制三个级联的WS2812灯的颜色。每组24bit对应的GRB编码如下所示。发送颜色顺序为GRB,字节的高位在前
WS2812驱动芯片采用单线归零码的通讯方式,芯片在上电复位以后,DIN端接收从控制器传输过来的数据。首先送过来的24 bit数据被第一个芯片提取后,送到芯片内部的数据锁存器。剩余的数据经过内部整形处理电路整形放大后,通过DO端口开始转发输入给下一个级联的芯片,每经过一个芯片的传输,信号减少24 bit。芯片采用自动整形转发技术,使得该芯片的级联个数不受信号传送的限制,仅仅受限信号传输速度要求。
驱动波形逻辑分析仪测试:
逻辑分析仪波形显示:
瑞萨RA8D1通过SPI总线控制ws2812
第一步:在上一个工程继续添加SPI驱动模块
配置SPI通道,通过配置通道3可以直接将SPI引脚P309、P311、P310这样直接通过开发板的引出排针引脚直接接入ws2812
经查询将SPI的配置速度设为7.5M,相关时钟可以为60Mhz或者120Mhz
配置系统时钟,采用内部时钟,相关时钟配置120Mhz
第二步:添加ws2812底层驱动库
ws2812.c文件
/*
* ws2812.c
*
* Created on: 2023年10月31日
* Author: Administrator
*/
#include <WS2812/ws2812.h>
#include "hal_data.h"
extern fsp_err_t err ;
extern volatile bool g_transfer_complete ;
//灯条显存SPI数据缓存
uint8_t gWs2812bDat_SPI[WS2812B_AMOUNT * 24+88] = {0};
//灯条显存
tWs2812bCache_TypeDef gWs2812bDat[WS2812B_AMOUNT] = {
//R G B
0XFF, 0X00, 0X00, //0
0X00, 0XFF, 0X00, //1
0X00, 0X00, 0XFF, //2
0X00, 0XFF, 0XFF, //3
0XFF, 0X00, 0XFF, //4
0XFF, 0XFF, 0X00, //5
0XFF, 0XFF, 0XFF, //6
0X00, 0X00, 0X00, //7
};
void WS2812b_Set(uint16_t Ws2b812b_NUM, uint8_t r,uint8_t g,uint8_t b)
{
uint8_t *pR = &gWs2812bDat_SPI[88+(Ws2b812b_NUM) * 24 + 8];
uint8_t *pG = &gWs2812bDat_SPI[88+(Ws2b812b_NUM) * 24];
uint8_t *pB = &gWs2812bDat_SPI[88+(Ws2b812b_NUM) * 24 + 16];
for(uint8_t i = 0; i < 8; i++) {
if(g & 0x80) {
*pG = CODE_1;
}
else {
*pG = CODE_0;
}
if(r & 0x80) {
*pR = CODE_1;
}
else {
*pR = CODE_0;
}
if(b & 0x80) {
*pB = CODE_1;
}
else {
*pB = CODE_0;
}
r <<= 1;
g <<= 1;
b <<= 1;
pR++;
pG++;
pB++;
}
}
void WS2812B_Task(void)
{
uint8_t dat = 0;
for(int i=0;i<88;i++)
{
gWs2812bDat_SPI[i]=0;
}
//将gWs2812bDat数据解析成SPI数据
for(uint8_t iLED = 0; iLED < WS2812B_AMOUNT; iLED++)
{
WS2812b_Set(iLED, gWs2812bDat[iLED].R, gWs2812bDat[iLED].G, gWs2812bDat[iLED].B);
}
//总线输出数据
/* Send the reset command */
g_transfer_complete = false;
err = R_SCI_B_SPI_Write(&g_sci_spi3_ctrl, gWs2812bDat_SPI, sizeof(gWs2812bDat_SPI), SPI_BIT_WIDTH_8_BITS);
assert(FSP_SUCCESS == err);
/* Wait for SPI_EVENT_TRANSFER_COMPLETE callback event. */
while ( g_transfer_complete==false)
{
;
}
// //使总线输出低电平
// g_transfer_complete = false;
// err = R_SCI_SPI_Write(&g_spi0_ctrl, dat, 1, SPI_BIT_WIDTH_8_BITS);
// assert(FSP_SUCCESS == err);
// /* Wait for SPI_EVENT_TRANSFER_COMPLETE callback event. */
// while ( g_transfer_complete==false)
// {
// ;
// }
//帧信号:一个大于50us的低电平
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MILLISECONDS);
}
ws2812.h文件
/*
* ws2812.h
*
* Created on: 2023年10月31日
* Author: Administrator
*/
#ifndef _WS2812_H_
#define _WS2812_H_
#include <stdint.h>
// 编码 0 : 11000000
#define CODE_0 0xc0
// 编码 1 : 11111000
#define CODE_1 0xF8
/*ws2812b灯珠数量*/
#define WS2812B_AMOUNT 8
typedef struct
{
uint8_t R;
uint8_t G;
uint8_t B;
} tWs2812bCache_TypeDef;
extern tWs2812bCache_TypeDef gWs2812bDat[WS2812B_AMOUNT];
void WS2812b_Set(uint16_t Ws2b812b_NUM, uint8_t r,uint8_t g,uint8_t b);
void WS2812B_Task(void);
#endif /* WS2812_H_ */
这个是主程序运行代码,让ws2812显示不同颜色
第三步:进行编译程序
第四步:程序运行效果:成功点亮ws2812全彩LED,SPI驱动一次性成功
视频演示:
ws2812
参考来源:
1.https://blog.csdn.net/qq_24312945/article/details/134152211
2.https://bbs.eeworld.com.cn/thread-1267092-1-1.html