DSP学习笔记之EWPM学习

\qquad 学习PWM模块的知识,最少需要掌握频率可调、占空比可调、互补死区可调、多个PWM相位差可调等。内容较多,主要是参照英文手册中几个模块的介绍,内容很多,最基本的需要掌握前三个模块;掌握前三个模块后可以看最后的代码。参考的DSP资料

EPWM概述

EPWM子模块

Time-Base(TB)子模块

在这里插入图片描述

\qquad TB模块用来配置

\qquad 1.设置epwm时基的计数器的频率或周期(TBCTR)来控制pwm频率;

\qquad 2.管理和其他时基模块的同步触发,即设置pwm的相位差;

\qquad 3.保持和其他epwm子模块的联系;

\qquad 4.(a)当CTR = PDR,时基计数器的值等于指定周期值(TBCTR = TBPRD);(b)当CTR = Zero,时基计数器清零(TBCTR = 0x0000);

\qquad 5.通过系统时钟预分频来配置时基时钟;通过合理分频系统时钟,计数的时候可以工作在相对较低的频率。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YO62Vjco-1648380837867)(file:///C:\Users\vastjust\AppData\Local\Temp\ksohtml\wps9F99.tmp.jpg)]

\qquad 上图是时基模块内部信号和寄存器分布图。从图中可以看到,首先系统时钟SYSCLKOUT经过预分频模块(由TBCLK寄存器的高速时基时钟分频HSPCLKDIV(注意,这个和高速时钟分频寄存器HSPCLK区分开)和时基时钟预分频CLKDIV位来控制)来产生计数器的计数时钟TBCLK。图中可以看到,TBPRD(时基周期寄存器)有一个影子寄存器和活跃寄存器,影子寄存器起到了一个缓冲器的作用,当需要改变周期数时,如果不需要立即改变(先让没有输出完的PWM继续输出),那么可以先将周期数给到影子计数器,当计数完成后,影子寄存器会将值传递给活跃寄存器,完成下一次计数;显然我们在PWM同步触发或者对PWM输出延时有要求的应用场合下,不需要使用到影子寄存器。图中需要将时基时钟,计数器值(0和计数最大值),计数器方向(由比较模块产生)等值写入计数器。继续看图中TBCTR计数和周期数进行比较,那当TBCTR等于TBPRD时,会输出一个Reset信号,这个reset信号将会重置计数器;重置寄存器后,TBPHS(时基相位寄存器)的值并不会直接赋给TBCTR(时基计数器),而是需要TBCTL[PHSEN](时基寄存器的控制加载位)置1,这样TBPHS(时基相位寄存器)的值就会赋给TBCTR(时基计数器)来改变占空比和相位。除了软件可以置1外,硬件也可以,当EPWMxSYNCI或软件TBCTL[SWFSYNC](软件强制同步触发位)为1时,也可以加载相位值。最后从图中可以看出,要想使得6个epwm同步触发,需要将EWPMx的EPWMxSYNCO给到EPWMx+1的EPWMxSYNCI

\qquad 三种计数方式: 向上向下计数模式,这个模式下时基计数器从0计数到周期数(TBPRD),而后向下计数直到0,这个过程为一个周期。向上计数模式,这个模式是时基计数器从0计数到周期数(TBPRD),这个过程为一个周期。向下计数模式,时基计数器从周期数(TBPRD)向下计数到0,这个过程为一个周期。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fSzkDuvU-1648380837869)(C:\Users\vastjust\AppData\Roaming\Typora\typora-user-images\1648259479008.png)]

影子寄存器

\qquad 在时基模块的控制寄存器(TBCLK,TBSTS,TBPHSHR,TBPHS,TBCTR,TBPRD)中,只有时基周期寄存器有影子寄存器。影子寄存器允许寄存器可以随硬件进行同步更新,Active Register(活跃寄存器)也就是被激活的寄存器,在工作的寄存器,控制着硬件,可以响应由硬件引起的相关事件。Shadow Register(影子寄存器)影子寄存器缓存器相当于为活跃寄存器提供了一个暂时的存放地址,不能直接影响硬件的控制,当系统运行到一定的时候,影子寄存器的值会传递给活跃寄存器,这样可以防止由于软件配置寄存器与硬件不 同步时而出现的系统崩溃或一些奇怪的故障。 影子寄存器与活跃寄存器的内存地址映射值是一致的,写或者读哪一个寄存 器,主要取决于 TBCTL[PRDLD]位。该位可以对 TBPRD 的影子寄存器进行使能或 者禁止。

\qquad 时基周期影子模式: 当 TBCTL[PRDLD]=0 时,TBPRD 的影子寄存器是使能的,读写 TBPRD 的映射地址的内容时,会读写影子寄存器。时基模块计数器值为 0 时(TBCTR=0x0000),影子寄存器的值传递给活跃寄存器。默认情况下,影子寄存器都是有效的。

\qquad 时基周期立即加载模式: 当 TBCTL[PRDLD]=1 时,为立即加载模式,读写时基周期寄存器对应的地址时,都是直接到活跃寄存器。

