当前位置: 首页 > news >正文

STM32 双 ADC 同步 + 注入通道:同步采样看趋势,过流插队保命

我前阵子做一块伺服驱动板,FOC 算法需要同步采三相电流加母线电压。前期直接用双 ADC 同步模式,电压和电流"同刻"采出来,算出来的转矩稳得一批。但板子打回来做安规测试时出了岔子:堵转过流那一下,MCU 还没来得及反应,驱动芯片先报故障把桥臂锁了——我的过流保护是靠主循环里轮询规则通道数据做的,等轮询到那一帧,过流早过去了几十毫秒,保护形同虚设。

复盘才想明白:双 ADC 同步模式管的是"看得准",但管不了"来得急"。规则通道在后台稳稳扫波形,等它扫完一圈你才读到电流,这个延迟对正常控制够用,对过流保护就太慢了。得把注入通道搬进来——给过流信号开一条硬件 VIP 通道,规则同步采样正在跑,过流一来立刻插队采一下保护点,采完自动回去接着同步采样。两个玩法拧一块,才是完整的"同步采集 + 紧急保护"架构。

一、两套采集为什么要同时存在

单看双 ADC 同步:ADC1 主机 + ADC2 从机,同一个触发沿同时采样,结果打包进 32 位 CDR,DMA 以 Word 宽度搬走。它解决的是"多路零相位差",适合连续、等间隔、要算相位的场景——FOC 的三相电流、功率计的 U/I、差分 IQ 都靠它。

单看注入通道:规则组忙着连续采,注入组平时不动,一旦注入触发来了,硬件暂停当前规则转换、插队采一下紧急信号,存进自己的 JDRx,完事自动回到规则组。它解决的是"随时插一脚",适合过流、过压、按键这些优先级高的采样。

把两个合起来,分工就清楚了:

  • 规则组(双 ADC 同步):负责"看趋势"——连续、同步、算功率/转矩,数据走 CDR 和 DMA。
  • 注入组(同步注入):负责"保命"——过流/过压瞬间插队采保护点,数据走 JDRx,进中断直接关 PWM。

一个 ADC 模块(ADC1+ADC2 这个 common pair)同时干这两件事,互不污染:规则数据在 CDR,注入数据在 JDRx。

二、CubeMX 怎么配

这次配置步骤多一点,因为两个 ADC 各要配"规则 + 注入"两组,外加公共区选对双模式。

1. ADCs_Common_Settings(公共区)

  • Mode下拉选Combined Regular Simultaneous + Injected Simultaneous(ADC_DUALMODE_SIMUL_INJE)。★ 这是本篇最关键的配置。如果只选规则同步(Regular Simultaneous),注入变成普通的单 ADC 注入,两个 ADC 的注入通道各采各的触发,紧急保护采样之间也有相位差——保护这种事差几微秒可能就烧了。
  • DMA Access ModeDMA access mode 1(规则同步走 CDR→DMA)。
  • Delay between 2 sampling phases默认 0。

2. ADC1(主机)规则组

  • 通道勾上同步采样要用的几路(比如 IN0=母线电压、IN1=相电流 U)。
  • External Trigger Conversion Source=TIM1_TRGO(规则组触发),Edge = Rising。
  • Continuous = Disable。

3. ADC1(主机)注入组

  • Injected Conversion ModeNumber Of Conversions填注入通道数(比如 1,过流保护点)。
  • JEXTSEL= 另一个触发源,比如TIM1_TRGO2或比较器输出 / EXTI,★ 别和规则组抢同一个 TIM1_TRGO。
  • JEXTEN= Rising Edge(必须开,注入触发没沿就不启动)。
  • 注入组 Rank、采样时间独立配。
  • NVIC 里打开 ADC 的JEOC(注入转换完成)中断。

4. ADC2(从机)规则组 + 注入组

  • 规则组勾配对的那几路(IN2=相电流 V、IN3=相电流 W),跟着主机同步。
  • 从机的注入组也要配:勾Injected Conversion Mode,同样填通道数,JEXTSEL配成和主机相同的注入触发源,这样注入触发一来,两个 ADC 一起暂停、一起采自己的注入通道(同步插队)。只配主机注入、从机注入留空,同步注入时从机那一路保护点采不到。

5. DMA(挂在 ADC1 上)

  • 给 ADC1 加 DMA,Mode = Circular,Data Width =Word(32 位)。注入组不走 DMA(用中断读 JDRx),DMA 只服务规则组的 CDR。

三、最少的代码

规则组用HAL_ADCEx_MultiModeStart_DMA启动(双 ADC 同步版本),注入组用HAL_ADCEx_InjectedStart_IT启动——而且主机从机都要启动:

