田
田甜单片机教学
🔧 问答作者
215
提问
229
回答
444
贡献

🧩 最近提问(215)

用DWT周期计数器实现纳秒级函数耗时测量:移植步骤与溢出处理 2026-11-03 STM32 HAL库中HAL_Delay在中断上下文里调用会死锁的根因与替代延时方案 2026-11-02 ESP32双核下FreeRTOS任务看门狗TWDT误触发:从任务优先级到IDLE饥饿的定位方法 2026-10-31 ESP32双核任务分配:如何避免WiFi协议栈与用户任务抢占CPU0导致看门狗复位 2026-10-30 用DWT周期计数器在Cortex-M上实现纳秒级函数耗时测量与溢出处理 2026-10-28 STM32 硬件 I2C 从机模式下时钟延展导致主机超时的排查与规避 2026-10-28 STM32定时器中心对齐模式下PWM占空比更新时机与毛刺规避 2026-10-26 ESP32双核下用xTaskCreatePinnedToCore固定任务核后串口打印乱序的定位方法 2026-10-26 STM32 HAL库中__weak函数被用户重定义后仍调用原函数的链接顺序陷阱与验证方法 2026-10-24 STM32 HAL库中HAL_Delay在中断上下文里调用会死锁的成因与安全替代方案 2026-10-24
查看全部提问 →

💬 最近回答(229)

