前言

本篇文章中,我们将介绍如何使用STM32的HAL库驱动RGB三色灯,实现彩色灯光的控制。通过本篇文章的学习,您将掌握RGB三色灯的基础知识和编程方法,以及PWM(脉冲宽度调制)技术的应用。

一、准备

1.RGB三色灯原理

RGB三色灯通常由红色、绿色和蓝色三种LED灯组成。通过控制每种颜色的亮度,可以混合出各种不同的颜色。RGB三色灯的工作原理基于颜色的加法混色原理,即通过对不同颜色的光线进行叠加,形成新的颜色。在STM32中,我们可以通过PWM技术控制每种颜色的LED灯的亮度,从而实现彩色灯光的控制。
在这里插入图片描述

2.RGB三色灯控制方法

  • 基础功能:RGB三色独立可控,显示为纯色,可通过普通GPIO进行控制。
  • 混合效果:实现多种颜色混合显示,可通过PWM进行控制,本文使用控制占空比来调节灯亮度。

二、实例

1. 建立工程

将上节《远程控制LED实验》代码复制并修改名字为:09.RGB_Led,打开Project.ioc文件,配置TIM3三个通道PWM输出,分别对应PA6、PA7、PB0。
在这里插入图片描述

生成代码后,通过Keil打开工程,在Application/User/Driver处右击选择Add New Item…,添加C文件,名称命名为drv_rgb。
在这里插入图片描述

同样方法创建drv_rgb.h文件, 上图第2步选择Header File(.h)文件即可,drv_rgb.h内容如下:

#ifndef __DRV_RGB_H__
#define __DRV_RGB_H__

#include "main.h"

void RGB_SetColor(uint8_t r, uint8_t g, uint8_t b);
void Breathing_Effect(uint16_t period_ms);
void Rainbow_Effect(uint16_t speed);
#endif

drv_rgb.c内容如下:

#include "drv_rgb.h"
#include "tim.h"

// 设置RGB颜色值(0-255)
void RGB_SetColor(uint8_t r, uint8_t g, uint8_t b)
{
  #ifdef COMMON_ANODE
    r = 255 - r;
    g = 255 - g;
    b = 255 - b;
  #endif
  
  __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, r * 250); // 红
  __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, g * 250); // 绿
  __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, b * 250); // 蓝
}

// 简化版HSV转RGB
void HSV_to_RGB(uint16_t h, uint8_t s, uint8_t v, uint8_t *r, uint8_t *g, uint8_t *b)
{
  uint8_t region = h / 60;
  uint8_t remainder = (h % 60) * 4;
  
  uint8_t p = (v * (255 - s)) >> 8;
  uint8_t q = (v * (255 - ((s * remainder) >> 8))) >> 8;
  uint8_t t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;

  switch(region) {
    case 0: *r = v; *g = t; *b = p; break;
    case 1: *r = q; *g = v; *b = p; break;
    case 2: *r = p; *g = v; *b = t; break;
    case 3: *r = p; *g = q; *b = v; break;
    case 4: *r = t; *g = p; *b = v; break;
    default: *r = v; *g = p; *b = q; break;
  }
}

// 呼吸灯效果
void Breathing_Effect(uint16_t period_ms)
{
  static uint32_t last_tick = 0;
  static uint8_t dir = 0;
  static uint8_t brightness = 0;
  
  if(HAL_GetTick() - last_tick > period_ms/255) {
    last_tick = HAL_GetTick();
    
    if(dir) {
      if(++brightness == 255) dir = 0;
    } else {
      if(--brightness == 0) dir = 1;
    }
    
    RGB_SetColor(brightness, 0, 0); // 红色呼吸
  }
}

// 彩虹渐变效果
void Rainbow_Effect(uint16_t speed)
{
  static uint16_t hue = 0;
  uint8_t r, g, b;
  
  HSV_to_RGB(hue, 255, 255, &r, &g, &b);
  RGB_SetColor(r, g, b);
  
  hue = (hue + 1) % 360;
  HAL_Delay(speed);
}

main函数内容如下, 关闭ESP8266相关代码,本节只进行本地RGB三色灯功能开发。

int main(void)
{

  /* USER CODE BEGIN 1 */
    int ret = 0;
    int cnt = 300;
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
  MX_USART3_UART_Init();
  MX_TIM3_Init();
  /* USER CODE BEGIN 2 */
    printf("start application\r\n");
    // 使能空闲中断
  __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE); 

  HAL_UART_Receive_DMA(&huart3, (uint8_t *)Uart_Frame_Record.Data_RX_BUF, RX_BUF_MAX_LEN);  // 启动DMA接收 

  HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);
  HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);
  HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_3);

#ifdef SUPPORT_ESP8266
    // 连接路由器
    ESP8266_STAInit();
    delay_ms(1000);
    if (wifi_connect_status != WIFI_GOT_IP)
    {
    while(ESP8266_STAConnect((char *)Wssid, (char *)Wpassword));
    }
    
    // 连接MQTT 服务器
    printf("ready to connect to mqtt server\r\n");
    mqtt_task_init();
    
    mqtt_task_subcribe();

// mqtt_task_report();
#endif

  // 固定颜色显示
  RGB_SetColor(255, 128, 0); // 橙色
  HAL_Delay(2000);

  while (cnt-- > 0)
  {
    Rainbow_Effect(100);
  }    
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    #ifdef SUPPORT_ESP8266
        mqtt_task_report();
        HAL_Delay(60000);
    #endif
    Breathing_Effect(3000);
  }
    return ret;
  /* USER CODE END 3 */
}

2. 核心函数

drv_rgb.c中核心函数为void RGB_SetColor(uint8_t r, uint8_t g, uint8_t b), 通过设置占空比来控制RGB三个引脚的输出电压,从而进行灯控制,注意:需要手动调用HAL_TIM_PWM_Start()函数才能正式启动输出PWM。

// 设置RGB颜色值(0-255)
void RGB_SetColor(uint8_t r, uint8_t g, uint8_t b)
{
  #ifdef COMMON_ANODE
    r = 255 - r;
    g = 255 - g;
    b = 255 - b;
  #endif
  
  __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, r * 250); // 红
  __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, g * 250); // 绿
  __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, b * 250); // 蓝
}

3. 程序执行

本实验实现了上电首先亮蓝色灯2秒,然后进行30秒彩虹渐变效果,最后实现循环红色呼吸灯效果。
在这里插入图片描述

三、小结

如您在使用过程中有任何问题,请加QQ群进一步交流。
QQ交流群:573122190 (备注:物联网项目交流)
在这里插入图片描述

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