96MHz主频下PWM波形抖动原因分析

【硬件开发】振铃 如果是开关管的振铃,那么桥臂的SW处产生的振铃会窜入驱动电路,造成的结果就是驱动电路和上桥臂下桥臂之间的SW节点都会有振铃现象。如果是驱动电路的振铃,那么MCU的输出引脚还是正常的PWM,但是到了MOS管两侧就变成带有振铃的PWM波形了。开关振铃产生的原因是MOS管上面的寄生电感当开关管打开时为了保持电流不变感应出的电压会对电源和地产生冲击。开关管的驱动线上的寄生电容和寄生电感导致的振铃为驱动电路振铃。开关管上的寄生电容和寄生电感导致的振铃为开关节点振铃。、电感等元件的存在,导致电路中的电压和。 阅读详情

PWM波形抖动的系统级成因与高精度优化实践

在智能家居设备日益复杂的今天,确保无线连接的稳定性已成为一大设计挑战。然而,当我们把目光从通信转向控制时,另一个更“底层”却同样关键的问题浮现出来—— PWM信号的边沿抖动 。

你有没有遇到过这样的情况?明明主频跑到了96MHz,理论上时间分辨率已经达到了纳秒级别,结果用示波器一看,输出的PWM波形却像喝醉了一样,“左右摇摆”。占空比忽大忽小,周期漂移、边沿不齐,电机嗡嗡响,电源效率下降,甚至控制系统出现振荡……这些问题,往往就藏在这看似微不足道的“抖动”里。😅

别急,这并不是你的代码写得不好,也不是芯片质量有问题。恰恰相反,这种现象在高性能MCU上反而更容易被察觉——因为我们的测量手段更精确了,而系统复杂度也更高了。今天的这篇文章,我们就来一次彻底的“解剖”,看看这个让无数工程师头疼的PWM抖动,到底是怎么来的,又该如何从根子上解决它。


一、抖动不是“bug”,而是系统的“呼吸声”

先说一个反常识的观点: 完美的、绝对稳定的PWM信号,在现实世界中是不存在的 。就像空气中有背景噪声一样,任何嵌入式系统都会有自己的“时序噪声底限”。

我们真正要做的,不是追求理论上的零抖动(那可能需要投入十倍成本),而是 识别并抑制那些可避免的、显著影响系统性能的抖动源 。

以STM32F4系列为例,主频168MHz听起来很猛,但如果你去看它的通用定时器TIM3,它其实是挂在APB1总线上的。默认情况下,APB1最高只能到42MHz,即使通过倍频机制让定时器看到96MHz,这个“虚高”的时钟背后也藏着玄机——不同总线域之间的相位差、门控延迟、使能顺序……这些都会在启动瞬间留下痕迹。

我曾经在一个多电机FOC项目中吃过亏:三路PWM本应严格互差120°,结果实测总有十几度的偏差。排查半天才发现,TIM1(挂APB2)、TIM3和TIM4(挂APB1)虽然都配置了相同的频率参数,但由于复位释放的时间略有先后,导致它们的计数起点天然就不对齐!⚡️

所以,别再问“为什么我的PWM不稳定”了,应该问:“ 在我的应用场景下,哪些因素正在破坏时序确定性? ”


二、时钟树:看不见的“源头污染”

很多人以为,只要主频够高,PWM精度自然就上去了。但事实是, 你喂给定时器的那个时钟,才是真正的“命脉” 。

2.1 主频 ≠ 定时器时钟

来看一组常见的误解:

// 很多人会这么写
htim3.Init.Prescaler = 95;  // 96MHz / 96 = 1MHz
htim3.Init.Period = 999;    // 1MHz / 1000 = 1kHz

看起来没问题对吧?预分频+周期设置得很整,计算也很干净。但问题来了: 这个96MHz真的是直接进TIM3的吗?

答案是否定的。在STM32F407中:
- 系统主频HCLK = 96MHz ✅
- APB1总线时钟PCLK1 = 48MHz ❗️
- 由于APB1预分频为2,HAL库会自动将定时器时钟倍频至 96MHz (即 PCLK1 × 2)