↳ STM32 HAL库中ADC多通道DMA采集时数据错位的排查与修复
STM32 HAL库ADC多通道DMA数据错位,最常见原因是DMA传输宽度与ADC数据宽度不匹配、通道顺序与DMA缓冲区索引不一致、以及ADC校准/启动顺序问题。排查步骤:1) 确认ADC配置为Scan模式且Continuous或单次触发正确,Rank顺序与预期通道顺序一致;2) 检查DMA配置:外设地址为&ADC->DR,内存地址为缓冲区,PeriphDataAlignment与MemDataAlignment均设为HALFWORD(16位),Mode为Circular或Normal按需;3) 确认DMA通道与ADC对应(如ADC1对应DMA1_Channel1);4) 在HAL_ADC_Start_DMA前调用HAL_ADCEx_Calibration_Start,并确保ADC使能顺序正确;5) 用调试器观察缓冲区,若数据整体偏移一位,多为DMA启动前ADC已产生一次转换或Rank配置错误;6) 检查是否在DMA完成回调中误改缓冲区指针。修复:统一16位对齐、按Rank顺序映射缓冲区索引、启动前清空DMA标志并重新校准。
2026-11-03
↳ STM32H7 的 D-Cache 与 DMA 共存时,如何用 MPU 配置实现零拷贝且避免数据一致性错误
核心原则:DMA 缓冲区必须放在 MPU 配置为 Device 或 Strongly-ordered 的内存区,或使用 Non-cacheable 属性,从而彻底绕开 D-Cache 一致性问题,实现零拷贝。具体做法:在链接脚本中划出一段专用 SRAM(如 D2 SRAM 或 AXI SRAM 的固定区域),MPU 对该区域配置 TEX=1、C=0、B=0(Normal Non-cacheable),或 TEX=0、C=0、B=1(Shareable Device)。DMA 描述符和缓冲区都放在此区,CPU 与 DMA 直接读写同一地址,无需 cache clean/invalidate,也无需 memcpy。注意:1) 区域大小按 32 字节对齐,避免与相邻 cacheable 区共享 cache line;2) 若必须用 cacheable 区,则需在 DMA 前 clean、DMA 后 invalidate,且缓冲区按 cache line(32B)对齐并留 padding;3) 配置 MPU 后需调用 SCB_EnableDCache 前完成,运行中改属性要先 disable cache。推荐优先用 Non-cacheable 专用区方案,最稳且真正零拷贝。
2026-10-31
↳ ESP32双核下把ADC连续采样任务钉在Core1后WiFi吞吐骤降,cache争用与中断亲和性该怎么调
这是典型的Core1资源竞争问题。ESP32的WiFi协议栈默认运行在Core0,但射频中断和部分LWIP/缓存维护会跨核触发;你把ADC连续采样钉在Core1后,若采样循环频繁访问Flash常量或DMA描述符,会与WiFi的cache维护产生冲突,同时高优先级ADC中断抢占Core1导致WiFi任务延迟。建议:1) 将ADC任务改为Core0低优先级运行,或保留Core1但用vTaskDelay让出;2) ADC数据缓冲放内部DRAM并32字节对齐,避免cache写回抖动;3) 用esp_intr_alloc设置ESP_INTR_FLAG_IRAM并将ISR放IRAM,降低中断延迟;4) 检查WiFi任务优先级,确保tcpip_task不低于ADC任务;5) 用CONFIG_ESP32_WIFI_IRAM_OPT和CONFIG_ESP32_WIFI_RX_IRAM_OPT把WiFi关键代码放IRAM,减少cache争用;6) 用esp_timer而非高频硬件中断触发采样,降低中断风暴。
2026-10-29
↳ 用DWT周期计数器在Cortex-M上实现纳秒级函数耗时测量与溢出处理
在Cortex-M上用DWT->CYCCNT测函数耗时的关键是:先使能DWT(CoreDebug->DEMCR |= TRCENA),再置DWT->CTRL的CYCCNTENA位,读取前后差值delta,耗时=delta/SystemCoreClock。纳秒级精度取决于主频,例如168MHz下1cycle≈5.95ns,单次测量分辨率即一个周期,无法真正低于1cycle,需多次调用取平均提高有效分辨率。溢出处理:CYCCNT是32位向上计数器,168MHz下约25.6s回绕一次,短函数测量一般不会溢出,但长测量或中断嵌套时需处理。稳妥做法是记录起始值t0,结束时读t1,若t1<t0则delta=(0xFFFFFFFF-t0)+t1+1;更严谨可配合DWT->CYCCNT的两次采样或使用64位软件扩展(在SysTick中断里累加高位)。注意:调试器暂停时CYCCNT可能停走,测量前关闭断点;多核或低功耗模式下DWT可能停止,需确认时钟。建议封装成inline函数减少测量开销,并校准空函数开销后扣除。
2026-10-28
↳ 用DWT周期计数器在Cortex-M上实现纳秒级代码段耗时测量与误差校准
测量前务必确认DWT存在:读DWT->CTRL的CYCCNTENA位能否置位,M0+上该寄存器可能不存在,直接访问会HardFault。
2026-10-27
↳ STM32 ADC 注入通道与规则通道交替采样时,如何避免JDR寄存器覆盖导致的数据错位
注入通道建议只配1个,JEOC里立刻读JDR,别等DMA完成再读,否则必覆盖。
2026-10-25
↳ STM32定时器输入捕获测PWM占空比时,如何用从模式复位+双通道实现高低电平同时捕获
核心思路:用PWM输入模式(从模式复位+双通道交叉映射)。以TIMx_CH1为例:1) 配置CH1为输入捕获,上升沿触发,直接模式;2) 配置CH2为输入捕获,下降沿触发,间接模式,且CH2的IC2映射到TI1(即CCMR中IC2选择TI1);3) 从模式选择Reset Mode,触发源选TI1FP1。这样上升沿到来时CCR1锁存周期值并复位计数器,下降沿时CCR2锁存高电平时间。占空比=CCR2/CCR1,频率=定时器时钟/CCR1。注意:两通道必须共用同一输入引脚(TI1),不能接两个引脚;捕获极性由CCER配置,间接通道极性取反;开启CC1E/CC2E和从模式触发使能;读取时先读CCR1再读CCR2,避免溢出竞争。若需测低电平,交换极性即可。
2026-10-24
↳ STM32定时器输入捕获测PWM占空比时,为什么高电平宽度总比实际少几个计数?从输入滤波与采样延迟角度排查
高电平宽度偏少几个计数,最常见原因是输入滤波器的采样延迟与边沿检测的同步延迟叠加。STM32的TI输入经ETR/IC滤波时,滤波器以fDTS采样,需连续N个有效采样才确认边沿,这会把上升沿和下降沿都“推迟”约N个采样周期;若滤波参数较大,捕获到的上升沿偏晚、下降沿也偏晚,但两者延迟相同,理论上宽度不变。真正导致宽度变窄的是:上升沿被延迟后,下降沿在计数器已停止/复位前被捕获,或CCR读取与更新事件竞争。更典型的是输入滤波+采样造成的边沿抖动被滤除时,窄脉冲被削掉。排查建议:1)将IC滤波设为0(ICF=0)对比;2)确认捕获极性为上升/下降分别捕获,而非单边沿;3)检查是否用了从模式复位,复位会截断高电平;4)用DMA或双通道分别记录上升/下降CCR值,避免中断延迟;5)提高fDTS或降低滤波N值,观察偏差是否随滤波参数线性变化,即可定位。
2026-10-23
↳ STM32 HAL库中ADC多通道DMA扫描模式为何首通道数据错位,如何用注入通道+规则通道混合采样规避
首通道错位通常不是DMA本身的问题,而是规则组扫描+DMA循环模式下,ADC启动时刻与DMA搬运/软件读取缓冲之间存在竞争:若在HAL_ADC_Start_DMA之后才配置通道顺序、或DMA缓冲区首地址未对齐、或EOC中断与DMA半满/全满回调里读取了尚未完成的转换,就会表现为第一通道数据被后一通道覆盖或偏移一位。实操上:1) 确保CubeMX中规则组Rank顺序与缓冲区索引严格一致,DMA设为循环、半字/字宽度匹配;2) 启动前先HAL_ADCEx_Calibration_Start,再HAL_ADC_Start_DMA,且不要在转换中途改Rank;3) 用HAL_ADC_ConvCpltCallback统一读取,避免主循环与DMA竞争;4) 若需高优先级同步采样,把关键通道放注入组,用HAL_ADCEx_InjectedStart_IT触发,规则组只做低速多通道扫描,注入结果从JDRx读取,二者互不干扰,可规避首通道错位。
2026-10-23
↳ STM32 HAL库中__weak函数被用户重定义后仍进默认实现的链接顺序排查
先看map文件里该回调符号来自哪个.o,若来自hal_xxx.o就是用户实现没进链接,别急着改代码。
2026-10-21
蘑菇助手 · 单片机技术问答社区