
一、适用场景
适用场景:状态指示(颜色+亮度表示多种状态)、氛围灯/指示灯、简单人机交互(通过颜色反馈)、学习 PWM 与颜色混合、嵌入式灯光效果(呼吸灯、渐变、跑马灯)与多通道驱动练习。
二、器材清单
三色 LED 模组×1
STM32 开发板(带 TIM / PWM 能力)×1
若干杜邦线(母对母/公对母)×1组
三、工作原理(要点)
三色 LED 内部包含红 (R)、绿 (G)、蓝 (B) 三个发光二极管,分别通过不同比例点亮可混合出多种颜色(加法混色)。
通常用 PWM 控制每一路的占空比实现亮度调节(注意每色的亮度-人眼感知并非线性,若要求美观可做 gamma 校正)。
四、接线示意
GND → GND
标准库
R→ PA6
G→ PA7
B→ PA8
HAL库
R→ PB4
G→ PB5
B→ PB0
五、示例代码
标准库
cpp
#include "stm32f10x.h"
#include "stdio.h"
#include "bsp_SysTick.h"
#include "adc_time.h"
#include "breathing.h"
#include "bsp_usart.h"
#define TIM_arr (10-1)
#define TIM_psc (72-1)
#define TIM_ccr1 5
static void TIM1_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形 GPIOA.8
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM1_CH1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//设置该引脚为复用输出功能,输出TIM1 CH2的PWM脉冲波形 GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //TIM1_CH2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//设置该引脚为复用输出功能,输出TIM1 CH3的PWM脉冲波形 GPIOA.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //TIM1_CH3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//设置该引脚为复用输出功能,输出TIM1 CH4的PWM脉冲波形 GPIOA.11
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //TIM1_CH4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void pwm_init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //设置为复用推挽输出
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
TIM_TimeBaseInitStructure.TIM_Period=arr;
TIM_TimeBaseInitStructure.TIM_Prescaler=psc;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM2;
TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;
TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;
TIM_OCInitStruct.TIM_Pulse=12;
TIM_OC1Init(TIM3,&TIM_OCInitStruct);
TIM_OCInitStruct.TIM_Pulse=24;
TIM_OC2Init(TIM3,&TIM_OCInitStruct);
TIM_OCInitStruct.TIM_Pulse=36;
TIM_OC3Init(TIM3,&TIM_OCInitStruct);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能预装载寄存器
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能预装载寄存器
TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能预装载寄存器
TIM_Cmd(TIM3,ENABLE);
}
static void TIM1_Model_Config(void)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
// 开启定时器时钟,即内部时钟CK_INT=72M
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
/*--------------------时基结构体初始化-------------------------*/
// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
TIM_TimeBaseStructure.TIM_Period=TIM_arr;
TIM_TimeBaseStructure.TIM_Prescaler= TIM_psc; // 驱动CNT计数器的时钟 = Fck_int/(psc+1)
// 时钟分频因子 ,配置死区时间时需要用到
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; //不分频
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;// 计数器计数模式,设置为向上计数
// 重复计数器的值,没用到不用管
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);// 初始化定时器
/*-------------------------输出比较结构体初始化---------------------------------*/
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;// 配置为PWM模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;// 输出通道电平极性配置
TIM_OCInitStructure.TIM_Pulse = 5;// 设置占空比大小red
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);//使能TIM1在CCR1上的预装载寄存器
//ch2 PWM模式
TIM_OCInitStructure.TIM_Pulse = 0;// 设置占空比大小greed
TIM_OC2Init(TIM1, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);//使能TIM1在CCR1上的预装载寄存器
//ch3 PWM模式
TIM_OCInitStructure.TIM_Pulse = 10;// 设置占空比大小blue
TIM_OC3Init(TIM1, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);//使能TIM1在CCR1上的预装载寄存器
//ch4 PWM模式
TIM_OCInitStructure.TIM_Pulse = 0;// 设置占空比大小
TIM_OC4Init(TIM1, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);//使能TIM1在CCR1上的预装载寄存器
TIM_Cmd(TIM1, ENABLE); // 使能计数器
}
void TIM1_Init(void)
{
TIM1_GPIO_Config();
TIM1_Model_Config();
}
//int main(void)
//{
// /* 高级定时器初始化 */
// TIM1_Init();
//
// while(1)
// {
//
// }
//}
int main()
{
int i,j,z;
SysTick_Init();
USART_Config();
pwm_init(49,0);
while(1)
{
i++;
j--;
z++;
if(i>=40 || j<=0 | z>=40)
{
i=j=z=0;
}
TIM_SetCompare1(TIM3,50);
TIM_SetCompare2(TIM3,50);
TIM_SetCompare3(TIM3,50);
Delay_us(500000);
}
// return 0;
}
HAL库
cpp
/* TIM3 init function */
void MX_TIM3_Init(void)
{
/* USER CODE BEGIN TIM3_Init 0 */
/* USER CODE END TIM3_Init 0 */
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM3_Init 1 */
// 72000000/720/2000=50 1/50=20ms
/* USER CODE END TIM3_Init 1 */
htim3.Instance = TIM3;
htim3.Init.Prescaler = 200-1;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 1024-1;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM2;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM3_Init 2 */
/* USER CODE END TIM3_Init 2 */
HAL_TIM_MspPostInit(&htim3);
}
int main(void)
{
/* USER CODE BEGIN 1 */
/* 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_USART1_UART_Init();
MX_TIM3_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);//定时器PWM初始化
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);//定时器PWM初始化
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_3);//定时器PWM初始化
HAL_TIM_Base_Start_IT(&htim4);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
/*
*/
pwm_output=1;
while (1)
{
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 1023); // 50%占空比
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 0);
HAL_Delay(500);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 0); // 50%占空比
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 1023);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 0);
HAL_Delay(500);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 0); // 50%占空比
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 1023);
HAL_Delay(500);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 1023); // 50%占空比
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 1023);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 0);
HAL_Delay(500);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 0); // 50%占空比
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 1023);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 1023);
HAL_Delay(500);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 1023); // 50%占空比
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 1023);
HAL_Delay(500);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 1023); // 50%占空比
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 1023);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 1023);
HAL_Delay(500);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 1023); // 50%占空比
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 512);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 0);
HAL_Delay(500);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 1023); // 50%占空比
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 512);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 768);
HAL_Delay(500);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 0); // 50%占空比
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 512);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 1023);
HAL_Delay(500);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 512); // 50%占空比
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 256);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 0);
HAL_Delay(500);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 512); // 50%占空比
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 768);
HAL_Delay(500);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
六、讲解视频