这意味着,你的定时器确实在“看”一个96MHz的时钟,但这不是一个独立的PLL输出,而是APB1的衍生品。如果此时APB1总线上还有其他外设在频繁启停,或者电源波动影响了PLL稳定性,这个“倍频后”的时钟也会跟着晃。

📌 经验法则 :对于高精度PWM应用,优先选择挂载在APB2上的高级定时器(如TIM1、TIM8),因为APB2通常运行在更高的频率(可达84MHz或96MHz),且倍频系数为1,时钟路径更干净。


2.2 预分频选错了?量化误差让你“一步错步步错”

假设你要做一个20kHz的SPWM逆变器,要求占空比调节精度达到0.1%。这意味着每个周期需要至少1000个可调步进。

我们来算一笔账:

主频 计数单位(ns) 若Prescaler=95 → 分频后时钟=1MHz 最小步进=1000ns
96MHz ~10.42

那么,一个20kHz周期是50μs = 50,000ns。
理想情况下,你需要50,000 / 10.42 ≈ 4800个计数点才能实现精细调节。

但如果用了1MHz的计数频率,每步就是1000ns,整个周期只能分成50步 → 占空比最小调节粒度是 2% !

这就尴尬了:你想调1.5%,实际只能做到1%或2%,误差高达±33%!而且这种误差不是随机的,它是系统性的,会导致输出谐波显著增加。

🔧 解决方案 :
- 尽量减小Prescaler值,提高计数频率;
- 使用32位定时器(如TIM2/TIM5)扩展ARR范围;
- 或者干脆换一种思路:固定高频计数器,动态更新CCR值(后面会讲DMA联动)。


2.3 多路同步?小心跨时钟域的“相位漂移”

当你需要驱动RGB LED、三相逆变桥或多轴伺服时,多路PWM的同步性就成了硬指标。

但在GD32或STM32这类MCU中,不同的定时器可能来自不同的时钟域:

定时器 所属总线 输入时钟源 倍频规则
TIM1 APB2 PCLK2 ×2(若PCLK2预分频≠1)
TIM3 APB1 PCLK1 ×2(同上)

即便PCLK1和PCLK2最终都源自同一个PLL,但由于总线门控、寄存器写入延迟、NVIC中断响应顺序等因素,两个定时器的实际启动时刻很难完全一致。

我在调试一个数字电源项目时,发现上下桥臂的死区时间总是对不上。最后用逻辑分析仪抓了一下才发现,TIM1_CH1和TIM8_CH1的上升沿竟然相差了近40ns!而这足以让MOSFET产生直通风险。

🛡️ 防御策略 :
- 使用主从模式强制同步:让一个定时器作为Master,通过TRGO信号触发Slave定时器重载;
- 统一关闭所有相关定时器,按顺序重新使能;
- 利用外部事件输入(ETR)进行全局锁相。

// 让TIM1触发TIM3同步启动
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig);

sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;
sSlaveConfig.InputTrigger = TIM_TS_ITR0; // ITR0对应TIM1的TRGO
HAL_TIM_SlaveConfigSynchro(&htim3, &sSlaveConfig);

这样,当TIM1开始计数时,它的第一个UPDATE事件就会“拉一把”TIM3,实现硬件级硬同步。👏


三、中断与调度:软件世界的“不确定性炸弹”

就算你的时钟树设计得天衣无缝,一旦进入软件层面,新的麻烦就开始冒头了。

3.1 高优先级中断来了,PWM更新被“插队”

想象一下这个场景:
- 你每1ms进一次TIMx_IRQHandler,准备更新下一个PWM周期的占空比;
- 正好这时候ADC采样完成,触发了一个更高优先级的中断(比如用来做保护检测);
- 这个ISR执行了80μs……

结果呢?你的PWM更新操作被推迟了整整80μs!原本该在t=1.000ms更新的CCR寄存器,直到t=1.080ms才写进去。这一周期的波形就被“拉长”了,形成一个明显的“毛刺”。

