天天看点

DSP_TMS320F28377D_ePWM学习笔记前言正文结束语

前言

本人需要使用ePWM来控制一个永磁同步电机(PMSM), 本文记录了对于TMS320F28377D ePWM模块的学习笔记。主要内容是FOC PMSM控制的ePWM配置,同时包含ADC触发源的配置,关于ADC的学习笔记,请参考DSP_TMS320F28377D_ADC学习笔记_江湖上都叫我秋博的博客-CSDN博客。

正文

关于一些PWM的基础知识,b站up主暗星归来老师的这个视频讲得非常好。开发教程篇-第5期-EPWM使用(上)_哔哩哔哩_bilibili,为了避免视频被删除,我搬运复述一下,好记性不如烂键盘。

PWM介绍

那么何谓PWM 呢?

字面意思上就是脉冲宽度调制,是通过固定开关周期,调节一个周期内的高电平时间的宽度然后控制开关器件的导通时间,进而调整单个周期内输入侧向输出侧提供能量的时间长度,达到控制输出的目的。说人话就是,控制给牛喂草的量。

PWM里面有几个重要的指标:

1开通时间 Ton: 每次给牛喂草的时间,单位:S

2 关断时间 Toff: 每次停止喂牛的时间,单位:S

3开关周期Tsw:每隔多长时间喂一次牛,Tsw = Ton + Toff,单位: S

4开关频率 Fsw:一秒钟之内喂多少次牛,Fsw = 1/Tsw,单位: Hz

以上4点指标无论是在模拟 PWM 还是数字PWM 中都适用,其示意图如下图所示。

DSP_TMS320F28377D_ePWM学习笔记前言正文结束语

而对于数字PWM,还有点特殊的特性

1 计数器: 相当于模拟领域中的积分器

2 步长: 每多长时间计数一次。

以上两点是数字 PWM 区别于模拟 PWM 的特点,其中尤以“步长”重要,因为它会牵涉到我们 PWM 的分辨率,通俗来讲就是会影响到输出的精度 (不是全部因素)。

数字PWM 的计数器通常有3 种计数方式:向上、向下及上下计数。对应到模拟领域的波形就是锯齿波、反锯齿波及三角波,其对应关系如下图所示。

DSP_TMS320F28377D_ePWM学习笔记前言正文结束语

可以看到,在模拟中计数 (严格来说是积分器)都是连续的,不存在台阶,而数字中是存在这个步长的。在众多仿真软件中,上图中的三种波形发生器都是存在的,但在实际的模拟芯片制造中,一般只会使用第一种方式,即锯齿波,因为这种波形很容产生:通过一个恒流源对电容充电,在通过一个复位器对电容进行瞬间放电,在电容两端产生的电压就是一个锯齿波。而后面两种方式在实现上是比较困难的,笔者没有做过芯片设计,不知道这个难易程度以及制造成本,但从市场上大量应用的芯片内部构造基本清一色的都是锯齿波来看,后面两种方式应该不容易设计生产或者制造成本很高。

28377D的ePWM介绍,首先我们来看,他们由哪些部分组成。

DSP_TMS320F28377D_ePWM学习笔记前言正文结束语
DSP_TMS320F28377D_ePWM学习笔记前言正文结束语

ePWM的组成:

1 Time-Base Submodule,时基模块

2 Counter Compare Submodule,计数比较模块

3 Action Qualifier Submodule,动作限定模块

4 Dead-Band Generator Submodule,死区生成模块

5 PWM Chopper Submodule,高频斩波模块

6 Trip Zone Submodule,触发区域模块

7 Event Triger Submodule,事件触发模块

8 Digital Compare Submodule,数字比较模块

TB 时基模块

DSP_TMS320F28377D_ePWM学习笔记前言正文结束语

如图所示,关键部位已经使用红色字体标出,TB 模块工作的大致流程如

  • 分频器对 SYSCLK 分频得到 ePWM TB 时钟
  • 2计数器按照所设置的计数方式进行计数
  • 计数器按照设定的同步方式进行同步操作
  • 生成相应的同步信号进行输出

其实 TB 模块也就这么简单而已,归根究底它的本质就是一个计数器

