STM32F103VET6实现全彩LED灯

全彩LED灯的实现


前言

利用PWM控制实现全彩LED灯


一、相关知识

1.全彩 LED 灯简介

全彩 LED 灯,实质上是一种把红、绿、蓝单色发光体集成到小面积区域中的 LED 灯,控制时对这三种颜色的灯管输出不同的光照强度,即可混合得到不同的颜色,其混色原理与光的三原色混合原理一致。

本工程配套开发板中的 RGB 灯就是一种全彩 LED 灯,实现LED 基本控制时候,只能控制 RGB 三色灯的亮灭,即 RGB 每盏灯有[0:1]两种等级,因此只能组合出 8种颜色。要使用 STM32 控制 LED 灯输出多种亮度等级,可以通过控制输出脉冲的占空比来实现
在这里插入图片描述
图中列出了周期相同而占空比分别为 100%、80%、50%和 20%的脉冲波形,假如利用这样的脉冲控制 LED 灯,即可控制 LED 灯亮灭时间长度的比例。若提高脉冲的频率,LED 灯将会高频率进行开关切换,由于视觉暂留效应,人眼看不到 LED 灯的开关导致的闪烁现象,而是感觉到使用不同占空比的脉冲控制 LED 灯时的亮度差别。即单个控制周期内,LED 灯亮的平均时间越长,亮度就越高,反之越暗。
把脉冲信号占空比分成 256 个等级,即可用于控制 LED 灯输出 256 种亮度,使用三种这样的信号控制 RGB 灯即可得到 256256256 种颜色混合的效果。而要控制占空比直接使用 STM32定时器的 PWM 功能即可。

2.硬件简介

LED 硬件原理图
在这里插入图片描述
RGB 灯使用阴极分别连接到了 PB5、PB0 及 PB1,它们分别是定时器
TIM3 的通道 2、3、4,其中 PB5用于定时器输出通道时,需要使用重定义功能。

二、代码实现

1.编程要点

  • 初始化 RGB灯使用的 GPIO;
  • 配置定时器输出 PWM 脉冲;
  • 编写修改 PWM脉冲占空比大小的函数;
  • 测试配置的定时器脉冲控制周期是否会导致 LED 灯明显闪烁;

2.LED灯硬件相关宏定义

color_led.h文件:


/********定时器通道*******/
#define  COLOR_TIMx      TIM3

#define  COLOR_TIM_APBxClock_FUN    	RCC_APB1PeriphClockCmd
#define  COLOR_TIM_CLK					RCC_APB1Periph_TIM3
#define  COLOR_TIM_GPIO_CLK     (RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO)
//红灯的引脚需要重映射
#define COLOR_GPIO_REMAP_FUN()  GPIO_PinRemapConfig(GPI0_PartialRemap_TIM3,ENABLE);
/********红灯*********/
#define COLOR_RED_TIM_LED_PORT   GPIOB
#define COLOR_RED_TIM_LED_PIN   GPIO_Pin_5

#define COLOR_RED_TIM_OCxInit    TIM_0C2Init      //初始化通道函数
#define COLOR_RED_TIM_OCxPreloadconfig      TIM_OC2Preloadconfig//通道重载配置函数

//通道比较寄存器,以TIMx->CCRx方式可访问该寄存器,设置新的比较值,控制占空比
//以宏封装后,使用这种形式: COLOR_TIMx->COLOR_RED_CCRx ,可访问该通道的比较寄存器

#define COLOR_RED_CCRx    CCR2

/************绿灯***********/

#define COLOR_GREEN_TIM_LED_PORT   GPIOB
#define COLOR_GREEN_TIM_LED_PIN   GPIO_Pin_0

#define COLOR_GREEN_TIM_OCxInit    TIM_0C3Init      //初始化通道函数
#define COLOR_GREEN_TIM_OCxPreloadconfig      TIM_OC3Preloadconfig//通道重载配置函数
//通道比较寄存器,以TIMx->CCRx方式可访问该寄存器,设置新的比较值,控制占空比
//以宏封装后,使用这种形式: COLOR_TIMx->COLOR_GREEN_CCRx ,可访问该通道的比较寄存器
#define COLOR_GREEN_CCRx    CCR3

/************蓝灯***********/

#define COLOR_BLUE_TIM_LED_PORT   GPIOB
#define COLOR_BLUE_TIM_LED_PIN   GPIO_Pin_1

#define COLOR_BLUE_TIM_OCxInit    TIM_0C4Init      //初始化通道函数
#define COLOR_BLUE_TIM_OCxPreloadconfig      TIM_OC4Preloadconfig//通道重载配置函数
//通道比较寄存器,以TIMx->CCRx方式可访问该寄存器,设置新的比较值,控制占空比
//以宏封装后,使用这种形式: COLOR_TIMx->COLOR_BLUE_CCRx ,可访问该通道的比较寄存器
#define COLOR_BLUE_CCRx    CCR4




