当前位置: 首页 > article >正文

STM407IGT6+WS2818灯带

WS2818驱动的时序要求如下:
在这里插入图片描述
STM32F407IGT6 是一款基于 ARM Cortex-M4 内核的高性能微控制器,具备丰富的外设接口。
以下是使用 STM32F407IGT6 控制 WS2812B 灯带的一些基本步骤:

硬件连接:

数据线:将 WS2812B 灯带的数据线连接到 STM32F407IGT6 的某个SPI TX引脚上,这个引脚需要配置为 SPI 输出模式。
电源:确保 WS2812B 灯带接收到合适的 5V(或其它规格要求的电压)电源供应,并注意共地连接。
限流电阻:可能需要在数据线上串联一个限流电阻,以防止过高的电流损坏 LED 或微控制器。
软件配置:

初始化 SPI:配置一个 GPIO 引脚作为 SPI 的 MOSI(主输出从输入)引脚,设置正确的 SPI 通讯参数(如时钟频率、CPOL、CPHA)以匹配 WS2812B 的要求。
定时器配置:WS2812B 对时序要求非常严格,因此需要配置一个定时器来生成精确的时间延迟。
编程控制:

数据缓冲区:创建一个数据缓冲区来存储每个 LED 的颜色值。
发送函数:编写一个函数来填充数据缓冲区,并将其发送到 WS2812B 灯带上。这个函数需要处理 WS2812B 的特定编码方式(通常是 GRB 格式)。
刷新函数:编写一个函数来触发 SPI 传输,将缓冲区中的数据发送到灯带上。
调试和测试:

初步测试:先尝试点亮一个或几个 LED,确保通信正常。

性能优化:根据需要优化 SPI 传输速率,以实现最佳性能。
功耗优化:如果功耗是一个考虑因素,可以调整时钟设置和电源管理策略。

以下是一个简化的代码示例,展示了如何初始化 SPI 和发送数据到 WS2812B 灯带:

WS2812.c
#include "WS2812.h"
//#include "tim.h"  // 引入定时器头文件用于延时

SPI_HandleTypeDef hspi2;
uint8_t ws2812_data_buffer[WS2812_LED_NUM][24];

/**
 * @Description   初始化SPI2用于WS2812
 * @Param         void
 * @Return        void
 */
void ws2812_SPI_Init(void) {
    __HAL_RCC_SPI2_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct = {0};

    // 初始化 PB13 (SCK), PB15 (MOSI)
    GPIO_InitStruct.Pin = GPIO_PIN_13 | GPIO_PIN_15;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    // SPI2 初始化
    hspi2.Instance = SPI2;
    hspi2.Init.Mode = SPI_MODE_MASTER;
    hspi2.Init.Direction = SPI_DIRECTION_1LINE;
    hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
    hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
    hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
    hspi2.Init.NSS = SPI_NSS_SOFT;
    hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;  // 根据实际需求设置
    hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
    hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
    hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    hspi2.Init.CRCPolynomial = 7;
    HAL_SPI_Init(&hspi2);
}

/**
 * @Description   延时函数(基于HAL库的定时器)
 * @Param         {uint32_t ms} 延时毫秒数
 * @Return        void
 */
void delay_ms(uint32_t ms) {
    HAL_Delay(ms);
}

/**
 * @Description   WS2812初始化
 * @Param         void
 * @Return        void
 */
void ws2812_Init(void) {
    ws2812_SPI_Init();
    delay_ms(WS2812_LED_NUM * 10);
}

/**
 * @Description   通过SPI2发送数据
 * @Param         {uint8_t *data} 数据缓冲区指针
 *                {uint16_t length} 数据长度
 * @Return        void
 */
void ws2812_Send_Data(uint8_t *data, uint16_t length) {
    HAL_SPI_Transmit(&hspi2, data, length, HAL_MAX_DELAY);
}

/**
 * @Description   关闭所有灯光
 * @Param         void
 * @Return        void
 */
void ws2812_AllShutOff(void) {
    uint16_t i;
    uint8_t j;

    for (i = 0; i < WS2812_LED_NUM; i++) {
        for (j = 0; j < 24; j++) {
            ws2812_data_buffer[i][j] = SIG_0;
        }
    }
    ws2812_Send_Data((uint8_t *)ws2812_data_buffer, WS2812_LED_NUM * 24);
    delay_ms(10 * WS2812_LED_NUM);
}

/**
 * @Description   合并RGB值为24位
 * @Param         {uint8_t red, green, blue} RGB颜色值
 * @Return        {uint32_t} 24位RGB值
 */
uint32_t ws281x_color(uint8_t red, uint8_t green, uint8_t blue) {
    return green << 16 | red << 8 | blue;
}

/**
 * @Description   点亮所有灯
 * @Param         {uint8_t red, green, blue} RGB颜色值
 * @Return        void
 */
