WS2811/WS2812 驱动灯带

本文分享一下如何实现灯带 WS2812b/W2811的驱动代码
主控芯片:华大HC32F460
灯带驱动芯片:WS2812b/W2811

1.WS2812b/W2811芯片产品概述&引脚排序

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
![在这里插入图片描述](https://img-blog.csdnimg.cn/7c889ae7010c4b7ebe8c302b8cb943b9.png

时序波形&数据格式:
在这里插入图片描述
在这里插入图片描述

驱动方式:
1.发送reset信号;
2.将数据按24bit(8bit red,8bit green,8bit blue)每盏灯,依次发送,速度为800Kbps

主控芯片驱动WS2811/WS2812的接口有很多种,常见的有
1.普通IO
2.SPI

本文使用的是SPI方式,需要将SPI速度与WS2811/WS2812速度匹配(800Kbps

2.代码

#include <stdint.h>
#include <string.h>

#define zero 0b11000000
#define one  0b11111000

#define SPI_SCK_PORT                    (PortA)//grop1
#define SPI_SCK_PIN                     (Pin07)
#define SPI_SCK_FUNC                    (Func_Spi1_Sck)

/* SPI_NSS Port/Pin definition */
#define SPI_NSS_PORT                    (PortA)//grop1
#define SPI_NSS_PIN                     (Pin12)
#define SPI_NSS_FUNC                    (Func_Spi1_Nss0)

/* SPI_MOSI Port/Pin definition */
#define SPI_MOSI_PORT                   (PortA) //grop1
#define SPI_MOSI_PIN                    (Pin02)
#define SPI_MOSI_FUNC                   (Func_Spi1_Mosi)

/* SPI_MISO Port/Pin definition */
#define SPI_MISO_PORT                   (PortA)//grop1
#define SPI_MISO_PIN                    (Pin11)
#define SPI_MISO_FUNC                   (Func_Spi1_Miso)

typedef struct
{
	uint8_t red;
	uint8_t green;
	uint8_t blue;
}ws2812b_color;

//传输一次WS2812灯带数据格式
typedef struct
{
    uint8_t head[3];				//reset
    uint8_t GRB[FRAME_BYTES];
	uint8_t tail;					//传输完后为低电平
} ws2812_stu;

ws2812_stu color_buff =
{
    .head[0] = 0,
    .head[1] = 0,
    .head[2] = 0,
    .tail = 0
};

void ws2812_spi1_Init(void)
{
    stc_spi_init_t stcSpiInit;

    /* configuration structure initialization */
    MEM_ZERO_STRUCT(stcSpiInit);

    /* Configuration peripheral clock */
    PWC_Fcg1PeriphClockCmd(PWC_FCG1_PERIPH_SPI1, Enable);

    /* Configuration SPI pin */
    PORT_SetFunc(SPI_SCK_PORT, SPI_SCK_PIN, SPI_SCK_FUNC, Disable);
    PORT_SetFunc(SPI_NSS_PORT, SPI_NSS_PIN, SPI_NSS_FUNC, Disable);
    PORT_SetFunc(SPI_MOSI_PORT, SPI_MOSI_PIN, SPI_MOSI_FUNC, Disable);
    PORT_SetFunc(SPI_MISO_PORT, SPI_MISO_PIN, SPI_MISO_FUNC, Disable);

    /* Configuration SPI structure */
    stcSpiInit.enClkDiv = SpiClkDiv16;  //16(16703IC对应是16分配,2811IC对应8分频)
    stcSpiInit.enFrameNumber = SpiFrameNumber1;
    stcSpiInit.enDataLength = SpiDataLengthBit8;
    stcSpiInit.enFirstBitPosition = SpiFirstBitPositionMSB;
    stcSpiInit.enSckPolarity = SpiSckIdleLevelLow;
    stcSpiInit.enSckPhase = SpiSckOddSampleEvenChange;
    stcSpiInit.enReadBufferObject = SpiReadReceiverBuffer;
    stcSpiInit.enWorkMode = SpiWorkMode4Line;
    stcSpiInit.enTransMode = SpiTransFullDuplex;
    stcSpiInit.enCommAutoSuspendEn = Disable;
    stcSpiInit.enModeFaultErrorDetectEn = Disable;
    stcSpiInit.enParitySelfDetectEn = Disable;
    stcSpiInit.enParityEn = Disable;
    stcSpiInit.enParity = SpiParityEven;

    stcSpiInit.enMasterSlaveMode = SpiModeMaster;
    stcSpiInit.stcDelayConfig.enSsSetupDelayOption = SpiSsSetupDelayCustomValue;
    stcSpiInit.stcDelayConfig.enSsSetupDelayTime = SpiSsSetupDelaySck1;
    stcSpiInit.stcDelayConfig.enSsHoldDelayOption = SpiSsHoldDelayCustomValue;
    stcSpiInit.stcDelayConfig.enSsHoldDelayTime = SpiSsHoldDelaySck1;
    stcSpiInit.stcDelayConfig.enSsIntervalTimeOption = SpiSsIntervalCustomValue;
    stcSpiInit.stcDelayConfig.enSsIntervalTime = SpiSsIntervalSck6PlusPck2;
    stcSpiInit.stcSsConfig.enSsValidBit = SpiSsValidChannel0;
    stcSpiInit.stcSsConfig.enSs0Polarity = SpiSsLowValid;
	
    SPI_Init(M4_SPI1, &stcSpiInit);
}

void ws2812_spi_dma_config(void)
{
    stc_dma_config_t stcDmaCfg;

    /* configuration structure initialization */
    MEM_ZERO_STRUCT(stcDmaCfg);

    /* Configuration peripheral clock */
    PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_DMA1, Enable);
    PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_AOS, Enable);

    /* Configure TX DMA */
    stcDmaCfg.u16BlockSize = 1u;
    stcDmaCfg.u16TransferCnt = FRAME_BYTES;
    stcDmaCfg.u32SrcAddr = (uint32_t)color_buff.GRB;
    stcDmaCfg.u32DesAddr = (uint32_t)(&M4_SPI1->DR);
    stcDmaCfg.stcDmaChCfg.enSrcInc = AddressIncrease;
    stcDmaCfg.stcDmaChCfg.enDesInc = AddressFix;
    stcDmaCfg.stcDmaChCfg.enTrnWidth = Dma8Bit;
    stcDmaCfg.stcDmaChCfg.enIntEn = Disable;
    DMA_InitChannel(M4_DMA1, DmaCh1, &stcDmaCfg);

    DMA_SetTriggerSrc(M4_DMA1, DmaCh1, EVT_SPI1_SPTI);

    /* Enable DMA. */
    DMA_Cmd(M4_DMA1, Enable);
}


