STM32控制WS2812灯带(含完整代码)


STM32控制WS2812灯带(含完整代码)

用STM32控制WS2812 RGB灯带的代码资料不多。这里的代码是通过示波器一点一点调整得到的。本着开源原则,和大家分享学习。


灯带信息

在这里插入图片描述

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

在这里插入图片描述
点击查看完整文档


实现代码

核心代码如下:

// 引脚对应的寄存器(更多信息见下文)
#define A0_HIGH  GPIOA->BSRR = 1           // A low electrical level. (GPIO_PIN_0: 1)
#define A0_LOW   GPIOA->BSRR = 65536u      // A high electrical level.(GPIO_PIN_0: 1 << 16u)
#define A1_HIGH  GPIOA->BSRR = 2           // A low electrical level. (GPIO_PIN_1: 2)
#define A1_LOW   GPIOA->BSRR = 131072u     // A high electrical level.(GPIO_PIN_1: 2 << 16u)
#define B12_HIGH GPIOB->BSRR = 4096        // A low electrical level. (GPIO_PIN_12: 4096)
#define B12_LOW  GPIOB->BSRR = 268435456u  // A high electrical level.(GPIO_PIN_12: 4096 << 16u)

#define HIGH     B12_HIGH   // 持续一个很短时间的高电平
#define LOW      B12_LOW    // 持续一个很短时间的低电平

// 连续多个HIGH/LOW == 一个HIGH/LOW + delay函数 (卡示波器得到的)
#define SIG1()     HIGH;HIGH;HIGH; HIGH;HIGH;LOW    // 一个 signal 1.
#define SIG0()     HIGH;HIGH;LOW;	 LOW;LOW;LOW    // 一个 signal 0.

// 示例颜色 (注意这里的颜色顺序是:高位->低位 —— G->R->B)
#define RED    0x00ff00
#define GREEN  0xff0000
#define BLUE   0x0000ff

#define LED_LEN       144  // 灯带长度
#define BIT_LEN       24   // 每颗灯对应24位 0/1 signal

uint32_t led_buf[LED_LEN] = {
    
     0 };  // 存储每颗灯的颜色值,范围:[0, 0xffffff].

void sync() {
    
    
	uint32_t bit_buf[LED_LEN * BIT_LEN] = {
    
     0 }; // 将要传输的bit数组
	
	for (uint32_t i = 0; i < LED_LEN; ++i) {
    
    
		for (uint32_t j = 0; j < BIT_LEN; ++j) {
    
    
			bit_buf[i * BIT_LEN + j] = (led_buf[i] >> (BIT_LEN - 1 - j)) & 1;  // 高位先传
		}
	}
	
	__disable_irq();  // 关闭中断
	
	for (uint32_t i = 0; i < LED_LEN * BIT_LEN; ++i) {
    
    
		if (bit_buf[i]) {
    
    
			SIG1();
		} else {
    
    
			SIG0();
		}
	}
	
	__enable_irq();  // 开启中断
}

引脚对应寄存器信息大全

#define GPIO_PIN_0                 ((uint16_t)0x0001)  /* Pin 0 selected    */
#define GPIO_PIN_1                 ((uint16_t)0x0002)  /* Pin 1 selected    */
#define GPIO_PIN_2                 ((uint16_t)0x0004)  /* Pin 2 selected    */
#define GPIO_PIN_3                 ((uint16_t)0x0008)  /* Pin 3 selected    */
#define GPIO_PIN_4                 ((uint16_t)0x0010)  /* Pin 4 selected    */
#define GPIO_PIN_5                 ((uint16_t)0x0020)  /* Pin 5 selected    */
#define GPIO_PIN_6                 ((uint16_t)0x0040)  /* Pin 6 selected    */
#define GPIO_PIN_7                 ((uint16_t)0x0080)  /* Pin 7 selected    */
#define GPIO_PIN_8                 ((uint16_t)0x0100)  /* Pin 8 selected    */
#define GPIO_PIN_9                 ((uint16_t)0x0200)  /* Pin 9 selected    */
#define GPIO_PIN_10                ((uint16_t)0x0400)  /* Pin 10 selected   */
#define GPIO_PIN_11                ((uint16_t)0x0800)  /* Pin 11 selected   */
#define GPIO_PIN_12                ((uint16_t)0x1000)  /* Pin 12 selected   */
#define GPIO_PIN_13                ((uint16_t)0x2000)  /* Pin 13 selected   */
#define GPIO_PIN_14                ((uint16_t)0x4000)  /* Pin 14 selected   */
#define GPIO_PIN_15                ((uint16_t)0x8000)  /* Pin 15 selected   */
#define GPIO_PIN_All               ((uint16_t)0xFFFF)  /* All pins selected */
GPIOx->BSRR = GPIO_Pin_x;  // 高电平
GPIOx->BSRR = (uint32_t)GPIO_Pin << 16u;  // 低电平

注意点

  1. 如果不在传输数据过程中停止中断,数据传输会因为被打断而出现误差,导致灯带闪烁,颜色变得离谱。
  2. 传输bit时应该高位先传(详见代码sync()函数),颜色顺序为:高位->低位 —— G->R->B

完整例程代码下载链接

点击下载

参考资料

WS2812手册
个人经验

猜你喜欢

转载自blog.csdn.net/weixin_39591031/article/details/112509186