STM32 HAL SPI DMA驱动RGB灯(XL-5050RGBC-WS2812B)学习笔记

0、连接引脚

1、CubeMX配置

2、驱动代码

WS2812B.C


#include "RGB.h"

volatile uint8_t RGB_BIT_Buffer[RGB_BIT];
volatile uint8_t buffer[RGB_BIT * LED_NUMS];
volatile LEDType LED[LED_NUMS];


//搞一个数组轮流播放吧
uint32_t RGB_ST[14]=
{
    0xFF0000,
    0xFF7F00,
    0xFFFF00,
    0x7FFF00,
    0x00FF00,
    0x00FF7F,
    0x00FFFF,
    0x007FFF,
    0x0000FF,
    0x7F00FF,
    0xFF00FF,
    0xFF007F,
    0xFFFFFF,
    0x000000
};  


/**
cook the whole buffer made by many(16 pieces) RGB_BIT_Buffers.
*/
//static void WS2812_MakeBuffer(void)
//{
//    for(uint16_t i = 0; i < LED_NUMS; i++)
//    {
//        WS2812_CreatData(LED[i].R, LED[i].G, LED[i].B);
//        memcpy(( int*)buffer + i * RGB_BIT,(const int*) RGB_BIT_Buffer, RGB_BIT);
//    }
//}

void WS2812_Update(void)
{
    HAL_SPI_Transmit_DMA(&hspi2,(uint8_t *)buffer, RGB_BIT * LED_NUMS);
//    HAL_SPI_Transmit(&hspi2, (uint8_t *)buffer, RGB_BIT * LED_NUMS,200);
}

/**
create 24 byte sent by SPI using RGB values.
*/
static void WS2812_CreatData(uint8_t R, uint8_t G, uint8_t B)
{
    uint8_t temp[RGB_BIT] = {0};
    for (uint8_t i = 0; i < 8; i++)
    {
        temp[7 - i] =  (G & 0x01) ? WS2812_1 : WS2812_0;
        G = G >> 1;
    }
    for (uint8_t i = 0; i < 8; i++)
    {
        temp[15 - i] =  (R & 0x01) ? WS2812_1 : WS2812_0;
        R = R >> 1;
    }                         
    for (uint8_t i = 0; i < 8; i++)
    {
        temp[23 - i] =  (B & 0x01) ? WS2812_1 : WS2812_0;
        B = B >> 1;
    }
    memcpy((int *)RGB_BIT_Buffer, temp, RGB_BIT);
}



void WS2812_TurnOff(void)
{
    for(uint16_t i = 0; i < LED_NUMS * 24; i++)
    {
        buffer[i] = WS2812_0;
    }
}


/**
一个位置的led会因颜色值而明亮
pos is [0 , max-1]
*/
 void WS2812_Color_Pos(uint32_t color, uint16_t Pos)
{
    uint8_t R, G, B;
    
    R = (color >> 16 ) & 0x00FF;
    G = (color >> 8  ) & 0x0000FF;
    B = (color       ) & 0x0000FF;

    WS2812_CreatData(R, G, B);
    if(Pos < LED_NUMS && Pos > 0)
    {
        memcpy(( int*)buffer + RGB_BIT * Pos,(const int*)RGB_BIT_Buffer, RGB_BIT);
    }
    else
    {
        WS2812_TurnOff();
    }
}


void WS2812_Show_Wheel(void)
{
    static uint16_t i = 0;
    i++;
    WS2812_Color_Pos(0xFF0000, (i) % 16);//红色
    WS2812_Color_Pos(0XFF7F00, (i + 1) % 16);
    WS2812_Color_Pos(0XFFFF00, (i + 2) % 16);
    WS2812_Color_Pos(0X7FFF00, (i + 3) % 16);
    WS2812_Color_Pos(0X00FF00, (i + 4) % 16);
    WS2812_Color_Pos(0X00FF7F, (i + 5) % 16);
    WS2812_Color_Pos(0X00FFFF, (i + 6) % 16);
    WS2812_Color_Pos(0X007FFF, (i + 7) % 16);
    WS2812_Color_Pos(0X0000FF, (i + 8) % 16);
    WS2812_Color_Pos(0X7F00FF, (i + 9) % 16);
    WS2812_Color_Pos(0XFF00FF, (i + 10) % 16);
    WS2812_Color_Pos(0XFF007F, (i + 11) % 16);
    WS2812_Color_Pos(0XFF0000, (i + 12) % 16);
    WS2812_Color_Pos(0XFF7F00, (i + 13) % 16);
    WS2812_Color_Pos(0XFFFF00, (i + 14) % 16);
    WS2812_Color_Pos(0X7FFF00, (i + 15) % 16);//绿色
    WS2812_Update();
}

WS2812B.H

#ifndef __RGB_H__
#define __RGB_H__

#include "string.h"
#include "main.h"
#include "spi.h"

#define     WS2812_0            0xC0
#define     WS2812_1            0xF0
#define     WS2812_RST          0x00
#define     LED_NUMS            16
#define     RGB_BIT             24