#defineDUAL_BUF_LEN128#defineOC_THRESH3500// 过流阈值(按实际标定)uint32_tadc_dual_buf[DUAL_BUF_LEN];// CDR 打包: 低16=ADC1, 高16=ADC2intmain(void){HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_DMA_Init();MX_ADC1_Init();// 主机: 规则+注入都配MX_ADC2_Init();// 从机: 规则+注入都配MX_TIM1_Init();HAL_TIM_Base_Start(&htim1);// 规则组触发源HAL_ADCEx_MultiModeStart_DMA(&hadc1,(uint32_t*)adc_dual_buf,DUAL_BUF_LEN);HAL_ADCEx_InjectedStart_IT(&hadc1);// 主机注入待命HAL_ADCEx_InjectedStart_IT(&hadc2);// ★ 从机注入也要启动, 否则同步注入时从机不采while(1){if(dual_ready){dual_ready=0;for(inti=0;i<DUAL_BUF_LEN;i++){uint16_tv_bus=adc_dual_buf[i]&0xFFFF;// ADC1 低16: 母线电压uint16_tv_iu=(adc_dual_buf[i]>>16)&0xFFFF;// ADC2 高16: 相电流Ufoc_update(v_bus,v_iu);// 同步数据算FOC}}}}// 规则同步完成(主机完成=整组完成)voidHAL_ADC_ConvCpltCallback(ADC_HandleTypeDef*hadc){if(hadc->Instance==ADC1)dual_ready=1;}// 注入同步完成 —— 过流插队到了, 进这里保命voidHAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef*hadc){if(hadc->Instance==ADC1){// 只需判主机, 回调里把两路注入值都读出来uint16_toc1=HAL_ADCEx_InjectedGetValue(&hadc1,ADC_INJECTED_RANK_1);// 主机保护点uint16_toc2=HAL_ADCEx_InjectedGetValue(&hadc2,ADC_INJECTED_RANK_1);// 从机保护点(同步采)if(oc1>OC_THRESH||oc2>OC_THRESH){motor_emergency_stop();// 过流! 立刻封PWM, 比主循环轮询快一个数量级}}}

这段在干嘛:TIM1 一来触发,ADC1+ADC2 同步采规则组(三相+母线),CDR→DMA 搬走给 FOC 用;与此同时注入组由另一个触发源(比如比较器判过流)驱动,一旦过流,硬件暂停规则序列、两个 ADC 同步插队采保护点,进中断读 JDRx 判阈值,超了直接关 PWM。规则采样在后台稳稳跑,过流保护靠硬件插队实时响应,两边谁也不耽误。

★ 注意:注入回调里判hadc->Instance == ADC1(主机)就够了,但在里面把&hadc1&hadc2的注入值都读出来——两个 ADC 是同步注入的,各自 JDRx 里都有值。你只 Start 了主机注入却想在回调里读从机 JDR,从机压根没采,读出来是旧值或 0。

四、真正会坑你的几个点

1. Dual Mode 选成 REGSIMULT。最高频的坑,也是本篇独有的。你图省事选了 Combined Regular Simultaneous,结果规则同步了、注入却不同步——两个 ADC 的注入通道各等各的触发,过流保护采样之间也有 skew,关键时刻差几微秒就晚了。要"规则 + 注入都同步"就选SIMUL_INJE

2. 从机注入组没配 / 没启动。只在 ADC1 里勾了注入、Start 了 ADC1 注入,ADC2 的注入组是空的也没 Start。同步注入触发一来,从机那一路保护点根本没采,你读&hadc2的 JDR 永远是 0。两个 ADC 的注入组都要勾、都要HAL_ADCEx_InjectedStart_IT

3. 注入数据搅进规则 DMA 缓冲。有人看注入也有数据,就想把它和规则数据拼一起搬。错。注入结果在各自 JDRx,规则在 CDR/DMA,两套完全独立。注入 ISR 里只读HAL_ADCEx_InjectedGetValue,别去碰adc_dual_buf,否则规则波形数据被你写乱。

4. 注入打断规则期间 DMA 缓冲错位。同步注入时规则序列被硬件暂停,CDR 的 DMA 传输也跟着停,恢复后继续。这个暂停对你拼接规则缓冲基本无感(DMA 只是停了一下),但★ 如果你在注入 ISR 里又去读/写adc_dual_buf,就可能拿到半截数据。铁律:注入 ISR 只读 JDR,绝不碰规则 DMA 缓冲。

5. 注入触发源和规则触发源抢同一信号。规则用 TIM1_TRGO,注入也配 TIM1_TRGO,两个触发打架,同步节奏全乱。注入换 TIM1_TRGO2、另一定时器、或比较器/EXTI,别和规则组抢同一个 TRGO。

6. 注入触发太频繁打断同步采样。过流信号抖(干扰毛刺、触点弹跳),注入一个接一个来,规则同步 DMA 被反复暂停,FOC 要的连续波形采不全,转矩算出来跳。触发源前面加硬件滤波 / 软件去抖,或只在运行态使能注入中断,保护完进故障态就关掉。

7. CDR 高低 16 位读反。低 16 位 = ADC1(主机)、高 16 位 = ADC2(从机)。>>16取电压和&0xFFFF取电流写反,三相电流和母线电压张冠李戴,FOC 直接飞车。拆包顺序别反。