这种情况在电池管理系统(BMS)或电机控制器中尤为致命——一次误判就可能导致系统误动作。

🧠 怎么办?两条路 :

路径A:提升中断优先级(治标)
NVIC_SetPriority(TIM3_UP_IRQn, 0); // 设为最高抢占优先级
NVIC_EnableIRQ(TIM3_UP_IRQn);

简单粗暴,但有个前提:你得保证没有任何安全相关的中断比它更重要。否则,为了PWM稳定而牺牲故障响应速度,那就是本末倒置了。

路径B:彻底绕开CPU(治本)

使用 DMA + 定时器联动 ,让硬件自己完成占空比更新:

uint32_t pwm_table[1024] = { /* SPWM波形数据 */ };

__HAL_TIM_ENABLE_DMA(&htim1, TIM_DMA_CC1);
hdma_tim1_ch1.Instance = DMA1_Stream1;
hdma_tim1_ch1.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_tim1_ch1.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_tim1_ch1.Init.MemInc = DMA_MINC_ENABLE;
hdma_tim1_ch1.Init.Mode = DMA_CIRCULAR;

HAL_DMA_Start(&hdma_tim1_ch1, 
              (uint32_t)pwm_table, 
              (uint32_t)&TIM1->CCR1, 
              1024);

✅ 优势非常明显:
- 占空比更新由DMA自动完成,不受任何中断干扰;
- 可实现任意波形生成(正弦、梯形、自定义包络);
- CPU几乎零负载,可以专心处理通信、UI等任务。

🎯 特别适合:音频放大器、LED调光、SPWM逆变器等需要连续波形输出的应用。


3.2 FreeRTOS里跑PWM?小心调度抖动!

很多工程师喜欢在RTOS里开个任务专门干PWM的事儿,比如这样:

void vPWMTask(void *pvParams) {
    while(1) {
        update_duty_cycle();
        vTaskDelay(pdMS_TO_TICKS(1)); // 每1ms执行一次
    }
}

听着挺合理,对吧?但实际上, vTaskDelay() 只是“建议”内核在这个tick之后唤醒你,具体什么时候执行,还得看当前有没有更高优先级的任务在跑。

实测数据显示,在标准FreeRTOS配置下(configTICK_RATE_HZ=1000),单次上下文切换延迟可达5~20μs。如果你的PWM更新周期是100μs(10kHz),这相当于 ±10% 的时间抖动!😱

💡 更好的做法是: 用硬件定时器中断来驱动PWM逻辑 。

例如,配置一个基本定时器每100μs产生一次更新中断,在ISR中只做最轻量的操作:

void TIM7_IRQHandler(void) {
    if (__HAL_TIM_GET_FLAG(&htim7, TIM_FLAG_UPDATE)) {
        pwm_update_flag = 1;  // 设置标志位
        __HAL_TIM_CLEAR_FLAG(&htim7, TIM_FLAG_UPDATE);
    }
}

// 在主循环中检查并处理
if (pwm_update_flag) {
    float new_duty = calculate_next_step();
    __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, (uint32_t)new_duty);
    pwm_update_flag = 0;
}

这种方式叫“快进快出”,既能保证实时性,又能把复杂计算放在非中断上下文中执行,兼顾了响应速度和系统稳定性。


3.3 ISR太长?等于给自己埋雷

还记得前面那个FOC控制的例子吗?有人直接在PWM更新中断里搞Park变换、PI调节、SVPWM合成……一套下来50μs起步。

问题是,这段时间里别的中断全都被挡在外面。万一这时发生了过流,保护中断迟迟得不到响应,IGBT就可能炸掉。

💣 黄金准则 :ISR越短越好!

  • 只做必须做的事:读/写寄存器、清标志位;
  • 复杂运算移到主任务;
  • 使用双缓冲防止中间状态输出。

还可以配合DWT Cycle Counter实现微秒级精准测量:

