TM4C123G Tiva C系列无PWM实现RGB呼吸灯C代码解析
TM4C123G 无硬件PWM实现RGB呼吸灯指导
现有代码逻辑解读
- 硬件初始化部分
- 操作寄存器打开GPIOF端口的时钟:
SYSCTL_RCGC2_R对应系统控制模块的时钟门控寄存器,写入SYSCTL_RCGC2_GPIOF即为GPIOF端口供电,是操作GPIOF引脚的前置必要步骤 - 配置PF1/PF2/PF3三个引脚为数字输出模式:
GPIO_PORTF_DIR_R=0x0E将三个引脚设为输出方向,GPIO_PORTF_DEN_R=0x0E开启引脚数字功能,这三个引脚正好对应板载RGB LED的红、蓝、绿通道 - 循环部分仅操作PF1引脚(对应数值0x02,即PF1控制位),通过固定时长的高低电平切换控制红灯亮灭
- 操作寄存器打开GPIOF端口的时钟:
- 现有代码的核心问题
- 高低电平的切换间隔为秒级,方波频率不到0.1Hz,人眼可以清晰分辨出亮灭跳变,本质是不同节奏的闪烁,不会产生亮度渐变效果
- 没有固定的方波周期,只是硬编码了多组长短不一的亮灭时长,无法通过占空比调整等效平均亮度
- 延时函数存在参数截断问题:形参
sec为double类型,但内部循环变量c为int,传入带小数的延时值时,小数部分会被直接丢弃,实际延时长度和预期偏差很大;且双层循环的延时为硬编码值,会受编译优化等级影响,精度很差 - 原有代码中传入
delay(0)时,因为循环判定条件为c<=sec,实际不会进入循环体,相当于无延时,进一步打乱了高低电平的固定时序 - 全局变量
cond从未在程序逻辑中被使用,属于无意义的冗余代码
无PWM实现呼吸灯的核心原理
利用人眼的视觉暂留特性:当电平切换速度高于人眼的闪烁感知阈值(通常≥100Hz)时,人眼无法分辨出单次的亮灭跳变,只会感知到LED的平均光强。通过软件手动生成高频方波,调整一个完整周期内高电平的时间占比(即占空比),就可以等效调节LED的平均亮度——占空比越高,高电平持续时间越长,LED平均亮度越亮;占空比越低,亮度越暗。
- 不需要硬件PWM模块,仅靠普通GPIO翻转即可实现等效的亮度调节
- 只要方波频率足够高,人眼不会察觉到闪烁,只会感受到平滑的亮度渐变
- 循环让占空比从0%逐步升到100%,再从100%逐步降到0%,就可以实现从暗到亮、再从亮到暗的呼吸效果
具体实现思路
- 重构延时函数
- 替换原来的长秒级延时,校准出可调节的微秒级短延时,支撑高频的GPIO电平翻转
- 移除形参的类型截断问题,保证不同时长的延时可以精准控制
- 定义固定的方波基频
- 选择2ms作为单个方波的总周期(对应500Hz频率,远高于人眼无闪烁阈值),把这个总周期拆成100个等长的微时间片(每个时间片20us)
- 实现占空比的动态调整
- 呼吸上升阶段:占空比从0%逐步提升到100%,即每个方波周期内,高电平持续的时间从0个时间片慢慢增加到100个时间片,低电平持续时间对应从100个时间片减少到0个时间片,LED从全暗慢慢变到全亮
- 呼吸下降阶段:占空比从100%逐步降到0%,和上升阶段反向操作,LED从全亮慢慢回到全暗
- 两个阶段循环往复,即可得到平滑的呼吸效果
- 注意硬件电平匹配
- 根据你现有代码的逻辑,你使用的板载LED为GPIO输出高电平时点亮、低电平时熄灭,调整占空比时不需要翻转点亮逻辑,直接和现有操作方式对齐即可
内容的提问来源于stack exchange,提问作者Alexa
相关产品推荐
相关产品推荐

