This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS320F28027:通过软件跳变在 PWM 代码中出现问题

Guru**** 2779905 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1172764/tms320f28027-issues-in-pwm-code-through-software-tripping

器件型号:TMS320F28027

尊敬的所有人:

我需要在通道2和3中生成 PWM、如图所示。

我将 PWM 频率设置为20us。PWMA 和 PWM b 需要相互补充。B 和 C 时序是使用计时器模块完成的、如代码所示。

有两个问题。

A.当我禁用 PWM 时、我需要 A 和 B 通道都拉低。 但是、这种情况并未发生。

b.是否有更好的方法来实现上述逻辑。

以下是代码。

#include "DSP28x_Project.h"//器件头文件和示例 include 文件

//此文件中找到的函数的原型语句。
void InitEPwm1Examples(void);
中断 void epwm1_ISR (void);
中断空 CPU_timer0_ISR (空);
中断 void epwm2_ISR (void);
中断 void epwm3_ISR (void);

uint32 discharge 周期=2000;
uint32 discharge 占空比= 140;
uint32 count_discharge 周期= 1;
uint32 count_discharge 占空比= 1;
void main (void)

//步骤1. 初始化系统控制:
// PLL、安全装置、启用外设时钟
//此示例函数位于 DSP2802x_SYSCTRL.c 文件中。
InitSysCtrl();

//步骤2. 初始化 GPIO:
//此示例函数位于 DSP2802x_GPIO.c 文件和中
//说明了如何将 GPIO 设置为其默认状态。
// InitGpio();//针对此示例跳过

//在这种情况下、只需初始化 ePWM1、ePWM2、ePWM3的 GPIO 引脚
//这些函数位于 DSP2802x_ePWM.c 文件中
InitEPwm1Gpio();
InitEPwm2Gpio();
InitEPwm3Gpio();
//步骤3. 清除所有中断并初始化 PIE 矢量表:
//禁用 CPU 中断
Dint;

//将 PIE 控制寄存器初始化为默认状态。
//默认状态为禁用所有 PIE 中断和标志
//被清除。
//此函数位于 DSP2802x_PIECTRL.c 文件中。
InitPieCtrl();
InitCpuTimer();//对于此示例,只初始化 CPU 计时器
//禁用 CPU 中断并清除所有 CPU 中断标志:
IER = 0x0000;
IFR = 0x0000;

//使用指向 shell 中断的指针初始化 PIE 矢量表
//服务例程(ISR)。
//这将填充整个表,即使是中断也是如此
//在本例中未使用。 这对于调试很有用。
//可以在 DSP2802x_DefaultIsr.c 中找到 shell ISR 例程
//此函数可在 DSP2802x_PieVect.c 中找到
InitPieVectTable();

//此示例中使用的中断被重新映射到
//此文件中的 ISR 函数。
EALLOW;//这是写入 EALLOW 受保护寄存器所必需的
PieVectTable.EPWM1_INT =&epwm1_ISR;
PieVectTable.EPWM2_INT =&epwm2_ISR;
PieVectTable.EPWM3_INT =&epwm3/ISR;
EDIS;//这是禁止写入 EALLOW 受保护寄存器所必需的

//此示例中使用的中断被重新映射到
//此文件中的 ISR 函数。
EALLOW;//这是写入 EALLOW 受保护寄存器所必需的
PieVectTable.TINT0 =&CPU_timer0_ISR;
EDIS;//这是禁止写入 EALLOW 受保护寄存器所必需的

//步骤4. 初始化器件外设。 该函数可以是
//可在 DSP2802x_CpuTimers.c 中找到


#IF (CPU_FRQ_60MHz)
//将 CPU 定时器0、1和2配置为每秒中断一次:
// 60MHz CPU 频率,1秒周期(以 μ 秒为单位)
ConfigCpuTimer (&CpuTimer0、60、1);
#endif


//步骤4. 初始化所有器件外设:
//此函数位于 DSP2802x_InitPeripherals.c 中
// InitPeripherals ();//此示例不需要


EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC=0;
EDIS;

InitEPwm1Examples();


EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC=1;
EDIS;