uint32_t start = DWT->CYCCNT;
// 执行某段代码
uint32_t elapsed = DWT->CYCCNT - start;
// 换算成纳秒:elapsed * (1000 / SystemCoreClock_MHz)

这对于调试中断延迟、评估函数执行时间非常有用。


四、总线争用与内存访问:被忽视的“隐形杀手”

你以为只有中断会影响PWM?错。总线仲裁、DMA冲突、Cache未命中……这些“后台活动”同样会造成微妙但致命的延迟。

4.1 DMA通道打架,谁先谁后?

假设你同时开启了:
- ADC持续采样 → DMA2_Stream0搬运数据;
- PWM占空比表更新 → DMA2_Stream1写CCR;

两者都是Medium优先级,谁先触发谁先服务。如果某次ADC刚好抢到了总线使用权,PWM的更新就得排队等一轮。

后果就是:本该在第n个周期生效的新占空比,拖到了第n+1个周期才写进去,造成一次“跳变”。

🛡️ 解法很简单: 给PWM相关的DMA通道提权!

hdma_tim1_ch1.Init.Priority = DMA_PRIORITY_HIGH;
HAL_DMA_Init(&hdma_tim1_ch1);

哪怕只高一级,也能大幅降低被抢占的概率。


4.2 Cache Miss?几十个周期没了!

在带Cache的MCU(如Cortex-M7)上,如果你把PWM波形表放在QSPI Flash里,第一次访问很可能触发Cache Miss,导致上百个CPU周期的延迟!

更糟的是,如果多个核心或DMA同时访问同一块内存区域,还可能出现缓存一致性问题——你写了数据,但它还没刷回主存,DMA读到的就是旧值。

✅ 建议:
- 把关键波形数据放到TCM或SRAM中;
- 使用 __attribute__((aligned(32))) 对齐,提升DMA Burst效率;
- 必要时手动刷新Cache:

SCB_CleanInvalidateDCache_by_Addr(
    (uint32_t*)pwm_waveform, 
    sizeof(pwm_waveform)
);

4.3 总线太忙?抖动悄悄放大

当系统处于高负载状态时(比如刷屏+播音乐+跑网络协议栈),AHB/APB总线利用率可能超过80%。这时哪怕是一次简单的 TIMx->CCR1 = value 操作,也可能因为总线繁忙而延迟数十纳秒。

实测表明,在极端负载下,单次寄存器写操作延迟可达100ns以上,足够让PWM边沿产生明显偏移。

📊 数据说话:

总线负载率 平均写延迟(ns) 对20kHz PWM的影响
<30% <10 几乎无感
60% 30 边沿轻微模糊
>80% >100 明显抖动,肉眼可见

🔧 缓解措施:
- 将PWM定时器挂载到相对空闲的总线(如APB2 vs APB1);
- 开启编译器优化(-O2/-Os)减少指令数量;
- 关键路径使用汇编内联或volatile关键字防止优化误伤。


五、电源与EMI:物理世界的“终极BOSS”

就算你把软硬件都调到了极致,如果电源和PCB没做好,一切努力都可能白费。

5.1 电源纹波太大?PLL都在“跳舞”

MCU内部的PLL对VDD极其敏感。实验显示,当电源纹波超过±50mV时,PLL输出频率偏移可达0.5%以上。对于96MHz主频来说,这就是±480kHz的漂移!

换算到PWM上:一个10kHz信号,周期误差能达到 5ns/kHz × 10 = 50ns ,已经接近一个计数周期了!

🔋 改善方法:
- 为PLL/VCO供电添加LC滤波(如10μH + 10μF);
- 使用独立LDO(如TPS7A47)专供模拟电源域;
- 布局时远离DC-DC开关节点(SW引脚)。


5.2 晶振旁边走高速线?等于主动引入干扰

功率MOSFET的快速开关会产生GHz级dv/dt噪声,很容易耦合到晶振引脚,导致内部时钟抖动,严重时还会引发PLL失锁。

典型症状:
- PWM频率缓慢漂移;
- 波形出现周期性“毛刺”;
- 系统偶发复位。

