【DSP学习】增强型脉宽调制 EPWM 实验-基于普中DSP开发攻略

0 参考材料

基于普中DSP开发攻略.pdf

1 PWM 输出配置步骤

让 F28355 的 ePWM 管脚输出 PWM,具体步骤如下:(EPWM 相关库函数在 DSP2833x_EPwm.c 和 DSP2833x_EPwm.h 文件中)

(1) 使能 ePWM 外设时钟及失能时基模块时钟
要使用 ePWM 外设则需开启相应时钟,在对 ePWM 相关寄存器配置时得先关闭时基模块时钟,待配置好后在开启,可以保证同步。具体代码如下:

EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;	// Disable TBCLK within the ePWM
SysCtrlRegs.PCLKCR1.bit.EPWM6ENCLK = 1;	// ePWM6
EDIS;

先关掉时钟,配置好所有寄存器,再开时钟,让所有配置同时生效


逐句解释

EALLOW;  // 解锁受保护寄存器(PCLKCR0/1是受保护的)
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;  // 关闭ePWM模块的时基时钟
SysCtrlRegs.PCLKCR1.bit.EPWM6ENCLK = 1;  // 使能ePWM6的外设时钟
  • EPWM6ENCLK = ePWM6 ENable CLock
  • = 1:给ePWM6模块提供外设时钟(让它能工作)
  • 注意:这里只开了ePWM6,其他ePWM模块没开(节省功耗)
EDIS;  // 重新锁定

为什么需要先关闭 TBCLKSYNC?

问题场景

假设你正在配置ePWM6模块:

  1. 先设置周期(TBPRD)
  2. 再设置比较值(CMPA)
  3. 最后设置死区时间(DBRED)

如果不关时钟:寄存器是边改边生效的。可能刚写完周期值,计数器就按新周期开始跑了,但比较值和死区还没配置好 → 输出不确定的、有害的波形


PCLKCR0 和 PCLKCR1 的区别

寄存器作用本例中使用
PCLKCR0.bit.TBCLKSYNC控制所有ePWM模块的时基时钟(计数器时钟)同步开关= 0(关闭)
PCLKCR1.bit.EPWM6ENCLK控制ePWM6模块的外设时钟(寄存器访问时钟)使能= 1(开启)

两者关系

  • 外设时钟(EPWM6ENCLK)= 让模块能被访问、配置寄存器
  • 时基时钟(TBCLKSYNC)= 让模块的计数器跑起来,真的产生PWM波

(2) 开启 ePWM 对应 GPIO 时钟及初始化配置
由于 PWM 输出通道是对应着 F28335 芯片的 IO 口,所以需要使能对应的端口时钟,并将对应 IO 口配置为 ePWM 输出功能。初始化 ePWM GPIO 的函数 TI 已经提供给我们了,直接调用即可。本章使用的是 ePWM6,调用的函数如下:

InitEPwm6Gpio();

其内部具体实现代码如下:

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 外设复用功能.


这段代码是在配置GPIO10和GPIO11引脚,让它们从普通的输入输出口,变成专门的ePWM6A和ePWM6B输出引脚

逐句解释

1. 使能内部上拉电阻

GpioCtrlRegs.GPAPUD.bit.GPIO10 = 0;  // Enable pull-up on GPIO10
GpioCtrlRegs.GPAPUD.bit.GPIO11 = 0;  // Enable pull-up on GPIO11
寄存器含义
GPAPUDGPIO100使能内部上拉电阻
GPAPUDGPIO101禁用上拉电阻

GPAPUD = GPIO A Port Pull-Up Disable(A端口上拉禁用)

  • 名字容易混淆:叫"Pull-Up Disable",但写0是使能上拉
  • 这是个反逻辑寄存器

上拉电阻的作用

  • 引脚悬空时,上拉电阻把电平拉高到3.3V(避免浮空)
  • PWM输出时,上拉不影响输出驱动能力(因为输出时驱动电路更强)

为什么要使能? 习惯性配置,防止在引脚状态切换的瞬间出现不确定电平。


2. 配置引脚为ePWM功能