时基时钟同步

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v1xLA35S-1648380837870)(file:///C:\Users\vastjust\AppData\Local\Temp\ksohtml\wps9181.tmp.jpg)]

在这里插入图片描述

\qquad 从上述计数波形可以看出当同步信号来临时,不管目前时基计数器已经到了什么值,都将置位为相位寄存器的值,这个作用可以协调各路 ePWM 模块间的固定相位差,对于先递增后递 减模式,同一相位寄存器的值,同时对应着两个段,例如相位值 3,既出现在递增的过程中,又出现在递减的过程中,通过 TBCTL 寄存器的 PHSDIR 位的设置,就可以确定究竟是递增过程还是递减过程中的 3。TBCTL[PHSDIR]=1 表示为相位 寄存器的值是递增过程中的值,TBCTL[PHSDIR]=0 时表示为相位寄存器的值是递减过程中的值。当时基计数器的值变化到特定值的时候,会产生特定的信号。

\qquad 每个 ePWM 模块可以通过软件配置使用或者忽略同步输入信号。如果TBCTL(PHSEN)位被设置为 1,那么时基计数器在下面任意两种情况下就会自动加载相位寄存器(TBPHS)的内容。①ePWMxSYNCI:同步信号脉冲:当同步信号输入脉冲到来的时候,时基计数器就会在时基模块时钟 TBCLK 的下一个边沿自动加载 TBPHS 的值。②软件强制同步信号脉冲:向 TBCTL 的 SWFYNC 位写入 1 后,时基计数器也 会在时基模块时钟 TBCLK 的下一个边沿自动加载 TBPHS 的值。外设时钟使能的TBCLKSYNC(时基同步)位可以使所有的ePWM模块的时基时钟(TBCLK)同步使能,即使得每一个时基模块在TBCLK的第一个上升沿时同步,要使得TBCLKS完美同步,还需要设置ePWM的预分频位。设置ePWM步骤如下:

a):使能所有的ePWM的PCLKCRx(时钟寄存器);

b):TBCLKSYNC(同步触发)位清零;

c):配置ePWM模块相应的寄存器;

d):TBCLKSYNC(同步触发)位置1;

下面列出TB模块所有的寄存器
// Time base control register bit definitions                                
struct TBCTL_BITS {          // bits   description
   Uint16 CTRMODE:2;         // 1:0    Counter Mode
   Uint16 PHSEN:1;           // 2      Phase load enable
   Uint16 PRDLD:1;           // 3      Active period load
   Uint16 SYNCOSEL:2;        // 5:4    Sync output select
   Uint16 SWFSYNC:1;         // 6      Software force sync pulse
   Uint16 HSPCLKDIV:3;       // 9:7    High speed time pre-scale
   Uint16 CLKDIV:3;          // 12:10  Timebase clock pre-scale
   Uint16 PHSDIR:1;          // 13     Phase Direction
   Uint16 FREE_SOFT:2;       // 15:14  Emulation mode 
};
union TBCTL_REG{
Uint16 all;
struct TBCTL_BITS bit;
}
// Time base status register bit definitions                                    
struct TBSTS_BITS {          // bits   description
   Uint16 CTRDIR:1;          // 0      Counter direction status
   Uint16 SYNCI:1;           // 1      External input sync status
   Uint16 CTRMAX:1;          // 2      Counter max latched status
   Uint16 rsvd1:13;          // 15:3   reserved
};
union TBSTS_REG {
   Uint16              all;
   struct TBSTS_BITS   bit;
};
// Time base Phase register 
struct TBPHS_HRPWM_REG {   	// bits   description
   Uint16  TBPHSHR;     	// 15:0   Extension register for HRPWM Phase (8 bits)
   Uint16  TBPHS;           // 31:16  Phase offset register
};
union TBPHS_HRPWM_GROUP {
   Uint32                  all;
   struct TBPHS_HRPWM_REG  half;
};
//next to define a struct including all registers in TB module
struct EPWM_TB_Module_Regs{
   union  TBCTL_REG           TBCTL;   // 
   union  TBSTS_REG           TBSTS;   // 
   union  TBPHS_HRPWM_GROUP   TBPHS;   // Union of TBPHS:TBPHSHR
   Uint16                     TBCTR;   // Counter
   Uint16                     TBPRD;   // Period register set 
   Uint16                     rsvd1;   // 
};
计数比较模块

在这里插入图片描述

\qquad 计数器比较模块可以产生两个独立的比较事件,对于向上(递增)或者向下(递减)计数模式来说,在一个 PWM 周期内,比较事件只发生一次。而对于向上向下(先递增后递减)计数器模式来说,如果比较寄存器的值在 0-TBPRD 之间, 在一个 PWM 周期内,比较事件就会发生两次。这些事件都会直接影响动作模块。 计数器比较模块比较寄存器 CMPA、CMPB 各自都有一个影子寄存器。CMPA 影子寄存器通过清除 CMPCTL[SHDWAMODE]位使能,CMPB 影子寄存器通过清零CMPCTL[SHDWAMODE]位使能。默认情况下,CMPA 和 CMPB 影子寄存器是使能的。若 CMPA 影子寄存器被使能的话,那么在以下情况时,影子寄存器的值会传递到有效寄存器中。
\qquad --CTR=PRD:时基计数器值与周期寄存器值相同。 --CTR=ZERO:时基计数器为 0。
\qquad 立即加载模式:如果影子寄存器被禁止,就进入立即加载模式,一旦将值写入到 CMP 寄存器时,这个值直接送到有效寄存器中,立即起作用;计数比较寄存器中除了CMPCTL(比较控制寄存器)外,其余寄存器CMPAHR(高分辨率比较寄存器)、CMPA(比较器A寄存器)、CMPB(比较器B寄存器)。