Shadow影子寄存器,怎么理解它,不太恰当的比喻:古代皇帝阅读奏折,最底层九品芝麻官的奏折无法直接递上来给皇帝看的,大部分情况下,都是由丞相审理出来,先过一道手,再交给皇帝。Shadow跟这个有点类似,你不是要给我写东西吗?你先把数据先放到影子寄存器,到某一个时刻,我再从影子寄存器里面取走,拿到我真的用的地方去。那么好处是什么?在环路控制的时候,如果说环路输出值计算完了以后,要往这个寄存器里面装载,刚好这个周期,还没完,如果这时候你让它立即生效的话,就可能会导致环路震荡,你本周期正在执行的,应该是上周期计算出来的理论值,结果你把上一个周期计算的理论值打破了。也就是Shadow寄存器的好处是当我本周期结束的时候,才把计算出来的东西放在下个周期来用,这样来讲要稳定一些。

对于这个计数器,我们重点需要设置的点包括:

  • 1 分频系数: 关系到计数步长,宏观上影响占空比/周期的最小刻度
  • 2 计数方式: Up、Down、Up-Down,前面章节已经介绍过;
  • 3 周期值: 直接影响开关频率
  • 4 同步输入:直接影响周期/占空比
  • 5 同步输出:影响其他 ePWM 模块
  • 6 周期生效方式:在 PFM 场景下,影响环路的控制方式,(上面讲的影子寄存器相关)

这里需要额外关注的是246,因为这3 项对能否熟练使用ePWM 控制环路影响很深远,我们在后面基于实物的操作中会再讲解,这里读者只需要有个印象知道它很重要就行。

CC 计数比较模块

CC,Counter-Compare,:很明显这里是比较器,用来产生跳边沿的,脉冲信号

DSP_TMS320F28377D_ePWM学习笔记前言正文结束语

从图中可以看到,CC 模块的主体是 TB 模块的计数值 TBCTR,和比较值CMPx,当CTR = CMPx时,就会产生一个脉冲,这个脉冲信号会送到 AQ模块和ET模块。

用于比较的值CMPx都有一个Shadow,TB 中的PRD寄存器也有一个Shadow, 这个 Shadow 到底是什么的? 有什么作用呢? 简单来说Shadow 就是一个缓存器将写入的值先放入到缓存器,然后再适时的加载到比较器中。官方称呼为影子寄存器,都是一个道理。前面我们也讲过了。

那么这里的CC模块输出的4个脉冲信号是否就是我们所谓的PWM 波波呢?当然不是,这里输出的脉冲信号,它就仅仅是脉冲信号而已,没错就是脉冲。那么PWM 波波到底是在哪里产生的呢?

AQ 动作限定模块

AQ,Action Qualifier,动作限定,用于产生 PWM 波形的模块。看这名字取的多么晦涩,如果没接触过 C2000 的 ePWM,大概率会以为这个是限幅用的而上面那个 CC 才是产生 PWM的,只能说TI的脑洞跟普通人有点不一样了。那么 AQ 是如何产生 PWM 的呢? 从下图 中可以得到答案。

DSP_TMS320F28377D_ePWM学习笔记前言正文结束语

AQ 模块依据 TBCLK 作为心跳,依据 CTR=Zero/PRD/CMPA/CMPB 以及CTR dir 5个输入信号,产生所设定的波形。例如,TB 模块设定计数方式为 Up-Mode,CC 模块设定的 CMPA/CMPB 非0且不等于 PRD,AQ 模块设定如下: CTR=0 时ePWMA/B 输出高;向上计数过程中,CTR=CMPA时EPWMA 输出低,CTR=CMPB时 ePWMB 输出低。则可以得到如下图 所示的输出波形。、

DSP_TMS320F28377D_ePWM学习笔记前言正文结束语

还有很多其他设置方式,这里不进行一一举例,读者可自行查阅 TI 官方手册阅读

AQ 模块中有两个比较有意思的寄存器

  1. AQSFRC,Action Qualifier Software Forced Register Control。
  2. AQCSFRC,Action Qualifier Continuous Software Forced Register Control。从英文全称上也可以猜出来它是干啥的: 强制让 EPWM 输出变成某个状态只是 AQSFRC 设置只能单次有效(下个周期继续按照PWM的产生逻辑输出),而 AQCSFRC 则是持续有效。

在控制具有驱动芯片的PMSM时,AQCSFRC是有可能被用到的。

DB 死区模块

死区一般在上下管驱动电路(专业点:半桥拓扑)中使用,为什么要加死区? 看下面这个图

DSP_TMS320F28377D_ePWM学习笔记前言正文结束语

由于功率器件并不是理想的器件,状态切换的时候实际上是存在斜率的,并非垂直的瞬间切换,所以需要设计死区,在Q1打开前,需要先把Q2关断一段时间,Q2打开前,要把Q1关断一段时间,否则就有可能同时导通的。 如果没有死区,Q1和Q2有可能会被同时导通,最终导致电源接低短路,导致炸鸡。 当然,有些PMSM配有驱动芯片,死区的问题驱动芯片已经考虑在内了,这时候不用考虑死区的问题。 如果你是用DSP接MOS管去控制PMSM,那么就要考虑死区了。

看下图,用DB模块配置一个带死区的互补的模型

DSP_TMS320F28377D_ePWM学习笔记前言正文结束语

PC 高频斩波模块

TI官方说这个模块用在脉冲变压器的, 对于咱们要用它来控制PMSM来讲,这个模块肯定是用不上的,简单了解一下就好。

DSP_TMS320F28377D_ePWM学习笔记前言正文结束语

看下面这个波形图,这个模块可以把低频的PWM波,弄成高频的。不多讲了

DSP_TMS320F28377D_ePWM学习笔记前言正文结束语

TZ 保护模块

TZ,Trip Zone,即触发区域模块。该模块一般用于封锁 PWM 波形保护电源。这部分的笔记就不赘述了。 当我们触发了保护之后,PWM波形就被拉低了。可以瞅瞅下面这个图

DSP_TMS320F28377D_ePWM学习笔记前言正文结束语

详情请去看这个视频。开发教程篇-第6讲-EPWM使用(中②)_哔哩哔哩_bilibili

ET 事件触发模块

事件触发模块,这个模块,我们在控制PMSM的时候,是可以用到的,重点关注一下。

何为事件触发?即EPWM 在某一时刻发生了某件事,这件事被 ET 模块知晓了,然后向外散播一个触发信号,告诉其他模块或 CPU 我这里出事了,你自己看着办

这里就牵涉到时间、事件,注意这里的时间是相对时间而非绝对时间。

看一下ET 模块的系统框图,就能知晓它能够接收哪种事件、向外散播的又是什么事件。

DSP_TMS320F28377D_ePWM学习笔记前言正文结束语

需要注意一点的是, 生成事件触发信号是可以有个计数的,比如当CTR = CMPA发生1次时候,我不触发事件,我要发生10次的时候再触发事件。这也是可以的。

DC 模块

DC,Digital Compare,即数字比较模块。简单来说,这就是一个针对各种触发信号的一个调理模块,调理成所需要的最终信号 DCAEVT1/2、DCBEVT1/2。那么 DC模块可以用来调理哪些输入信号呢?  用于扩大用于保护的TZ信号的输入范围

DSP_TMS320F28377D_ePWM学习笔记前言正文结束语

这个有点复杂,不想记了,感兴趣的朋友看开发教程篇-第6讲-EPWM使用(中③)_哔哩哔哩_bilibili。 

代码理解

EPWM的相关代码可以分为三个部分,一部分是GPIO复用的配置,一部分是EPWM的控制器寄存器配置,最后一部分就是EPWM的使用。

void epwm_init(void){
    epwm_gpio_init();
    epwm_register_init();
}

void epwm_gpio_init(void){
    InitEPwm1Gpio();
    InitEPwm2Gpio();
    InitEPwm3Gpio();
}

void epwm_register_init(void){

    EPwm1Regs.TBCTL.bit.CTRMODE     = TB_COUNT_UPDOWN;      // Count updown
    EPwm1Regs.TBPRD                 = EPWM1_TIMER_TBPRD;    // Set timer period
    EPwm1Regs.TBCTL.bit.PHSEN       = TB_DISABLE;           // Disable phase loading
    EPwm1Regs.TBPHS.bit.TBPHS       = 0x0000;               // Phase is 0
    EPwm1Regs.TBCTR                 = 0x0000;               // Clear counter
    EPwm1Regs.TBCTL.bit.HSPCLKDIV   = TB_DIV1;              // Clock ratio to SYSCLKOUT
    EPwm1Regs.TBCTL.bit.CLKDIV      = TB_DIV1;

    // 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.bit.CMPA         = EPWM1_MIN_CMPA;       // Set compare A value
    // EPwm1Regs.CMPB.bit.CMPB = EPWM1_MIN_CMPB;            // Set Compare B value

    // Set actions
    EPwm1Regs.AQCTLA.bit.CAU        = AQ_SET;               // Set PWM1A on event A, down count
    EPwm1Regs.AQCTLA.bit.CAD        = AQ_CLEAR;             // Clear PWM1A on event A, up count

    // EPwm1Regs.AQCTLB.bit.CBU     = AQ_SET;               // Set PWM1B on Zero
    // EPwm1Regs.AQCTLB.bit.CBD     = AQ_CLEAR;             // Clear PWM1B on event B, up count
    // EPwm1Regs.DBCTL.bit.POLSEL   = 0x02;
    // EPwm1Regs.DBCTL.bit.OUT_MODE = 0x01;

    // Interrupt where we will change the Compare Values
    EPwm1Regs.ETSEL.bit.SOCAEN      = 0x00;                 // 0 Disable 1 Enable
    EPwm1Regs.ETSEL.bit.SOCASEL     = 0x01;                 // Start-of-Conversion(SOC) 选择什么时候产生SOCA脉冲, 当计数器等于零时产生SOCA事件,以触发ADC的SEQ1开始采集电流
    EPwm1Regs.ETPS.bit.SOCAPRD      = 0x02;                 //

… EPwm2、EPwm3的配置类似
}


