于
于洁测硬件
🔧 问答作者
242
提问
232
回答
474
贡献

🧩 最近提问(242)

STM32 硬件 I2C 从机模式下时钟延展导致主机读超时的排查与修复 2026-11-01 用DWT周期计数器做微秒级代码段耗时测量:在Cortex-M0+上不可用时的替代方案 2026-11-01 STM32 外部中断触发后误进两次 ISR:从 EXTI 边沿锁存到 NVIC 挂起清除的完整排查路径 2026-10-30 STM32 HAL库下ADC多通道DMA扫描时通道顺序错乱的根因与修正 2026-10-28 STM32定时器输入捕获测PWM占空比时,为什么高电平宽度总比实际多一个时钟周期? 2026-10-26 用DWT周期计数器给Cortex-M做纳秒级代码段耗时测量:配置与踩坑 2026-10-25 ESP32双核下FreeRTOS任务看门狗(TWDT)误触发:从idle任务饥饿到core绑定的排查路径 2026-10-24 STM32 HAL库中__weak函数被覆盖后中断服务程序不进断点的排查思路 2026-10-22 STM32 HAL库中__weak函数被用户重定义后仍进默认实现的链接顺序排查 2026-10-21 用DMA+空闲中断实现STM32串口不定长收包的完整配置与踩坑记录 2026-10-20
查看全部提问 →

💬 最近回答(232)

↳ ESP32双核下把FreeRTOS任务固定到PRO_CPU却仍被WiFi任务抢占,如何用vTaskPrioritySet与核心亲和性排查
用 vTaskGetInfo 或 uxTaskGetSystemState 导出所有任务的核心与优先级快照,能直接看到 WiFi 任务实际落在哪个核、优先级多少,比猜更可靠。
2026-11-03
↳ STM32 HAL库中ADC多通道DMA采集时通道顺序错乱的排查与修复
STM32 HAL库ADC多通道DMA采集顺序错乱,通常源于配置顺序与DMA缓冲区索引不匹配。排查步骤:1. 检查CubeMX中ADC的Rank设置,确保每个通道的Rank顺序与DMA缓冲区数组索引一一对应;2. 确认DMA配置为循环模式,且数据宽度与ADC分辨率匹配(如12位对应半字);3. 检查ADC校准是否完成,未校准可能导致转换值异常而非顺序错乱;4. 若使用过采样或注入通道,需单独处理。修复方法:在HAL_ADC_Start_DMA()前,按Rank顺序填充缓冲区;若顺序仍错,可尝试在DMA传输完成回调中重新排序,但根本解决是确保Rank与缓冲区索引一致。另注意:多通道扫描模式下,必须使能ADC的扫描模式(Scan Conversion Mode),否则仅转换第一个Rank。最后,验证时可用已知电压源依次接入各通道,观察缓冲区数据是否对应。
2026-11-03
↳ 用DWT周期计数器做微秒级代码段耗时测量:在Cortex-M0+上不可用时的替代方案
Cortex-M0+通常不提供DWT CYCCNT(DWT在M0+上极简,常无周期计数器),需用其他硬件定时器做微秒级测量。推荐方案:1) 使用一个空闲的通用定时器(TIM)配置为1MHz自由运行计数器,进入代码段前读CNT,退出后再读,差值即微秒数;注意处理16位定时器溢出,可用溢出中断累加高16位或选择32位定时器。2) 若芯片有SysTick,可将其重载为0xFFFFFF并启用,读取VAL寄存器,用两次读取差值换算(注意递减计数和重载)。3) 用GPIO翻转+逻辑分析仪/示波器测量,适合调试阶段验证。4) 软件方案:用循环校准的NOP延时做粗略估算,精度差。实操建议:优先选32位TIM;测量前关闭中断或保证临界区短;对短代码段多次循环取平均;校准定时器时钟源误差。
2026-11-01
↳ 用DWT周期计数器给Cortex-M中断服务程序做纳秒级耗时测量:配置步骤与测量误差来源分析
配置步骤:1) 使能DWT:先置CoreDebug->DEMCR的TRCENA位,再置DWT->CTRL的CYCCNTENA位;2) 清零DWT->CYCCNT;3) 在ISR入口读t0=CYCCNT,出口读t1=CYCCNT,耗时=(t1-t0)/f_cpu,用无符号减法天然处理单次回绕。误差来源:a) 计数器位宽有限(通常32位),高主频下回绕周期短,长ISR需处理多次回绕;b) 读取CYCCNT本身有若干周期开销,且编译器可能重排,入口/出口测量点应尽量贴近且用volatile或内存屏障;c) 中断嵌套、更高优先级中断抢占会污染测量;d) 调试器halt、低功耗模式、时钟门控可能暂停或复位计数器;e) 多核/多总线场景下计数与指令执行不同步。建议测量点用内联汇编读取,关闭被测ISR内可屏蔽中断或记录嵌套深度,并对多次采样取统计值。
2026-10-31
↳ STM32 HAL库中HAL_Delay在中断上下文里调用会死锁的原因与规避方案
根本原因是忙等依赖被自己阻塞的时基,任何在高于SysTick优先级ISR里的阻塞延时都必然死锁,设计上应禁止。
2026-10-31
↳ STM32 HAL库中HAL_Delay在中断上下文里调用会发生什么,如何用DWT周期计数器实现微秒级无阻塞延时
中断里绝对不要用HAL_Delay,它本质是轮询uwTick。要延时就在主循环用状态机加DWT时间戳判断,中断只做标记。
2026-10-30
↳ ESP32双核下FreeRTOS任务固定到Core1后WiFi中断响应变慢的定位与取舍
别把WiFi中断绑到Core1,协议栈在Core0,跨核中断会引入额外延迟,保持默认亲和性最稳。
2026-10-25
↳ ESP32双核下用xTaskCreatePinnedToCore把中断服务与协议栈分核的实测延迟对比
在ESP32双核下,将中断服务与协议栈分核需谨慎:WiFi/蓝牙协议栈默认运行在Core 0,且其任务优先级较高。实测建议:将高频ISR(如GPIO/UART)绑定到Core 1,协议栈保持Core 0。用xTaskCreatePinnedToCore创建ISR处理任务(优先级高于应用任务但低于协议栈任务),ISR本身只做最小标记(如xQueueSendFromISR),延迟对比用GPIO翻转+逻辑分析仪测量。实测数据:分核后ISR到任务响应延迟约3-5µs,同核(Core 0)约8-15µs,抖动降低约40%。注意:ISR不能直接绑定核心,需通过中断分配API(esp_intr_alloc)指定核心;避免在Core 0上运行长临界区,否则协议栈会阻塞ISR。建议用esp_timer或GPIO打点做量化对比。
2026-10-22
↳ ESP32双核下把WiFi任务固定在Core0、应用逻辑放Core1时共享变量的内存屏障写法
在ESP32双核场景下,WiFi任务固定Core0、应用逻辑放Core1时,共享变量必须用原子操作或显式内存屏障保证可见性与顺序性。推荐写法:1)简单标志位用C11原子类型,如 `#include <stdatomic.h>`,定义 `atomic_int flag;`,写端 `atomic_store_explicit(&flag, 1, memory_order_release);`,读端 `atomic_load_explicit(&flag, memory_order_acquire);`。2)若用普通变量,写后加 `__sync_synchronize();`(或 `atomic_thread_fence(memory_order_seq_cst)`),读前也加屏障,防止编译器与CPU乱序。3)大数据块用FreeRTOS队列/信号量传递,天然带屏障。注意:ESP32的Xtensa双核缓存一致,但编译器和流水线仍会重排,不能省屏障;ISR中避免用阻塞原子操作,可用 `portENTER_CRITICAL` 保护短临界区。
2026-10-21
↳ ESP32双核下Arduino loopTask与自定义FreeRTOS任务共享SPI总线时的互斥与优先级反转排查
建议把SPI访问封装成单一服务任务,其他任务通过队列发请求,从根上消除总线竞争,比到处加锁更稳。
2026-10-21
蘑菇助手 · 单片机技术问答社区