GpioCtrlRegs.GPAMUX1.bit.GPIO10 = 1;  // Configure GPIO10 as EPWM6A
GpioCtrlRegs.GPAMUX1.bit.GPIO11 = 1;  // Configure GPIO11 as EPWM6B
寄存器含义
GPAMUX1GPIO100普通GPIO
GPAMUX1GPIO101ePWM6A
GPAMUX1GPIO102其他外设功能
GPAMUX1GPIO103其他外设功能

GPAMUX1 = GPIO A Port MUX 1(A端口复用选择寄存器1)

MUX = Multiplexer(多路复用器),相当于一个电子开关:

GPAMUX1 = 0 → 选 GPIO
GPAMUX1 = 1 → 选 ePWM6A
GPAMUX1 = 2 → 选 其他

GPAMUX1 = 1 就是把内部ePWM6A模块的输出,连接到GPIO10引脚上。


(3) 初始化时基模块,即配置 TB 相关寄存器值
要产生 PWM 波,时基模块是必不可少的,通过配置它可以确定计数器的计数方式、周期频率、是否同步等。比如我们要设置 ePWM6 计数方式为向上计数,不使用相位同步功能,计数器计数频率为系统时钟频率,计数器初值为 0 等,具体配置代码如下:

//SetupSync
EPwm6Regs.TBCTL.bit.SYNCOSEL=TB_SYNC_DISABLE; //Passthrough
//Alloweachtimertobesync'ed
EPwm6Regs.TBCTL.bit.PHSEN=TB_DISABLE;
EPwm6Regs.TBPHS.half.TBPHS=0;
EPwm6Regs.TBCTR=0x0000; //Clearcounter
EPwm6Regs.TBPRD=tbprd;
EPwm6Regs.TBCTL.bit.CTRMODE=TB_COUNT_UP; //Countup
EPwm6Regs.TBCTL.bit.HSPCLKDIV=TB_DIV1;
EPwm6Regs.TBCTL.bit.CLKDIV=TB_DIV1;

这段代码是配置ePWM6模块的时基模块,决定了PWM波形的频率、计数模式、同步行为等基础参数。

简单说:设置PWM的"心跳"节奏


逐句解释

1. 配置同步输出

EPwm6Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;
寄存器位含义
SYNCOSELTB_SYNC_DISABLE禁用同步输出(不向后续ePWM模块发送同步信号)
SYNCOSELTB_SYNC_IN(0)同步输入信号直接作为同步输出
SYNCOSELTB_SYNC_DISABLE(2)不同步

同步的作用:让多个ePWM模块的计数器同时从0开始,保证它们的相位一致。比如三相电机控制,U/V/W三相的PWM需要同步。

这里设为禁用,意思是ePWM6不需要去同步后面的模块(因为ePWM6可能是最后一个)。


2. 禁用相位加载

EPwm6Regs.TBCTL.bit.PHSEN = TB_DISABLE;
寄存器位含义
PHSENTB_ENABLE(1)使能相位加载(收到同步信号时,把TBPHS加载到TBCTR)
PHSENTB_DISABLE(0)禁用相位加载

相位加载:当收到同步输入信号时,是否把TBPHS(相位寄存器的值)加载到计数器。

PHSEN = 0:收到同步信号时,计数器不做任何事(不从0开始,保持当前值)。


3. 设置相位值

EPwm6Regs.TBPHS.half.TBPHS = 0;
  • TBPHS = Time Base Phase(时基相位寄存器)
  • = 0:收到同步信号时,要加载的相位值是0

虽然上面PHSEN = TB_DISABLE禁用了相位加载,但还是设置了TBPHS=0,是一种规范性写法,方便以后修改。


4. 清零计数器

EPwm6Regs.TBCTR = 0x0000;  // Clear counter
  • TBCTR = Time Base Counter(时基计数器)
  • 手动把计数器清零,确保从一个已知的初始状态开始

这是配置阶段的准备工作,防止之前残留的计数值干扰。


5. 设置周期值

EPwm6Regs.TBPRD = tbprd;
  • TBPRD = Time Base Period(时基周期寄存器)
  • tbprd是一个变量/宏,决定了PWM的周期

周期与频率的关系

PWM频率 = 系统时钟 / (TBPRD + 1) / (HSPCLKDIV × CLKDIV)

例如:系统时钟=100MHz,tbprd=2000,分频=1
频率 = 100MHz / (2000+1) ≈ 50kHz

