1、简单介绍
LED 也叫发光二极管,我们可以简单看一下他的工作原理,主要看一下这个他的发光需要的条件,当然他的发光原理也可以了解一下。
2、分析原理图
1、单片机直接控制LED

单片机直接控制LED,这里先说明各个元器件的作用,
- 发光二极管是发光用的,这里需要了解灯的压降,从而用不同的电阻来控制灯的发光亮度。
- 电阻R1是限流的作用,在不同的灯需要不同的电阻的。
- GNG就是电源的地了,PC13是单片机的控制引脚
我们可以直接通过单片机的引脚控制发光二极管的亮灭或者闪烁等功能,这个部分我们可以通过程序来分析。
2、单片机通过三极管控制USB灯

单片机通过控制三极管来间接控制灯,先分析每个器件的功能和作用,
- USB-A的这个接口就是用来插上USB的灯的,这里USB的接口1和4是供电引脚,2和3是通讯引脚,USB灯没有通讯,只有供电,插上去直接就亮了,我们只需要控制1和4的引脚;
- 这里的三极管是用来做开关使用的,三极管是电流型器件,所以对于电流相对较大的也是可以控制,这样就不会对单片机的引脚造成压力了;
- 电阻R4是限流的作用,防止单片机引脚和三极管的基极电流过大,从而导致器件损毁。
- PB1是单片机的控制引脚,+5 是USB的供电电压,GND是电源地。
3、实物展示
实物均有特纳斯电子拍摄,不加任何丝印,望能为各位同学提供帮助。
1、Led

2、USB灯

4、资料预览
1.原理部分

2.程序部分

5、程序分析
1、流程图

2、LED业务逻辑控制代码(基于STM32 HAL库)
/***************************************************************************************
* 本程序由特纳斯电子创建并免费共享
* 你可以任意查看、使用和修改,并应用到自己的项目之中
* 程序版权归特纳斯电子所有,任何人或组织不得将其据为己有
*
* 程序名称: LED灯驱动程序
* 程序创建时间: 2026.01.09
* 当前程序版本: V1.0
* 当前版本发布时间: 2026.01.09
*
* 特纳斯电子官方网站: www.mcude.com
* 特纳斯电子官方淘宝店: tenas.taobao.com
* 程序介绍及更新动态: https://www.mcude.com/edu/2758/
*
* 如果你发现程序中的漏洞或者笔误,可通过网页向我们反馈: https://www.mcude.com/edu/2758/
***************************************************************************************/
/*********************************************************************
* 文件说明:LED业务逻辑控制代码(基于STM32 HAL库)
* 功能描述:实现LED的熄灭、常亮、慢闪、快闪、状态翻转五种功能
* 实现方式:采用轮询计数模拟计时,需按指定周期调用核心循环函数
********************************************************************/
// 包含自定义LED硬件抽象层头文件(内含LedState枚举、LED引脚宏定义等)
#include "./HAL/LED/LED.H"
// 包含STM32 HAL库GPIO驱动头文件(提供GPIO引脚读写函数)
#include "gpio.h"
// 全局变量:记录LED当前的工作状态,初始化为熄灭状态(LED_OFF)
// LedState为自定义枚举类型,包含LED_OFF/ON/SLOW_BLINK/FAST_BLINK/TOGGLE
LedState currentLedState = LED_OFF;
// 宏定义:LED逻辑循环函数的轮询时间基准,单位为毫秒(ms)
// 建议按此时间间隔调用ledLogicLoop()函数,保证计时准确性
#define LED_POLLING_TIME 10
// 宏定义:慢闪对应的计数阈值(模拟1秒闪烁周期)
// 计算逻辑:总闪烁周期(1000ms) / 轮询基准时间(10ms) = 周期内函数调用次数
#define LED_SLOW_BLINK_TIME (1000 / LED_POLLING_TIME)
// 宏定义:快闪对应的计数阈值(模拟0.2秒闪烁周期)
#define LED_FAST_BLINK_TIME (200 / LED_POLLING_TIME)
// 全局变量:记录ledLogicLoop()函数被调用的次数,用于模拟计时(无硬件定时器依赖)
// 通过累积调用次数,判断是否达到闪烁周期的时间节点
uint32_t callLedCount = 0;
/*********************************************************************
* 函数名称:setLedState
* 函数功能:设置LED的目标工作状态
* 入口参数:state - 要设置的LED状态(LedState枚举类型)
* 出口参数:无
********************************************************************/
void setLedState(LedState state) {
// 将全局变量更新为目标状态,后续逻辑循环会根据此状态执行操作
currentLedState = state;
}
/*********************************************************************
* 函数名称:getLedState
* 函数功能:获取LED当前的工作状态
* 入口参数:无
* 出口参数:LedState - LED当前的工作状态
********************************************************************/
LedState getLedState(void) {
// 直接返回全局状态变量的值
return currentLedState;
}
/*********************************************************************
* 函数名称:ledLogicLoop
* 函数功能:LED业务逻辑核心循环(需按LED_POLLING_TIME周期调用)
* 函数说明:根据当前LED的工作状态,执行对应的GPIO引脚操作
* 入口参数:无
* 出口参数:无
********************************************************************/
void ledLogicLoop(void) {
// 多分支判断:根据当前LED状态执行对应逻辑
switch (currentLedState) {
// 状态1:LED熄灭
case LED_OFF:
// 置位LED对应GPIO引脚(熄灭LED,电平对应关系取决于硬件接线)
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
callLedCount = 0; // 重置调用计数器,避免影响后续其他状态的计时
break;
// 状态2:LED常亮
case LED_ON:
// 复位LED对应GPIO引脚(点亮LED,电平对应关系取决于硬件接线)
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
callLedCount = 0; // 重置调用计数器,避免影响后续其他状态的计时
break;
// 状态3:LED慢闪(1秒周期:亮500ms,灭500ms)
case LED_SLOW_BLINK:
// 闪烁周期前半段:点亮LED(计数未达到周期的1/2)
if (callLedCount < LED_SLOW_BLINK_TIME / 2) {
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
}
// 闪烁周期后半段:熄灭LED(计数达到周期的1/2及以上)
else {
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
// 判断是否完成一个完整闪烁周期,若是则重置计数器,循环闪烁
if (callLedCount >= LED_SLOW_BLINK_TIME) {
callLedCount = 0;
}
}
break;
// 状态4:LED快闪(0.2秒周期:亮100ms,灭100ms)
case LED_FAST_BLINK:
// 闪烁周期前半段:点亮LED(计数未达到周期的1/2)
if (callLedCount < LED_FAST_BLINK_TIME / 2) {
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
}
// 闪烁周期后半段:熄灭LED(计数达到周期的1/2及以上)
else {
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
// 判断是否完成一个完整闪烁周期,若是则重置计数器,循环闪烁
if (callLedCount >= LED_FAST_BLINK_TIME) {
callLedCount = 0;
}
}
break;
// 状态5:LED状态翻转(常亮?熄灭 互转)
case LED_TOGGLE:
// 读取当前LED状态,实现翻转逻辑
if (getLedState() == LED_ON) {
// 若当前是常亮,置位GPIO引脚熄灭LED
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
setLedState(LED_OFF); // 更新全局状态为熄灭
} else {
// 若当前是熄灭,复位GPIO引脚点亮LED
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
setLedState(LED_ON); // 更新全局状态为常亮
}
break;
// 默认分支:防止未定义状态导致程序异常,无实际操作
default:
break;
}
// 每次函数调用后,计数器自增1,累积计数以实现模拟计时
callLedCount++;
}