\qquad 上图是计数比较器子模块内部图;首先看到的是CMPA和CMPB加载CTR的选择器;将CTR值分别放在CMPA、CMPB影子寄存器中,再由影子寄存器加载到活跃寄存器中开始进行计数比较,比较器会输出相应的信号到AQ模块(Action Qualifier 动作限定模块)。其中CTR = CMPA代表时基计数器计数到和CMPA值相等,CTR = CMPB代表时基计数器计数到和CMPB相等,CTR = PDR代表计数到周期最大值,这时候将CMPA或CPMB影子寄存器中的值加载到对应的活跃寄存器中,CTR = ZERO表示计数到0,此时也会活跃寄存器加载相应的值;
\qquad 下图显示了计数到CMPA、B后产生的事件,以向上计数为例。

在这里插入图片描述

下面列出CC模块的寄存器
// Compare control register bit definitions                                   
struct CMPCTL_BITS {          // bits   description
   Uint16 LOADAMODE:2;        // 0:1    Active compare A
   Uint16 LOADBMODE:2;        // 3:2    Active compare B
   Uint16 SHDWAMODE:1;        // 4      Compare A block operating mode
   Uint16 rsvd1:1;            // 5      reserved
   Uint16 SHDWBMODE:1;        // 6      Compare B block operating mode
   Uint16 rsvd2:1;            // 7      reserved
   Uint16 SHDWAFULL:1;        // 8      Compare A Shadow registers full Status
   Uint16 SHDWBFULL:1;        // 9      Compare B Shadow registers full Status
   Uint16 rsvd3:6;            // 15:10  reserved
};
union CMPCTL_REG {
   Uint16                all;
   struct CMPCTL_BITS    bit;
};
// define Compare A High Resolution register
struct CMPA_HRPWM_REG {   	// bits   description
   Uint16  CMPAHR;     	    // 15:0   Extension register for HRPWM compare (8 bits)
   Uint16  CMPA;            // 31:16  Compare A reg
};
union CMPA_HRPWM_GROUP {
   Uint32                 all;
   struct CMPA_HRPWM_REG  half;
};
//next define a struct incling all registers in CC module
struct EPWM_CC_Module_Regs{
       union  CMPCTL_REG          CMPCTL;  // Compare control
   union  CMPA_HRPWM_GROUP    CMPA;    // Union of CMPA:CMPAHR
   Uint16                     CMPB;    // Compare B reg
};
Action Qualifier (动作限定)子模块

在这里插入图片描述

\qquad 动作限定模块将时基模块TB的事件信号、计数器比较模块CC的事件信号进行转换来产生要求的各种类型的PWM输出(EPWMAx和EPWMBx)动作限定模块的作用如下:

\qquad a)动作模块根据下列事件产生动作(置高、拉低、翻转);

\qquad ∙ \bullet CTR=PRD:时基模块来的信号,时基计数器的值等于周期寄存器的值;

\qquad ∙ \bullet CTR=ZERO:时基模块来的信号,时基计数器的值等于 0;

\qquad ∙ \bullet CTR=CMPA:计数比较模块来的信号,时基计数器的值等于比较寄存器 A 的值;

\qquad ∙ \bullet CTR=CMPB:计数比较模块来的信号,时基计数器的值等于比较寄存器 B 的值;

\qquad b)管理以上事件发生后 PWM 的输出极性;

\qquad c)针对时基计数器递增或者递减时提供独立的动作控制;

\qquad 在动作限定模块中,仅有寄存器AQCSFRC(动作限定软件连续强制寄存器)有影子寄存器外,其余的寄存器AQCTRA(动作限定A输出控制寄存器)、AQCTRB(动作限定B输出控制寄存器)、AQCSFRC(动作限定软件强制寄存器)都没有影子寄存器。动作限定模块是基于事件驱动的,下图展示了动作限定模块的输入逻辑和输出动作:


\qquad 软件强制是个异步事件,这个控制由 AQSFRC 和 AQCSF 两个寄存器处理。动作模块可以控制输出ePWMA和ePWMB的动作。输入动作模块的事件也可以被量化,这样就可以控制在递增或递减计数模式时,输出独立的相位

ePWMA 和 ePWMB 输出的几种操作方式如下:

\qquad ∙ \bullet 置高(SET HIGH):使 ePWMA 和 ePWMB 输出高电平。

\qquad ∙ \bullet 置低(CLEAR LOW):使 ePWMA 和 ePWMB 输出低电平。

\qquad ∙ \bullet 取反(TOOGLE):当 ePWMA 或者 ePWMB 当前状态是低电平时,那么下一时刻就是高电平;当 ePWMA 或者 ePWMB 当前状态是高电平时,那么下一时刻就是低电平。

\qquad ∙ \bullet 不动作(DO NOTHING)(RESET后默认状态):不对 ePWM 输出做任何改变。但是还是可以产生相应的事件触发信号以及相关中断。

AQ事件优先级

在这里插入图片描述

\qquad 在同一时间,AQ模块有可能收到多个epwm事件,这种情况下就需要在硬件上指派优先级。一般而言,后发生的事件的优先级较高,而软件强制触发事件的优先级最高。对向上向下计数模式而言,优先级如下表,其中“1”代表优先级最高,“7”代表优先级最低。

