这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 企业专区 » Renesas » 瑞萨RA0单片机连载之十一——SPI驱动WB2812B

共2条 1/1 1 跳转至

瑞萨RA0单片机连载之十一——SPI驱动WB2812B

助工
2024-06-14 06:50:14     打赏

【前言】

WS2812B是一种数字可编程LED灯条,也被称为NeoPixel。它由RGB(红、绿、蓝)三种颜色的LED组成,并集成了控制电路和信号处理功能。每个WS2812B LED都有一个唯一的地址,并可以通过单个数据线进行串联连接。

WS2812B具有以下特点:

高度可编程性:每个LED可以独立地设置颜色和亮度,因此可以实现各种动态效果和彩色变化。

简单的控制接口:WS2812B使用单个数据线进行通信,通过发送特定的序列来控制每个LED的颜色和亮度。

低功耗:WS2812B采用高效的LED驱动技术,具有较低的功耗,适合电池供电的应用。

灵活的应用:WS2812B可广泛应用于室内装饰、灯光艺术、电子产品原型设计等领域,具有丰富的创意空间和应用场景。

【引脚图】

101image.png

  • 当然,在使用的过程中,我们往往会使用不止一个LED灯,会将多个灯级联成灯带或者灯板,我们这次使用的就是灯板。

具体级联方式如下:

image.png

其中DIN作为数据的输入端,每个LED需要24位数据控制,多出的数据会通过DOUT引脚传递给下一个LED,以此类推,当WS2812接收到280us以上的低电平时,数据被写入LED,灯的颜色改变。

image.png

以下是数据的表示方法:

image.png

此次我采用SPI的方式来驱动。SPI的时钟调整为8MHz,发送一字节正好是1.25us,给ws2812发送0即通过SPI总线发送11000000b,发送1即通过SPI总线发送11111100b,非常巧妙的一种方式。

根据以上原理,我先配置SPI的stack如下:

image.png

经查看原理图,配置SPI的MOSI为P101。

生成工程后,编写代码ws2812b.c如下:

#include "ws2812.h"

static uint8_t spidate[SPIBUFL] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  \

0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,  \

0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,  \

0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8,  \

0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8,  \

0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8,  \

0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,  \

0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8,  \

0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8, 0xf8,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,  \

0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8, 0xf8,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,  \

0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8, 0xf8,  \

0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8, 0xf8,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8, 0xf8,  \

0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8, 0xf8,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8, 0xf8,  \

0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8, 0xf8,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8, 0xf8,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,  \

0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8, 0xf8,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8, 0xf8,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8, 0xf8,  \

0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8, 0xf8, 0xf8,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8, 0xf8, 0xf8,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8, 0xf8, 0xf8,  \

0xc0, 0xc0, 0xc0, 0xc0, 0xf8, 0xf8, 0xf8, 0xf8,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xf8, 0xf8, 0xf8, 0xf8,  \
0xc0, 0xc0, 0xc0, 0xc0, 0xf8, 0xf8, 0xf8, 0xf8
};

void ws2812Init(void)
{
R_SAU_SPI_Open(&g_spi0_ctrl, &g_spi0_cfg);

}

void show(void)
{
R_SAU_SPI_Write(&g_spi0_ctrl, spidate, SPIBUFL, SPI_BIT_WIDTH_8_BITS);
R_BSP_SoftwareDelay(80, BSP_DELAY_UNITS_MICROSECONDS);
}

void clear(void)
{
memset(& spidate[NUMRES], 0xc0, (NUMPIXELS) * 3 * 8);
}

void setPixelColor(uint16_t n, uint8_t g, uint8_t r, uint8_t b)
{
if (n < NUMPIXELS) {
uint8_t *p;
p = &spidate[NUMRES + n * 24];
for(uint8_t i = 0; i < 8; i++)
{
*(p + i) = (0 == (g & (1 << (7 - i)))) ? 0xc0 : 0xf8;
}
for(uint8_t i = 0; i < 8; i++)
{
*(p + i + 8) = (0 == (r & (1 << (7 - i)))) ? 0xc0 : 0xf8;
}
for(uint8_t i = 0; i < 8; i++)
{
*(p + i + 16) = (0 == (b & (1 << (7 - i)))) ? 0xc0 : 0xf8;
}
}
}

ws18b20c.h:

#ifndef WS2812_H_
#define WS2812_H_
#include "hal_data.h"

#define NUMPIXELS   (8)
#define NUMRES      (60)
#define SPIBUFL     ((NUMPIXELS) * 3 * 8 + NUMRES)

void ws2812Init(void);
void show(void);
void clear(void);
void setPixelColor(uint16_t n, uint8_t g, uint8_t r, uint8_t b);

#endif /* WS2812_H_ */

在主函数中添加测测试代码如下:

void sau_spi_callback(spi_callback_args_t *p_args)
{
    (void)p_args;
    /* TODO: add your own code here */
}

/*******************************************************************************************************************//**
 * main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used.  This function
 * is called by main() when no RTOS is used.
 **********************************************************************************************************************/
void hal_entry(void)
{
    /* TODO: add your own code here */
    ws2812Init();

            while(1)
            {
                clear();

                for(uint8_t i = 0; i < NUMPIXELS; i++)
                {
                    setPixelColor(i, i*8+2, i*2, i*15);
                    show();
                    R_BSP_SoftwareDelay(50, BSP_DELAY_UNITS_MILLISECONDS);
                }

            }


#if BSP_TZ_SECURE_BUILD
    /* Enter non-secure code */
    R_BSP_NonSecureEnter();
#endif
}

代码的主要思路是,将写入buff先清零,然后向数据中写信指定个数的RGB数据,最后刷新到spi总线之中。

【工程效果】





关键词: 刘工爱评测之瑞萨RA0单片机     WS2812B    

高工
2024-06-14 12:51:44     打赏
2楼

谢谢分享


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]