时基中断
从中断响亮表中,我们知道,跟PWM有关的中断向量一共有四个,PWM1的周期匹配和故障A,以及PWM2的周期匹配和故障A.
中断的产生主要跟两个设置有关,一个就是模式设置,在哪里发生中断,另外一个是后分频,主要设定中断的频率。
自由模式下,当TMR和PXTPER匹配产生中断,可以设置后分频来减少中断次数。 单次时间,当然后分频无效,产生的位置同自由模式。 增减计数模式,后分频有效,在TMR到0的时候产生中断。 这种模式,后分频无效,两次更新占空比寄存器,具体看后面的内容。
PWM输出状态控制
PWMxCON1有三个设置功能,一个是设置是否PWM对独立输出还是反相输出,另外一个是设置高输出使能,一个是设置低输出使能。
另外,在配置寄存器中,还有三位作为初始化设置,如下
HPOL:高端是高有效还是低有效。
LPOL:低端是高有效还是低有效。
PWMPIN:这个是器件复位端口的状态,是三态还是PWM模块来控制设置位。
PWM输出模式
单次模式:这种模式对驱动整流电机比较有用,比如开关磁阻电机,这种模式下,只能输出单次边沿对齐。
在单次模式下,PWM的IO驱动到有效的状态,PTEN置1,当匹配产生,IO驱动到不激活状态,PXTMR清零,所有的PWM驱动到非激活状态,PTEN清零,中断产生,软件使能PTEN置1之前,模块停止工作.
上图中,PXDC1和PXDC2为占空比值寄存器。
边沿对齐PWM,自由运行的模式下,MCPWM产生边沿对齐的PWM信号。
给定PWM通道通过PXTPER寄存器来设置周期,通过PXDCY寄存器来设置占空比。假如一个非零的占空比或者没有执行立即更新的信号,在PWM开始的周期,所有使能的PWM将都会被激活。在PXTMR匹配这个占空比值的时候,切换为非激活状态。如果占空比值为0,则输出全部为非激活状态,如果占空比值比PXTPER值大,则一直输出为激活状态,如果写入新分PXDCY值,并且IUE使能,则会立即更新新的占空比值。
中心对齐的PWM
中心对齐的PWM模式为时基配置为增减计数。这种状态下,匹配一次切换一次激活与非激活的状态。如果占空比为0,则输出一直为非激活状态,而如果占空比值大于PXTPER值,则一直输出为激活状态。
互补型PWM
互补性PWM用于交流感应电机和直流无刷电机类似的应用中,这种模式下,PWM对不能同时激活,因为在内部已经绑定,这两个相反输出的PWM对可以设置死区时间,具体看后面死区时间的设置问题。器件复位时,默认为这种工作模式。
PWM独立输出模式
这种模式的结构如下:
这种模式下,不能设置死区时间,引脚的输出也没有限制。
占空比寄存器缓存
占空比寄存器一共有4个:PxDC1~4,允许立即更新。
没个占空比生成器有一个占空比寄存器,用于用于设置,用来保存实际用来比较的值。PWM更新PxDCy的值,需要经过指定的次数,来避免立即更新PWM的输出信号。在自由运行状态和单次状态下,占空比值在每次匹配完成后进行更新。每次PTEN=0,也就是去使能一次,就会更新一次PWM的占空比值。
在增减计数模式下,必须等到计数器清零以后更新一次。而双更新模式则在每次匹配和计数器清零都会更新一次占空比。
立刻更新PWM占空比
有一个强制性立即更新占空比的位IUE,这个很容易理解,当立即更新了占空比,可能会引起如下的情况。如下图:
假如首先是50%的占空比
情况1:新占空比值来了,需要到90%,那就立刻切到90%的位置再去使能。
情况2:如果新的占空比值小于现在的,那就立即拉到非使能状态,下一个周期就按照这个占空比设置。
情况3:如果本来就在非使能状态,那就立即拉高,到设置的占空比状态。
PWM占空比精度
MCPWM模块中,时基的PWM精度取决于PWM的频率和器件的操作频率。计算公式如下:
下表就是通过公式计算出来的PWM精度。
MCPWM可以产生TCY/2的精度值,PXTMR按照1倍频增计数,则可以设置为TCY/2的精度。定时器为15为,则PXDCY的最后一位用来定义是否进行TCY/2。时序图如下:
PWM死区控制
每个反相输出对有一个6位的减计数,用来产生一个死区的插入时间设置。每一个死区单元包括了一个上升沿和下降沿的检测模块,很显然,6位的减计数到0以后,才能产生一个PWM的激活状态,如下图:
死区的分配
死区时间控制寄存器包括两个位来分配这个反相输出对,DTSxA和DTSxI,前者用来设置高端准备激活,后者用来设置低端准备激活的状态。这两个位分别叫做“死区选择激活”和“死区选择不激活”状态。
死区的范围
死区的范围由两个参数决定,一个是6位的减计数位,一个是分频。根据器件的操作频率来设置时钟分频值,这个分频值可以独立设置,在死区单元A和B的分频选择位可以进行选择。
DTAPS: Dead Time Unit A Prescale Select bits
11 = Clock period for Dead Time Unit A is 8 TCY
10 = Clock period for Dead Time Unit A is 4 TCY
01 = Clock period for Dead Time Unit A is 2 TCY
00 = Clock period for Dead Time Unit A is TCY
这样,很容易计算出死区的时间:
DT =Dead Time /Prescale Value *TCY
------------------------------------------------------- - =
死区的失效
试想如果占空比很小,小到和死区时间一样,或者更小,那么将不会有激活状态的输出。这样就存在了死区的失效。用户可以设置占空比最小也需要比死区时间大3倍来减小死区的失效,也可以通过其他计数来防止死区的失效,比如设置闭环的电流控制。
还有一个很常见的情境就是,占空比接近于100%,则最大的占空比选择的时候,最小必须留出一段非激活状态的时间,这个时间是死区时间的3倍。
下面的6段小程序,用来配置和使用PWM。
模式和时基选择
_FPOR(RST_PWMPIN & PWMxH_ACT_HI & PWMxL_ACT_HI) //配置PWM的初始状态,这个在上面有所讲过,第一个位为复位时由PWM模块来控制IO,后面的两位分别设置为PWM1H激活的时候为高还是为低。
P1TCONbits.PTMOD = 0b00;//一共有四种模式,这个是自由运行的模式。
P1TCONbits.PTCKPS = 0b00; //时基,这里设置为TCY
P1TCONbits.PTOPS = 0b00;//设置后分频,这里设置为1:1
P1TPER = 999;//设置时基的周期
输出模式选择
PWM1CON1bits.PMOD1 = 0;
PWM1CON1bits.PMOD2 = 0;
PWM1CON1bits.PMOD3 = 0; //设置3对都是互补输出模式
PWM1CON1bits.PEN1H = 1;
PWM1CON1bits.PEN2H = 1;
PWM1CON1bits.PEN3H = 1; //使能引脚为PWM,否则为普通IO输出
PWM1CON1bits.PEN1L = 1;
PWM1CON1bits.PEN2L = 1;
PWM1CON1bits.PEN3L = 1;
PWM1CON2bits.IUE = 1;//设置为立即更新占空比值
死区插入设置
P1DTCON1bits.DTAPS = 0b00;
P1DTCON1bits.DTBPS = 0b00;//死区A和死区B的分频,这里设置为TCY不分频
P1DTCON1bits.DTA = 10;
P1DTCON1bits.DTB = 20;//设置6位减计数的值
P1DTCON2bits.DTS3A = 0;
P1DTCON2bits.DTS2A = 0;
P1DTCON2bits.DTS1A = 0;
P1DTCON2bits.DTS3I = 1;
P1DTCON2bits.DTS2I = 1;
P1DTCON2bits.DTS1I = 1;//设置高端激活都用A模块,低端激活都用B模块
PWM的IO控制
P1OVDCONbits.POVD3H = 1;
P1OVDCONbits.POVD2H = 1;
P1OVDCONbits.POVD1H = 1;
P1OVDCONbits.POVD3L = 1;
P1OVDCONbits.POVD2L = 1;
P1OVDCONbits.POVD1L = 1;//输出都由PWM控制,而不是POUTxH:POUTxL位值来控制
占空比初始化
P1DC1 = 200;
P1DC2 = 200;
P1DC3 = 200;//
使能,开始产生PWM信号
P1TCONbits.PTEN = 1;
PWM的错误处理
PWM模块有两个错误引脚,FLTxA和B,定义以后,这个引脚可以驱动PWM的引脚到一个默认的状态。这个动作不需要软件来设置,可以快速的响应一个错误事件。
这些错误引脚跟其他的IO是共用的,当使用为错误输出,则每一个位都可以通过PORT寄存器来读,这两个引脚为低有效,可以通过上拉电阻和其他的错误源进行“或”来处理其他错误。当然也可以当成普通的IO口来进行操作,这个错误引脚都有中断向量号,标志以及使能设置,优先级设置。
故障使能:PxFLTACON的FAEN位用来设置,该PWM模块是否受故障A控制。 故障状态:可以通过PxFLTACON来设置当故障输出的时候,输出应该默认到哪种状态,这里有一个特殊情况就是反相对,不能同时输出为active的模式 故障输入的模式:每个引脚都有两个模式: 锁存模式:很显然,需要软件的参数来重新设置此引脚为高,这里记得要将中断也清空。 循环模式:这个只要等到故障引脚被拉高就可以。 PxFLTACON中有一位用于此功能的设置:TLTAM 进入故障状态:当这个引脚驱低,PWM引脚立即驱动到设置的默认状态,优先级高于任何寄存器。 退出故障状态:当外部电路拉高引脚,或在锁存模式下,故障中断标志清除了,之后,从下一个PWM周期或者半周期边界开始。如果PTEN=0,则需要重载PWM的输出信号。 故障引脚的优先级:如果A,B同时有一个故障,则A优先级高于B,如果A退出故障,则,如果B故障继续,则处理B故障,如果B故障不存在了,则忽略。 故障引脚的配置:可以配置为IO引脚。
时序图:
循环模式的三种情况:
锁存模式则需要继续清空一下标志位,如下:
下面表示A的优先级比B要高的情况
MCPWM的特殊性能
PWM输出改写:也就是说可以设置为特殊的逻辑,而不需要管他们作为一对的时序配合。
改写控制寄存器中的位定义如下:
bit 13-8 POVDxH:POVDxL:PWM输出改写位
1 = PWMx I/O引脚上的输出由 PWM 发生器控制
0 = PWMx I/O引脚上的输出由对应 POUTxH:POUTxL 位中的值控制
bit 7-6 未实现:读为0
bit 5-0 POUTxH:POUTxL:PWM手动输出位
1 = 当对应的 POVDxH:POVDxL位清零时, PWMx I/O引脚被驱动为有效状态
0 = 当对应的 POVDxH:POVDxL位清零时, PWMx I/O引脚被驱动为无效状态
比如通过如下的程序来配置:
PWM1CON2bits.OSYNC = 1; //改写同步
P1OVDCONbits.POVD3H = 0;
P1OVDCONbits.POVD2H = 0;
P1OVDCONbits.POVD1H = 0;
P1OVDCONbits.POVD3L = 0;
P1OVDCONbits.POVD2L = 0;
P1OVDCONbits.POVD1L = 0; //通过POUTxH:POUTxL来控制输出
P1OVDCONbits.POUT3H = 1;
P1OVDCONbits.POUT2H = 1;
P1OVDCONbits.POUT1H = 1;
P1OVDCONbits.POUT3L = 1;
P1OVDCONbits.POUT2L = 1;
P1OVDCONbits.POUT1L = 1; //设置激活状态是1还是0
反相输出改写:NO! 改写同步:改写同步的定义如下:
bit 1 OSYNC: 输出改写同步位
1 = 通过 PxOVDCON 寄存器进行的输出改写与PWM时基同步
0 = 通过 PxOVDCON 寄存器进行的输出改写在下一个TCY 边界发生
一个例子:比如三相电机控制的是一个6步的控制逻辑,如下:这个时序就可以用改写的PWM来实现。
特殊时间的触发:特殊事件的触发,为AD转换,需要根据AD转换的值来更新占空比的情况中。
P1SECMPbits.SEVTDIR = 1; //触发时基方向
PWM1CON2bits.SEVOPS = 0b0000; //触发后分频选择
P1SECMPbits.SEVTCMP = 100; //特殊事件的比较值
AD1CON1bits.SSRC = 0b011;//011 = 由电机控制 PWM1间隔结束采样并启动转换
PWM占空比更新暂时锁存
这个流程为设置更新暂时锁存,然后写入PxTPER,然后清暂锁,这样就可以更新所有的PWM的占空比。
器件仿真:支持 写保护:支持
低功耗模式下的使用
睡眠模式:因为TCY停止工作,所以在睡眠状态下,PWM输出停止工作,但是故障输入继续有效。并且故障输入可以用来唤醒芯片。
空闲模式下,同其他模块。