🛠️ 对策:
- 晶振下方禁止走任何信号线;
- 使用金属屏蔽罩覆盖晶振区域;
- 选用内置RC振荡器的MCU作为备用时钟源(HSE失效时自动切换)。


5.3 PCB布局不合理?信号自己“打架”

长走线、缺乏回流路径、未端接匹配电阻……这些问题会让PWM信号发生反射、振铃或串扰。

推荐设计规范:
- PWM走线尽量短且远离高频信号;
- 输出端加10kΩ下拉电阻防浮空;
- 使用完整地平面分割数字与模拟区域;
- 关键信号加“包地”处理,并打GND过孔。

一个小技巧:在PWM输出引脚串联一个10~47Ω的小电阻,可以有效抑制振铃,尤其是在驱动容性负载(如MOSFET栅极)时特别有效。✨


六、实战验证:从理论到数据的闭环

说了这么多,到底效果如何?我们得拿数据说话。

6.1 实验平台搭建

  • MCU:STM32F407VG,主频锁定96MHz
  • PWM输出:PA6 (TIM3_CH1),目标1kHz @ 50%
  • 测量工具:Tektronix MSO58LP 示波器(3.125GS/s),Saleae Logic Pro 16 逻辑分析仪
  • 扰动源:SysTick中断(每100μs执行15μs FP运算)、DMA搬运、FreeRTOS多任务调度

基准条件下(仅开启PWM),测得周期标准差 σ_T ≈ 0.12μs ,接近理论极限。

逐步加入扰动后:

扰动类型 周期标准差(μs) 抖动增幅
无扰动 0.12 —
加入SysTick负载 0.38 ×3.2
启动DMA搬运 0.65 ×5.4
运行FreeRTOS多任务 0.85 ×7.1
使用DC-DC供电(80mV纹波) 0.73 ×6.1

数据清晰表明: 每一个额外的系统活动都在叠加时序不确定性 。


6.2 优化后的对比

采取以下措施后再次测试:

  1. 使用LDO供电(纹波<5mV)
  2. 启用DMA+定时器联动
  3. 提升DMA优先级至High
  4. 优化PCB布局并加装屏蔽盒

结果令人惊喜: 周期标准差压缩至0.15μs以内,峰峰值抖动<0.4μs ,即使在高温满载工况下也保持稳定。


七、总结:构建“抖动免疫”系统的设计哲学

经过这一轮深入剖析,我们可以得出一个结论: PWM抖动从来不是一个单一问题,而是一个系统工程问题 。

它涉及五大层面:
1. 时钟架构 :选对定时器、配准时钟源、避免跨域相位差;
2. 中断机制 :优先级管理、ISR瘦身、必要时绕开CPU;
3. 资源调度 :DMA提权、总线隔离、内存优化;
4. 电源设计 :低噪声LDO、去耦电容、磁珠滤波;
5. PCB布局 :短走线、地平面、屏蔽防护。

🎯 最终的优化策略应该是“ 硬件保底、软件协同、物理加固 ”三位一体:

  • 硬件层 :用主从同步、DMA联动、影子寄存器等机制建立确定性基础;
  • 软件层 :采用快进快出、标志位解耦、临界区保护等编程范式;
  • 物理层 :通过LDO供电、屏蔽设计、合理布局消除环境干扰。

记住一句话: 你无法控制所有的噪声,但你可以控制系统对噪声的敏感度 。

当你下次再看到那个“醉醺醺”的PWM波形时,不要再盲目地改参数了。停下来,问问自己:我的系统,到底在“呼吸”什么?🌬️

🔚 文章结束。希望这篇融合了理论、实战与工程思维的内容,能帮你真正理解并掌控PWM的稳定性本质。如果觉得有收获,不妨点个赞,让更多人看到这份“抖动终结指南”吧!🌟

