前面我是用霍尔触发中断进行换相,这里将使用定时器的COM事件来换相。吐槽下看懂这个还真不容易。另外有什么不对的请帮忙指出。
在中文参考手册中的13.3.14产生六步PWM输出有以下描述:
COM事件,其实就是为了让换相时相应的通道同时打开/关断,因为如果按前面在霍尔触发中断中写配置函数的话,是顺序进行的,有延时,不能做到同时配置。那么在切换的时候上一步的MOS状态多少会影响下一步(其实我感觉影响很小)。COM事件能让下一步的配置暂时缓存在影子寄存器中,等待COM事件触发生效,触发后就将相应的输出比较通道使能位同步更新,进行换相,然后可以在COM中断中配置下一步的通道状态。
我理解的使用COM事件另一个好处就是,能更灵活的对定时器进行同步操作。比如在ADC进行瞬时电流采样时候,就可以利用一个通用定时器去和高级定时器(输出PWM)同步,去触发ADC转换。方式更灵活。
需要注意的是,COM事件产生时,生效的是上一次在中断中的配置(硬件完成),在COM中断中配置的是下一步的状态。所以我们需要提前一相进行配置。
COM事件可由软件产生,也可以由硬件产生,这里主要解析硬件COM事件。
上面是ST官方的主要流程框图,不过我觉得还是结合下面通用定时器功能框图解析比较清晰。
总的说就是用一个通用定时器去触发一个高级定时器。下面是官方参考手册中给出的产生COM事件流程。
- 三个hall信号经过异或后,任意一相跳变,都会产生脉冲信号IC1PS,先将计数值传给输入捕获寄存器1
- 计数器复位,重新从零开始计数。在下一个脉冲IC1PS到来之前,输入捕获寄存器1的值,就表示了两个霍尔之间的时间。
- 将输出比较通道2发出的PWM作为TRGO输入源,注意配置为PWM2模式(当CNT<CCR时输出无效电平),设置一个较小的占空比,将主定时器的TRGO作为另一个高级定时器(从定时器)的TRGI触发源,每一次主定时器的TRGO有上升沿时,就会在从定时器触发一次硬件COM事件,进行换相。
下面是中文参考手册实例:
这里也注明了,在COM事件到来时,要写入的是下一个步骤的通道配置。
用OC2REF作为TRGO好处就是能够自定义触发COM时间。
我用的是TIM3去触发TIM1产生COM事件。
TIM3的初始化和前面文章中用霍尔触发中断的初始化中,时基和输入捕获通道初始化是一样的,只不过加入输出比较通道2的初始化和COM事件的配置。
因为计数器一直在计数,而且计数器的ARR是有限的,所以这里就需要理清楚整个思路(ps:只是个人理解,可能我还没遇到这个情况,如果不对麻烦指出来)
- 刚开始,电机停止时候,初始设置PWM占空比为0,因为没有霍尔状态改变,计数器一直在计数,那么就一直产生溢出事件,不断触发COM事件,但是无所谓,因为没有霍尔状态改变,并不会捕获CNT的值,并且因为设置占空比为0,所以电机还是停转状态
- 电机启动,按照给定PWM占空比转动,TIM3利用TIM_TS_TI1F_ED正常触发COM事件,因为开始计数器一直计数,第一次产生捕获事件时候,并不知道会停在哪里,可能并不是我们想要的CNT值,但是我们可以将其过滤掉。我们通过设置反馈调整时间(50ms在滴答定时器进行转速计算和PI算法),其实就已经把这个值过滤掉了。之后正常捕获。关于电机转速慢到超出计数器ARR,则需要根据实际最低转速调整时基配置,保证长于霍尔传感器上的两次变化的时间间隔。触发延时变长其实是相对而言的,最大65535个周期我觉得是足以应对大部分情况的。
- 电机停止,同1,设置占空比为0等操作进行停转。
- 考虑堵转保护,我的思路是使能TIM3输入捕获中断,每次在里面将堵转标志清零,在COM中断中加一,如果超过一定数值就关闭PWM输出(这个数值不能太大,比如为5),这样做是因为两个中断理论上时间线上是不同的,会先触发输入捕获中断,再触发COM中断,不过需要控制输入捕获中断的执行时间,不要在里面进行太多事务处理,做到互不妨碍,这里我的配置应该有10us间隔时间,应该是足够的,这里待我完善。
COM中断服务函数#TIM1初始化#
TIM1的初始化和前面文章中用输出六步PWM的初始化中,时基和输出比较通道初始化是一样的,加入COM事件配置,注意换相函数需要提前一相配置。
然后在COM中断中检测霍尔相位,进行换相。
启动的时候由于没有霍尔状态改变来触发,需要软件触发COM事件。