这些宏定义包括使用的定时器编号 COLOR_TIMx、定时器时钟使能库函数COLOR_TIM_APBxClock_FUN 和引脚重映射操作COLOR_GPIO_REMAP_FUN。
控制各个 LED 灯时,每个颜色占用一个通道,这些与通道相关的也使用宏封装起来了,如:端口号 COLOR_xxx_TIM_LED_PORT、引脚号 COLOR_xxx_TIM_LED_PIN、通道初始化 库函 数 COLOR_xxx_TIM_OCxInit 、 通 道 重 载 配 置 库 函 数COLOR_xxx_TIM_OCxPreloadConfig 以及通道对应的比较寄存器名 COLOR_xxx_CCRx。其中 xxx宏中的 xxx指 RED、GREEN 和 BLUE 三种颜色。
为方便修改定时器某通道输出脉冲的占空比,初始化定时器后,可以直接使用形如―TIM3->CCR2=0xFFFFFF‖的代码修改定时器 TIM3 通道 2 的比较寄存器中的数值,使用本工程中的宏封装后,形式改为―COLOR_TIMx ->COLOR_RED_CCRx=0xFFFFFF。

2.初始化 GPIO

初始化用于定时器输出通道的 GPIO


//配置COLOR_TIMx复用输出PWM时用到的工/O

static void COLOR_TIMx_GPIO_Config (void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	/* GPIo clock enable */
	RCC_APB2PeriphClockCmd (COLOR_TIM_GPIO_CLK,ENABLE);
	//IO设置
	COLOR_GPIO_REMAP_FUN () ;
	/*配置LED灯用到的引脚*/
	//红
	GPIO_Initstructure.GPIO_Pin = COLOR_RED_TIM_LED_PIN ;
	GPIO_Initstructure.GPIO_Mode = GPIO_Mode_AF_PP;     //复用推挽输出
	GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(COLOR_RED_TIM_LED_PORT,&GPIO_Initstructure) ;
	//绿
	GPIO_Initstructure.GPIO_Pin = COLOR_GREEN_TIM_LED_PIN ;
	GPIO_Init(COLOR_GREEN_TIM_LED_PORT,&GPIO_Initstructure) ;
	//蓝
	GPIO_Initstructure.GPIO_Pin = COLOR_BLUE_TIM_LED_PIN ;
	GPIO_Init(COLOR_BLUE_TIM_LED_PORT,&GPIO_Initstructure) ;

}

与 LED 灯的基本控制不同,由于本实训直接使用定时器输出通道的脉冲信号控制LED 灯,此处代码把 GPIO 相关的引脚都配置成了复用推挽输出模式。其中由于红灯使用的引脚需要用到第二功能,本代码使用 COLOR_GPIO_REMAP_FUN()进行了该引脚的功能重定义操作。

3.定时器 PWM配置

配置定时器输出 PWM 的工作模式

//配置 COLOR_TIMx输出的PWM信号的模式,如周期、极性
static void cOLOR_TIMx_Mode_Config (void)
{
	TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;
	TIM_OCInitTypeDef    TIM_OCInitStructure;
	/*设置TIM CLK时钟*/
	//使能COLOR_TIMx时钟
	COLOR_TIM_APBxClock_FUN(COLOR_TIM_CLK,ENABLE);
	/*基本定时器配置*/
	//当定时器从0计数到255,即为256次,为一个定时周期
	TIM_TimeBaseStructure.TIM_Period = 255;
	//设置预分频
	TIM_TimeBaseStructure.TIM_Prescaler = 1999 ;
	//设置时钟分频系数:不分频(这里用不到)
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;
	//向上计数模式
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(COLOR_TIMx,&TIM_TimeBaseStructure) ;


	/* PwM模式配置*/
	//配置为PWN模式1
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWMl;
	//使能输出
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	//设置初始PWM脉冲宽度为О
	TIM_OCInitStructure.TIM_Pulse = 0 ;
	//当定时器计数值小于CCR Val时为低电平
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
	//使能通道和预装载
	COLOR_RED_TIM_OCxInit(COLOR_TIMx,&TIM_OCInitStructure);
	COLOR_RED_TIM_OCxPreloadConfig (COLOR_TIMx,TIM_OCPreload_Enable);
	//使能通道和预装载
	COLOR_GREEN_TIM_OCxInit (COLOR_TIMx,&TIM_OCInitStructure) ;
	COLOR_GREEN_TIM_OCxPreloadConfig(COLOR_TIMx,TIM_OCPreload_Enable) ;
	//使能通道和预装载
	COLOR_BLUE_TIM_OCxInit(COLOR_TIMx,&TIM_OCInitStructure);
	COLOR_BLUE_TIM_OCxPreloadConfig (COLOR_TIMx,TIM_OCPreload_Enable);
	//使能COLOR_TIMx重载寄存器ARR
	TIM_ARRPreloadConfig(COLOR_TIMx,ENABLE) ;
	//使能定时器
	TIM_Cmd(COLOR_TIMx,ENABLE) ;
}