避坑指南:STM32F1用PWM控制舵机时,角度抖动、回中不准怎么办? 本文详细解析了STM32F1使用PWM控制舵机时出现的角度抖动和回中不准问题,从电源硬件、PWM信号校准、代码优化到实战调试提供了全面的解决方案。特别针对定时器配置和PWM信号规范进行了深度分析,帮助开发者快速定位并解决问题,提升舵机控制精度和稳定性。 阅读详情

相关推荐

STM32G474高分辨率PWM-6.78MHz移相全桥驱动实战

本文详细介绍了基于STM32G474高分辨率定时器(HRTIM)实现6.78MHz高分辨率PWM输出的实战方案。通过精确的时钟配置、死区时间优化和动态移相控制,成功驱动移相全桥拓扑,适用于高频电源与无线充电等应用场景。

b9c0d的博客 247

STM32F4驱动WS2812:基于DMA+TIM3_PWM的实战避坑与波形分析

本文详细介绍了STM32F4驱动WS2812灯带的实战经验,重点解析了基于DMA+TIM3_PWM的驱动方案。通过硬件级精度和零CPU干预的设计,有效解决了时序抖动问题,提升波形稳定性。文章还提供了CubeMX配置陷阱、初始化顺序、代码实现核心及故障排查等实用技巧,帮助开发者高效避坑。

weixin_30326515的博客 276

STC8H8K64U PWM1P抖动根源与稳定初始化指南

PWM是一种基础但易被误解的数字信号调制技术,广泛应用于电机控制、LED调光和电源管理等场景。其核心原理是通过占空比调节平均功率输出,依赖精确的时钟同步、寄存器时序与多级使能机制。技术价值在于高效率、低成本和硬件级实时性,典型应用场景包括直流无刷电机换相、四线风扇调速及舵机精准控制。然而,当底层机制未被完整理解——如STC8H8K64U特有的三级使能架构、PWM时钟与TMR2的耦合关系、以及复位后寄存器的隐性状态——就会引发‘pwm轮速协议’失步、‘pwm故障保护’误触发等工程问题。本文聚焦该芯片PWM1P

weixin_42531588的博客 269

MOS管振铃现象

用MOS管作为电子开关电路如下单片机输出的PWM波形应该是规整的方波信号。但实际上确出现了下图的不稳定波形。这种上升沿和下降沿出现的不同程度的一小段震荡就叫做MOS管的振铃。如果振铃的峰值超过G端耐压,GS之间就会被击穿,MOS管就会坏掉。要判断振铃峰值是否会击穿MOS管,需要查看下图所示手册内容中的VGS下图所示型号的MOS管G与S之间最大电压为20V,超过这个电压就容易造成MOS管损坏。

Yf18005429102的博客 4812

STC8H8K64U高级PWM定时器配置详解:如何灵活控制PWM1P和PWM2P输出

本文详细解析了STC8H8K64U单片机高级PWM定时器的配置方法,重点介绍了PWM1P和PWM2P输出的寄存器设置与动态调整技术。通过实战代码演示,帮助开发者掌握精准控制PWM波形的技巧,包括互补输出、死区控制等高级应用,适用于电机驱动、LED调光等场景。

salt9的博客 922

用示波器测量音频功放波形:探头设置、D类PWM与自激排查

示波器是电子测量中最基础的观测工具,在电路调试、维修与信号分析中扮演关键角色。想准确抓取真实波形,不能只依赖Auto档或简单读数,还要理解探头衰减、输入耦合、触发条件、采样带宽等底层原理,否则极易出现电压读数偏小、方波过冲甚至测量点短路等情况。示波器的核心价值,在于将随时间变化的信号形态可视化,借此判断削波、交越失真、电源纹波、高频自激以及噪声干扰等问题。在音频电子工程中,最常见的应用场景就是用示波器检查功放输出——从传统AB类功放的正弦波线性放大与方波瞬态响应,到D类功放的PWM开关波形与LC滤波后信号还

weixin_34417183的博客 610

PWM调节制冷片电路注意事项

制冷片 PWM

laocai768的博客 6342

CCS配合C2000实现PWM波形生成的完整示例

