GD32F130F8P6写个驱动WS2812B流水灯效果的程序
时间: 2023-06-14 17:02:49 浏览: 336
下面是一个简单的流水灯效果程序,使用GD32F130F8P6驱动WS2812B:
```c
#include "gd32f1x0.h"
#define LED_NUM 8 // WS2812B个数
#define LED_BUF_SIZE (LED_NUM * 24) // WS2812B数据总长度,每个WS2812B需要24个bit
// RGB颜色定义
#define COLOR_RED 0xFF0000
#define COLOR_GREEN 0x00FF00
#define COLOR_BLUE 0x0000FF
// WS2812B数据缓存
static uint8_t led_buf[LED_BUF_SIZE];
/**
* @brief 向WS2812B发送一个位
* @param bit: 要发送的位,0或1
* @retval None
*/
static void ws2812b_send_bit(uint8_t bit)
{
if (bit) {
GPIO_BOP(GPIOB) = GPIO_PIN_13;
__ASM volatile("nop");
__ASM volatile("nop");
__ASM volatile("nop");
GPIO_BC(GPIOB) = GPIO_PIN_13;
__ASM volatile("nop");
__ASM volatile("nop");
} else {
GPIO_BOP(GPIOB) = GPIO_PIN_13;
__ASM volatile("nop");
GPIO_BC(GPIOB) = GPIO_PIN_13;
__ASM volatile("nop");
__ASM volatile("nop");
}
}
/**
* @brief 向WS2812B发送一个字节
* @param byte: 要发送的字节
* @retval None
*/
static void ws2812b_send_byte(uint8_t byte)
{
for (int i = 0; i < 8; i++) {
ws2812b_send_bit(byte & 0x80);
byte <<= 1;
}
}
/**
* @brief 向WS2812B发送一个RGB颜色值
* @param color: RGB颜色值
* @retval None
*/
static void ws2812b_send_color(uint32_t color)
{
ws2812b_send_byte(color >> 16);
ws2812b_send_byte(color >> 8);
ws2812b_send_byte(color);
}
/**
* @brief 清空WS2812B数据缓存
* @param None
* @retval None
*/
static void ws2812b_clear(void)
{
for (int i = 0; i < LED_BUF_SIZE; i++) {
led_buf[i] = 0;
}
}
/**
* @brief 设置WS2812B的颜色
* @param index: WS2812B的编号,从0开始
* @param color: RGB颜色值
* @retval None
*/
static void ws2812b_set_color(uint8_t index, uint32_t color)
{
if (index >= LED_NUM) {
return;
}
index *= 24;
for (int i = 0; i < 24; i += 8) {
led_buf[i + index] = (color & 0xFF0000) >> 16;
led_buf[i + index + 1] = (color & 0x00FF00) >> 8;
led_buf[i + index + 2] = color & 0x0000FF;
color >>= 8;
}
}
/**
* @brief 发送WS2812B数据
* @param None
* @retval None
*/
static void ws2812b_send_data(void)
{
__disable_irq();
for (int i = 0; i < LED_BUF_SIZE; i++) {
for (int j = 0; j < 8; j++) {
if (led_buf[i] & (1 << (7 - j))) {
GPIO_BOP(GPIOB) = GPIO_PIN_13;
__ASM volatile("nop");
__ASM volatile("nop");
__ASM volatile("nop");
GPIO_BC(GPIOB) = GPIO_PIN_13;
__ASM volatile("nop");
__ASM volatile("nop");
} else {
GPIO_BOP(GPIOB) = GPIO_PIN_13;
__ASM volatile("nop");
GPIO_BC(GPIOB) = GPIO_PIN_13;
__ASM volatile("nop");
__ASM volatile("nop");
}
}
}
__enable_irq();
}
int main(void)
{
// 初始化WS2812B数据缓存
ws2812b_clear();
ws2812b_set_color(0, COLOR_RED);
ws2812b_set_color(1, COLOR_GREEN);
ws2812b_set_color(2, COLOR_BLUE);
RCC_AHBPeriphClock_Enable(RCC_AHBPERIPH_GPIOB, ENABLE);
// 配置GPIOB13为推挽输出,用于控制WS2812B
GPIO_InitPara GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_13;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_50MHZ;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 发送WS2812B数据
ws2812b_send_data();
while (1) {
// 简单的流水灯效果
for (int i = 0; i < LED_NUM; i++) {
ws2812b_clear();
ws2812b_set_color(i, COLOR_RED);
ws2812b_send_data();
delay_ms(100);
}
}
}
```
这个程序使用了一个静态数组led_buf来存储WS2812B的颜色数据,每个WS2812B需要3个字节,即RGB颜色值,因此数组长度为LED_NUM * 24。程序中的ws2812b_send_bit、ws2812b_send_byte和ws2812b_send_color函数分别用于向WS2812B发送1个bit、1个字节和1个RGB颜色值。ws2812b_clear函数用于清空led_buf数组,ws2812b_set_color函数用于设置指定WS2812B的颜色。ws2812b_send_data函数用于将led_buf数组中的数据发送给WS2812B。
程序中的主要逻辑是一个简单的流水灯效果,每隔100ms将红色的LED从一个WS2812B移动到下一个。你可以根据自己的需要修改流水灯效果的实现方式。
阅读全文