//启用连接到 EPWM1-3 INT 的 CPU INT3:
// IER |= M_INT3;
//启用连接到 CPU 定时器0的 CPU INT1,
IER |= M_INT1;


//在 PIE 中启用 TINT0:组1中断7
PieCtrlRegs.PIEIER1.bit.INTx7=1;

//在 PIE 中启用 ePWM INTn:组3中断1-3
PieCtrlRegs.PIEIER3.bit.INTx1 = 1;
PieCtrlRegs.PIEIER3.bit.INTx2 = 1;
PieCtrlRegs.PIEIER3.bit.INTx3=1;

//启用全局中断和更高优先级的实时调试事件:
EINT;//启用全局中断 INTM
ERTM;//启用全局实时中断 DBGM

//为了确保精确的时序,使用只写指令写入整个寄存器。 因此、如果有的话
配置位的//在 ConfigCpuTimer 和 InitCpuTimers (在 DSP2802x_CpuTimer.h 中)中更改、
//下面的设置也必须更新。

CpuTimer0Regs.TCR.ALL = 0x4001;//使用只写指令将 TSS 位设置为0
//步骤5. 特定于用户的代码、启用中断:

//启用全局中断和更高优先级的实时调试事件:
EINT;//启用全局中断 INTM
ERTM;//启用全局实时中断 DBGM


//步骤6. 空闲循环。 只需坐下来循环(可选):
for (;;)

asm (" NOP");

中断空 epwm1_ISR (空)

EPwm1Regs.ETCLR.bit.INT = 1;
//确认此中断以接收来自组3的更多中断
PieCtrlRegs.PIEACX.ALL = PIEACK_Group3;

中断空 epwm2_ISR (空)

EPwm2Regs.ETCLR.bit.INT = 1;
//确认此中断以接收来自组3的更多中断
PieCtrlRegs.PIEACX.ALL = PIEACK_Group3;

中断空 epwm3_ISR (空)

EPwm3Regs.ETCLR.bit.INT = 1;
//确认此中断以接收来自组3的更多中断
PieCtrlRegs.PIEACX.ALL = PIEACK_Group3;


中断空 CPU_timer0_ISR (空)

if (count_discharge <DISCHARGE_DUTY && count_discharge_period<=DISCHARGE_PERIOD))

count_discharge 占空比= count_discharge 占空比+ 1;
COUNT_DELOAD_PERIOD=COUNT_DELOAD_PERIOD+1;

否则、如果(COUNT_DELOAD_DUTY >= DELOAD_DUTY &&<DISCHARGE_PERIOD)

COUNT_DELOAD_PERIOD=COUNT_DELOAD_PERIOD+1;
EPwm3Regs.TBCTR = 0x0000;
EPwm2Regs.TBCTR = 0x0000;

否则、如果(COUNT_DELOAD_Duty= DELOAD_DUTY & COUNT_DELOAD_PERIOD=DELOAD_PERIOD)

COUNT_DELOAD_DUTY = 1;
COUNT_DELOAD_PERIOD=1;

EPwm3Regs.AQCTLA.bit.PRD = AQ_SET;
EPwm3Regs.AQCTLA.bit.CAU = AQ_CLEAR;
EPwm3Regs.AQCTLB.bit.PRD= AQ_CLEAR;
EPwm3Regs.AQCTLB.bit.CAU = AQ_SET;

EPwm2Regs.AQCTLA.bit.PRD = AQ_SET;
EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR;
EPwm2Regs.AQCTLB.bit.PRD = AQ_CLEAR;
EPwm2Regs.AQCTLB.bit.CAU = AQ_SET;


// CpuTimer0.InterruptCount++;
//确认此中断以从组1接收更多中断
PieCtrlRegs.PIEACX.ALL = PIEACK_Group1;


空 InitEPwm1Examples()

// ePWM 模块1配置
EPwm1Regs.TBPRD = 500;//周期= 1201 TBCLK 计数
EPwm1Regs.TBPHS.Half.TBPHS = 0;//将相位寄存器设置为零
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;//非对称模式
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;//相位加载被禁用
EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW;
EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;


EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;// TBCLK = SYSCLKOUT //如果不包含代码中的内容,则默认频率变为一半
EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;

EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;// CTR 上的负载=零
EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;// CTR 上的负载=零


EPwm1Regs.AQCTLA.bit.PRD = AQ_SET;
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;
EPwm1Regs.AQCTLB.bit.PRD = AQ_CLEAR;
EPwm1Regs.AQCTLB.bit.CAU = AQ_SET;


EPwm1Regs.CMPA.half.CMPA = 250;

//低电平有效 PWM -设置死区
EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FUL_ENABLE;
EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;
//EPwm1Regs.DBCTL.bit.IN_MODE = DBA_ALL;
EPwm1Regs.DBRED = 20;
EPwm1Regs.DBFED = 20;
//EPwm1_DB_DIRECTION = DB_UP;

//中断,我们将在其中更改死区
EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;//选择零事件时的 INT
EPwm1Regs.ETSEL.bit.INTEN = 1;//启用 INT
EPwm1Regs.ETPS.bit.INTPRD = et_3rd;//在第三个事件发生时生成 INT

// EPWM2配置

EPwm2Regs.TBPRD = 1200;//周期= 1201 TBCLK 计数
EPwm2Regs.TBPHS.Half.TBPHS = 0;//将相位寄存器设置为零
EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;//非对称模式
EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE;//相位加载被禁用
EPwm2Regs.TBCTL.bit.PRDLD = TB_SHADOW;
EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;


EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;// TBCLK = SYSCLKOUT //如果代码中不包含此内容,则默认频率变为一半
EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV1;

EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm2Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;// CTR 上的负载=零
EPwm2Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;// CTR 上的负载=零


EPwm2Regs.AQCTLA.bit.PRD = AQ_SET;
EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR;
EPwm2Regs.AQCTLB.bit.PRD = AQ_CLEAR;
EPwm2Regs.AQCTLB.bit.CAU = AQ_SET;


EPwm2Regs.CMPA.half.CMPA = 600;


//低电平有效 PWM -设置死区
EPwm2Regs.DBCTL.bit.OUT_MODE = DB_FUL_ENABLE;
EPwm2Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;
//EPwm1Regs.DBCTL.bit.IN_MODE = DBA_ALL;
EPwm2Regs.DBRED = 20;
EPwm2Regs.DBFED = 20;
//EPwm1_DB_DIRECTION = DB_UP;

////中断,我们将在其中更改死区
// EPwm2Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;//选择零事件时的 INT
// EPwm2Regs.ETSEL.bit.INTEN = 1;//启用 INT
// EPwm2Regs.ETPS.bit.INTPRD = et_3rd;//在第3个事件发生时生成 INT

// EPWM3配置

EPwm3Regs.TBPRD = 1200;//周期= 1201 TBCLK 计数
EPwm3Regs.TBPHS.Half.TBPHS = 0;//将相位寄存器设置为零
EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;//非对称模式
EPwm3Regs.TBCTL.bit.PHSEN = TB_DISABLE;//相位加载被禁用
EPwm3Regs.TBCTL.bit.PRDLD = TB_SHADOW;
EPwm3Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;


EPwm3Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;// TBCLK = SYSCLKOUT //如果代码中不包含此内容,则默认频率变为一半
EPwm3Regs.TBCTL.bit.CLKDIV = TB_DIV1;

EPwm3Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm3Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm3Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;// CTR 上的负载=零
EPwm3Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;// CTR 上的负载=零


EPwm3Regs.AQCTLA.bit.PRD= AQ_SET;
EPwm3Regs.AQCTLA.bit.CAU = AQ_CLEAR;
EPwm3Regs.AQCTLB.bit.PRD = AQ_CLEAR;
EPwm3Regs.AQCTLB.bit.CAU = AQ_SET;


EPwm3Regs.CMPA.half.CMPA = 600;

//低电平有效 PWM -设置死区
EPwm3Regs.DBCTL.bit.OUT_MODE = DB_FUL_ENABLE;
EPwm3Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;
//EPwm1Regs.DBCTL.bit.IN_MODE = DBA_ALL;
EPwm3Regs.DBRED = 20;
EPwm3Regs.DBFED = 20;
//EPwm1_DB_DIRECTION = DB_UP;

