news 2026/2/15 15:25:12

【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/2/15 3:24:48

清华大学LaTeX论文模板完全攻略:5步掌握专业学术排版

清华大学LaTeX论文模板完全攻略&#xff1a;5步掌握专业学术排版 【免费下载链接】thuthesis LaTeX Thesis Template for Tsinghua University 项目地址: https://gitcode.com/gh_mirrors/th/thuthesis 还在为毕业论文的格式要求头疼吗&#xff1f;清华大学官方推出的Th…

作者头像 李华
网站建设 2026/2/8 22:33:21

Topit窗口置顶大师:重新定义Mac多任务工作流

Topit作为一款专业的Mac窗口置顶工具&#xff0c;通过创新的层级控制技术&#xff0c;让任意应用程序窗口都能稳定悬浮在屏幕最前端&#xff0c;彻底解决窗口遮挡问题&#xff0c;为现代多任务工作环境带来革命性的效率提升。 【免费下载链接】Topit Pin any window to the top…

作者头像 李华
网站建设 2026/2/10 3:18:57

突破性体验:IndexTTS2语音合成系统让AI语音触手可及

突破性体验&#xff1a;IndexTTS2语音合成系统让AI语音触手可及 【免费下载链接】index-tts An Industrial-Level Controllable and Efficient Zero-Shot Text-To-Speech System 项目地址: https://gitcode.com/gh_mirrors/in/index-tts IndexTTS2作为新一代工业级可控零…

作者头像 李华
网站建设 2026/2/9 7:52:30

XCOM 2 AML启动器:模组管理的技术解决方案

XCOM 2 AML启动器&#xff1a;模组管理的技术解决方案 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/xcom2-lau…

作者头像 李华
网站建设 2026/2/7 21:35:38

WzComparerR2终极完整指南:从新手到高手的冒险岛资源提取工具

WzComparerR2终极完整指南&#xff1a;从新手到高手的冒险岛资源提取工具 【免费下载链接】WzComparerR2 Maplestory online Extractor 项目地址: https://gitcode.com/gh_mirrors/wz/WzComparerR2 作为冒险岛玩家和开发者必备的资源提取神器&#xff0c;WzComparerR2以…

作者头像 李华
网站建设 2026/2/11 18:48:48

B站缓存视频转换完整指南:快速解锁永久播放权限

B站缓存视频转换完整指南&#xff1a;快速解锁永久播放权限 【免费下载链接】m4s-converter 将bilibili缓存的m4s转成mp4(读PC端缓存目录) 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter m4s-converter是一款专为解决B站缓存视频播放难题而设计的工具软件…

作者头像 李华