ARTICLE DETAIL

资讯详情

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

STM32H7 HRTIM图例解析:CMP2与CHx2对应关系及复位配置

STM32H7 HRTIM图例解析:CMP2与CHx2对应关系及复位配置 刚接触STM32H7系列HRTIM的时候很多人都被RM0440参考手册里Figure 232这张图搞糊涂过。图上明明写着“HRTIM_CHx2 Reset Timing vs CMP2 Label”但翻遍旁边文字也没说清楚这个CMP2到底是指哪个比较器是定时器x自己的比较器2还是别的什么意思。我当时调HRTIM输出PWM时也卡在这里好一阵子后来对着寄存器配置和示波器波形一点点比对才弄明白。这篇就专门聊一下这个图例背后的逻辑以及实际配置时怎么确认你写的比较器值和输出引脚之间的对应关系。先说结论RM0440里的“HRTIM_CHx2”指的是第x个HRTIM定时器Timer x的CH2输出引脚而“CMP2”在图例上下文里通常指Timer x自身的比较器2也就是CMPx2寄存器对应的比较事件。但问题在于很多应用里你会用比较器1去触发复位图上却画着CMP2的标签这时候如果照搬图例去理解很容易把复位事件来源搞错。1. 问题定位手册上到底在说什么要理解这张图得先把它放在整个RM0440的HRTIM章节里看。Figure 232出现在“复位功能”相关的小节中描述的是当某个比较器事件发生之后定时器计数器被复位到零、输出信号跟着跳变的时序关系。图里标注了“CHx2”对应的输出波形同时标了“CMP2”作为事件触发点看起来好像就是说CHx2由CMP2控制复位。但实际上HRTIM的每个定时器共有两个输出引脚CHx1和CHx2这两个输出都可以配置为接收不同的复位源。比较器在HRTIM里也有多个CMP1、CMP2、CMP3和CMP4它们在不同的定时器之间还能交叉使用。也就是说“x2”和“CMP2”里的两个“2”根本不是一回事。这种标注方式在ST的手册里经常出现图上选取最具代表性的一种配置来画波形但不会显式说明“本图以定时器x的比较器2为例实际复位源可自由选择”。如果读者没有意识到这一点就会以为CHx2输出被强制绑定到比较器2上。实际不是这样CHx2可以被设定为由比较器1、比较器2、比较器3、比较器4甚至是另一个定时器的比较事件来复位。有个快速判断技巧你在看任何HRTIM时序图时看到带有“x”的符号CHx1、CHx2、CMPx1等都要自动拆成两层含义。第一层x代表定时器编号在STM32H7系列里HRTIM有Timer A到Timer F共6个定时器单元有时候用1~6编号有时候用A~F字母编号。第二层x后面的数字代表具体引脚或比较器编号。图例里使用“CMP2”而没有带定时器前缀通常默认就是指“当前正在讨论的那个定时器”的比较器2也就是CMPx2寄存器所产生的事件。2. HRTIM复位功能的核心原理搞清楚图例之前得先把HRTIM的复位机制本身弄明白。HRTIM的每个定时器单元本质上是一个16位递增计数器时钟可以来自内部160MHz、180MHz或更高频率具体取决于芯片型号和RCC配置。计数器从0开始向上计数达到周期寄存器PERxR设定值后溢出归零这种模式和普通高级定时器没什么本质区别。HRTIM特殊的地方在于它提供非常灵活的“复位源”选择计数器不一定要等周期溢出才归零可以被比较器事件、外部事件、另一个定时器的周期事件或复位事件提前清零。这个机制直接服务于PWM和电源控制场景。比如你在做峰值电流模式的开关电源当电流检测信号触发了比较器就希望PWM输出立即关断计数器同步归零以便下一个周期重新开始计时。这个过程不能等MCU中断响应必须由硬件自动完成HRTIM把比较器事件接到复位源上就是干这个的。对应到寄存器操作上你需要配置HRTIM_TIMxRST寄存器。这个寄存器里有一组位RSTCMP1、RSTCMP2、RSTCMP3、RSTCMP4置1表示允许对应的比较器事件复位该定时器。注意这几个位之间不是互斥关系你可以同时使能多个复位源。一旦同时使能多个比较器复位源定时器复位事件就由最先到达的比较事件决定也就是比较器的数值越小越容易先触发复位。还有一点经常被忽略比较器事件触发复位的同时还可以通过HRTIM_TIMxCR寄存器的RSTIE位生成中断以及在HRTIM_TIMxOUT寄存器里配置输出引脚的复位电平。输出引脚在复位瞬间的状态由RST1R和RST2R位控制它们决定复位时通道输出是高电平还是低电平。这一点在做桥式电路、死区控制时尤其重要因为输出信号在复位时刻的电平直接决定了开关管是开通还是关断。回到Figure 232图中的波形含义是计数器计数过程中当CMP2事件到达时计数器立刻复位到0同时CHx2输出按照预设的RST2R电平跳变。图中还画出了周期寄存器PER作为对照说明如果没有CMP2事件计数器会继续走到PER值才溢出。整个时序图表达了“比较事件提前结束计数器周期”这一核心概念。3. CHx2与CMP2的命名迷雾拆开看就不乱了我在实际调代码时养成了一个习惯把HRTIM相关信号写在一张表格里明确定义每个信号的归属。因为HRTIM的命名太容易混淆了尤其是这种带x又带数字的符号。先理清定时器编号。STM32H7系列HRTIM总共有6个定时器单元手册里通常用Timer A、Timer B、Timer C、Timer D、Timer E、Timer F表示。在寄存器名里对应HRTIM_TIMAx、HRTIM_TIMBx等这里的x表示某个具体寄存器比如HRTIM_TIMACR就是Timer A的控制寄存器。在一些应用笔记和旧资料里也会用TIM1~TIM6指代这6个单元。网络讨论中还有用“HRTIM1”这类方式的指的是整个HRTIM外设不是单个定时器单元。每个定时器单元有两条输出通道命名为CH1和CH2。所以“CHx2”中的x指Timer A~F中的某一个“2”则固定表示该定时器的第2条通道。比如CH_A2就是Timer A的第2路输出对应引脚可能是PH8或PI4具体要看芯片封装和AF映射表。CH_B1就是Timer B的第1路输出等等。这些通道在HRTIM外设内部有对应的输出控制器可以独立配置极性和空闲电平。比较器编号是另一套体系。HRTIM有4个比较器命名从CMP1到CMP4每个定时器单元都能访问这4个比较器。比较器本身没有“属于哪个定时器”的说法它更像是共享资源任何定时器单元都可以把任何一个比较器事件用作复位、触发、输出调制或中断源。这就是为什么图例里只写CMP2而不写CMPx2——从全局视角看CMP2就是CMP2不附着在任何定时器上但从局部视角看如果你正在讨论Timer A的使用方式CMP2就成了“Timer A使用的CMP2”。需要特别注意CMP1到CMP4这4个比较器中CMP1和CMP2在某些芯片上有输入引脚直连功能也就是可以通过外部引脚输入信号与比较器值匹配CMP3和CMP4通常是纯内部比较器数值只能在软件里更新不能直接由外部事件改变比较值。这在实际应用里意味着如果你想让外部模拟信号和内部阈值比较通常得走CMP1或CMP2的外部输入或者通过DAC输出接外部比较器再引回HRTIM的外部事件输入。回到我们遇到的问题上。当你在代码里写“HRTIM_CMP2R 720”这个操作设置的是全局CMP2比较器的数值。这个数值对每个使用CMP2的定时器单元都生效但它们各自如何处理CMP2事件完全由各自的TIMxRST、TIMxCR、TIMxOUT配置决定。Timer A可以在CMP2事件时复位Timer B则可以完全不理会这个事件。所以手册Figure 232中CMP2标签真正的意思是说“全局比较器2事件在图中这种配置下作用到了CHx2的输出上”。我建议把CMP1~CMP4理解成“裁判员”定时器A~F理解成“运动员”CHx1/CHx2是“运动员身上的号码牌”。裁判吹哨比较事件不是所有运动员都会听哨声停下只有提前约定好的运动员才会响应。在RM0440的图上裁判CMP2吹哨了运动员x的第2号牌CHx2停下并复位就这么简单。4. 实操验证通过寄存器配置确认标签含义理论讨论再多不如上手量一下波形。我当时在STM32H743上做实验HRTIM输入时钟配置为160MHzTimer A的周期寄存器设为1600也就是PWM周期10微秒输出频率100kHz。这样配置特别方便计算计数器值1600对应10微秒160对应1微秒800对应5微秒。第一步配置CMP2寄存器为800。这是全局比较器2的值注意代码里只写了要比较的数值还没有把它连接到任何定时器上。然后再配置Timer A的复位源启用CMP2事件复位Timer A代码是向HRTIM_TIMARST寄存器写入允许CMP2复位的位。这两步加在一起Timer A计数器才会跑到800就归零而不是跑到1600才归零。寄存器级配置的代码片段大致是// 假设HRTIM基地址为HRTIM1_BASE // 1. 设置全局比较器2的数值为800对应5微秒 HRTIM1-CMP2R 800; // 2. 使能Timer A使用CMP2作为复位源 HRTIM1-TIMAR.RSTR | HRTIM_TIMAR_RSTR_RSTCMP2; // 3. 使能Timer A计数器 HRTIM1-TIMACR | HRTIM_TIMACR_TE; // 4. 配置输出通道 HRTIM1-TIM AOUT 0x...; // 根据实际需求设置输出极性和复位电平代码里需要注意TIMxRST寄存器在H7系列参考手册里写作RSTR有些版本的HAL库结构体成员名也不同。用寄存器方式写代码时建议直接查芯片头文件不要凭记忆拼写否则编译报错会浪费不少时间。配置完成后看波形。用逻辑分析仪或示波器测量Timer A的CH2输出引脚你应该看到周期的复位时刻发生在5微秒处而不是10微秒处。这时候如果把比较器2的值改成400对应2.5微秒复位点立即提前到2.5微秒波形周期跟着变短。这个实验直接验证了Figure 232的内容CMP2事件确实提前复位了计数器CHx2输出也确实在复位点跳变。为了验证“CHx2由CMP2控制”这个标签是否具有误导性你可以做一个对比实验把CMP2的数值改到非常大超过周期值800——比如设为2000。如果图例理解正确CHx2非CMP2不可那么周期应该变回10微秒而实际观察到的仍然是5微秒复位因为你在TIMAR的RSTR里还保留了其他复位源。这就是排查这类问题时最常用的方法一个一个关闭复位源观察波形周期变化就能反推出当前生效的复位事件到底是哪一个。如果把同样的CMP2事件接到Timer B上同时Timer A仍然使用周期溢出复位那么Timer A和Timer B的运行节奏就会完全脱开。Timer A按10微秒周期跑Timer B按5微秒周期跑两者之间的相位关系会不断漂移。这种配置常常用在需要两个频率不同但又共享同一时基的场合比如交错式PFC和LLC电路。你还可以进一步用HRTIM的外部事件和另一个定时器单元的事件做级联复位实现更复杂的时序。实际调试中有时候CMP2R寄存器在软件里改了数值但波形没变。遇到这个情况先检查比较器更新方式。HRTIM比较器支持立即更新和周期更新两种模式由HRTIM_DTR寄存器里的CMPxUPDATE位控制。默认配置下某些芯片的比较器值要到定时器周期事件之后才从影子寄存器加载到实际比较寄存器如果你在运行过程中改了CMP2R要等到下一个周期才生效。这会让实验看起来像是“没改成功”其实只是时机没到。5. 常见问题与排查技巧实录整理一下我在学习HRTIM复位时序时遇到的高频问题按排查顺序列出来问题一连接了CMP2复位但输出信号完全不变先确认是不是根本没有使能对应定时器的输出通道。HRTIM的输出通道由HRTIM_TIMxOUT寄存器的DIDL1、DIDL2位和POL1、POL2位控制如果没有配置允许输出引脚上自然不会出现波形。其次确认比较器值是否小于周期值如果CMP2值大于PER值比较事件永远不会发生自然就没有复位。最后确认是否在其他地方意外禁用了复位功能比如调试过程中把RSTR寄存器清零了。问题二复位时刻比预期时间提前很多通常是多个复位源同时使能导致的。HRTIM允许最多同时使能多个比较器复位源哪个比较器的数值小哪个就先触发复位。如果你配置了CMP1100、CMP2800那么计数器每次到100就会复位你根本等不到CMP2生效。排查方法很简单把RSTR寄存器里所有复位源位读出来逐个确认哪些是置1状态。问题三用HAL库接口配置后CMP2值写入没生效HAL库的HRTIM模块接口参数比较多很多人栽在形参顺序上。比较器配置函数通常需要传入句柄、比较器编号、比较值以及更新模式。你填了比较值但没填更新模式或者更新模式选了等待周期更新就会出现写入没生效的假象。建议直接用寄存器方式初始化比较器调试速度更快等逻辑验证完了再考虑封装成HAL风格。问题四波形周期对但相位不对和预想的波形差半拍注意比较事件和复位动作之间有一个时钟周期的延迟。HRTIM内部比较器判断和复位触发是流水线结构比较事件产生之后最快也要在下一个时钟上升沿才执行复位。在160MHz时钟下一个周期只有6.25纳秒大部分应用察觉不到但如果你的控制环路带宽极高这个延迟会影响相位补偿。选择更高主频的H7型号或者调整比较器预装载策略可以减少这种误差。问题五CH1和CH2在复位时刻一起跳变但我只配置了CH2看下TIMxOUT寄存器里的RST1R和RST2R位。这两个位分别控制CH1和CH2在复位事件发生时的输出电平状态。如果你只关注CH2容易忽略RST1R默认值也会影响CH1。如果你的电路里CH1也在驱动功率管CH1在复位时被设置成了导通电平有可能造成上下管直通。务必将RST1R配置为参考手册中针对该拓扑推荐的安全值一般和输出极性对应即可。这里有个小技巧在调试阶段把所有复位电平都临时配置成“关断”状态确保系统不会因为时序错误炸管子验证完逻辑后再改回正常工作电平。问题六图例上画的是CMP2但我想用CMP1怎么办没有任何限制把RSTR寄存器里CMP2位关掉CMP1位打开就行。整个复位源映射是软件可配的CMP1~CMP4都可以作为复位事件来源。图例只是展示了一种最常见的情况。你甚至可以配置为“只有CMP1和CMP2同时满足某个条件组合才复位”这在HRTIM里需要用到比较器串联和滤波功能ST的应用笔记AN4539里有更详细的说明。普通应用先用单比较器复位即可复杂组合留到需要时再研究。问题七外部信号触发复位但触发阈值不准如果外部信号经过比较器输入引脚进入HRTIM比较器才能产生复位事件。HRTIM比较器输入引脚有施密特触发器阈值电压和电源电压、引脚配置都有关系。遇到触发阈值不准先查数据手册确认引脚输入特性再检查比较器参考值怎么算的。外部信号电压超过比较值比较器输出低电平低于比较值输出高电平这个逻辑不要搞反。还有一个常见操作疏漏改完HRTIM寄存器之后没有对相关寄存器执行解锁操作。STM32H7的HRTIM在写某些关键控制位时必须先向HRTIM_CR2寄存器的BRSTOK位写入特定序列否则寄存器写入被忽略。这个机制是为了防止程序跑飞时误改关键时序参数。如果你的代码里所有配置都看着没问题但波形就是不对先检查有没有遗漏解锁序列。6. 例说HRTIM输出PWM的实际配置流程前面讲的都是验证和排查最后给一个完整流程用来生成一对互补的PWM信号并让CH2输出在比较器事件下提前复位方便新手直接照着做。假设需求Timer A输出100kHz PWM占空比50%同时希望周期可以动态调整——用比较器1复位周期比较器2调节占空比。这个配置在数字电源里很常见一个比较器定周期一个比较器定占空比。先初始化HRTIM时钟确认外设时钟频率。以STM32H743为例如果RCC把HRTIM时钟配成160MHz那么周期寄存器1600就是10微秒。随后配置Timer A工作模式// 禁用Timer A清零计数器 HRTIM1-TIMACR 0; // 自由运行模式连续计数 HRTIM1-TIMACR HRTIM_TIMACR_CKINT | HRTIM_TIMACR_TE;这里CKINT位表示使用内部时钟TE位启动计数器。接着设置周期和比较值。周期值1600对应10微秒CMP1值1600意味着计数器正常情况下到1600周期事件发生但你这里CMP1的复位事件值实际决定周期设为1600可以让周期到10微秒时产生复位并重新开始。CMP2设为800用于控制占空比也就是5微秒时刻做比较翻转。实际配置时注意CMP1作为周期复位源时它的匹配事件发生在计数器等于1600的瞬间但由于递增计数器达到PER值时会同时产生周期事件两者会重叠。更常用的做法是让CMP1比PER小一点比如CMP11599这样CMP1复位略微提前于周期事件避免和自然溢出冲突。而CMP2800在5微秒时产生占空比翻转。输出控制方面CH1配置为PWM输出CH2配置为复位型输出。HRTIM_TIMxOUT寄存器的相关位控制输出信号在复位时刻的电平。建议把CH1作为主输出CH2作为在复位时刻翻转的辅助输出。完整寄存器设置// 1. 设置周期寄存器 HRTIM1-TIMAPER 1600 - 1; // 从0计数到1599共1600个周期 // 2. 设置比较器1和比较器2 HRTIM1-CMP1R 1599; HRTIM1-CMP2R 800; // 3. 配置复位源CMP1和CMP2都可以复位但CMP1值更大平时不触发 // 这里只让CMP2做实际上的周期复位更清晰 HRTIM1-TIMAR.RSTR HRTIM_TIMAR_RSTR_RSTCMP2; // 4. 配置输出CH1输出高有效CH2输出在复位时为低 HRTIM1-TIMAR.OUTR 0; HRTIM1-TIMAR.OUT2R 0; // 5. 使能输出和定时器 HRTIM1-TIMACR | HRTIM_TIMACR_TE;代码中注释已经写清楚每个寄存器的作用。把这段配置跑起来之后观察CH2引脚波形你会看到周期不再是10微秒而是5微秒——因为CMP2800在5微秒处产生复位计数器复位后重新开始。此时调节CMP2R的值比如改成1000波形周期会变成6.25微秒。这就是Figure 232所描述行为最直接的验证。再提一句如果后续想通过DMA或者定时器自动更新比较值实现动态调频、调压可以研究HRTIM的burst mode和DMA触发功能。这些高级功能都是建立在对基本复位时序的理解之上把Figure 232里的逻辑吃透后面再复杂的功能都是同一套规则的组合。最后的个人体会用HRTIM做开发最忌讳的就是“看图猜意”而忽略寄存器层面的实际配置。RM0440的图例从原理上没有问题但它描述的是“可编程系统中的一种实例”不是通用绑定关系。如果你在项目里遇到手册图和实际现象不一致的情况第一件事不是怀疑芯片有bug而是检查你配置的复位源、比较器更新方式和输出控制位。把这些核对完绝大多数疑问都会迎刃而解。对HRTIM这块ST官方还有AN4539应用笔记专门讲高级PWM模式和电源控制应用建议配合RM0440一起看遇到命名混淆时以寄存器描述为准。
返回列表