// EPwm使用就下面这几行代码,也就是平时改一下比较器的值   
    EPwm1Regs.CMPA.bit.CMPA    =   (Uint16)(t_cm1*EPWM1_TIMER_TBPRD);
    EPwm2Regs.CMPA.bit.CMPA    =   (Uint16)(t_cm2*EPWM2_TIMER_TBPRD);
    EPwm3Regs.CMPA.bit.CMPA    =   (Uint16)(t_cm3*EPWM3_TIMER_TBPRD);
           

GPIO的配置

首先来看GPIO的配置,EPwm的GPIO复用配置函数是官方提供的,所以用的时候直接调用就行了, 不过需要注意是,EPWM的每组通道支持的IO有两组,比如EPWM1A/1B支持的IO可以是GPIO0/1,也可以是GPIO145/146。这个根据硬件实际的连接来选择就好了,官方代码都写好了,修改只需要修改注释即可。

void InitEPwm1Gpio(void)
{
    EALLOW;

    //
    // Disable internal pull-up for the selected output pins
    // for reduced power consumption
    // Pull-ups can be enabled or disabled by the user.
    // Comment out other unwanted lines.
    //
    GpioCtrlRegs.GPAPUD.bit.GPIO0 = 1;    // Disable pull-up on GPIO0 (EPWM1A)
    GpioCtrlRegs.GPAPUD.bit.GPIO1 = 1;    // Disable pull-up on GPIO1 (EPWM1B)
    // GpioCtrlRegs.GPEPUD.bit.GPIO145 = 1;    // Disable pull-up on GPIO145 (EPWM1A)
    // GpioCtrlRegs.GPEPUD.bit.GPIO146 = 1;    // Disable pull-up on GPIO146 (EPWM1B)

    //
    // Configure EPWM-1 pins using GPIO regs
    // This specifies which of the possible GPIO pins will be EPWM1 functional
    // pins.
    // Comment out other unwanted lines.
    //
    GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1;   // Configure GPIO0 as EPWM1A
    GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1;   // Configure GPIO1 as EPWM1B
    // GpioCtrlRegs.GPEMUX2.bit.GPIO145 = 1;   // Configure GPIO145 as EPWM1A
    // GpioCtrlRegs.GPEMUX2.bit.GPIO146 = 1;   // Configure GPIO0146 as EPWM1B

    EDIS;
}
           

Epwm-TB控制器寄存器的配置

EPwm1Regs.TBCTL.bit.CTRMODE     = TB_COUNT_UPDOWN;

CTRMODE表示计数模式,PWM的计数模式可以配置成三种,PMSM的FOC控制,一般使用上下计数模式。

#define TB_COUNT_UP      0x0

#define TB_COUNT_DOWN    0x1

#define TB_COUNT_UPDOWN  0x2

EPwm1Regs.TBPRD                 = EPWM1_TIMER_TBPRD;

TBPRD表示计数周期,注意,假设你的计数周期设置成100,你的计数模式是向上/向下模式,那么你Tsw = 100 * ΔT。但如果你的计数模式是上下计数模式,那么你的Tsw = 200 * ΔT

计数器TBCTR会从0开始递增到100,然后再从100递减到0。 因此Tsw = 200。

EPwm1Regs.TBCTL.bit.PHSEN       = TB_DISABLE;

EPwm1Regs.TBPHS.bit.TBPHS       = 0x0000;

PHSEN表示相移模块的使能,TBPHS表示相移多少,这个部分的功能我们没有用到,因此把它关闭掉。

EPwm1Regs.TBCTR                 = 0x0000;

TBCTR表示时基模块TB的计数值,我们在初始化配置的时候,令其=0。

EPwm1Regs.TBCTL.bit.HSPCLKDIV   = TB_DIV1;

