news 2026/4/18 10:23:40

【stm32简单外设篇】- 三色LED

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【stm32简单外设篇】- 三色LED

一、适用场景
适用场景:状态指示(颜色+亮度表示多种状态)、氛围灯/指示灯、简单人机交互(通过颜色反馈)、学习 PWM 与颜色混合、嵌入式灯光效果(呼吸灯、渐变、跑马灯)与多通道驱动练习。

二、器材清单

三色 LED 模组×1

STM32 开发板(带 TIM / PWM 能力)×1

若干杜邦线(母对母/公对母)×1组

三、工作原理(要点)

三色 LED 内部包含红 (R)、绿 (G)、蓝 (B) 三个发光二极管,分别通过不同比例点亮可混合出多种颜色(加法混色)。

通常用 PWM 控制每一路的占空比实现亮度调节(注意每色的亮度-人眼感知并非线性,若要求美观可做 gamma 校正)。

四、接线示意
GND → GND

标准库

RPA6

GPA7

BPA8

HAL库

RPB4

GPB5

BPB0

五、示例代码
标准库

#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库

/* 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 */ }

六、讲解视频

https://www.bilibili.com/video/BV1DmmoBYEXY/?spm_id_from=333.1387.upload.video_card.click&vd_source=f7dfe1b14f260b9cc3a146d2dbfd0719

https://www.bilibili.com/video/BV1dBmoBzEgZ/?spm_id_from=333.1387.upload.video_card.click&vd_source=f7dfe1b14f260b9cc3a146d2dbfd0719

https://www.bilibili.com/video/BV1RBmoBzEdp/?spm_id_from=333.1387.upload.video_card.click&vd_source=f7dfe1b14f260b9cc3a146d2dbfd0719

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 6:28:04

pkNX深度探索:解锁宝可梦游戏无限可能的编辑神器

pkNX深度探索&#xff1a;解锁宝可梦游戏无限可能的编辑神器 【免费下载链接】pkNX Pokmon (Nintendo Switch) ROM Editor & Randomizer 项目地址: https://gitcode.com/gh_mirrors/pk/pkNX 想要彻底改变宝可梦游戏的体验吗&#xff1f;厌倦了千篇一律的野外遭遇和固…

作者头像 李华
网站建设 2026/4/18 8:29:44

暗黑破坏神II角色编辑器:从新手到专家的完全掌控指南

暗黑破坏神II角色编辑器&#xff1a;从新手到专家的完全掌控指南 【免费下载链接】diablo_edit Diablo II Character editor. 项目地址: https://gitcode.com/gh_mirrors/di/diablo_edit 想要彻底解锁暗黑破坏神II角色编辑器的强大功能吗&#xff1f;这款开源工具为玩家…

作者头像 李华
网站建设 2026/4/15 19:23:17

高效离线包管理:apt-offline完全实战手册

高效离线包管理&#xff1a;apt-offline完全实战手册 【免费下载链接】apt-offline Offline APT Package Manager 项目地址: https://gitcode.com/gh_mirrors/ap/apt-offline 在Linux系统管理工作中&#xff0c;网络连接问题常常成为软件包安装和系统更新的障碍。apt-of…

作者头像 李华
网站建设 2026/4/18 8:20:10

ChanlunX缠论插件:解锁专业K线分析的智能技术新境界

ChanlunX缠论插件&#xff1a;解锁专业K线分析的智能技术新境界 【免费下载链接】ChanlunX 缠中说禅炒股缠论可视化插件 项目地址: https://gitcode.com/gh_mirrors/ch/ChanlunX 想要在复杂的股票市场中找到清晰的技术分析路径吗&#xff1f;ChanlunX缠论插件正是您需要…

作者头像 李华
网站建设 2026/4/18 1:10:46

ESP32蓝牙音频开发终极指南:轻松打造专业级无线音乐系统

ESP32蓝牙音频开发终极指南&#xff1a;轻松打造专业级无线音乐系统 【免费下载链接】ESP32-A2DP A Simple ESP32 Bluetooth A2DP Library (to implement a Music Receiver or Sender) that supports Arduino, PlatformIO and Espressif IDF 项目地址: https://gitcode.com/g…

作者头像 李华