利用stm32f103c8t6实现对WS2812的控制(从硬件出发)

代码思路(IO翻转模拟时序方法)

目录

所用IO资源 电路图

STM32CUBEMX配置

延时函数思路

代码部分


所用IO资源 电路图

调试所用开发板开源平台链接(含原理图,PCB)https://oshwhub.com/jhx275816/stm32f103c8t6-zui-xiao-xi-tong-ban

PB8 为串行数据线(连WS2812)

PB9 为三极管基极(连蜂鸣器)

PC13为调试指示灯(低电平有效)

STM32CUBEMX配置

GPIO设置(基于开头所述 电路图)

时钟树配置(系统时钟72mhz)

 WS2812数据手册部分

数据传输时间(TH+TL=1.25μs±600ns)

T0H 0码高电平时间 0.35μs ± 150ns
T0L 0码低电平时间 0.8μs ± 150ns
T1H 1码高电平时间 0.7μs ± 150ns
T1L 1码低电平时间 0.6μs ± 150ns
RES帧单位 低电平时间 50μs以上

 一定时间的高电平 + 一定时间的低电平 = WS2812承认的一位信号

延时函数思路

在keil的C代码里,可以用__NOP()【两个下划线】产生一个有nop效果的指令

因为系统时钟72mhz,所以一个__nop()=1/72 us。(实测波形中第二个高电平持续时间和理论趋于一致)

接下来仍需要构建一个函数,实测N=1时,延时330-360ns之间(第一个高电平时间为N=2,延时约750ns)

void delay_ns(u32 nus)//n=1 330-360ns
	{
	for(int i=0;i<nus;i++)
		__nop();
}

代码部分

要使用单片机控制一个WS2812b灯珠要给它发送24bit的数据,这24bit的数据就是灯珠的RGB值,不过发送的时候要按照GRB的顺序来发送。

24bit数据格式:

G7 G6 G5 G4 G3 G2 G1 G0 R7 R6 R5 R4 R3 R2 R1 R0 B7 B6 B5 B4 B3 B2 B1 B0

我们把24bit数据分为三次发送 先构建一个发 8bit 函数

void RGB_WriteByte(u8 in_data){
	uint8_t n = 0;
	uint8_t y = 0,z = 0;
		n = in_data;
		for(y = 0;y < 8;y++){
			z = ((n<<y)&0x80);
			if(z){
				HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);
				delay_ns(2);
				HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
				__nop();// 1码

			}else{    
				HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);
				__nop();    //
				HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
				delay_ns(2);// 0码 
			}
		}
}

分三次发送(注意是RGB,该函数改变了GRB这个难受的发送方式)

// 设置一个灯的颜色
void RGB_ColorSet(u8 red,u8 green,u8 blue)
{
	// 灯的实际写入颜色是GRB
	RGB_WriteByte(green);  // 写入绿色
	RGB_WriteByte(red); // 写入红色
	RGB_WriteByte(blue); // 写入蓝色
}

放在while里

        RGB_ColorSet(0x00,0x00,0xff);	
		RGB_ColorSet(0xff,0x00,0xff);
		RGB_ColorSet(0x00,0xff,0x00);
		RGB_ColorSet(0xff,0xff,0x00);	
		
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
		delay_ns(500);// 大于280us的低电平过来,然后才会将刚刚发送过来的24bit数据应用到灯上 
		
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);//关闭
		
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
		HAL_Delay(500);//作为送数据结束标志
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
		HAL_Delay(500);

IO翻转时序法代码链接https://download.csdn.net/download/qq_44125275/86875749

最后效果图

2022.11.9更新(完善代码架构)

test-stm32-ws2812-IO-2022.11.9.7z

/* USER CODE BEGIN PV */
uint8_t rgb_data[24] = {0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0X00,0XFF,0XFF};
/* USER CODE END PV */
/* USER CODE BEGIN PFP */
	
//IO模拟时序延时
void delay_ns(u32 nus)//n=1 330ns
	{
	while(nus--);
}
//RGB解算并发送
void send_code(u8 * sdata){    //
	uint8_t n = 0,j=0;
	uint8_t x = 0,y = 0,z = 0;
	for(j = 0;j < led_number;j++)
	{
		for(x = 0;x < 3;x++)
		{        //
			n = sdata[x];
				for(y = 0;y < 8;y++)
				{
					z = ((n<<y)&0x80);
					if(z)
						{
						HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);
						delay_ns(7);        
						HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
						delay_ns(1);    //
						}
					else
						{
						HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);
						delay_ns(1);
						HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
						delay_ns(7);
						}
				}
		}
  }
}
//自定义颜色
void colorset(u8 i)
{
	switch(i)
	{
		case 0:
				 send_code(&rgb_data[0]);//所有灯清零
					break;
		case 1:
					send_code(&rgb_data[3]);//所有灯变红灯
					break;
		case 2:
					send_code(&rgb_data[6]);//所有灯变绿灯
					break;
		case 3:
					send_code(&rgb_data[9]);//所有灯变蓝灯
					break;
		case 4:
					send_code(&rgb_data[13]);//所有灯变红灯//所有灯变绿灯
					break;
		case 5:
					send_code(&rgb_data[22]);//所有灯变红灯//所有灯变蓝灯
					break;
		case 6:
					send_code(&rgb_data[19]);//所有灯变红灯//所有灯变绿灯//所有灯变蓝灯
					break;
		case 7:
		      send_code(&rgb_data[16]);//所有灯变绿灯//所有灯变蓝灯
					break;
		
	}

}

	// 循环显示各种彩色