优先级事件/增计数时事件/减计数时
1(Highest)软件强制软件强制
2向上计数到CMPB(CBU)向下计数到CMPB
3向上计数到CMPA(CAU)向下计数到CMPA
4计数到0计数到周期值
5向下计数到CMPB(CBD)向上计数到CMPB
6(Lowest)向下计数到CMPA(CAD)向上计数到CMPA

\qquad 对于向上计数而言

优先级事件
1(Highest)软件强制
2向上计数到周期值
3向上计数到CMPB
4向上计数到CMPA
5(Lowest)计数到0

\qquad 对于向下计数而言

优先级事件
1(Highest)软件强制
2向下计数到0
3向下计数到CMPB
4向下计数到CMPA
5(Lowest)计数到周期值

\qquad 上述说的计数最大值都是时基周期数。比较的值有可能会大于周期值,这种情况下比较输出事件如下表所示,其实很好理解,就是CMPA的值大于或小于周期值时的事件顺序。

计数方式在增计数比较在减计数比较
向上计数CMPA /B ≤ \leq TBPRD,事件发生在TBCTR=CMPA/B
CMPA/B >TBPRD,没有事件发生
不可能发生
向下计数不可能发生CMPA/B < TBPRD,事件正常在TBCTR = CMPA/B
CMPA/CMPB ≥ \geq TBPRD,事件发生在TBPRD
向上向下计数CMPA /B < TBPRD,事件发生在TBCTR=CMPA/B
CMPA/B ≥ \geq TBPRD,事件发生在TBPRD
CMPA /B < TBPRD,事件发生在TBCTR=CMPA/B
CMPA/B ≥ \geq TBPRD,事件发生在TBPRD
动作限定模块一般配置条件下的输出波形

\qquad 使用向上向下计数模式产生同步PWM: 实际使用中,如果装载 CMPA 或者 CMPB 为 0 时,那么设置 CMPA 或者 CMPB 的值要大于或等于 1,如果装载 CMPA 或 CMPB 为周期寄存器的值时,那么设置 CMPA或 CMPB 的值要小于或等于 TBPRD-1,这就意味着每个 PWM 周期至少有一个时基时钟周期的脉冲,在系统角度来看,这个周期很短,所以可以忽略。

\qquad 使用向上向下计数模式产生异步PWM: 为了产生0-50%的异步PWM需要在周期上加载CMPA/CMPB,使用周期动作来清除PWM,并通过比较动作来设置PWM,从0到TBPRD调节比较值,实现0-50%PWM占空 。

\qquad 当使用向上计数模式产生异步PWM: 为了实现0-100%异步pwm需要在周期上加载CMPA/CMPB,使用清零动作来清除PWM,并通过比较动作来设置PWM,从0到TBPRD调节比较值,实现0-100%PWM占空 。
在这里插入图片描述

上图中
\qquad a):TBPRD、CMPA和CMPB指的是写在各自寄存器中的值;硬件使用的是活动寄存器,而不是影子寄存器

\qquad b):CPMx指的是CMPA或CMPB;EPWMxA/B指的是EPWMx的输出信号;

单边非对称波形(ePWMxA 和 ePWMxB 独立调制,高电平有效)如下图所示

在这里插入图片描述

a):PWM周期是(TBPRD+1) × T T B C L K \times T_{TBCLK} ×TTBCLK

b):CMPA 决定 ePWMxA 的占空比,CMPB 决定ePWMxB 占空比。

\qquad 同理可以查找芯片手册看到,单边非对称波形(ePWMxA 和 ePWMxB 独立调制,低电平有效)、 非对称波形(仅调制ePWMxA)、 双边单边非对称波形(ePWMxA 和 ePWMxB 独立调制,低/高电平有效)

下面列出AQ模块所有的寄存器
// Action qualifier register bit definitions */                                    
struct AQCTL_BITS {           // bits   description
   Uint16 ZRO:2;              // 1:0    Action Counter = Zero
   Uint16 PRD:2;              // 3:2    Action Counter = Period
   Uint16 CAU:2;              // 5:4    Action Counter = Compare A up
   Uint16 CAD:2;              // 7:6    Action Counter = Compare A down
   Uint16 CBU:2;              // 9:8    Action Counter = Compare B up
   Uint16 CBD:2;              // 11:10  Action Counter = Compare B down
   Uint16 rsvd:4;             // 15:12  reserved
};
union AQCTL_REG {
   Uint16                all;
   struct AQCTL_BITS     bit;
};
//all bits in Reg AQCTLA and Reg AQCTLB are the same
// Action qualifier SW force register bit definitions */                                    
struct AQSFRC_BITS {           // bits   description
   Uint16 ACTSFA:2;            // 1:0    Action when One-time SW Force A invoked
   Uint16 OTSFA:1;             // 2      One-time SW Force A output
   Uint16 ACTSFB:2;            // 4:3    Action when One-time SW Force B invoked
   Uint16 OTSFB:1;             // 5      One-time SW Force A output
   Uint16 RLDCSF:2;            // 7:6    Reload from Shadow options
   Uint16 rsvd1:8;             // 15:8   reserved
};
// Action qualifier continuous SW force register bit definitions */                                    
struct AQCSFRC_BITS {          // bits   description
   Uint16 CSFA:2;              // 1:0    Continuous Software Force on output A
   Uint16 CSFB:2;              // 3:2    Continuous Software Force on output B
   Uint16 rsvd1:12;            // 15:4   reserved
};
union AQCSFRC_REG {
   Uint16                  all;
   struct AQCSFRC_BITS     bit;
};
//next we define a struct inclding all registers in AQ module
struct EPWM_AQ_Module_Regs{
   union  AQCTL_REG           AQCTLA;  // Action qual output A
   union  AQCTL_REG           AQCTLB;  // Action qual output B
    //all bits in AQCTLA and AQCTLB are the same ,we delcare in a struct
   union  AQSFRC_REG          AQSFRC;  // Action qual SW force
   union  AQCSFRC_REG         AQCSFRC; // Action qualifier continuous SW force 
};

