ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

超低频PWM调光真的护眼吗?频闪原理与STM32工程实践解析

超低频PWM调光真的护眼吗?频闪原理与STM32工程实践解析 把手机亮度调到最低再用另一台手机相机对准屏幕你经常会看到几条滚动的黑色条纹。很多人以为这只是“相机拍到了屏幕刷新”但实际上这正是 PWM 调光在“露馅”屏幕并不是真的变暗了而是通过快速点亮、熄灭来平均出一档更低的亮度。于是很多做硬件开发的读者会问既然手机屏幕用高频 PWM 是为了减少可见闪烁那我把 PWM 频率做得非常低比如几赫兹、几十赫兹让灯光变化更“缓慢”、更“柔和”是不是反而更护眼这篇文章想先给一个明确判断超低频 PWM 调光并不护眼正常情况下应该尽量避免。这个结论不是感性猜测而是从人眼视觉感知、LED 频闪风险标准、嵌入式 PWM 工程实现三个层面都能说通的。为了让它落地文章后面会结合 STM32 的 PWM 实际配置给出可运行的代码示例、频闪实测方法、常见坑和产品选型建议。无论你是在做 LED 台灯、氛围灯、屏幕背光还是想搞清楚“PWM 频率到底设多少合适”这篇文章都值得读完再收藏。1. 先把结论说清楚超低频 PWM 属于“高风险区”先说一个很容易被误解的点很多人觉得“频率越低变化越慢眼睛看起来越舒适”这其实是把“平滑”和“缓慢”混为一谈了。在照明领域“护眼”主要看几个指标显色指数、色温、亮度均匀性、连续光谱、紫外线/蓝光水平以及非常关键的一项——频闪。而 PWM 调光的频率直接决定了频闪的严重程度。按照常见区间划分PWM 频率区间典型表现更适合的使用场景1Hz ~ 20Hz 超低频肉眼能明确感知一亮一灭非常容易引发不适氛围效果、蜡烛模拟不适合读写照明50Hz ~ 500Hz 低频部分人可感知闪烁眼睛容易疲劳应急照明或低成本场合不推荐1kHz ~ 3kHz 中频多数人感觉不到闪烁但仍存在频闪风险一般 LED 调光可选3.125kHz 以上常见标准中认为高频区域频闪风险明显降低可用作照明 PWM 调光数十 kHz ~ 数百 kHz高频、超高频 PWM可配合滤波实现“准直流”LED 照明、显示背光、电机驱动如果我们把 PWM 频率降到 5Hz、10Hz虽然在示波器上看起来“波形很漂亮”但 LED 灯实际上就是在以 5 到 10 次每秒的节奏重复“点亮—熄灭”。这种闪烁早就超过了人眼正常辨认范围会迫使瞳孔、睫状肌和视觉神经不断调整。长期在这种光线下读写头痛、眼酸、注意力下降都属于常见反馈。所以从频率选择的第一原则来看超低频 PWM 不适合作为护眼调光方案。它更适合被当成一种“效果工具”而不是“照明工具”。2. PWM 信号的核心概念与适用场景2.1 什么是 PWM 信号PWM全称 Pulse Width Modulation脉冲宽度调制。它本质上是一种方波信号信号在“高电平”和“低电平”之间周期切换。一个 PWM 信号由两个关键参数决定频率Frequency每秒钟完成多少个完整周期单位是 Hz。占空比Duty Cycle高电平时间占整个周期的百分比。用 LED 举例如果 PWM 频率是 1kHz占空比是 50%那么 LED 每 1ms 里亮 0.5ms、灭 0.5ms。由于人眼有视觉暂留效应当频率足够高时人眼不会看到闪烁只看到平均亮度下降。这就是 PWM 调光的基础。2.2 PWM 不只是“调光”在嵌入式开发中PWM 实在太常见了。但不同负载对 PWM 频率的要求完全不同PWM 控制电机通常用 10kHz 到 20kHz原因之一是避免频率落在人耳听觉范围内减少电机啸叫。舵机 PWM 控制典型周期是 20ms也就是 50Hz 基础频率脉宽在 1ms 到 2ms 之间变化。这里的 50Hz 只是控制信号频率舵机本身是位置伺服系统并不会像光源那样直接闪烁。PWM 控制风扇风扇有机械惯量转速平滑度可以通过惯性来换取但 PWM 频率过低仍然可能产生周期转动噪声。PWM 触发 ADC 采样在交流电机控制和 LED 电流采样中经常让 PWM 中央对齐时触发 ADC目的是在固定相点采集电流避免开关噪声干扰。PPM 与 PWM 的区别遥控领域常说的 PPM 是脉位调制属于把多路通道打包成串行信号PWM 则是单通道脉宽编码。两者完全不同不能混淆。这些场景说明同一个道理PWM 频率必须根据负载特性选择不存在一个“万能频率”。对于人眼这个负载频率和频闪风险必须重点考虑。3. 为什么超低频 PWM 不护眼频闪、人眼与标准3.1 人眼对频闪的感知能力很多人以为“超过了 60Hz 就看不见闪烁了”这并不准确。人眼的临界闪烁融合频率CFF通常在 50Hz 到 90Hz 左右但这只是“能否明确分辨出亮灭交替”的边界。当 PWM 频率处于 100Hz 到 1kHz 之间时虽然你主观上可能“感觉不到”光源在闪烁但视网膜感光细胞接收到的光强仍然是高频波动。视觉系统会尝试跟随这种波动产生了一系列非主观可感知的生理反应比如瞳孔括约肌持续微调、视觉疲劳、偏头痛敏感人群症状加重。换句话说“看不见闪烁”不等于“没有频闪风险”。3.2 频闪对视觉的影响频闪带来的问题不只是“看起来闪”还有几个实际影响读写时光线不稳定眼睛需要不断适应亮度变化运动物体在频闪光源下会出现“频闪效应”例如旋转的钻头或风扇看起来变慢甚至反转低频 PWM 下LED 照明会让建筑空间产生空间莫尔条纹影响视觉舒适度。超低频 PWM 场景下肉眼能直接看到明暗交替眼部肌肉会跟着光源节奏不断调节这显然不是“护眼”的理想状态。3.3 行业标准和共识在照明行业IEEE 1789 等标准把 LED 频闪风险划分为高风险、低风险和无风险区域并给出频率与调制深度之间的关系。总的方向非常明确频率越高允许的波动范围越宽风险越低频率越低允许的波动范围越窄风险越高行业普遍把 3125Hz 以上视为频闪风险显著降低的高频区间。当然具体产品要满足哪个标准、阈值是多少要以目标市场和最终认证要求为准。这里不过度展开某个具体数字但“低频 低风险”在标准层面并不成立。3.4 为什么有人会误以为“超低频护眼”这种误解主要来自几个渠道呼吸灯、氛围灯看起来很“温馨”让人误以为柔和就是护眼某些“复古”电子蜡烛使用 PWM 模拟火焰低频闪烁反而增加了真实感有人把低频 PWM 和“低频电磁辐射”概念混淆认为频率低就更安全。实际上照明的护眼性看的是光线是否稳定、光谱是否连续、显色是否准确“慢速闪烁”并不会带来额外好处。模拟蜡烛那种低频闪烁是艺术效果不是照明护眼方向。4. 用 STM32 做 PWM 调光CubeMX 配置与核心代码聊完原理进入硬件开发环节。很多读者做 LED 调光时会用 STM32F103C8T6 这类芯片。这里用 STM32CubeMX HAL 库演示。4.1 环境准备建议准备一块 STM32F103C8T6 最小系统板或者任意带 TIM 定时器的 STM32STM32CubeMXSTM32CubeIDE 或 Keil MDK一个 LED 驱动电路三极管/MOSFET 限流电阻或现成 LED 驱动模块示波器或 LED 频闪测试工具。关于 IDE 和固件包版本建议以你手头工程实际版本为准。本文重点演示通用思路并不是某个固定版本的操作手册。4.2 CubeMX 配置要点以 TIM1 的 Channel 1 输出 PWM对应 STM32F103 的 PA8 引脚为例在 STM32CubeMX 中选择 STM32F103C8T6RCC 开启 HSE系统时钟设为 72MHz左侧选择 TIM1将 Channel1 设置为 PWM Generation CH1在 Parameter Settings 里确认 PSC、ARR、Pulse生成初始化代码。PA8 是 TIM1_CH1可以直接连接一个 LED 驱动开关。如果不想用 PA8也可以把 TIM2 的 Channel 映射到 PA0、PA1 等引脚原理相同。4.3 基本 PWM 输出代码CubeMX 生成的tim.c中会包含初始化函数例如// 文件路径Core/Src/tim.c void MX_TIM1_Init(void) { TIM_OC_InitTypeDef sConfigOC {0}; htim1.Instance TIM1; htim1.Init.Prescaler 72 - 1; // 72MHz / 72 1MHz htim1.Init.CounterMode TIM_COUNTERMODE_UP; htim1.Init.Period 1000 - 1; // 1MHz / 1000 1kHz htim1.Init.ClockDivision TIM_CLOCKDIVISION_DIV1; htim1.Init.RepetitionCounter 0; htim1.Init.AutoReloadPreload TIM_AUTORELOAD_PRELOAD_ENABLE; HAL_TIM_PWM_Init(htim1); sConfigOC.OCMode TIM_OCMODE_PWM1; sConfigOC.Pulse 500; // 50% 占空比 sConfigOC.OCPolarity TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(htim1, sConfigOC, TIM_CHANNEL_1); HAL_TIM_MspPostInit(htim1); }在main.c中启动输出// 文件路径Core/Src/main.c int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIM1_Init(); // 启动 TIM1 通道 1 的 PWM 输出 HAL_TIM_PWM_Start(htim1, TIM_CHANNEL_1); while (1) { // 占空比设为 20%即 200 / 1000 __HAL_TIM_SET_COMPARE(htim1, TIM_CHANNEL_1, 200); HAL_Delay(1000); // 占空比设为 80% __HAL_TIM_SET_COMPARE(htim1, TIM_CHANNEL_1, 800); HAL_Delay(1000); } }4.4 动态修改 PWM 频率如果你想直观对比“超低频”和“高频”的视觉效果可以运行时修改 ARR。要注意修改 ARR 后 PWM 频率会改变但占空比通常也需要同步重算。// 动态设置 PWM 频率和占空比 void set_pwm_freq_duty(TIM_HandleTypeDef *htim, uint32_t channel, uint32_t freq_hz, float duty) { uint32_t timer_clock 1000000; // 假设当前 PSC 72-1计数频率 1MHz uint32_t arr timer_clock / freq_hz - 1; uint32_t compare (uint32_t)(duty * (arr 1)); __HAL_TIM_SET_AUTORELOAD(htim, arr); __HAL_TIM_SET_COMPARE(htim, channel, compare); }使用示例while (1) { set_pwm_freq_duty(htim1, TIM_CHANNEL_1, 5, 0.5f); // 5Hz能明显看到闪烁 HAL_Delay(3000); set_pwm_freq_duty(htim1, TIM_CHANNEL_1, 1000, 0.5f); // 1kHz肉眼基本不可见 HAL_Delay(3000); set_pwm_freq_duty(htim1, TIM_CHANNEL_1, 10000, 0.5f);// 10kHz高频 HAL_Delay(3000); }当你把频率降到 5Hz 再看 LED就会明白为什么超低频 PWM 不护眼了它已经不能算“照明”更像是舞台频闪灯。4.5 软件 PWM 的演示与局限STM32 也可以用 GPIO 定时器中断实现软件 PWM适合学习但存在明显局限。// 软件 PWM使用 SysTick 中断1kHz 周期 volatile uint16_t pwm_counter 0; volatile uint16_t pwm_duty 500; // 0 ~ 1000 void SysTick_Handler(void) { if (pwm_counter 1000) { pwm_counter 0; } if (pwm_counter pwm_duty) { HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET); } else { HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET); } }软件 PWM 的主要问题是中断频率越高CPU 占用越大多路软件 PWM 很难做到严格同步如果中断被其他任务打断波形会抖动导致频闪更不规则。所以产品级调光更推荐用硬件定时器或者用 DMA 自动更新比较寄存器。比如用 STM32 的定时器触发的 DMA 将一串占空比序列送入 CCR这样可以生成更复杂的亮度渐变而不占用 CPU。5. 低频频段在工程上的隐藏问题很多朋友设置一个低 PWM 频率后发现“示波器波形是正确的LED 亮度也稳定”但这个“稳定”只停留在平均电流层面。5.1 16 位定时器的 ARR 溢出STM32F103 的 TIM1、TIM2、TIM3、TIM4 中TIM2 和 TIM5 是 32 位计数器TIM1、TIM3、TIM4 是 16 位计数器。16 位计数器最大只能表示 65535。如果系统时钟 72MHzPSC 设为 72-1计数频率是 1MHz1kHz 时ARR 需要 1000-1没问题10kHz 时ARR 需要 100-1没问题5Hz 时ARR 需要 200000-1超过 16 位最大值。想要在 16 位定时器上输出 5Hz就必须把 PSC 调大但这样会导致计数精度下降占空比调节粒度变粗。5.2 高频 PWM 的分辨率下降反过来频率调到 100kHz 时如果计数频率还是 1MHz那么每个周期只有 10 个计数点占空比只能做到 10%、20%、30% 这种粗糙档位根本无法平滑调光。这是 PWM 调光里的经典矛盾频率越高闪烁风险越低但占空比分辨率越低。解决方向有几个提高定时器输入时钟让计数器频率更高使用高分辨率定时器 HRTIM比如 STM32F334 的 HRTIM 可以实现更高精度的 PWM使用英飞凌 AURIX 系列里的 CCU6 等专用于电机控制和 PWM 生成的定时器单元高频 PWM 输出后在负载端加入滤波电路把 PWM 波形变成平滑的直流电流。5.3 LED 驱动器的响应时间还需要考虑 LED 驱动器的开关延迟。PWM 频率太高、占空比太小时一个高电平脉冲可能只有几十纳秒驱动器根本来不及完全导通实际亮度就会低于理论值。这就会导致低亮度下亮度调节不够线性甚至出现“前段突变、后段没变化”。工程上常用处理是加查表补偿把占空比按亮度曲线做非线性修正在极低亮度时使用抖动Dithering技术用多帧平均达到目标亮度用模拟调光代替数字 PWM 调光。6. 如何实测你调出来的 PWM 是否频闪代码写完之后一定要实测。实测方法并不需要昂贵设备。6.1 手机摄像头快速判断把手机相机对准 LED 光源观察取景画面有没有滚动条纹。有滚动条纹说明光源存在明显频闪没有滚动条纹不能完全说明无频闪只是相机采样没有覆盖到某个频段。手机摄像头只能作为“初筛工具”不适合做最终判断。6.2 光电二极管 示波器更可靠的方法是使用光敏二极管或太阳能电池板外加示波器。步骤把一个大面积光电二极管或小太阳能电池板接在示波器探头输入端让 LED 光源直接照射光电二极管示波器选择直流耦合调整时基和幅度观察输出电压波形记录波形的最高值、最低值和频率。如果波形是一条平直线说明光强非常稳定如果波形是一个周期性波动的方波或锯齿波说明存在频闪。还可以利用示波器的 FFT 功能看主频分量出现在哪里。如果主频分量集中在低频段说明 PWM 频率偏低。6.3 利用 PWM 触发 ADC 采样做闭环验证在嵌入式系统里可以更进一步用定时器事件触发 ADC 采样 LED 电流或光敏传感器输出再将结果反馈给 MCU实现闭环调光。这样既能精确掌握 PWM 的真实波形也能验证 LED 驱动是否存在非线性。// 伪代码ADC 采样完成回调中更新占空比 void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) { uint32_t adc_value HAL_ADC_GetValue(hadc); if (adc_value 100) { __HAL_TIM_SET_COMPARE(htim1, TIM_CHANNEL_1, 100); } else { __HAL_TIM_SET_COMPARE(htim1, TIM_CHANNEL_1, (adc_value / 4096) * 900); } HAL_ADC_Start_IT(hadc); }这种做法的价值在于不只看 PWM 引脚波形还能看到光电、电流等最终物理量。7. 常见问题与排查思路问题现象可能原因排查方式解决方案手机相机拍屏幕有滚动条纹PWM 频率与相机卷帘快门产生差频观察条纹分布确认 PWM 频率提高 PWM 频率或改用 DC 调光低亮度时肉眼能看见 LED 闪PWM 频率过低或占空比脉冲过宽示波器测 PWM 引脚和 LED 电流波形提高频率检查驱动最小脉冲宽度频率调高后亮度调节不平滑ARR 太小占空比档位太少计算当前分辨率提高计数频率、使用 HRTIM 或加入抖动修改 ARR 后频率不生效预装载功能导致 ARR 需要在更新事件后才生效检查初始化配置和更新事件关闭预装载或触发更新事件软件 PWM 占用 CPU 过高中断太频繁或代码在中断里处理过多统计中断耗时改用硬件 PWM DMALED 驱动有啸叫PWM 频率落在人耳听觉范围用手机录音或听感判断提高 PWM 频率到 20kHz 以上8. 做产品时的调光选型建议8.1 照明产品优先选高频 PWM 或 DC 调光如果是读写台灯、室内主照明建议PWM 频率不低于 3125Hz最好更高在 LED 驱动输出端加 LC 滤波把 PWM 电流平滑成接近直流的电流或直接使用线性恒流 模拟调光本质上不依赖 PWM 亮度波动。这里的“DC 调光”并不是直接把 PWM 引脚拉高拉低而是用 0-10V、DALI 等模拟或通信协议控制恒流驱动芯片的参考电压从而改变输出电流。这样 LED 电流是平滑的频闪风险最低。8.2 显示产品注意低频 PWM 频段手机 OLED 屏幕早期因为低频 PWM 被用户吐槽“辣眼睛”后来各家都在追求高频 PWM 调光或类 DC 调光。这说明用户对屏幕频闪非常敏感。如果你的项目是在做显示屏背光尽量避免把 PWM 频率设置在 1kHz 以下。驱动方案允许时优先选择几千赫兹以上的 PWM 调光。8.3 特殊效果场景可以单独看超低频 PWM 并非没有价值它特别适合做模拟蜡烛、呼吸灯、氛围灯这类“非照明目的”的产品。例如用 STM32 生成随机变化的 PWM 波形模拟电子蜡烛火焰正是利用了超低频 PWM 的不稳定感来模拟真实火焰。但这是“效果要求”不是“护眼要求”不要混为一谈。8.4 硬件安全和保护不能省用 PWM 控制大功率 LED 或电机时要额外注意驱动管保护。STM32 定时器通常支持刹车输入Break Input和故障保护当检测到过流、过温信号时硬件会强制关闭 PWM 输出。这在电机控制、电源系统中都属于基本要求。在汽车电子和 AUTOSAR MCU 开发中PWM 外设例如英飞凌的 CCU6也会配合故障保护使用。做调光产品时不要只看“能不能闪”还要看“异常时能不能可靠停”。8.5 调光协议要考虑兼容性实际项目中PWM 只是底层输出方式上层还会接调光协议0-10V模拟调光简单可靠适合工业照明DALI数字调光协议支持寻址和状态反馈PWM 控制接口很多 LED 驱动电源直接接受 PWM 信号作为调光输入。做产品时先确认驱动电源支持的调光接口是电压式还是 PWM 式。若把 0-10V 输入设计成 PWM 驱动可能烧毁控制端口。9. 总结与后续学习方向回到最初的问题超低频 PWM 调光是不是也挺护眼的答案很明确不护眼而且应该尽量避免。真正的护眼调光要么把 PWM 频率提高到 3125Hz 以上并控制调制深度要么直接用 DC 调光让 LED 电流尽量平滑。低频 PWM 只是让“看起来变化慢”但这种慢速重复的亮度波动恰恰是视觉系统最需要处理的情况。如果你正在用 STM32 或其他 MCU 做调光项目建议按这个顺序检查确认产品最高可接受 PWM 频率优先选高频检查定时器 ARR 和占空比分辨率是否满足调节精度用示波器和光电二极管实测实际光强波动必要时在驱动输出端加滤波或直接转成模拟调光最后再根据效果需求选择是否加入低频 PWM 的“氛围闪烁”功能。后续还可以深入学习几个方向高分辨率定时器 HRTIM 的互补 PWM 输出、PWM 触发 ADC 采样实现闭环控制、DMA PWM 生成复杂波形、LED 驱动器的恒流控制和输出滤波设计。这些内容都能让同一块 MCU 产生更稳定、更细腻的光。如果你恰好也在做类似项目欢迎在评论区聊聊你最终选的 PWM 频率是多少以及有没有被低频频闪坑过。
返回列表