void circular_led_show()
{
u8 i=0,j=0;
	for(i=0;i<8;i++)
	{
	colorset(i);
	HAL_Delay(300);
	
	}

}
/* USER CODE END PFP */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		circular_led_show();
		
//reset信号
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET); 
		HAL_Delay(500);
  }

Tip:2020 RGB颜色查询大全 #000000 【颜色列表】 (改变灯的颜色需要用到的)

        【STM32】晶振,主时钟,外设频率介绍

         STM32驱动WS2812B-2020 RGB彩灯(一)

### 回答1: 要驱动WS2812B,需要使用STM32F103C8T6的定时器和DMA功能。以下是大致的步骤: 1. 配置定时器为PWM模式,设置周期为WS2812B的周期(大约是1.25us)。 2. 配置DMA,将要发送的数据缓存地址设置为定时器的CCR寄存器地址。 3. 在主程序中,将要发送的数据按照WS2812B的协议格式转换为PWM信号,存储到缓存中。 4. 启动DMA传输,将缓存中的数据发送到定时器的CCR寄存器中。 5. 等待DMA传输完成,即可完成WS2812B的驱动。 需要注意的是,WS2812B的协议比较严格,需要按照一定的时间序列发送数据,否则会出现颜色失真等问题。因此,在编写驱动程序时需要仔细考虑时序问题。 ### 回答2: WS2812B是一种RGB LED灯条,通常会被用于LED灯带或背景照明等领域。STM32F103C8T6是STM32系列的一种单片机,具有高速和高性能,被广泛应用于嵌入式系统和电子设备中。因此,如何利用STM32F103C8T6驱动WS2812B是非常重要的。 在控制WS2812B时,首先需要了解它的通信协议。WS2812B使用单线通讯,即将控制数据串联在第一个LED的输出端口,并以每个LED的指令格式顺序传输数据。每个数据位的传递速率大约是800KHz。在每个数据周期中,每个LED都有24个字节,分别是三种颜色红、绿、蓝的8位值。 接下来,我们将看看如何将STM32F103C8T6WS2812B相连接。STM32F103C8T6共有72个引脚,其中有GPIO引脚可供使用,用于数据输入和WS2812B引脚连接。为了实现单线通讯,需配置USART通讯方式的GPIO引脚。并需要将STM32F103C8T6的输出数据设置为WS2812B需要的频率。 接下来是代码部分。在STM32F103C8T6中,可以通过CubeMX来生成WS2812B的控制代码框架。在Code Generator中生成的代码中,需要添加头文件并声明数据的输出端口。此外,还需要编写RGB的颜色值,以及控制数据流的各种参数如延时和T1/T0时间等。最后将控制数据输出至GPIO引脚即可实现WS2812B灯带的控制操作。 总之,通过以上步骤,通过STM32F103C8T6驱动WS2812B是可行的,只需按照上述步骤进行轻微的调整。这将为设计者提供广泛的应用前景,可以实现许多照明和显示应用。如开发了WS2812B的诸多驱动方案,并加入了丰富的特性,将为工程师提供更多控制方式和更丰富的灯光形式。 ### 回答3: WS2812B是一种RGB LED灯条,它具有低电压驱动、数字信号控制、颜色饱和和一致性好等特点,成为了目前应用于LED照明的较为普遍的方案之一。而STM32F103C8T6则是一款通用型微控制器,它小巧玲珑但功能非常强大,常常用于各类小型嵌入式系统。那么如何驱动WS2812B呢? 首先,由于WS2812B的控制信号是基于一种叫做“时间着色码”的协议来实现的,所以我们需要在STM32F103C8T6实现这个协议,生成正确的控制信号,从而控制WS2812B。具体步骤如下: 1. 确定RGB灯条的引脚分配: 为了控制WS2812B,我们需要知道这个灯条的引脚分配,通常是三个引脚:VCC、GND和DIN。其中,VCC和GND表示电源接口,DIN则表示数据输入接口。 2. 配置STM32F103C8T6的引脚输出: 根据WS2812B的引脚分配,将STM32F103C8T6的GPIO输出端口与RGB灯条的DIN引脚连接。此时,需要将这个GPIO口的工作模式设置为推挽输出,并且将输出速度设置为高速模式,以确保生成正确的控制信号。 3. 编写代码: 在STM32F103C8T6上编写代码,生成正确的数位信号序列,驱动RGB灯条发出相应的颜色。具体而言,代码的逻辑包括以下几个步骤: (1)初始化引脚:将GPIO配置为输出口,以控制WS2812B; (2)计算控制信号:计算出合适的时间着色码,生成正确的控制信号; (3)驱动RGB LED:将生成的控制信号通过GPIO口输出,从而控制WS2812B发出相应的颜色; (4)生成信号循环:在控制信号发送完毕后,通过循环产生需要的信号周期,驱动rgb灯条完成显示。 综上所述,驱动WS2812B需要实现正确的时间着色码协议代码,以及正确的GPIO口配置和信号输出循环。需要注意,由于WS2812B是一种数字通讯信号协议,所以在实际使用中需要对电源线、信号线和数据线进行完整性和干扰等相关的判断和处理。这样,我们才能驱动WS2812B成功。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

姜浩鑫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值