模拟技术
有人使用STM32F103系列想实现如下需求,碰到些许配置困难。【因没说完整型号,这里假定为STMF103R8来聊。其实,对于下面话题,它是什么型号已经不重要了,后面话题重点跟芯片型号基本无关。】
现在欲配置一个ADC采样,配置Timer1通道1,2,3输出三路PWM,同时想用Timer3的TRGO通道触发ADC,要求ADC在三路PWM输出高电平中间点采样【即下图红色箭头所指位置】。目前已经知道配置方式是Timer1配置成中央对齐方式,然后ADC使能外部触发,为了观察是否在高电平中间点采样,在ADC中断做了一个IO口翻转操作,现在观察PWM和IO口波形,发现IO口翻转还是在PWM高电平上升沿时出现,那么 该怎么配置呢?
要实现上面PWM输出,我们可以考虑STM32芯片内的高级定时器【TIM1或TIM8】,并让更新事件发生在上面箭头所指位置,同时将该更新事件作为ADC的触发启动信号那就最方便了。
这样是否可行,我们还得具体看看硬件资源上是否支持。
我们通过CubeMx可以快速查到,对于TIMER1的事件,这里的ADC仅支持它的前3个通道的比较事件来触发它。因为这里选定要在那个中心点做触发,那选择3个比较通道的任一个都不太合适。
如果说ADC支持TIM1的第4个通道的话,我们倒还可以用用它,但这里也不支持。
从上面截图可以看到,ADC是支持来自TIM3的TRGO触发信号的。既然这样,如果将TIM1、TIM3主从级联起来,让TIM3与TIM1同步计数、并使用相同的计数周期,让TIM3的更新事件发生在TIM1 PWM输出的中心点,这样按理应该是可以的。
为了验证这点,因为手上没有F1系列开发板,找了块F411的开发板来做测试。其外设方面跟F103系列比较接近。
通过查看手册,TIM1/TIM3可以主从级联起来。TIM1的TRGO可以作为TIM3的触发输入信号。
这里我们让TIM1的更新事件作为TIM3的触发启动信号,即让TIM3工作在Trigger mode,让TIM1启动TIM3. 这里令TIM1->ARR=10000, TIM3->ARR=20000,TIM1工作在中心对齐计数模式,TIM3工作在向上单向计数模式。TIM1的更新事件产生TRGO作为TIM3的触发输入信号。通过TIM3的更新事件触发ADC转换。
TIMER1相关参考配置如下:
TIMER3相关参考配置如下:
ADC部分配置代码,这里只是开启了内部Vrefint通道。主要验证ADC触发时间点。
配置OK后组织如下用户代码。【注意:眼尖的人会发发现代码里看到不到启动TIM3的语句。另外,我开启TIM3的更新中断是为了在那里基于某gpio输出个尖峰脉冲便于观察。】
测试结果发现,采样点不是每个周期都有,而变成2个周期才有,ADC转换结果倒是出来了,是下面的样子:【黄色尖峰表示采样触发点】
这样看起来,明显感觉TIM3与TIM1的时钟相差了1倍,也就说TIM3要比TIM1慢1倍。难道二者所在外设时钟不一样?这个要看看手册确认下。
从手册上看,TIM1/TIM3挂在不同的外设总线APB1和APB2上,总线时钟上限不一样。我们再看看CubeMx里的配置:
从上图时钟树来看,APB1分频系数为4,导致挂APB1上的TIM3的时钟才48MH,而挂APB2上的TIM1的时钟则是96MHz,这样导致了TIM1/TIM3的计数时钟不一样,前面设计时误以为二者一样了。那我把APB1分频系数由4改成2应该是可以的。只调整这个地方,其它不动再做测试。
调整后,效果立竿见影,不再每两个周期才采样一次,采样点似乎也没啥问题。
不对,瞧着示波器多观察会儿就会发现输出不对劲!感觉那个采样点相对于PWM输出波形在做漂移!刚开始以为示波器问题,细看明显不是,因为二者是相对移动,即采样点并不固定在PMW输出的中心位置。【如下图所示】
基于上面的初步设计,2个定时器应该是可以严格同步的,这样的话采样点不该偏移啊?难道上面2个TIMER的时间参数哪里有问题?现在二者的时钟是一样的了,都是96Mhz,然后经过96分频进入计数器。目前两个定时器的时间是这样的:
看到这里,有人可能发现问题了!TIM1是双向计数模式,按现有配置算起来,其计数周期是2*10000个时钟,而TIM3是单向向上计数模式,它的计数周期则是20000+1个时钟周期。跟TIM1的计数周期在数字上差了个1,因为计数时钟是经过96分频后过来的,意味着一个完整计数周期就差了96个PCLK 周期。也就说这两个TIMER即使有相同的计数起点,后面会不断积累时间偏差【或者说相位差更合适】,导致基于TIM3的更新事件的采样点相对TIM1总是在飘动。显然,对于TIM3而言,如果它1个周期也计数20000个时钟,它的ARR值应该设置为19999,此处错了!
修改后再行测试,采样点相对PWM输出的高电平中心就非常稳定了。你可以久久的凝视她,久久地,也见不到之前的漂移了,稳如磐石。【下图中黄色尖峰脉冲指示ADC采样触发时刻。ADC结果是同一内部通道的转换值。】
OK,稍作小结。开发时我们可以基于现有资源看菜吃饭,这里只是想借开篇问题分享点东西。问题不复杂,但真要做起来总会有七七八八的事情冒出来,也只有真正做起来才会体验到诸多细节,比如TIMER时基参数的拟定,它虽不复杂、不深奥但不代表不容易出错。这点也是本篇旨在重点提醒的地方。
对于STM32常规定时器而言,在单向【向上或向下】计数模式下,计数周期对应于ARR+1;对于中心对齐计数模式,计数周期对应于2倍ARR值。分频系数对应于PSC+1,溢出事件重复计数值对应于RCR+1.
试想下,对于前面采样点发生漂移现象,如果我不对时钟源先做96分频,这个漂移就不那么容易发现了。不容发现不代表那个漂移不存在,如果变成产品的话,就容易遇到那种奇怪的现象,产品刚开始功能很正常,后来用着用着功能就不太对劲了,然后当对产品复位或重启后问题似乎又消失了,但随着时间的推移问题又会重现,就很可能陷入那种没完没了而又无计可施的困扰和无奈状态。
当然,这里还涉及中心对齐计数模式下更新事件的位置拟定、定时器主从同步等内容,有兴趣的可以进一步尝试体验。
好,不多聊了。此中有真意,欲辨已忘言。
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !