STM32C0开发(1)----SPI 驱动WS2812灯珠

发布时间:2024-09-23  

概述

本文介绍了如何使用STM32微控制器,结合STM32CubeMX配置工具和SPI通讯接口,来驱动和控制WS2812 LED灯带。这是一个集硬件连接、软件配置和编程开发于一体的综合性项目,目标是实现对LED灯带颜色和亮度的精确控制。

在这里插入图片描述

视频教学

[https://www.bilibili.com/video/BV1X94y157W8/

样品申请

[https://www.wjx.top/vm/OhcKxJk.aspx#]
在这里插入图片描述

源码下载

[https://download.csdn.net/download/qq_24312945/88489586

芯片级联方法

在这里插入图片描述

芯片在上电复位以后,接收DIN端打来的数据,接收够24bit后,DO端口开始转发数据,供下一个芯片提供输入数据。在转发之前,DO口一直拉低。此时灯珠将不接收新的数据,内置RGB芯片根据接收到的24bit数据后产生的不同占空比信号,展现不同亮度。如果DIN端输入信号为RESET信号,芯片将接收到的数据送显示,芯片将在该信号结束后重新接收新的数据,在接收完开始的24bit数据后,通过DO口转发数据,灯珠在没有接收到RESET码前,RGB亮度保持不变,当接收到80us以上低电平RESET码后,灯珠内部RGB芯片将根据刚才接收到的24bit数据后产生的不同占空比信号,展现不同亮度。

在这里插入图片描述

数据传输

在这里插入图片描述
24bit数据结构:

在这里插入图片描述

时序

时序波形图如下所示。

在这里插入图片描述
在这里插入图片描述

SPI配置

将SPI的配置速度设为6M,数据宽度设为8位。
CPHA配置为第二边沿采样;在第一个跳变沿时,MOSI在空闲状态保持高电平,而在第二个跳变沿,它会保持上一次传输的最终电平。由于发送数据的最后一位总是低电平,这样配置可以避免WS2812误判。CPOL设置为高,确保SCK在空闲时保持高电平状态。

在这里插入图片描述

系统采用单总线协议,通过总线上高低电平的时长来区分逻辑0和1。WS2811工作在800kHz频率下,将SPI设置为6.4MHz—即其工作频率的8倍—可以确保每个字节(8位)正好对应一个逻辑位。在这种设置下,‘11111000’(0xF8)代表逻辑1,‘11000000’(0xC0)代表逻辑0。

在这里插入图片描述

逻辑0下发送的数据为11000000’(0xC0)。
逻辑0下高电平位320ns。

在这里插入图片描述

逻辑0下低电平位1.01us。

在这里插入图片描述

逻辑1下发送的数据为‘11111000’(0xF8)。
逻辑1下高电平位830ns。

在这里插入图片描述
逻辑1下低电平位500ns。
在这里插入图片描述

这种精确的时序配置和电平控制对于确保WS2812灯带的正确驱动至关重要,可以通过上述配置来优化SPI接口的性能,确保与WS2812的高效通信。

CPHA配置

CPHA配置为第二边沿采样下数据传输结束如下所示。

在这里插入图片描述
CPHA配置为第二边沿采样下数据传输结束如下所示。

在这里插入图片描述

由于RESET Code为低电平,且要大于80us,所以数据传输完毕必须为低电平。

在这里插入图片描述

代码

在main.c中添加头文件。


/* USER CODE BEGIN Includes */

#include 'ws2812.h'

#include < string.h >

/* USER CODE END Includes */

在main.c中添加函数申明和移位操作。


/* USER CODE BEGIN 0 */

extern tWs2812bCache_TypeDef gWs2812bDat[WS2812B_AMOUNT];


void move_Front()

{

uint8_t i;

uint8_t temp[3];

temp[0] = gWs2812bDat[0].R;

temp[1] = gWs2812bDat[0].G;

temp[2] = gWs2812bDat[0].B;

for (i = 0; i < WS2812B_AMOUNT-1; i++)

{

gWs2812bDat[i].R = gWs2812bDat[i+1].R;

gWs2812bDat[i].G = gWs2812bDat[i+1].G;

gWs2812bDat[i].B = gWs2812bDat[i+1].B;

}

gWs2812bDat[7].R = temp[0];

gWs2812bDat[7].G = temp[1];

gWs2812bDat[7].B = temp[2];

}



/* USER CODE END 0 */

添加初始化显示。


/* USER CODE BEGIN 2 */

WS2812B_Task();

HAL_Delay(1000);

  /* USER CODE END 2 */

添加流水灯。


/* Infinite loop */

  /* USER CODE BEGIN WHILE */

  while (1)

  {

WS2812B_Task();

move_Front();

HAL_Delay(100);

    /* USER CODE END WHILE */


    /* USER CODE BEGIN 3 */

  }

  /* USER CODE END 3 */

ws2812.c

#include 'ws2812.h'

#include 'spi.h'


//灯条显存SPI数据缓存

uint8_t gWs2812bDat_SPI[WS2812B_AMOUNT * 24] = {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[(Ws2b812b_NUM) * 24 + 8];

uint8_t *pG = &gWs2812bDat_SPI[(Ws2b812b_NUM) * 24];

uint8_t *pB = &gWs2812bDat_SPI[(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;

//将gWs2812bDat数据解析成SPI数据

for(uint8_t iLED = 0; iLED < WS2812B_AMOUNT; iLED++)

{

WS2812b_Set(iLED, gWs2812bDat[iLED].R, gWs2812bDat[iLED].G, gWs2812bDat[iLED].B);

}

//总线输出数据

HAL_SPI_Transmit(&hspi1, gWs2812bDat_SPI, sizeof(gWs2812bDat_SPI),0XFFFF);

//使总线输出低电平

HAL_SPI_Transmit(&hspi1, &dat, 1,0XFFFF);

//帧信号:一个大于50us的低电平

HAL_Delay(1);

}

ws2812.h

#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


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>