死区产生器模块

在这里插入图片描述

\qquad 上面的几个模块已经可以产生频率、占空比、相位差可调的PWM了,接下来学习产生死区的模块。在前面学习的AQ模块中,我们可以知道通过设置合适的CMPA/B也可以产生全控型的带有死区的PWM,然而,如果需要更灵活的基于边缘延迟和极性控制的死区,那么应该使用死区子模块了,死区模块中的寄存器DBCTL(死区控制寄存器)、DBRED(死区上升沿延时计数寄存器)、DBFED(死区下降沿计数寄存器)都没有影子寄存器。死区模块的关键作用:

\qquad a):产生合适的带死区的互补的PWM信号(ePWMxA和ePWMxB);

\qquad b):对信号对(signals pair)编程:输出高有效(Active High)、输出低有效(AL)、输出互补高有效(AHC),输出互补低有效(ALC);

\qquad c):加入可编程上升沿延时(RED);

\qquad d):加入可编程下降沿延时(FED);

在这里插入图片描述

死区控制模块的特点

\qquad 输入源选择: 输入到死区模块的的信号EPWMxA和EPWMxB是从上一个模块AQ模块中来的,使用DBCTL(死区控制寄存器)的[IN_MODE](输入模式位)来使得EPWMxA和EPWMxB选择上升、下降或是上升下降延时;

\qquad 输出模式控制: 输出是通过配置DBCTL[OUT_MODE](输出模式位),这个位可以决定输出是上生延时、下降延时、或是都有,或是直接将输入的EPWMxA/B给到输出;

\qquad 极性控制: DBCTL的[POLSEL]可以指定输出PWM时在上升延时或下降延时时是否发生翻转;

\qquad 上图中我们注意到上升沿、下降沿都是10bit的计数器。死区模块可以设置独立的RED(上升沿延时)和FED(下降沿延时),总的延时之和就是RED+FED,其中RED = DBRED × T T B C L K \times T_{TBCLK} ×TTBCLK,FED = DBRED × T T B C L K \times T_{TBCLK} ×TTBCLK;

\qquad 下面的表格显示了其他典型的死区工作模式
在这里插入图片描述

\qquad 至此,已经可以得到频率、占空比、相位、互补死区可调的PWM了。

列出死区模块所有的寄存器
// Dead-band generator control register bit definitions   
struct DBCTL_BITS {          // bits   description
   Uint16 OUT_MODE:2;      	 // 1:0    Dead Band Output Mode Control 
   Uint16 POLSEL:2;          // 3:2    Polarity Select Control 
   Uint16 IN_MODE:2;         // 5:4    Dead Band Input Select Mode Control
   Uint16 rsvd1:10;          // 15:4   reserved
};

union DBCTL_REG {
   Uint16                  all;
   struct DBCTL_BITS       bit;
};
//next we define a struct including all regs in DB module
struct EPWM_DB_Module_Regs{
   union  DBCTL_REG           DBCTL;   // Dead-band control
   Uint16                     DBRED;   // Dead-band rising edge delay//6-0 bit are active
   Uint16                     DBFED;   // Dead-band falling edge delay
}
PWM 斩波(PC)子模块

在这里插入图片描述

\qquad PWM 斩波器模块通过高频信号来调制经由动作模块与死区模块产生的 PWM 波形,这个功能在基于脉冲变压器(我也没接触过)的门极驱动型功率器件控制中很重要。PWM斩波子模块只有一个寄存器PCCTL(PWM斩波控制寄存器),且没有影子寄存器

\qquad PWM斩波模块的作用:

\qquad a):可编程斩波(载波)频率;

\qquad b):可编程第一个脉冲的宽度;

\qquad c):可编程第2个和后续的脉冲的宽度;

\qquad d):如果不需要可以直接旁路掉;
在这里插入图片描述

\qquad 上图显示了PWM斩波模块工作的细节图;载波时钟是由系统时钟分频而来,他的频率和占空比是由PCCTL(PWM斩波控制寄存器)的CHPFREQ(斩波时钟频率控制位)和CHPDUTY(斩波时钟占空比控制位)控制的。一次触发模块(one-shot)子模块主要是提供较大能量的第一个脉冲,迅速有效的开通功率开关,改变功率开关的状态,接下来的脉冲只要维持开关的状态就行,例如多数功率器件开通电流要比维持电流大得多。单触发模块的第一个脉冲的宽度可以由 OSHTWTH 位来确定。PWM 斩波器这一功能模块可以用 CHPEN 位进行使能控制与禁止。