//中断,我们将在其中更改死区
EPwm3Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;//选择零事件时的 INT
EPwm3Regs.ETSEL.bit.INTEN = 1;//启用 INT
EPwm3Regs.ETPS.bit.INTPRD = et_3rd;//在第三个事件发生时生成 INT


//启用 TZ1和 TZ2作为一个逐周期触发源
EALLOW;
EPwm2Regs.TZFRC.bit.CBC = 1;
EPwm2Regs.TZCTL.bit.TZA = TZ_FORCE_LO;
EPwm2Regs.TZCTL.bit.TSB = TZ_FORCE_LO;


EPwm3Regs.TZFRC.bit.CBC = 1;
EPwm3Regs.TZCTL.bit.TZA = TZ_FORCE_LO;
EPwm3Regs.TZCTL.bit.TSB = TZ_FORCE_LO;
EDIS;


//============================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================
//不再需要。
//============================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好 Sachin、  

    当您是要禁用 PWM 时、您是要完全关闭 PWM 通道吗(即设置 TBCLKSYNC = 0)?

    您希望何时将所有输出设置为低电平、是否有外部信号或特定计数器来生成这些事件?

    您的 TBCLK 设置为 60 MHz 是正确的吗?

    对于图中的 A、B、C、这些通道分别是1、2、3吗?  

    现在、通道1看起来设置为20us、通道2设置为140us、通道3设置为2000us、这是因为它们的 PWM 频率。

    这是另 一个 e2e 线程 、可能会有所帮助。  

    另一种解决方案是发生一次性跳闸事件。 可以使用 GPIO 12、13、14并选择启用跳闸区域来生成此单次触发。 然后、在跳闸区域(TZCTL)中、您可以强制 epwmxA 或 epwmxB 输出低电平或高电平、具体取决于您的配置。 device_support/F2802x\examples\drivers\ePWM_TRIP_zone 文件夹中确实存在一个一次性跳闸示例作为参考。  

    最棒的

    Ryan Ma

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢 Ryan Ma 的回复。

    我的意思是禁用 PWM (建立适当的逻辑) 以在通道(PWM2、PWM3)中生成波形、如图所示。 通过禁用、我是说通道2、3的 A、B 都 应该为低电平。

    图中提到的时序都适用于 给定 的 PWM 通道(例如2、3)(设置为互补模式)。

    它不是通道1=20us、通道2=140us 、通道3=2000us

    在互补模式下、PWM 应设置为高频率(例如50kHz)。 然后、应禁用/启用(或任何其他更好的逻辑)、以获得脉冲 打开时的持续时间、如140us 以及没有脉冲时的持续时间 约为2000us 或更长。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好 Sachin、

    对于关闭 PWM 信号的逻辑:

    您是否曾尝试过在您想要关闭 PWM 信号时设置一次性软件强制跳闸事件? 然后、当您想要再次启动 PWM 脉冲时、可以清除此跳闸事件标志。

    查看您的代码、您似乎希望在满足此逻辑时停止 PWM 脉冲:

    (COUNT_DELOAD_DUTY >=放电占空比&& COUNT_DELOAD_AFET <DISCHARGE_PERIOD)

    您可以在此处设置软件一次性跳闸区域事件标志、这会将 PWM 输出设置为低电平。

    2.然后、当您想要再次启动 PWM 输出时、您可以清除此一次性触发区标志、输出将再次启动。

    最棒的

    Ryan Ma

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢 Ryan 的回复。

    我使用了基于软件的跳闸区域(一次性)及其工作。 但是,PWM 有时会呈指数衰减。 可能是什么问题。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好 Sachin、

    这种情况经常发生吗? 如果您可以将您的项目私下或在这里发送给我、我可以进一步了解这种情况的发生原因。

    我在代码中注意到的另一件事是在中断期间设置 AQ 事件。

    如果您现在注释出这些行并对其进行测试、会发生什么情况? 我想您已经在 PWM 信号的初始化中初始化了 AQCTL 值。

    我不建议动态更改 AQCTL、因为这是 在中断期间发生的、这可能是您看到的结果的原因。  

    最棒的

    Ryan Ma