6. 设置计数模式

EPwm6Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
模式计数器行为
TB_COUNT_UP(0)向上计数0 → TBPRD → 0 → TBPRD …
TB_COUNT_DOWN(1)向下计数TBPRD → 0 → TBPRD → 0 …
TB_COUNT_UPDOWN(2)向上向下计数0 → TBPRD → 0 → TBPRD …(对称)

向上计数是最常用的模式,产生的PWM波形左边对齐。


7. 设置时钟分频

EPwm6Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;  // 高速外设时钟分频
EPwm6Regs.TBCTL.bit.CLKDIV = TB_DIV1;     // 时基时钟分频
分频系数效果
TB_DIV1(0)1不分频,频率最高
TB_DIV2(1)22分频
TB_DIV4(2)44分频

HSPCLKDIVCLKDIV 两级分频,可以灵活地降低PWM频率。

TB_DIV1 = 不分频:计数器频率 = 系统时钟频率(通常是100MHz)


综合效果

这段配置产生的效果:

计数模式:向上计数(0 → 2000 → 0 → 2000)
频率:假设系统时钟100MHz,不分频,周期2000 → 频率≈50kHz
相位加载:禁用,不同步其他模块
同步输出:禁用

(4) 初始化比较模块,即配置 CC 相关寄存器值
要产生可调的 PWM 波,除了需要时基模块外,CC 模块也是必不可少的,通过配置它可以确定比较寄存器值的加载模式,比较器值、占空比等。比如我们要设置 ePWM6 加载方式为计数器为 0 加载、比较器值为 0 等,具体配置代码如下:

//SetupshadowregisterloadonZERO
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;
//SetComparevalues
EPwm6Regs.CMPA.half.CMPA=0; //SetcompareAvalue
EPwm6Regs.CMPB=0; //SetCompareBvalue


(5) 初始化动作限定模块,即配置 AQ 相关寄存器值
要产生可调 PWM 波,除了需要 TB、CC 模块外,AQ 模块也是必不可少的,通过配置它可以确定 PWM 输出波形方式等。比如我们要设置 ePWM6 输出,当 ePWMA计数器计数到 0 时输出低电平,当 ePWMA 计数器向上计数到 CMPA 时输出高电平,当 ePWMB 计数器计数到 0 时输出低电平,当 ePWMB 计数器向上计数到 CMPB 时输出高电平,具体配置代码如下:

//Setactions
EPwm6Regs.AQCTLA.bit.ZRO=AQ_CLEAR; //SetPWM1AonZero
EPwm6Regs.AQCTLA.bit.CAU=AQ_SET; //ClearPWM1AoneventA,upcount
EPwm6Regs.AQCTLB.bit.ZRO=AQ_CLEAR; //SetPWM1BonZero
EPwm6Regs.AQCTLB.bit.CBU=AQ_SET; //ClearPWM1BoneventB,upcount

(6)初始化事件触发模块,即配置ET相关寄存器值
当需要事件触发输出控制,就需要对ET相关寄存器配置。比如计数器计数到0时,同时使能事件触发中断,每发生一次触发事件就输出PWM。相关配置代码如下:

EPwm6Regs.ETSEL.bit.INTSEL=ET_CTR_ZERO; //SelectINTonZeroevent
EPwm6Regs.ETSEL.bit.INTEN=1; //EnableINT
EPwm6Regs.ETPS.bit.INTPRD=ET_1ST; //GenerateINTon1stevent

(7) 初始化死区模块、斩波模块,即配置 DB、PC 相关寄存器值
如果不是特殊应用的话,一般不对死区模块和斩波模块配置,它们的应用方法在前面各小节也介绍过,所以这里我们不作介绍。
(8) 使能时基计数器时钟
将各模块寄存器配置好后,最后开启时基计数器时钟,完成这步操作,对应的 IO 口即可输出 PWM 波。开启时基计数器时钟代码如下:

EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;// Start all the timers synced
EDIS;

这里列举的是 ePWM6 的配置,至于其他 ePWM 配置都是一样,只需修改对应的数字即可。里面涉及到的相关寄存器在前面已做介绍,大家可以用到哪个就查询哪个,不需要完完全全记住。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

金色光环

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值