一、DSP28335ePWM简介
ePWM 模块由两路 ePWM 输出组成,分别为 ePWMxA 和每不ePWMxB,这一对 PWM输出,可以配置成两路独立的单边沿 PWM 输出,或者两路独立的但互相相对称的双边沿 PWM 输出,或者一对双边沿非对称的 PWM 输出,共有 6 对这样的 ePWM 模块。因为每对 PWM 模块中的两个 PWM 输出均可以单独使用,所以也可以认头有12 路单路 ePWM,除此之外还有 6个APWM,这 6个APWM 通CAP 模块扩展配置,可以独立使用,所以 F28335 最多可以有路 PWM 输出。
每一组 ePWM 模块都包含以下 7 个模块:时基模块 TB、计数比较模块 CC、动作模块 AQ、死区产生模块DB、PWM 斩波模块 PC、错误联防模块 TZ、事件触发模块 ET。
时钟信号经时基模块 TB 产生时基信号, 可以设定 PWM 波形的周期, 通过计数比较模块 CC, 可以对 PWM 波形的脉宽进行配置, 再由动作模块 AQ 限定 PWM 输出状态即脉冲波形的起落, 经过死区模块 DB, 可以将同组内的互补输出 PWM 波形进行边沿延迟,接着可选择是否进入 PWM 斩波模块, 进行第一个脉冲宽度设置和后级脉冲占空比调整以适应基于脉冲变压器的门级驱动控制, 若 PWM 波形输出后, 功率器件有错误响应, 可以将错误信号引入错误联防模块, 从而强制复位PWM 的输出。也可以通过事件触发模块配置触发一些事件, 如 ADC 转换开始。
二、DSP28335ePWM子模块
1.时基模块TB
①确定 ePWM 时基模块的频率或者周期, 进一步确定了事件发生的频率。 主要是通过配置 PWM 时基计数器(TBCTR) 来标定与系统时钟(SYSCLKOUT) 有关的时基时钟的频率或周期。
②管理 ePWM 模块之间的同步性。
③维护 ePWM 与其他 ePWM 模块间的相位关系。
④设置时基计数器的计数模块。 可以工作在向上计数(递增计数) 、 向下计数(递减计数) 、 向上-向下计数模式(先递增后递减计数) 。
⑤产生下列事件:
–CTR=PRD: 时基计数器的值与周期寄存器的值相同(TBCTR=TBPRD) 。
–CTR=ZERO: 时基计数器的值为 0(TBCTR=0x0000) 。
时基计数器按照指定模式进行计数, 递增时会达到与周期寄存器的值一致,递减时则会减到最小值 0。
⑥配置时基模块的时钟基准, 对系统时钟 SYSCLKOUT 进行分频可以得到时基时钟, 通过合理分频系统时钟, 计数的时候可以工作在相对较低的频率。
2.计数比较模块 CC
计数器比较模块是以时基计数器的值作为输入, 与比较寄存器 CMPA 和比较寄存器 CMPB 不断进行比较, 当时基计数器的值等于其中之一时, 就会产生相应的事件。 计数比较模块 CC 的原理框图如下所示:
①产生比较事件具体取决于编程时是采用寄存器还是寄存器 B:
–CTR=CMPA: 时基计数器的值与比较寄存器 A 的值相等。
–CTR=CMPB: 时基计数器的值与比较寄存器 B 的值相等。
②动作模块 AC 恰当配置后可以控制 PWM 的占空比。
③采用影子寄存器来更新比较值可以有效防止在 PWM 周期内出现故障以及毛
刺。
3.动作限定模块 AQ
动作限定模块在 PWM 波形形成过程中起到了关键作用, 它决定了相应事件发生时应该输出什么样的电平, 从而使 ePWMxA 和 ePWMxB 输出所需要的开关波形。
4.死区控制模块 DB
F28335 的死区模块主要作用就是让两个互补的对称的 PWM 波形中, 上升沿的发出滞后于 PWM 波的下降时间发出。 在实际编程或者实际情况中更灵活一些, 有可能管子是低电平状态开通, 所以延时的方式可以更灵活。 在动作限定模块中就可以产生死区, 但是如果要严格控制死区的边沿延时和极性, 则需要通过死区模块来实现。
死区模块的主要功能如下:
①根据型号 ePWMxA 输入产生带死区的信号对(ePWMxA 和 ePWMxB) , 也就是输出一对互补 PWM 输出边沿延时。
②信号对可编程完成如下操作:
–ePWMA\B 输出高有效(AH) 。
–ePWMA\B 输出低有效(AL) 。
–ePWMA\B 输出互补高有效(AHC) 。
–ePWMA\B 输出互补低有效(ALC) 。
③加入可编程上升沿延时(RED) 。
④加入可编程下降沿延时(FED) 。
⑤可以忽略延时。
5.PWM 斩波模块 PC
斩波可以认为是一个降压电路, 从上向下, ePWMxA、 ePWMxB 分别为经过前面动作模块与死区模块后的输出波形, 为斩波模块的输入波形, 中间 PSCLK 是斩波模块的时钟信号, 输入的ePWMxA 相当于一个闸门实际是与 PSCLK 作与运算, 得到 ePWMxA 斩波波形, 经斩波后, ePWMxA 的占用能量和平均电压均可以通过占空比等设置进行调整, 对于一些功率器件而言, 可以降低开通期间的功耗。
6.错误联防模块 TZ
每个 ePWM 模块都与 GPIO 多路复用引脚中的 6 个 TZn(TZ1-TZ6)信号脚连接。这些信号脚用来响应外部错误或外部触发条件, 当错误发生时, PWM 模块可以通过编程来响应这些问题。
7.事件触发模块
事件触发模块的功能主要如下:
①接收来自时基模块和计数比较模块产生的相关事件的输入。
②利用时基模块中的方向信息识别是递增还是递减计数模式以便产生相应的事件。
③使用预定标判断逻辑发出中断请求或者 ADC 开始转换启动信号:
–每个事件。
–每两个事件。
–每三个事件。
④允许软件配置, 强制产生中断事件或者 ADC 启动信号。
三、PWM输出配置
1.使能 ePWM 外设时钟及失能时基模块时钟
要使用 ePWM 外设则需开启相应时钟, 在对 ePWM 相关寄存器配置时得先关闭时基模块时钟, 待配置好后在开启, 可以保证同步。
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; // Disable TBCLK within the ePWM
SysCtrlRegs.PCLKCR1.bit.EPWM6ENCLK = 1; // ePWM6
EDIS;
2.开启 ePWM 对应 GPIO 时钟及初始化配置
由于 PWM 输出通道是对应着 F28335 芯片的 IO 口, 所以需要使能对应的端口时钟, 并将对应 IO 口配置为 ePWM 输出功能。 初始化 ePWM GPIO 的函数 TI 已经提供给我们了, 直接调用即可。 本章使用的是 ePWM6, 调用的函数如下:
void InitEPwm6Gpio(void)
{
EALLOW;
/* Enable internal pull-up for the selected pins */
// Pull-ups can be enabled or disabled by the user.
// This will enable the pullups for the specified pins.
// Comment out other unwanted lines.
GpioCtrlRegs.GPAPUD.bit.GPIO10 = 0; // Enable pull-up on GPIO10 (EPWM6A)
GpioCtrlRegs.GPAPUD.bit.GPIO11 = 0; // Enable pull-up on GPIO11 (EPWM6B)
/* Configure ePWM-6 pins using GPIO regs*/
// This specifies which of the possible GPIO pins will be ePWM6 functional pins.
// Comment out other unwanted lines.
GpioCtrlRegs.GPAMUX1.bit.GPIO10 = 1; // Configure GPIO10 as EPWM6A
GpioCtrlRegs.GPAMUX1.bit.GPIO11 = 1; // Configure GPIO11 as EPWM6B
EDIS;
}
我们是使用 GPIO10、 GPIO11 的 ePWM6A 和 ePWM6B 功能, 即对这两个 IO 口初始化, 使能上拉和 GPIO 外设复用功能。
3.初始化时基模块,即配置 TB 相关寄存器值
要产生 PWM 波, 时基模块是必不可少的, 通过配置它可以确定计数器的计数方式、 周期频率、 是否同步等。 比如我们要设置 ePWM6 计数方式为向上计数, 不使用相位同步功能, 计数器计数频率为系统时钟频率, 计数器初值为 0 等, 具体配置代码如下:
// Setup Sync
EPwm6Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE; // Pass through
// Allow each timer to be sync'ed
EPwm6Regs.TBCTL.bit.PHSEN = TB_DISABLE;
EPwm6Regs.TBPHS.half.TBPHS = 0;
EPwm6Regs.TBCTR = 0x0000; // Clear counter
EPwm6Regs.TBPRD = tbprd;
EPwm6Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up
EPwm6Regs.TBCTL.bit.HSPCLKDIV=TB_DIV1;
EPwm6Regs.TBCTL.bit.CLKDIV=TB_DIV1;
4.初始化比较模块, 即配置 CC 相关寄存器值
要产生可调的 PWM 波, 除了需要时基模块外, CC 模块也是必不可少的, 通过配置它可以确定比较寄存器值的加载模式, 比较器值、 占空比等。 比如我们要设置 ePWM6 加载方式为计数器为 0 加载、 比较器值为 0 等, 具体配置代码如下:
// Setup shadow register load on ZERO
EPwm6Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm6Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm6Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
EPwm6Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
// Set Compare values
EPwm6Regs.CMPA.half.CMPA = 0; // Set compare A value
EPwm6Regs.CMPB = 0; // Set Compare B value
5.初始化动作限定模块, 即配置 AQ 相关寄存器值
通过配置AQ模块可以确定 PWM 输出波形方式等。 比如我们要设置 ePWM6 输出, 当 ePWMA计数器计数到 0 时输出低电平, 当 ePWMA 计数器向上计数到 CMPA 时输出高电平,当 ePWMB 计数器计数到 0 时输出低电平, 当 ePWMB 计数器向上计数到 CMPB 时输出高电平, 具体配置代码如下:
// Set actions
EPwm6Regs.AQCTLA.bit.ZRO = AQ_CLEAR; // Set PWM1A on Zero
EPwm6Regs.AQCTLA.bit.CAU = AQ_SET; // Clear PWM1A on event A, up count
EPwm6Regs.AQCTLB.bit.ZRO = AQ_CLEAR; // Set PWM1B on Zero
EPwm6Regs.AQCTLB.bit.CBU = AQ_SET; // Clear PWM1B on event B, up count
6.初始化事件触发模块, 即配置 ET 相关寄存器值
当需要事件触发输出控制, 就需要对 ET 相关寄存器配置。 比如计数器计数到 0 时, 同时使能事件触发中断, 每发生一次触发事件就输出 PWM。 相关配置代码如下:
EPwm6Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event
EPwm6Regs.ETSEL.bit.INTEN = 1; // Enable INT
EPwm6Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on 1st event
8.使能时基计数器时钟
将各模块寄存器配置好后, 最后开启时基计数器时钟, 完成这步操作, 对应的 IO 口即可输出 PWM 波。 开启时基计数器时钟代码如下:
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Start all the timers synced
EDIS;
四、硬件设计
本实验使用到硬件平台是普中dsp28335开发板,硬件资源如下:
(1) D1、 D7 指示灯
(2) ePWM
LED 灯模块电路在前面章节已介绍, 这里就不多说, 至于 ePWM 它是 F28335芯片内部外设资源,只需通过软件配置即可使用。
五、软件设计
实现的功能是: 通过 ePWM6A 和 ePWM6B 两个管脚输出 ePWM 波, 分别控制 D6 和 D7 指示灯亮度, 由暗变亮后又由亮变暗, 呈现出呼吸灯效果。
1.ePWM6 初始化函数
该函数实现了对 ePWM6 的初始化配置, 内部实现过程是按照上一节介绍 ePWM操作步骤完成, 函数的入口带有一个参数 tbprd, 通过该参数可修改 ePWM 的频率。
void EPWM6_Init(Uint16 tbprd)
{
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; // Disable TBCLK within
the ePWM
SysCtrlRegs.PCLKCR1.bit.EPWM6ENCLK = 1; // ePWM6
EDIS;
InitEPwm6Gpio();
// Setup Sync
EPwm6Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE; // Pass through
// Allow each timer to be sync'ed
EPwm6Regs.TBCTL.bit.PHSEN = TB_DISABLE;
EPwm6Regs.TBPHS.half.TBPHS = 0;
EPwm6Regs.TBCTR = 0x0000; // Clear counter
EPwm6Regs.TBPRD = tbprd;
EPwm6Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up
EPwm6Regs.TBCTL.bit.HSPCLKDIV=TB_DIV1;
EPwm6Regs.TBCTL.bit.CLKDIV=TB_DIV1;
// Setup shadow register load on ZERO
EPwm6Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm6Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm6Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
EPwm6Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
// Set Compare values
EPwm6Regs.CMPA.half.CMPA = 0; // Set compare A value
EPwm6Regs.CMPB = 0; // Set Compare B value
// Set actions
EPwm6Regs.AQCTLA.bit.ZRO = AQ_CLEAR; // Set PWM1A on Zero
EPwm6Regs.AQCTLA.bit.CAU = AQ_SET; // Clear PWM1A on event A, up count
EPwm6Regs.AQCTLB.bit.ZRO = AQ_CLEAR; // Set PWM1B on Zero
EPwm6Regs.AQCTLB.bit.CBU = AQ_SET; // Clear PWM1B on event B, up count
EPwm6Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event
EPwm6Regs.ETSEL.bit.INTEN = 1; // Enable INT
EPwm6Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on 1st event
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Start all the timers synced
EDIS;
}
2.主函数
void main()
{
int i=0;
unsigned char fx=0;
InitSysCtrl();
InitPieCtrl();
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();
// LED_Init();
EPWM6_Init(400);
while(1)
{
if(fx==0)
{
i++;
if(i==300)
{
fx=1;
}
}
else
{
i--;
if(i==0)
{
fx=0;
}
}
EPwm6A_SetCompare(i); //i 值最大可以取 499, 因为 ARR 最大值是 399.
EPwm6B_SetCompare(300-i); //i 值最大可以取 499, 因为 ARR 最大值是 399.
DELAY_US(1000);
}
}