ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

英飞凌AURIX TC3xx GTM PWM配置实战:从TOM到ATOM

英飞凌AURIX TC3xx GTM PWM配置实战:从TOM到ATOM 1. 为什么TC3xx的PWM配置不能照搬STM32那套思路刚接触英飞凌AURIX TC3xx系列的人十有八九是从STM32或者类似的MCU转过来的。在STM32上配PWM思路很直接开时钟、配GPIO复用、设ARR和PSC、配CCR、使能输出完事。到了TC3xx上很多人第一反应是去找类似的定时器模块然后发现——CCU6确实能出PWM但如果你想做多通道、高精度、带死区、甚至和电机控制强相关的PWM社区里几乎所有人都会指向同一个模块GTM。GTM全称Generic Timer Module通用定时器模块。它不是传统意义上的一个定时器而是一整套定时器子系统内部由多个子模块拼装而成包括TOM、ATOM、TIM、DTM、MCS、SPE、PSM、CMU、TBU等等。你可以把它理解成一个定时器乐高不同子模块负责不同职责通过内部总线互联最终输出你想要的波形。为什么TC3xx要搞这么复杂因为汽车电子里的PWM需求差异极大。有的场景要几十路独立PWM有的要中心对齐加死区有的要跟ADC采样精确同步有的要做PWM输入捕获测转速。传统单一CCU6定时器搞不定这些GTM就是为这种多面手需求设计的。但代价也很明显GTM的配置复杂度远高于普通定时器。时钟树要一层层算子模块要一个个使能寄存器要按顺序写稍有不慎就是配置全对但没波形。我见过太多人卡在TOM通道配好了但引脚没输出这种问题上一查就是CMU时钟没使能或者端口复用没切到GTM。这篇内容就是把我自己在TC3xx上从零跑通GTM PWM的完整过程拆开讲。目标很明确用TOM子模块输出一路标准PWM给出可直接复用的代码同时把每一步背后的为什么讲清楚。适合已经上手TC3xx、但被GTM文档劝退过的嵌入式工程师也适合正在做电机控制、LED驱动、舵机控制这类需要PWM外设的项目的人。提示本文以TC375为例其他TC3xx型号的GTM结构基本一致差异主要在端口映射和时钟频率上代码框架可以直接迁移。2. GTM内部到底谁在干活TOM、ATOM、CMU的分工在动手写代码之前必须先把GTM内部的角色分工搞清楚。否则你会在文档里看到一堆缩写完全不知道哪个该配、哪个不用管。2.1 TOM最常用的PWM输出单元TOM全称Timer Output Module是GTM里专门负责输出比较的子模块。一个GTM实例通常有多个TOM每个TOM有16个通道分成两组TOM0_CH0~7和TOM0_CH8~15。每个通道都能独立输出PWM互不干扰。TOM的工作逻辑很朴素内部有一个计数器CNT从0开始往上数数到CM0寄存器的值就归零重新开始。同时每个通道有两个比较寄存器CM1和CM2CNT和它们比较决定输出电平什么时候翻转。这就是典型的边沿对齐PWM。具体来说TOM通道有两种输出模式PWM模式模式1CNT CM1时输出一种电平CNT CM1时翻转周期由CM0决定。这种模式下占空比 CM1 / CM0。PWM模式模式2用CM1和CM2两个比较值可以产生更灵活的波形比如相位偏移。对于绝大多数应用模式1就够了。周期 (CM0 1) × TOM时钟周期占空比 CM1 / (CM0 1)。2.2 ATOM带死区、带ADC触发的进阶版ATOM全称ARU-connected Timer Output Module比TOM多了两个关键能力死区生成和ARU互联。死区是电机H桥驱动必须的防止上下管同时导通。ARU是GTM内部的跨模块通信总线ATOM可以通过ARU和其他子模块比如ADC、MCS联动。如果你只是点个LED、驱动个舵机TOM完全够用。但如果你在做BLDC电机控制、需要互补PWM加死区那就得上ATOM。本文先用TOM把基础跑通ATOM留到后续进阶。2.3 CMU所有子模块的时钟源头CMU全称Cluster Management Unit是GTM的总闸。它负责给GTM内部各个子模块分配时钟。这是新手最容易忽略的一环你在TOM里配了半天结果CMU没使能TOM的时钟寄存器写进去也没用输出永远是死的。CMU里有个关键寄存器叫CMU_CLK_EN每一位对应一个时钟使能。TOM的时钟通常来自CMU_CLK0到CMU_CLK7中的某几个。具体哪个TOM用哪个时钟要看芯片手册的时钟分配表。TC375上TOM0通常挂在CLK0上。CMU的时钟源又来自GTM的全局时钟而全局时钟由GTM_CLS_CLK_CFG寄存器配置分频。所以完整链路是系统时钟 → GTM全局时钟 → CMU分频 → TOM通道时钟 → PWM周期每一级都要算清楚否则出来的频率和你预期差十万八千里。2.4 端口映射GTM信号怎么跑到引脚上GTM内部产生的是逻辑信号要真正输出到芯片引脚还得经过端口控制模块。TC3xx的每个引脚都有多个复用功能GTM输出通常映射到ALT功能上。比如TC375的P02.0可以复用为TOM0_0输出但默认可能是GPIO。这一步需要配置PORT模块的IOCR寄存器把对应引脚的输出功能切到GTM。很多人卡在波形在GTM内部有但引脚测不到99%是这一步没做。3. 从系统时钟到PWM频率完整时钟链路计算配置GTM PWM最核心的一步是算清楚时钟。算错了频率就不对。我见过有人想要1kHz结果出来是1.6kHz查了半天发现是CMU分频算错了。3.1 先确定GTM的输入时钟TC3xx的GTM时钟源通常来自系统PLL。以TC375为例假设系统时钟f_SPB 100MHzGTM的全局时钟由GTM_CLS_CLK_CFG寄存器配置。这个寄存器里有个CLS_CLK_DIV字段可以对输入时钟分频。假设我们不分频GTM全局时钟 100MHz。3.2 CMU分频决定TOM的计数时钟CMU里每个CLK都有独立的分频配置。以CMU_CLK0为例它的分频由CMU_CLK_CFG寄存器控制分频系数可以是1、2、4、8、16等。假设我们配置CMU_CLK0分频为1那么TOM0的计数时钟 100MHz。3.3 TOM周期计算CM0决定频率TOM通道的PWM频率公式f_PWM f_TOM / (CM0 1)其中f_TOM是TOM通道的计数时钟。如果我们要输出1kHz的PWMCM0 1 100MHz / 1kHz 100000 CM0 99999CM0是16位寄存器最大值65535。100000超过了所以必须先用CMU分频。把CMU_CLK0分频设为2则f_TOM 50MHzCM0 1 50MHz / 1kHz 50000 CM0 4999949999在16位范围内可行。3.4 占空比计算CM1决定高电平时间假设要50%占空比CM1 (CM0 1) × 50% 25000如果要25%CM1 50000 × 25% 12500注意CM1必须小于CM0否则输出会一直是一个电平。3.5 一张表看清所有参数参数值说明系统时钟100MHzTC375典型值GTM全局时钟100MHz不分频CMU_CLK0分频2得到50MHzTOM计数时钟50MHzCMU输出CM049999周期计数CM12500050%占空比PWM频率1kHz50MHz / 50000占空比50%25000 / 50000这张表建议你配置前先填一遍把所有参数算清楚再写代码比写完再调试快得多。注意不同TC3xx型号的GTM时钟源频率不同务必查你手上芯片的时钟树章节。TC375、TC387、TC397的GTM时钟可能来自不同的PLL分支。4. 寄存器级配置一步步把TOM通道跑起来现在进入实操。我按配置顺序把每一步拆开每步都说明为什么这么写。4.1 第一步使能GTM全局时钟在配置任何GTM子模块之前必须先让GTM模块本身有时钟。这通过GTM_CLS_CLK_CFG寄存器完成。// 使能GTM全局时钟不分频 GTM_CLS_CLK_CFG.B.CLS_CLK_DIV 0; GTM_CLS_CLK_CFG.B.CLS_CLK_EN 1;CLS_CLK_DIV 0表示不分频CLS_CLK_EN 1使能时钟。这一步不做后面所有寄存器写入都是无效的。4.2 第二步配置CMU给TOM分配时钟CMU的配置分两步先配置时钟分频再使能对应时钟。// 配置CMU_CLK0分频为2 CMU_CLK_CFG.B.CLK0_DIV 1; // 1表示分频2 CMU_CLK_CFG.B.CLK0_EN 1; // 使能CLK0 // 使能TOM0的时钟 CMU_CLK_EN.B.EN_CLK0 1; // TOM0使用CLK0这里CLK0_DIV 1对应分频2是因为CMU的分频字段是分频值减1的编码方式。具体编码要看手册不同型号可能不同。4.3 第三步配置TOM通道为PWM模式TOM通道的配置涉及几个关键寄存器TOM0_CH0_CTRL通道控制设置输出模式TOM0_CH0_CM0周期TOM0_CH0_CM1占空比TOM0_CH0_SR0输出电平配置// 配置TOM0通道0为PWM模式 TOM0_CH0_CTRL.B.SL 1; // 选择CM0作为周期 TOM0_CH0_CTRL.B.CLK_SRC 0; // 使用CMU_CLK0 TOM0_CH0_CTRL.B.RST_CCU0 0; // CNT归零由CM0触发 // 设置周期和占空比 TOM0_CH0_CM0.B.CM0 49999; // 周期 TOM0_CH0_CM1.B.CM1 25000; // 50%占空比 // 配置输出电平CNT CM1时高电平 TOM0_CH0_SR0.B.SR0 1; TOM0_CH0_SR0.B.SR1 0;SL 1表示用CM0作为周期寄存器。CLK_SRC 0选择CMU_CLK0。SR0和SR1决定CNT和CM1比较时输出的电平。4.4 第四步使能TOM通道输出配置完参数后还要使能通道输出TOM0_CH0_CTRL.B.EN 1; // 使能通道这一步不做通道不会输出波形。4.5 第五步配置端口复用把信号引到引脚这是最容易漏的一步。以TC375的P02.0为例它需要配置为TOM0_0输出// 配置P02.0为GTM输出 PORT2_IOCR0.B.PC0 0x11; // ALT1 TOM0_0PC0字段控制P02.0的复用功能。0x11对应ALT1具体值要看手册的端口复用表。不同引脚的ALT编号不同务必查表。4.6 完整代码示例把上面所有步骤串起来void GTM_TOM_PWM_Init(void) { // 1. 使能GTM全局时钟 GTM_CLS_CLK_CFG.B.CLS_CLK_DIV 0; GTM_CLS_CLK_CFG.B.CLS_CLK_EN 1; // 2. 配置CMU_CLK0分频为2使能 CMU_CLK_CFG.B.CLK0_DIV 1; CMU_CLK_CFG.B.CLK0_EN 1; CMU_CLK_EN.B.EN_CLK0 1; // 3. 配置TOM0通道0 TOM0_CH0_CTRL.B.SL 1; TOM0_CH0_CTRL.B.CLK_SRC 0; TOM0_CH0_CTRL.B.RST_CCU0 0; TOM0_CH0_CM0.B.CM0 49999; TOM0_CH0_CM1.B.CM1 25000; TOM0_CH0_SR0.B.SR0 1; TOM0_CH0_SR0.B.SR1 0; // 4. 使能通道 TOM0_CH0_CTRL.B.EN 1; // 5. 配置端口复用 PORT2_IOCR0.B.PC0 0x11; }这段代码在TC375上实测可以输出1kHz、50%占空比的PWM。你可以用示波器在P02.0上直接测到波形。5. 实测中踩过的坑波形不出来怎么查代码写完了但波形没出来这是最常见的情况。我把自己踩过的坑和排查思路整理出来按顺序查基本都能定位。5.1 坑一CMU时钟没使能寄存器写了没用现象所有寄存器读回来都是你写的值但引脚就是没波形。原因CMU的时钟使能位没置1TOM通道虽然配置了但没有时钟驱动计数器不走。排查读CMU_CLK_EN寄存器确认对应位是1。再读CMU_CLK_CFG确认分频配置正确。5.2 坑二端口复用没切信号卡在GTM内部现象GTM内部寄存器都正常CNT在跑但引脚测不到。原因端口还处于GPIO模式没有切换到GTM输出功能。排查读PORTx_IOCR寄存器确认对应引脚的PC字段是ALT功能值。如果不确定ALT编号查手册的Port Pin Function表。5.3 坑三CM0值超过16位周期不对现象波形有但频率和预期差很多。原因CM0是16位寄存器最大值65535。如果你算出来的CM0超过这个值写进去会被截断频率就错了。排查重新算时钟链确保CM0在范围内。如果超了加大CMU分频。5.4 坑四CM1 CM0输出一直是一个电平现象引脚有电平但不翻转一直是高或一直是低。原因CM1是占空比比较值必须小于CM0。如果CM1 CM0比较条件永远不满足输出不翻转。排查确认CM1 CM0。占空比100%时CM1 CM0但这种情况输出会一直高不会翻转。5.5 坑五通道没使能配置全对也没用现象所有配置都正确但CNT不走。原因TOM0_CH0_CTRL.B.EN没置1。排查读CTRL寄存器确认EN位是1。5.6 排查顺序总结顺序检查项寄存器预期值1GTM全局时钟GTM_CLS_CLK_CFGCLS_CLK_EN12CMU时钟使能CMU_CLK_ENEN_CLK013CMU分频CMU_CLK_CFGCLK0_DIV正确4TOM通道使能TOM0_CH0_CTRLEN15CM0/CM1TOM0_CH0_CM0/CM1CM1 CM06端口复用PORTx_IOCRPCALT值按这个顺序查基本5分钟内能定位问题。提示如果条件允许用调试器实时读TOM的CNT寄存器。如果CNT在变化说明时钟链路是通的问题在输出或端口如果CNT不动问题在时钟或使能。6. 动态调占空比与频率运行时改参数的正确姿势PWM跑起来只是第一步实际项目里经常需要在运行时改占空比比如调LED亮度、调电机转速。这里有几个细节要注意。6.1 改占空比只改CM1如果频率不变只改占空比直接写CM1就行void SetDutyCycle(uint16_t duty) { // duty范围0~10000对应0~100% uint32_t cm1 ((uint32_t)(CM0_VALUE 1) * duty) / 10000; TOM0_CH0_CM1.B.CM1 cm1; }注意CM1的更新时机。TOM有个影子寄存器机制可以配置成周期结束时更新避免改到一半出现毛刺。这通过TOM0_CH0_CTRL.B.CM1_UPDATE控制。6.2 改频率改CM0同时按比例改CM1改频率要同时改CM0和CM1否则占空比会变void SetFrequency(uint32_t freq_hz) { uint32_t period TOM_CLK_FREQ / freq_hz; uint32_t cm0 period - 1; uint32_t cm1 (period * current_duty) / 10000; TOM0_CH0_CM0.B.CM0 cm0; TOM0_CH0_CM1.B.CM1 cm1; }改CM0时要注意如果新值比当前CNT小可能会出现一个异常周期。稳妥做法是先停通道改完再启动。6.3 影子寄存器避免改参数时的毛刺TOM的CM0和CM1都有影子寄存器。配置CTRL寄存器的CM0_UPDATE和CM1_UPDATE位可以决定新值是立即生效还是等周期结束生效。对于调光、调速这类应用建议配置成周期结束更新波形更干净。对于需要快速响应的场景可以立即更新。6.4 多通道同步让几路PWM同相位如果一个TOM的多个通道要同相位输出需要让它们共享同一个CNT。TOM的通道分组机制天然支持这个同一组内的通道共享CNT只要配置相同的CM0输出就是同步的。跨TOM的同步就复杂一些需要用到GTM的TBUTime Base Unit做全局时间基准。这个留到多路复杂PWM的场景再展开。7. 从TOM到ATOM什么时候该升级TOM能搞定大部分基础PWM需求但有几类场景必须上ATOM。7.1 需要死区的时候电机H桥驱动上下管之间必须留死区否则会直通烧管。TOM本身不带死区生成ATOM有专门的死区配置寄存器可以独立设置上升沿和下降沿的死区时间。死区时间的计算死区时间 死区计数值 × ATOM时钟周期比如ATOM时钟50MHz死区计数值100死区时间 100 / 50MHz 2微秒。7.2 需要和ADC精确同步的时候电机控制里PWM和ADC采样必须严格同步否则采样到的电流值不对应PWM的特定时刻。ATOM可以通过ARU总线触发ADC实现硬件级同步比软件触发精确得多。7.3 需要互补PWM的时候BLDC的六步换向需要三对互补PWM。ATOM的通道可以配置成互补输出对TOM做不到。7.4 TOM和ATOM的选型对照需求TOMATOM普通PWM输出支持支持死区生成不支持支持互补输出不支持支持ADC硬件触发不支持支持ARU互联不支持支持配置复杂度低中高如果你的项目只是驱动LED、舵机、简单电机调速TOM足够。如果涉及三相电机控制、需要死区和ADC同步直接上ATOM别在TOM上浪费时间。8. 几个实际项目中的经验补充最后分享几个我在实际项目里积累的细节文档里不会写但很实用。第一CMU分频尽量选大一点。很多人为了追求频率精度把CMU分频设得很小结果CM0很容易超过16位。实际上PWM频率通常不高几kHz到几十kHzCMU分频大一点CM0有更大调整空间改频率时不容易溢出。第二端口配置放在最后做。我习惯先把GTM内部全部配好确认CNT在跑最后再切端口复用。这样如果波形不出来能快速判断是GTM问题还是端口问题。第三用示波器测的时候注意探头。GTM输出是数字信号但如果你的探头接地不好测出来的波形会有振铃容易误判。建议用短地线弹簧别用长鳄鱼夹。第四改频率时先停通道。运行时直接改CM0如果新值比当前CNT小会出现一个超短周期可能触发下游电路的异常。稳妥做法是EN0改完再EN1。第五多通道应用注意CNT共享。同一个TOM的8个通道共享一个CNT如果你给通道0配了CM049999通道1配了CM029999通道1的周期会被通道0覆盖。多通道要么用相同CM0要么用不同TOM。第六调试时善用CNT寄存器。读TOM的CNT如果它在0到CM0之间循环说明时钟和计数都正常。如果CNT不动问题一定在时钟链路或使能位。这个技巧能帮你快速缩小排查范围。第七注意不同TC3xx型号的差异。TC375、TC387、TC397的GTM结构基本一致但端口映射和时钟源可能不同。移植代码时重点检查CMU时钟源和端口ALT配置这两处最容易出问题。GTM这个模块刚上手确实劝退文档厚、缩写多、配置链路长。但一旦把TOM这条线跑通理解了时钟链路和子模块分工后面上ATOM、做多路PWM、搞电机控制都是在这个框架上扩展。我自己的经验是别一上来就啃完整本GTM手册先照着本文的步骤把一路PWM跑出来用示波器看到波形再回头读文档很多概念自然就通了。
返回列表