\qquad PC模块具体频率和占空比不再说明(ti不愧是电源、硬件做的牛的公司 Respect | Salute);

列出所有PC模块的寄存器
// PWM chopper control register bit definitions */                                    
struct PCCTL_BITS {         // bits   description
   Uint16  CHPEN:1;         // 0      PWM chopping enable
   Uint16  OSHTWTH:4;       // 4:1    One-shot pulse width
   Uint16  CHPFREQ:3;       // 7:5    Chopping clock frequency
   Uint16  CHPDUTY:3;       // 10:8   Chopping clock Duty cycle
   Uint16  rsvd1:5;         // 15:11  reserved
};
union PCCTL_REG {
   Uint16                  all;
   struct PCCTL_BITS       bit;
};
Trip-Zone (TZ,错误联防)模块

在这里插入图片描述
\qquad 每个 ePWM 模块都与 GPIO 多路复用引脚中的 6 个 T Z n ‾ \overline{TZn} TZn T Z 1 ‾ − T Z 6 ‾ \overline{TZ1}-\overline{TZ6} TZ1TZ6)信号脚连接。这些信号脚用来响应外部错误或外部触发条件,当错误发生时,PWM 模块可以通 过编程来响应这些问题;TZ模块的寄存器TZSEL(TZ选择寄存器)、TZCTL(TZ控制寄存器)、TZEINT(TZ使能中断寄存器)、TZFLG(TZ标志寄存器)、TZCLR(TZ清零寄存器)、TZFRC(TZ强制寄存器)都没有影子寄存器。错误联防模块的作用:

\qquad a):错误联防引脚 TZ1-TZ6 可以灵活的映射到对应的PWM 模块;

\qquad b):针对错误信息,ePWMxA 和 ePWMxB 可以被强制: --高电平–低电平。 --高阻抗–无动作;

\qquad c):在短路或者过流条件时,支持一次错误联防触发;

\qquad d):针对限流操作时,支持周期错误联防触发;

\qquad e):每个错误联防输入引脚都可以配置为一次或者周期错误联防触发;

\qquad f):任何一个错误联防引脚都可以产生中断;

\qquad g):支持软件强制错误联防;

\qquad h):如果不需要此模块,可以选择禁止;

\qquad TZ1-TZ6 的输入引脚为低有效。当这些引脚中的任意一个有效时,表明一个错误事件发生,每个 PWM 模块都可以单独配置为禁止或者使能此错误联防触发引脚。ePWM 模块选择哪一个错误引脚是通过 TZSEL 进行设置的,错误信号可以和系统时钟同步,也可以不同步,同样具有数字滤波功能,跟 GPIO 引脚一样。一 个系统时钟的低脉冲输入即可以有效触发错误控制逻辑。异步触发确保在系统时钟发生错误的情况下,错误引脚仍能触发错误控制逻辑。其余的配置可以参照GPIO 的引脚配置。每个 TZn 输入引脚可以单独配置一次触发或者周期触发。

\qquad 周期触发: 当周期错误联防事件发生时,TZCTL 寄存器中的动作立刻输出到 ePWMxA 和 ePWMxB 引脚上,另外,周期错误联防事件标志位(TZFLG[CBC])被置位,同时当 TZEINT 寄存器和 PIE 模块的中断使能时,ePWMx_TZINT 中断就会产生;

\qquad 单次触发: 当单次错误联防事件发生时,同样 TZCTL 寄存器中的动作立刻输出到 ePWMxA 和 ePWMxB 引脚上,另外单次错误联防事件标志位(TZFLG[OST])被置位,同时当 TZEINT 寄存器和 PIE 模块的中断使能时,ePWMx_TZINT 中断就会产生的。两种模式触发的区别在于周期错误联防事件标志可以自动清零,但是单次错误联防事件标志需要软件清零。下表是可能的触发事件
在这里插入图片描述

\qquad 上图是错误联防模块控制逻辑,单次触发和周期触发的方式完全一样,只是需要设置不同的位。