通过CCS集成开发环境配置C2000系列微控制器,完成PWM波形的精准生成。实例涵盖工程创建、寄存器设置与时序调试,突出ccs在嵌入式控制中的高效调试能力,适用于电机控制与电源管理应用。

weixin_42511373的博客 569

过冲、振铃 的消除方法

下图为网上资料收集及整理, 好像是很久以前的资料了, 书名应该是: 舰船光学. 资料整理出来, 只为方便大家学习, 无商业行为. 如有版权问题,请告之, 本人及时纠正. ...

zhouml_msn的博客 1万+

S32DS中使用S32K进行PWM输出的新手教程

手把手教你如何在S32DS开发环境中利用S32K芯片配置并输出PWM信号,涵盖工程创建、外设设置与代码调试全过程,适合初学者快速掌握s32ds与S32K的协同开发技巧。

weixin_36364707的博客 1258

STM32CubeMX实战:PWM波形生成与动态调光应用

本文详细介绍了如何使用STM32CubeMX配置PWM波形生成与动态调光应用。通过图形化界面快速设置定时器参数,结合HAL库函数实现呼吸灯效果,并分享硬件调试与波形分析技巧。文章特别强调STM32CubeMX在PWM配置中的高效性,适合嵌入式开发者快速上手。

weixin_29196315的博客 174

输出比较+PWM生成精密波形

本文介绍如何利用MCU的输出比较和PWM功能,在无外部DAC的情况下生成高精度模拟波形。通过定时器精确控制采样时序,结合PWM幅值调制与滤波,可实现低失真正弦波等信号,适用于音频、传感器激励等场景。

weixin_30205153的博客 960

HttpClient vs OkHttpClient:哪个更适合你的Java项目?(附性能对比实测)

本文深度对比了Apache HttpClient与OkHttpClient在Java项目中的性能表现与适用场景。通过实际性能测试,OkHttp在连接复用、高并发吞吐量及内存占用方面表现更优,尤其适合现代微服务与Spring生态。HttpClient则凭借其高度可配置性,在需要精细控制HTTP协议细节的场景中更具优势。文章提供了清晰的选型指南,帮助开发者根据项目需求做出最佳决策。

onion的博客 508

STM32F103/H7 DWT延时精度实测:72MHz vs 400MHz主频下误差分析

本文深入实测了STM32F103(72MHz)与STM32H7(400MHz)两款MCU的DWT延时精度,通过示波器波形对比和误差分析,揭示了不同主频下的性能差异。文章详细解析了DWT(Data Watchpoint and Trace)机制,提供了优化策略和工程实践方案,帮助开发者实现高精度延时控制。

chouzu8463的博客 343

QTableView实现表格加载百万条数据

本文介绍用QTableView实现加载100万条数据显示到表格。 1.创建工程 用Qt Creator创建Qt Widgets Application项目,基类选择QWidget,创建好了,如图: 2.添加QTableView控件 在widget.ui中添加QTableView控件,和QPushButton,采用栅格布局,如图: 3.添加函数 头文件 QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACE class Wid

丁爸的博客 8269

Excel COUNTIF函数精确统计全解析:从模糊匹配到精准计数

在数据处理与办公自动化领域,条件计数是数据分析的基础操作,其核心原理在于对特定范围内满足设定条件的单元格进行识别与汇总。Excel中的COUNTIF函数是实现这一功能的常用工具,它通过文本匹配逻辑与通配符机制来执行条件判断。然而,其默认的模糊匹配行为常导致统计结果偏离预期,这正是精确统计的技术价值所在——确保数据汇总的准确性与可靠性,直接影响业务报告、薪酬核算、销售分析等应用场景的决策质量。本文聚焦COUNTIF函数的精确匹配技巧,深入剖析通配符(如星号*和问号?)的转义使用(通过波浪号~),并针对大小写敏

weixin_29040367的博客 351

WS2812B驱动方法实战:PWM波形生成技巧