本配置初始化了控制 RGB 灯用的定时器,它被配置为向上计数,TIM_Period 被配置为 255,即定时器每个时钟周期计数器加 1,计数至 255时溢出,从 0 开始重新计数;而代码中的 PWM 通道配置,当计数器的值小于输出比较寄存器 CCRx 的值时,PWM 通道输出低电平,点亮 LED 灯。所以上述代码配置把输出脉冲的单个周期分成了 256 份(注意区分定时器的时钟周期和输出脉冲周期),而输出比较寄存器 CCRx 配置的值即该脉冲周期内LED 灯点亮的时间份数,所以修改 CCRx 的值,即可控制输出[0:255]种亮度等级。
关于定时器中的 TIM_Prescaler 分频配置,只要让它设置使得 PWM 控制脉冲的频率足够高,让人看不出 LED 灯闪烁即可,您可以亲自修改使用其它参数测试。

4.设置混合颜色

#define COLOR_TIMx TIM3
#define COLOR_RED_CCRx CCR2
#define COLOR_GREEN_CCRX CCR3
#define COLOR_BLUE_CCRx CCR4.
/**
* @brief设置 RGB LED 的颜色
* @param rgb:要设置LED显示的颜色值格式RGB888
* @retval 无
*/
void SetRGBColor (uint32_t rgb)
{
//根据颜色值修改定时器的比较寄存器值
COLOR_TIMx->COLOR_RED_CCRx = (uint8_t) (rgb>>16) ;//R
COLOR_TIMx->COLOR_GREEN_CCRx = (uint8_t) (rgb>>8); //G
COLOR_TIMx->COLOR_BLUE_CCRx = (uint8_t) rgb;//B
}
/**
* @brief设置 RGB LED 的颜色
* @param rgb:要设置LED显示的颜色值
* @retval 无
*/
void SetColorValue (uint8_t r,uint8_t g,uint8_t b)
{
//根据颜色值修改定时器的比较寄存器值
COLOR_TIMx->COLOR_RED_CCRx = r ;//R
COLOR_TIMx->COLOR_GREEN_CCRx = g; //G
COLOR_TIMx->COLOR_BLUE_CCRx = b;//B
}

本工程提供 SetRGBColor 和 SetColorValue 这两个函数用于设置 RGB 灯的颜色值,这两个函数功能和原理都一样,只是输入参数格式不同,方便使用不同格式的颜色值。
在代码层面,控制 RGB 灯的颜色实质就是控制各个 PWM 通道输出脉冲的占空比,而占空比可以通过设置定时器相应通道的输出比较寄存器值修改,又因为定时器已经把单个控制脉冲周期分成[0:255]份,控制时只要把 RGB888 各通道的颜色值直接赋予给输出比较寄存器即可。

5.主函数

#define SOFT_DELAY() Delay(0xFFFFFF);

void Delay(_IO u32 nCount);
int main(void)
{
	 COLOR_TIMx_LED_Init();//初始化LED灯
	while(1)
	{
		//显示各种颜色
		SetRGBColor (0x8080ff) ;
		SOFT_DELAY () ;
		
		SetRGBColor (0xff8000) ;
		SOFT_DELAY () ;
		
		SetRGBColor (0xffc90e) ; .
		SOFT_DELAY () ;
		
		SetColorValue(181,230,29) ;
		SOFT_DELAY () ;
		
		SetColorValue (255, 128, 64) ;
		SOET_DELAY () ;

	}
}
void Delay(_IO uint32_t nCount)//简单的延时函数
{
	for(; nCount != 0; nCount--) ;

}

main 函数中直接调用了 COLOR_TIMx_LED_Init 函数,而该函数内部又直接调用了前面 讲 解 的 GPIO 和 PWM 配 置 函 数 : COLOR_TIMx_GPIO_Config 和COLOR_TIMx_Mode_Config。初始化完成后,在 while 循环中调用 SetRGBColor 和SetColorValue切换 RGB灯显示的颜色。


总结

编译并下载本程序到开发板,给开发板上电复位,可看到 RGB彩灯显示不同的色彩。

版权声明:本文为CSDN博主「清道 夫」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_44890147/article/details/121499393

生成海报
点赞 0

清道 夫

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

RT-Thread Studio移植LAN8720A驱动

RTT网络协议栈驱动移植(霸天虎) 1、新建工程 ​ 工程路径不含中文路径名,工程名用纯英文不含任何符号。 2、用CubeMx配置板子外设 2.1、配置时钟 ​ 按照自己板子配置相应时钟。

Lin总线通信在STM32作为主机代码以及从机程序

距离上次做资料准备已经过去六天了。最近在学车,上周末就没有开电脑。这周开始进行了Lin通信的代码整理,目前是可以正常通信的了,采用的是增强型校验方式。后期再进一步跟进研究。。。更新一博,留

4路红外循迹模块使用教程

4路红外循迹模块使用教程 个人原创博客:点击浏览模块详细信息: 工作电压:DC 3.3V~5V 工作电流:尽量选择1A以上电源供电 工作温度:-10℃~50℃ 安装孔

HAL库串口中断

一,配置串口初始化 void MX_USART1_UART_Init(void) {huart1.Instance USART1;huart1.Init.BaudRate 115200;huart1.Init.WordLen