列出所有TZ模块的寄存器
// Trip zone select register bit definitions                                   
struct TZSEL_BITS {           // bits   description
   Uint16  CBC1:1;            // 0      TZ1 CBC select
   Uint16  CBC2:1;            // 1      TZ2 CBC select
   Uint16  CBC3:1;            // 2      TZ3 CBC select
   Uint16  CBC4:1;            // 3      TZ4 CBC select
   Uint16  CBC5:1;            // 4      TZ5 CBC select
   Uint16  CBC6:1;            // 5      TZ6 CBC select
   Uint16  rsvd1:2;           // 7:6    reserved
   Uint16  OSHT1:1;           // 8      One-shot TZ1 select             
   Uint16  OSHT2:1;           // 9      One-shot TZ2 select             
   Uint16  OSHT3:1;           // 10     One-shot TZ3 select             
   Uint16  OSHT4:1;           // 11     One-shot TZ4 select             
   Uint16  OSHT5:1;           // 12     One-shot TZ5 select             
   Uint16  OSHT6:1;           // 13     One-shot TZ6 select             
   Uint16  rsvd2:2;           // 15:14  reserved
};
union TZSEL_REG {
   Uint16                  all;
   struct TZSEL_BITS       bit;
};
// Trip zone control register bit definitions */                                    
struct TZCTL_BITS {         // bits   description
   Uint16 TZA:2;            // 1:0    TZ1 to TZ6 Trip Action On EPWMxA
   Uint16 TZB:2;            // 3:2    TZ1 to TZ6 Trip Action On EPWMxB
   Uint16 rsvd:12;          // 15:4   reserved
};
union TZCTL_REG {
   Uint16                  all;
   struct TZCTL_BITS       bit;
};
// Trip zone control register bit definitions */                                    
struct TZEINT_BITS {         // bits   description
   Uint16  rsvd1:1;          // 0      reserved
   Uint16  CBC:1;            // 1      Trip Zones Cycle By Cycle Int Enable
   Uint16  OST:1;            // 2      Trip Zones One Shot Int Enable
   Uint16  rsvd2:13;         // 15:3   reserved
};   
union TZEINT_REG {
   Uint16                  all;
   struct TZEINT_BITS      bit;
};
// Trip zone flag register bit definitions */                                    
struct TZFLG_BITS {         // bits   description
   Uint16  INT:1;           // 0      Global status
   Uint16  CBC:1;           // 1      Trip Zones Cycle By Cycle Int
   Uint16  OST:1;           // 2      Trip Zones One Shot Int
   Uint16  rsvd2:13;        // 15:3   reserved
};
union TZFLG_REG {
   Uint16                  all;
   struct TZFLG_BITS       bit;
};
// Trip zone flag clear register bit definitions */                                    
struct TZCLR_BITS {         // bits   description
   Uint16  INT:1;           // 0      Global status
   Uint16  CBC:1;           // 1      Trip Zones Cycle By Cycle Int
   Uint16  OST:1;           // 2      Trip Zones One Shot Int
   Uint16  rsvd2:13;        // 15:3   reserved
};
union TZCLR_REG {
   Uint16                  all;
   struct TZCLR_BITS       bit;
};
// Trip zone flag force register bit definitions */                                    
struct TZFRC_BITS {         // bits   description
   Uint16  rsvd1:1;         // 0      reserved
   Uint16  CBC:1;           // 1      Trip Zones Cycle By Cycle Int
   Uint16  OST:1;           // 2      Trip Zones One Shot Int
   Uint16  rsvd2:13;        // 15:3   reserved
};
union TZFRC_REG {
   Uint16                  all;
   struct TZFRC_BITS       bit;
};
//next we define a struct including all regs in ET module
struct EPWM_TZ_Module_Regs{
   union  TZSEL_REG           TZSEL;   // Trip zone select
   Uint16                     rsvd2;   
   union  TZCTL_REG           TZCTL;   // Trip zone control
   union  TZEINT_REG          TZEINT;  // Trip zone interrupt enable
   union  TZFLG_REG           TZFLG;   // Trip zone interrupt flags
   union  TZCLR_REG           TZCLR;   // Trip zone clear   
   union  TZFRC_REG    	      TZFRC;   // Trip zone force interrupt
}
Event-Trigger(ET事件触发)模块

\qquad 事件触发模块的功能主要如下:

\qquad a):接收来自时基模块和计数比较模块产生的相关事件的输入;

\qquad b):利用时基模块中的方向信息识别是递增还是递减计数模式以便产生相应的事件;

\qquad c):使用预定标判断逻辑发出中断请求或者 ADC 开始转换启动信号:/每一个事件/每两个事件/每三个事件

\qquad d):允许软件配置,强制产生中断事件或者 ADC 启动信号

在这里插入图片描述

\qquad 事件触发模块主要响应时基模块与计数比较模块的相关事件,当这些事件发生时,PWM 事件触发模块产生相应的中断事件或 ADC 启动事件。ET模块内部寄存器ETSEL(ET选择寄存器)、ETPS(ET预分频寄存器)、ETFLG(ET标志寄存器)、ETCLR(ET清零寄存器)、ETFRC(ET强制触发寄存器)都没有影子寄存器。事件触发模块的内部结构图如下:

在这里插入图片描述

\qquad 所有的 ePWM 模块的 ADC 启动转换信号是一起做或运算之后连接到 ADC 单元的,因此一个有效的 ADC 转换信号可能对应着多个模块,当两个以上 ADC 转换请求同时发生时,实际为一个请求被识别。事件触发子模块监控各种事件的状态,并且可以在发出中断请求或者 ADC 转换启动之前可以预先进行定标配置。

\qquad 下面的事件可以通过配置中断选择位ETSEL[INTSEL]来选择触发中断:

\qquad ∙ \bullet 时基计数器等于0(TBCTR = 0x0000);

\qquad ∙ \bullet 时基计数器等于周期值(TBCTR = TBPRD);

\qquad ∙ \bullet 增/减计数时等于CMPA;

\qquad ∙ \bullet 增/减计数时等于CMPB;

\qquad 通过中断事件计数器(ETPS[INTCNT])寄存器位可以得到事件的数量。当ETPS[INTCNT]递增计数直到数值等于 ERPS[INTPRD]确定的值时,停止计数且输出 置 位 , 只 有 当 中 断 发 送 到 PIE 时 , 计 数 器 才 会 清 零 。 当 ETPS[INTCNT]=ETPS[INTPRD]将发生以下动作:

\qquad ∙ \bullet 如果中断被使能,ETSEL[INTEN]=1 并且中断标志清零,ETFLG[INT]=0,则产 生 中 断 脉 冲 且 中 断 标 志 位 置 位 , ETFLG[INT]=1 , 事 件 计 数 器 清 零ETPS[INTCNT]=0,再重新对事件计数。