void ws2812_AllOpen(uint8_t red, uint8_t green, uint8_t blue) {
    uint16_t i, j;

    for (j = 0; j < WS2812_LED_NUM; j++) {
        for (i = 0; i < 24; ++i) {
            ws2812_data_buffer[j][i] =
                (((ws281x_color(red, green, blue) << i) & 0X800000) ? SIG_1 : SIG_0);
        }
    }
    ws2812_Send_Data((uint8_t *)ws2812_data_buffer, WS2812_LED_NUM * 24);
    delay_ms(10);
}



ws2818.h

#ifndef __WS2812_H
#define __WS2812_H

#include "stm32f4xx_hal.h"

#define WS2812_LED_NUM  14

// 11111000  SIG_1   5/8 = 62.5%
// 11100000  SIG_0   3/8 = 37.5%
#define SIG_1   0XF8
#define SIG_0   0XC0

void ws2812_Init(void);
void ws2812_Send_Data(uint8_t *data, uint16_t length);
void ws2812_AllShutOff(void);
void ws2812_AllOpen(uint8_t red, uint8_t green, uint8_t blue);

#endif
测试代码
main.c

```c
#include "main.h"
#include "ws2812.h"
#include "./usart/bsp_debug_usart.h"

static void SystemClock_Config(void);

int main(void) {
    HAL_Init();
    SystemClock_Config();  // 配置时钟168MHz
		DEBUG_USART_Config();
		printf("start\r\n");
    ws2812_Init();
		ws2812_AllOpen(255,0,0);
		printf("end\r\n");
    while (1) {
        // 点亮第一个LED为红色
       ws2812_AllOpen(255,0,0);
        HAL_Delay(1000);

        // 点亮第二个LED为绿色
       ws2812_AllOpen(0,255,0);
        HAL_Delay(1000);
			
		// 点亮第二个LED为蓝色
       ws2812_AllOpen(0,0,255);
        HAL_Delay(1000);

        // 关闭所有LED
        ws2812_AllShutOff();
        HAL_Delay(1000);
    }
}




/**
  * @brief  System Clock Configuration
  *         The system Clock is configured as follow : 
  *            System Clock source            = PLL (HSE)
  *            SYSCLK(Hz)                     = 168000000
  *            HCLK(Hz)                       = 168000000
  *            AHB Prescaler                  = 1
  *            APB1 Prescaler                 = 4
  *            APB2 Prescaler                 = 2
  *            HSE Frequency(Hz)              = 8000000
  *            PLL_M                          = 25
  *            PLL_N                          = 336
  *            PLL_P                          = 2
  *            PLL_Q                          = 7
  *            VDD(V)                         = 3.3
  *            Main regulator output voltage  = Scale1 mode
  *            Flash Latency(WS)              = 5
  * @param  None
  * @retval None
  */
static void SystemClock_Config(void)
{
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_OscInitTypeDef RCC_OscInitStruct;

  /* Enable Power Control clock */
  __HAL_RCC_PWR_CLK_ENABLE();
  
  /* The voltage scaling allows optimizing the power consumption when the device is 
     clocked below the maximum system frequency, to update the voltage scaling value 
     regarding system frequency refer to product datasheet.  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  
  /* Enable HSE Oscillator and activate PLL with HSE as source */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 25;
  RCC_OscInitStruct.PLL.PLLN = 336;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    while(1) {};
  }
  
  /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 
     clocks dividers */
  RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;  
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;  
  if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    while(1) {};
  }

  /* STM32F405x/407x/415x/417x Revision Z devices: prefetch is supported  */
  if (HAL_GetREVID() == 0x1001)
  {
    /* Enable the Flash prefetch */
    __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
  }
}

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

http://www.kler.cn/a/420069.html

相关文章:

  • 组合问题变式——选数(dfs)
  • 44 基于32单片机的博物馆安全监控系统设计
  • yarn install遇到问题处理
  • linux 获取公网流量 tcpdump + python + C++
  • 【鸿蒙NEXT】arrayBuffer和base64字符串互相转换
  • 《Spring Boot 整合 Avro 与 Kafka》
  • ubuntu部署RocketMQ
  • Kubernetes 集群网络:Flannel 与 Calico 的区别
  • AD7606使用方法
  • 学习记录:js算法(一百零七):解码方法
  • 求自然数N的所有约数之和。:JAVA
  • LWIP和FATFS 实现 FTP 服务端
  • EasyMedia播放rtsprtmp视频流(flvhls)
  • 事务常见分类
  • 软件质量保证——单元测试之白盒技术
  • hdlbits系列verilog解答(Dff16e-同步复位上升沿16位触发器)-85
  • Python中字符串和正则表达式
  • python 练习题
  • 基于Spring Boot的宠物咖啡馆平台的设计与实现
  • Canal mysql数据库同步到es
  • 1001:Hello,World!(https://ybt.ssoier.cn/problem_show.php?pid=1001)
  • docker ps -a里的项目怎么运行
  • 如何在CentOS 7上安全地设置Apache网站目录权限
  • Visual Studio code中编写和运行C语言
  • 【HarmonyOS开发】华为商城应用页面实验示例解析(ArkTS实战解析)
  • 单片机状态机实现多个按键同时检测单击、多击、长按等操作