8. 主从 ADC 都要单独校准。HAL_ADCEx_Calibration_Start(&hadc1)&hadc2两个都做。只校准主机,从机的偏移误差没消除,同步采样两路基准不一致,算出来的功率/转矩带固定偏差。

9. DMA 宽度还是 Half Word。双 ADC 同步的规则 DMA 必须 Word(32 位),和注入无关——注入不占 DMA。你要是按单 ADC 习惯设成 Half Word,每次只搬 16 位,ADC2 那一路(高 16 位)整段丢,相电流 V/W 永远 0 或乱跳。

10. 想用 AUTO_INJECT 代替外部触发插队。CubeMX 里Auto Injected Conversion开了会在每个规则序列结束后自动跑注入组——这是"尾巴附加",不是"随时插队",过流来了也得等当前规则序列扫完才采,保护延迟又回来了。要随时插队就别开 AUTO_INJECT,靠 JEXTSEL 触发源驱动。

五、完整例程骨架

把启动三连和两组回调拼起来:TIM1 触发双 ADC 规则同步(CDR→DMA 给 FOC),注入组由独立触发源驱动同步插队(JDRx→中断保命),主机从机都 Start。规则看趋势、注入保命,一个 ADC 模块干两件事。

HAL_TIM_Base_Start(&htim1);HAL_ADCEx_MultiModeStart_DMA(&hadc1,(uint32_t*)adc_dual_buf,DUAL_BUF_LEN);HAL_ADCEx_InjectedStart_IT(&hadc1);// 主机注入HAL_ADCEx_InjectedStart_IT(&hadc2);// 从机注入(同步插队)// 之后: 主循环拆包CDR算FOC; HAL_ADCEx_InjectedConvCpltCallback里读JDR保命

双 ADC 同步让你"看得准",注入通道让你"来得急"——同步采样负责稳态精度和功率,过流插队负责那几十微秒里的保命,两套采集在一个 ADC 模块里各司其职,才是工业级电机驱动该有的采集架构。

适合:电机 FOC(同步采三相+母线算转矩,过流随时插队保命)、数字电源(同步算功率、过压过流即时保护)、任何"既要连续同步采样、又要紧急采样"的场景。不适合:只用得上其中一项的——纯同步用双 ADC 规则同步模式就够了,纯过流保护用单 ADC 注入通道也够,没必要把两套都开。铁律三条:Dual Mode 选 SIMUL_INJE(规则+注入都同步);主机从机的注入组都要配、都要 Start_IT;规则数据走 CDR-DMA、注入数据走 JDRx-中断,两套绝不混。

http://www.cnnetsun.cn/news/3945183.html

相关文章:

  • AI驱动的Browser-Use网页自动化框架解析与应用
  • 3个关键模块让老Mac重获新生:OpenCore Legacy Patcher完全指南
  • Spring IOC与DI:控制反转与依赖注入详解
  • Translumo终极指南:如何免费实现游戏与视频的实时屏幕翻译
  • B站视频下载工具:解锁大会员4K和充电专属内容的秘密武器
  • 从零构建角色化终端:以安全审计为例的Otaku实战指南
  • PostgreSQL数据库监控:15个核心指标与实施策略
  • c语言链表与结构体
  • 深入探讨辽阳网站建设58的行业现状与未来趋势,揭秘辽阳网站优化58的核心竞争力及辽阳建站公司58的服务流程解析
  • FlowChartCharter:基于多智能体协作与YAML流程配置实现高精度知识库问答
  • PTA基础编程题目集 7-23币值转换(C++语言实现)
  • 中介者模式:解耦复杂交互的设计模式实践
  • 网盘直链下载助手完整指南:九大网盘高速下载免费解决方案
  • Adobe-GenP 3.0:5分钟完成Adobe全系列软件激活的终极指南
  • 关于cesium初始化配置参数说明
  • Noto Emoji字体终极指南:告别乱码,轻松实现跨平台统一表情显示
  • 金融数据分类分级实战系列三:生成全量数据清单
  • WorkshopDL高效指南:一站式免费获取Steam创意工坊模组的智能解决方案
  • VMware虚拟机安装Windows XP Media Centre Edition完整教程与优化指南
  • 终极指南:5个简单步骤让旧Mac免费升级最新macOS系统
  • 多端商城怎么做?一套代码 vs 各端各写,4 个开源项目的实现路线对比
  • 2.宏碁掠夺者擎控制台无法识别电源状态?一次驱动层排查与修复实录
  • ArrayList与LinkedList核心差异及性能对比
  • HTTP请求死循环:原理、检测与防御实践
  • 终极文档下载神器:如何免费下载百度文库、原创力文档等30+平台内容
  • 告别繁琐手动操作:百度网盘批量转存神器5分钟上手指南
  • 如何实现跨平台游戏模组下载:WorkshopDL终极完整指南
  • 从零构建游戏服务器:基于Netty与Java的DNF私服技术解析
  • Palantir 给中国企业上了一课:AI 落地缺的不是模型,是“操作系统“
  • HTTP解析器核心原理与实战:从状态机到高性能网络编程