void ws2812_spi_transmit_dma( ws2812b_color buffer[], uint16_t len) //提取spi发送
{
    int  transmit_len = 0;

    for(i = 0; i < len; i++)
    {
        uint8_t j = 0;

		//RED
		for(int8_t k = 7; k >= 0; k--)
		{
			if(((uint8_t)(buffer[i].red) & (1 << k)) == 0)
				color_buff.GRB[i * 24 + j] = zero;
			else
				color_buff.GRB[i * 24 + j] = one;

			j++;
		}

		//BLUE
		for(int8_t k = 7; k >= 0; k--)
		{
			if(((uint8_t)(buffer[i].blue) & (1 << k)) == 0)
				color_buff.GRB[i * 24 + j] = zero;
			else
				color_buff.GRB[i * 24 + j] = one;

			j++;
		}

		//GREEN
		for(int8_t k = 7; k >= 0; k--)
		{
			if(((uint8_t)(buffer[i].green) & (1 << k)) == 0)
				color_buff.GRB[i * 24 + j] = zero;
			else
				color_buff.GRB[i * 24 + j] = one;

			j++;
		}
	}
    transmit_len = len * 24 + 4;
	
    DMA_SetSrcAddress(M4_DMA1, DmaCh1, (uint32_t)color_buff.GRB);
    DMA_SetTransferCnt(M4_DMA1, DmaCh1, transmit_len);
    DMA_ChannelCmd(M4_DMA1, DmaCh1, Enable);
    SPI_Cmd(M4_SPI1, Enable);

    while (Reset == DMA_GetIrqFlag(M4_DMA1, DmaCh1, TrnCpltIrq))
    {
    }

    DMA_ClearIrqFlag(M4_DMA1, DmaCh1, TrnCpltIrq);
    SPI_Cmd(M4_SPI1, Disable);
}












  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于STM32的WS2812灯带驱动是一种通过STM32微控制器来控制WS2812灯带的方法。WS2812是一种数字可编程RGB LED灯带。与传统的RGB LED灯带相比,WS2812具有更高的亮度、更丰富的颜色以及更灵活的控制方式。 在实现基于STM32的WS2812灯带驱动时,首先需要将STM32与WS2812灯带连接起来。通常使用的连接方式是通过单线串行通信协议(比如WS2812协议)连接。这需要将STM32的单个IO口与WS2812灯带的DIN(数据输入)引脚相连。 然后,需要在STM32上编程实现WS2812灯带的控制逻辑。首先,需要配置STM32的GPIO引脚为输出模式,并设置输出频率以满足WS2812的通信速率要求。 接下来,在STM32的程序中,通过发送一系列特定的数据序列来控制WS2812灯带的颜色。这些数据序列包含灯带的控制命令和对应的RGB颜色值。通常,每个WS2812灯珠需要24位数据来表示RGB颜色。 在程序中,首先通过STM32的GPIO口向WS2812灯带发送重置信号,然后按照一定的时序和数据格式发送数据,实现对灯带的亮灭和颜色控制。发送数据时,需要按照一定的协议将数据转换为对应的电平信号,并严格控制信号的时序。 通过不断发送数据,可以实现对WS2812灯带的各种控制效果,如单色、多色和动态变化等。 综上所述,基于STM32的WS2812灯带驱动是一种利用STM32微控制器通过串行通信协议控制WS2812灯带的方法。通过在STM32上编程实现相应的控制逻辑和数据传输,可以实现对WS2812灯带的各种颜色和亮度控制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值