HSPCLKDIV表示高速EPWM的分频,其实我们没有用的高速EPWM,因此暂时把它1分频。

EPwm1Regs.TBCTL.bit.CLKDIV      = TB_DIV1;

CLKDIV表示EPWM时基模块分频,为了让PWM有尽量高的分辨率,时基模块一般都是1分频。

Epwm-CMP(CC)控制器寄存器的配置

EPwm1Regs.CMPCTL.bit.SHDWAMODE  = CC_SHADOW;

EPwm1Regs.CMPCTL.bit.LOADAMODE  = CC_CTR_ZERO;

SHDWAMODE 表示CC模块影子寄存器的模式,前面也提到了,影子寄存器是一种稳妥的办法,因此我们肯定是配置成影子模式(CC_SHADOW),而不是立即生效模式(CC_IMMEDIATE)

LOADAMODE 表示CC模块比较寄存器的加载模式,即,我在什么时候把影子寄存器里面的比较值加载进来使用。我们有4中选择

#define CC_CTR_ZERO      0x0

#define CC_CTR_PRD       0x1

#define CC_CTR_ZERO_PRD  0x2

#define CC_LD_DISABLE    0x3

而,我们选择了CC_CTR_ZERO,即计数器(CTR),等于0(ZERO)的时刻。

// EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;

// EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;

这两行注释,解释一下,由于在PWM作为半桥拓扑电路的输入波形时,常需要带死区且互补的两个PWM波形,因此一个PWM模块一般都可以输出两个PWM波。 但是呢,我们控制PMSM的硬件电路里面有驱动芯片,而驱动芯片已经把死区、互补的相关工作做了,所以每相我们DSP这边只需要1个PWM波。 因此在我们的配置中,就不配置EPWM1的B PWM波了。PMSM控制需要三个相的PWM波,我们用的分别是EPWM1A、EPWM2A、EPWM3A。而EPWM1B、EPWM2B、EPWM3B就都不配置了。

EPwm1Regs.CMPA.bit.CMPA         = 0;

CMPA表示CC模块EPwm1的A组PWM波的比较值。 初始化为0,后续FOC控制主要就是改变这个寄存器的值了,还有另两相EPwm2Regs.CMPA.bit.CMPA和EPwm3Regs.CMPA.bit.CMPA。由于前面的配置,影子寄存器模式会自动运行了。

Epwm-AQ控制器寄存器的配置

EPwm1Regs.AQCTLA.bit.CAU        = AQ_SET;

EPwm1Regs.AQCTLA.bit.CAD        = AQ_CLEAR;

CAU表示AQ模块,当计数值大于比较值时,PWM的输出是拉高还是拉低。

CAD表示AQ模块,当计数值小于比较值时,PWM的输出是拉高还是拉低。

我们的设置是当计数值大于比较值时,PWM输出拉高,反之,则拉低。

Epwm-DB控制器寄存器的配置

// EPwm1Regs.DBCTL.bit.POLSEL   = 0x02;

// EPwm1Regs.DBCTL.bit.OUT_MODE = 0x01;

上面也提到了,由于死区的工作在驱动芯片上做了,所以我们不配置死区功能。

Epwm-ET控制器寄存器的配置

EPwm1Regs.ETSEL.bit.SOCAEN      = 0x00;                 // 0 Disable 1 Enable

EPwm1Regs.ETSEL.bit.SOCASEL     = 0x01;                 // Start-of-Conversion(SOC) 选择什么时候产生SOCA脉冲, 当计数器等于零时产生SOCA事件,以触发ADC的SEQ1开始采集电流

EPwm1Regs.ETPS.bit.SOCAPRD      = 0x02;                 //

SOCAEN表示EPWM1SOCA事件的使能,这里初始化先Disable,后面所有模块都初始化完了,再Enable。

SOCASEL表示选择什么时候产生EPWM1SOCA事件,0x01表示当时基模块的计数值为0的时候产生这个事件。

DSP_TMS320F28377D_ePWM学习笔记前言正文结束语

SOCAPRD 表示当SOCASEL发生多少次之后,才产生EPWM1SOCA事件,事件产生周期。0x02,表示时基模块的计数值为0第二次发生的时候才产生一次EPWM1SOCA事件。

DSP_TMS320F28377D_ePWM学习笔记前言正文结束语

结束语

关于EPWM2和EPWM3的配置和EPWM1是类似的,只是ADC触发源这块不需要配置了,终于把这坑填上了,不觉身边的人都走完了,已经下班很久了。

感谢您的阅读,欢迎留言讨论、收藏、点赞、分享。

继续阅读