WS2811/WS2812 驱动灯带

本文介绍使用华大HC32F460主控芯片通过SPI接口驱动WS2812b/W2811灯带的方法。详细讲解了SPI配置过程及DMA传输实现,并提供了完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文分享一下如何实现灯带 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);
}












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值