\qquad ∙ \bullet 如果中断被禁止,ETSEL[INTEN]=0 或者中断标志置位,ETFLG[INT]=1,则当计数器的值等于周期值即 ETPS[INTCNT]=ETPS[INTPRD],计数器停止计数。如果中断被使能,但是中断标志已经复位,则计数器将输出高电平直到ETFLG[INT]=0,这就允许当接收一个中断时,另一个中断进行等待。INTPRD 位写操作时,计数自动清零即 INTCNT=0,并且计数器输出复位。写 1到 ETFRC[INT]位,计数器 INTCNT 将增加。当 INTCNT=INTPRD 时,计数器将按照上述描述进行工作。当 INTPRD=0 时,计数器将被禁止,所以不会检测到任何时间并且 ETFRC[INT]位被忽略。

在这里插入图片描述

\qquad 上图显示了事件触发器触发SOCA;除了产生连续脉冲外,ETPS[SOCACNT]计数器和 ETPS[SOCAPRD]周期值同上述中断产生逻辑中的计数器和周期寄存器功能相同,所不同的是此模块产生连续脉 冲。当一个脉冲产生时,脉冲标志 ETFLG[SOCA]被锁存,但是不会停止脉冲的产生。使能/禁止位 ETSEL[SOCAEN]用于停止脉冲的产生,但是输入时间仍就被继续 计 数 直 到 其 值 等 于 周 期 寄 存 器 的 值 。 可 以 通 过 ETSEL[SOCASEL] 和ETSEL[SOCBSEL]位独立设置 SOCA 和 SOCB脉冲触发事件。事件触发模块 SOCB 的产生电路,SOCB 产生过程和 SOCA 相同。

电源中的应用

\qquad 手册上主要说的就是同步触发的buck电路,半桥电路、带ZVS的全桥电路等,这个等实际使用过程再讨论。

代码实例

\qquad 将所有的ePWM(6对)输出,设置死区、占空比、频率、相位差

SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;   // Disable TBCLK within the ePWM
SysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK = 1;  // enable ePWM1
InitEPwm1Gpio()//configure GPIO as ePWM mode 
//TZ  设置// Enable TZ1 and TZ2 as one shot trip sources
EPwm1Regs.TZSEL.bit.OSHT1 = 1;
EPwm1Regs.TZSEL.bit.OSHT2 = 1;
EPwm1Regs.TZCTL.bit.TZA = TZ_FORCE_HI;
EPwm1Regs.TZCTL.bit.TZB = TZ_FORCE_LO;
// Enable TZ interrupt
EPwm1Regs.TZEINT.bit.OST = 1;
//configure as Sync
EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO;
EPwm1Regs.TBCTL.bit.PHSEN = TB_ENABLE;
EPwm1Regs.TBPHS.half.TBPHS = 0;
EPwm1Regs.TBCTR = 0x0000;// Clear counter
EPwm1Regs.TBPRD = tbprd;
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
EPwm1Regs.TBCTL.bit.HSPCLKDIV=TB_DIV1;
EPwm1Regs.TBCTL.bit.CLKDIV=TB_DIV1;//set division factor
// Setup shadow register load on ZERO
EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
// Set Compare values
EPwm1Regs.CMPA.half.CMPA = 0; // Set compare A value
EPwm1Regs.CMPB = 0; // Set Compare B value
//configure AQ module 
EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET;
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;
EPwm1Regs.AQCTLB.bit.ZRO = AQ_CLEAR;
EPwm1Regs.AQCTLB.bit.CBU = AQ_SET;
//configure DB module 
EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;
EPwm1Regs.DBCTL.bit.IN_MODE = DBA_ALL;
EPwm1Regs.DBRED = DeathTime;
EPwm1Regs.DBFED = DeathTime;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;// Start all the timers synced

//next we need set ePWM2 
EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN;// sync signal from last syncOut
EPwm2Regs.TBCTL.bit.PHSEN = TB_ENABLE;//enable phase register 
EPwm2Regs.TBPHS.half.TBPHS=Phase;//set the phase value 
//then,all ePWM can be set as the same way 

下面讨论一下PWM的精度

\qquad 首先,我们知道频率的计算公式, f = f T B C L K / T B P R D f = f_{TBCLK}/TBPRD f=fTBCLK/TBPRD,在不考虑功耗下,显然不分频下(即TBCTL[CLKDIV]TBCTL[HSPCLKDIV] = 0)的可以有较大的频率范围和较高的PWM精度;
p = 1 T B P R D = f f T B C L K C L K D I V × H S P C L K D I V p = \frac{1}{TBPRD}=\frac{f}{\cfrac{f_{TBCLK}}{CLKDIV\times HSPCLKDIV}} p=TBPRD1=CLKDIV×HSPCLKDIVfTBCLKf
\qquad 那么以100kHz为例,带入有
p = f × C L K D I V × H S P C L K D I V f T B C L K = 100 k 150 M = 0.067 % p = \frac{f\times CLKDIV\times HSPCLKDIV} {f_{TBCLK}}= \frac{100k}{150M}=0.067\% p=fTBCLKf×CLKDIV×HSPCLKDIV=150M100k=0.067%

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