//以下编码准寻· 光学色相环(RGB模型)-12色
#define     red_0               0xFF0000 //红
#define     brown_30            0xFF7F00 //棕色
#define     yellow_60           0xFFFF00 //黄色
#define     Dark_green_90       0x7FFF00 //深绿色
#define     Medium_green_120    0x00FF00 //中绿色
#define     Light_green_150     0x00FF7F //浅绿色
#define     Baby_blue_180       0x00FFFF //浅蓝色
#define     Medium_blue_210     0x007FFF //中蓝色
#define     Dark_blue_240       0x0000FF //深蓝色
#define     modena_270          0x7F00FF //深紫色
#define     Medium_purple_300   0xFF00FF //中紫色
#define     lilac_330           0xFF007F //浅紫色

#define     white_360           0xFFFFFF //白色
#define     off_390             0x000000 //熄灯



extern uint32_t RGB_ST[14];

typedef struct
{
    uint8_t R;
    uint8_t G;
    uint8_t B;
} LEDType;


extern volatile uint8_t RGB_BIT_Buffer[RGB_BIT];
extern volatile uint8_t buffer[RGB_BIT * LED_NUMS];
extern volatile LEDType LED[LED_NUMS];

/**
turn off all leds
*/
void WS2812_TurnOff(void);
void WS2812_Show_Wheel(void);
void WS2812_Update(void);
static void WS2812_MakeBuffer(void);
static void WS2812_CreatData(uint8_t R, uint8_t G, uint8_t B);

 void WS2812_Color_Pos(uint32_t color, uint16_t Pos);

#endif

main.c

__IO uint32_t RGB_delay=0;
uint8_t x=0;
void RGB_Process(void)//颜色轮询
{
    if(uwTick-RGB_delay < 1000) return;
        RGB_delay=uwTick;

    x =(x+1)%15;
    WS2812_Color_Pos(RGB_ST[x], 1);
    
    WS2812_Update();
   
}

控制RGB色号的编码如图:

本文章学习自:【STM32】硬件SPI+DMA驱动WS2812灯珠,基于HAL库_stm32 ws2812-CSDN博客

  • 8
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
STM32驱动RGB带的关键是理解RGB带的工作原理和时序要求。RGB带通常使用WS2812B芯片进行控制,这种芯片需要特定的高低电平时序来传输颜色信息。在STM32驱动RGB带可以通过使用定时器和GPIO来实现。 首先,你需要配置定时器作为PWM输出模式,并设置合适的频率。然后,通过GPIO输出控制RGB带的数据引脚。在每个PWM周期中,通过改变GPIO输出的高低电平来实现对RGB带的控制。具体来说,你需要根据WS2812B芯片的时序要求,确定每个逻辑1和逻辑0对应的高电平和低电平持续的时间。通过调整PWM的占空比来达到正确的时序。 以下是一个基本的示例代码,用于驱动RGB带: ```c #include "stm32f1xx_hal.h" // 定义RGB带的引脚 #define LED_PIN GPIO_PIN_0 #define LED_PORT GPIOA // 定义PWM定时器和通道 #define TIM_HANDLE htim3 #define TIM_CHANNEL TIM_CHANNEL_1 // 定义RGB带的像素数量 #define NUM_LEDS 10 // 定义RGB带的颜色数组 uint8_t colors[NUM_LEDS][3] = { {255, 0, 0}, // 红色 {0, 255, 0}, // 绿色 {0, 0, 255}, // 蓝色 // 更多颜色... }; // 发送一个时序为H的bit void sendBitH(void) { HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_SET); // 根据具体时序要求延时 HAL_Delay(1); // 延时时间需要根据实际情况进行调整 HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET); // 根据具体时序要求延时 HAL_Delay(1); } // 发送一个时序为L的bit void sendBitL(void) { HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_SET); // 根据具体时序要求延时 HAL_Delay(1); HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET); // 根据具体时序要求延时 HAL_Delay(1); } // 发送一个字节的数据 void sendData(uint8_t data) { for (int i = 0; i < 8; i++) { if ((data & 0x80) != 0) { // 判断最高位是否为1 sendBitH(); } else { sendBitL(); } data <<= 1; // 左移一位,处理下一个bit } } // 发送一个像素的颜色数据 void sendColor(uint8_t red, uint8_t green, uint8_t blue) { sendData(green); sendData(red); sendData(blue); } // 发送所有像素的颜色数据 void sendColors(void) { for (int i = 0; i < NUM_LEDS; i++) { sendColor(colors[i][0], colors[i][1], colors[i][2]); } } int main(void) { // 初始化STM32和定时器 // 配置GPIO为推挽输出模式 GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = LED_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct); // 配置定时器为PWM输出模式 TIM_OC_InitTypeDef pwmConfig; pwmConfig.OCMode = TIM_OCMODE_PWM1; pwmConfig.Pulse = 0; // 初始占空比为0,带关闭 HAL_TIM_PWM_ConfigChannel(&TIM_HANDLE, &pwmConfig, TIM_CHANNEL); HAL_TIM_PWM_Start(&TIM_HANDLE, TIM_CHANNEL); while (1) { // 发送颜色数据到RGB带 sendColors(); // 延时一段时间,使带显示颜色 HAL_Delay(1000); } } ``` 请注意,上述示例代码仅作为概念演示,实际应用中需要根据硬件和时序要求进行适当的调整。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

桂北研猛男

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

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

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

打赏作者

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

抵扣说明:

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

余额充值