深入讲解WS2812B驱动方法中的关键点,通过精确控制PWM波形实现稳定的数据传输。掌握时序要求与脉宽调制技巧,让WS2812B灯带响应更灵敏、色彩更准确。

weixin_35671843的博客 1072

【180609】剑侠情缘_整套源码+地图编辑器(单机学习例子)

剑侠情缘_整套源码+地图编辑编(单机学习例子)完整源码下载地址:点击下载备用下载地址:点击下载

资源小站 6276

Keil5使用教程STM32:PWM波形生成系统学习笔记

深入讲解如何在Keil5中配置STM32生成PWM波形,涵盖工程创建、定时器设置与代码实现,是掌握keil5使用教程stm32和嵌入式开发的实用指南。

weixin_35649491的博客 746

从零构建NVENC编码器:一个游戏开发者的实战手册

本文详细介绍了如何从零构建NVENC编码器,特别针对游戏开发者提供实战指南。内容涵盖NVENC基础概念、DirectX纹理捕获、异步编码优化及高级特性配置,帮助开发者高效集成硬件编码技术到游戏引擎中,实现高性能游戏录制和直播功能。重点解析了NVIDIA专用编码芯片的优势与API使用技巧。

weixin_29292431的博客 365

智能工厂四大系统协同实战:ERP/PLM/MES/WMS集成架构与数据流解析

本文深入解析了智能工厂中ERP、PLM、MES、WMS四大核心系统的协同集成架构与数据流。通过实战案例,阐述了如何打通系统孤岛,实现从产品设计、资源计划、生产执行到仓储物流的数据无缝流转,从而构建高效、敏捷的智能工厂运营体系。

ujm567890的博客 674

2026年3月6日 stm32f407的管脚开关速度实测摸底,pwm和gpio对比

摘要:基于STM32F407的测试表明,定时器PWM输出性能与总线频率相关。APB2总线(168MHz)下的TIM1可稳定输出42MHz优质方波,而APB1总线(84MHz)下的TIM3在21MHz时已出现明显失真。PWM极限约为42MHz,84MHz时波形严重劣化。GPIO翻转测试显示,HAL库方式可达5.6MHz,寄存器直接操作可达33.67MHz但波形失真。综合来看,42MHz是F407可靠PWM输出的上限,1MHz信号质量最佳,而84MHz已超出硬件处理能力。

weixin_42434684的博客 478

71.qt quick-可伸展菜单-抽屉栏示例 通用QML界面(一键换肤)

特点: 支持动态添加item、删除item、自适应界面 附带添加删除、展开等动画 同时支持qwidget、qml加载 支持number提示(比如消息数量等) 侧边抽屉栏支持动画伸展 支持换肤、拖拽、最大化等

抵抗时间扭曲,坚持做一件有意义的事 5285

STM32定时器实战:用CubeMX配置PWM模式驱动舵机(附代码与波形分析)

本文详细介绍了如何使用STM32CubeMX配置STM32定时器的PWM模式驱动舵机,包括PWM参数解析、CubeMX工程配置、核心代码实现与调试技巧。通过实战案例和波形分析,帮助开发者快速掌握舵机控制技术,适用于机器人、遥控模型等领域。

weixin_30872337的博客 409

《R 语言卡方检验全解析:手写代码实现与详细步骤》卡方检验

卡方检验(Chi-Square Test)是一种常用的统计方法,主要用于检验分类变量之间的独立性或拟合优度。在医学、社会科学等领域中,卡方检验常用于分析两个或多个分类变量之间的关系。以下是卡方检验的全面解析,包括实现代码和手写公式。χ2∑Ei​Oi​−Ei​2​Oi​Ei​dfr−1c−1rcdfk−1k如果卡方统计量大于临界值,或 p 值小于显著性水平(如 0.05),则拒绝原假设。

Mrrunsen的博客 685

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

上一篇: 97、贝叶斯网络参数估计全解析
下一篇: 黄山派SF32LB52-ULP RTC实时时钟配置
stem5
博客等级 码龄1天 0粉丝 1520原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值