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.

[参考译文] TMS320F28069:如何通过其中一个 ePWM 引脚生成 STEP 信号

Guru**** 2577385 points


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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/951261/tms320f28069-how-to-generate-a-step-signal-through-one-of-the-epwm-pins

器件型号:TMS320F28069

您好!

我有一个 ePWM 引脚、其工作频率为200kHz、 但是、为了测试电压模式控制器的带宽、我设计了一个阶跃信号、它将在正常运行5秒后施加一个额外的负载(设置为与5欧姆串联的 MOSFET)、以查看控制器响应。 这是我计划通过单独的 ePWM 引脚实现的、该引脚将在5秒后变为高电平并保持持续高电平。 连续高电平部分 很简单,但我可以做到这一点,但我在5秒后无法准确地将其设置为高电平(5秒不是强制性的,它可以是大于2秒的时间(当输出在没有额外负载的情况下稳定到最终状态时)

请告诉我 TI 或任何人是否有适合它的解决方案。

此致、

原始的

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

    PWM 不能输出缓慢、您可以在 PWM ISR 中运行计数器、如果 ISR 计数大于 x、则切换 GPIO 的信号

    eCAP 可用于输出 PWM 信号、并可与 PWM 同步、具有32位计时器。 这些计时器应足够长、以满足您的延迟要求。

    此致、
    Cody  

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

    好的、所以我创建了一个 CPU 定时器 ISR、其设置的时序为5秒、其中 CPU 定时器每1ms 运行一次(中断)。 之后、我将 GPIO6引脚设置为 GPIO 输出。 您可以看到下面的代码,但是当我在 GPIOReg GPDAT --> BITS --> GPIO6中监视 GPIO6引脚输出时,它会显示"0",这意味着在 CPU 计时器 ISR 运行5秒后,GPIO6引脚永远不会被激活为输出引脚。

    此外、CPU 定时器本身是一个32位定时器、因此应该可以通过它实现长延迟。

    请忽略任何有关 ADC 的陈述、我已将其注释掉。

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

    //此文件中找到的函数的原型语句。

    void InitEPwm2Examples(void);


    中断 void epwm2_ISR (void);

    中断空 CPU_timer0_ISR (空);
    //中断 void ADC_ISR (void);
    void GPIO_setup (void);
    //void ADC_Config (void);

    #define DB_UP 1.
    #define DB_DOWN 0

    浮点周期= 450;  // 200kHz -递增计数
    浮点占空比= 0.25;// 1.8/9 = Vo/Vin
    //float Duty_active = 0.2;

    uint16环计数;
    UINT16转换计数;
    //uint16 VOFB[10]={0.0、0.0、0.0、0.0、0.0、0.0、 0.0、0.0、0.0、0.0、0.0};
    //uint16 ILFB[10]={0.0、0.0、0.0、0.0、0.0、0.0、 0.0、0.0、0.0、0.0、0.0};
    浮点 VOFB[10];
    UINT16 VINFB[10];

    //uint16 ILFB[10];

    //此示例中使用的全局变量

    uint32 EPwm2TimerIntCount;

    uint16 EPwm2_DB_DIRECTION;

    //最大死区值

    #define EPWM2_MAX_DB 0x03FF


    #define EPWM2_MAX_DB 50


    #define EPWM2_MIN_DB 50//50--> 0.5us,自第55页,spru791f 文档

    //跟踪死区的移动方式
    #define DB_UP 1.
    #define DB_DOWN 0
    无符号 pwmcount2;
    无符号 pwmcount3;
    //void GPIO_setup (void);

    void main (void)


    InitSysCtrl();

    // CpuSysRegs.PCLKCR1.bit.EPWM1=1;  

    InitEPwm2Gpio();


    GpioDataRegs.GPADAT.bit.GPIO6 = 1;
    GpioCtrlRegs.GPAPUD.bit.GPIO6 = 0;//启用 GPIO6上的上拉
    GpioDataRegs.GPASET.bit.GPIO6 = 1;//加载输出锁存器
    GpioCtrlRegs.GPAMUX1.bit.GPIO6 = 0;// GPIO6 = GPIO6
    GpioCtrlRegs.GPADIR.bit.GPIO6 = 1;// GPIO6 =输出

    //步骤3. 清除所有中断并初始化 PIE 矢量表:

    //禁用 CPU 中断
    Dint;

    //将 PIE 控制寄存器初始化为默认状态。
    //默认状态为禁用所有 PIE 中断和标志
    //被清除。
    //此函数位于 F2806x_PIECTRL.c 文件中。
    InitPieCtrl();

    //禁用 CPU 中断并清除所有 CPU 中断标志:
    IER = 0x0000;
    IFR = 0x0000;

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

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

    PieVectTable.EPWM2_INT =&epwm2_ISR;

    //PieVectTable.ADCINT3 =&ADC_ISR;
    // PieVectTable.ADCINT1 =&ADC_ISR;
    PieVectTable.TINT0 =&CPU_timer0_ISR;

    EDIS;//这是禁止写入 EALLOW 受保护寄存器所必需的

    CpuTimer0.InterruptCount= 0;
    ConfigCpuTimer (&CpuTimer0、90、1000);//90MHz 和100us、因为 ISR 在205行中的运行时间为0.0001s --> 100us
    CpuTimer0Regs.TCR.All = 0xC020;//第109-110页--> 0前三位


    // InitPeripherals ();//此示例不需要
    //InitAdc ();//对于此示例,初始化 ADC
    //AdcOffsetSelfCal();

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


    InitEPwm2Examples();

    //ADC_Config ();


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

    //步骤5. 特定于用户的代码、启用中断
    //初始化计数器:

    EPwm2TimerIntCount = 0;

    //启用连接到 EPWM1-3 INT 的 CPU INT3:
    IER |= M_INT3;
    IER |= M_INT1;
    //IER |= M_INT10;
    //在 PIE 中启用 ePWM INTn:组3中断1-4
    //PieCtrlRegs.PIEIER3.bit.INTx1 = 1;
    PieCtrlRegs.PIEIER3.bit.INTx2 = 1;

    //PieCtrlRegs.PIEIER1.bit.INTx1 = 1;//在 PIE 中启用 ADCINT1 -在 PIE 中启用 INT 1.1
    PieCtrlRegs.PIEIER1.bit.INTx7=1;//在 PIE:组1中断7页中启用 TINT0 SPRU791F


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

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

    _asm (" NOP");


    中断空 CPU_timer0_ISR (空)

    CpuTimer0.InterruptCount++;

    if (((CpuTimer0.InterruptCount = 5000000)))

    GpioCtrlRegs.GPAPUD.bit.GPIO6 = 0;//启用 GPIO6上的上拉
    GpioDataRegs.GPASET.bit.GPIO6 = 1;//加载输出锁存器
    GpioCtrlRegs.GPAMUX1.bit.GPIO6 = 0;// GPIO6 = GPIO6
    GpioCtrlRegs.GPADIR.bit.GPIO6 = 1;// GPIO6 =输出


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

    //////// GPIO 引脚设置

    /////////////////////////////////////////////////////// 按照 spru791f doc page 128查找 ePWM 对应的 GPIO ////////////////////////////////////////////////

    void GPIO_setup (void)

    EALLOW;//始终受 EALLOW 保护



    GpioDataRegs.GPADAT.bit.GPIO6 = 1;
    GpioCtrlRegs.GPAPUD.bit.GPIO6 = 0;//启用 GPIO6上的上拉
    GpioDataRegs.GPASET.bit.GPIO6 = 1;//加载输出锁存器
    GpioCtrlRegs.GPAMUX1.bit.GPIO6 = 0;// GPIO6 = GPIO6
    GpioCtrlRegs.GPADIR.bit.GPIO6 = 1;// GPIO6 =输出

    EDIS;


    中断空 epwm2_ISR (空)


    pwmcount2++;
    if (EPwm2_DB_DIRECTION = DB_UP)

    IF (EPwm2Regs.DBFED < EPWM2_MAX_DB)

    EPwm2Regs.DBFED++;
    EPwm2Regs.DBRED++;

    其他

    EPwm2_DB_DIRECTION = DB_DOWN;
    EPwm2Regs.DBFED--;
    EPwm2Regs.DBRED--;


    其他

    if (EPwm2Regs.DBFED = EPWM2_MIN_DB)

    EPwm2_DB_DIRECTION = DB_UP;
    EPwm2Regs.DBFED++;
    EPwm2Regs.DBRED++;

    其他

    EPwm2Regs.DBFED--;
    EPwm2Regs.DBRED--;

    EPwm2TimerIntCount++;

    //清除此计时器的 INT 标志
    EPwm2Regs.ETCLR.bit.INT = 1;

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

    空 InitEPwm2Examples()


    EPwm2Regs.TBPRD =周期;//设置计时器周期- 450计数-> 200kHz - 5us 时间周期-监控
    //EPwm2Regs.TBPRD = 6000;
    EPwm2Regs.TBPHS.Half.TBPHS = 0x0000;//相位为0
    EPwm2Regs.TBCTR = 0x0000;//清除计数器

    //设置 TBCLK
    EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;//向上计数
    EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE;//禁用相位加载
    EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;//时钟与 SYSCLKOUT 的比率
    EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV1;

    EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADODE;//每0加载一次寄存器
    EPwm2Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
    EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
    EPwm2Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;

    //设置比较
    EPwm2Regs.CMPA.half.CMPA =周期*占空比;
    //EPwm2Regs.CMPA.half.CMPA = 3000;
    //EPwm1Regs.CMPB = 50000;
    //设置操作
    EPwm2Regs.AQCTLA.bit.ZRO = AQ_SET;
    EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR;

    // EPwm1Regs.AQCTLB.bit.CAU = AQ_CLEAR;//清除 CAU 上的 PWM1B
    // EPwm1Regs.AQCTLB.bit.CAD = AQ_SET;//在 CAD 上设置 PWM1B

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

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

    EPwm2Regs.ETSEL.bit.SOCAEN = 1;//在组上启用 SOC
    EPwm2Regs.ETSEL.bit.SOCASEL = 1;//第366页-在递增计数时从 CMPA 中选择 SOC
    EPwm2Regs.ETPS.bit.SOCAPRD = 1;//在发生第一个事件时生成脉冲


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

    sourceish、

    您完成了什么调试? 在我看来、这里有一些不错的地方值得检查。

    • 您的 CPU 定时器是否正在运行?  
    • 它的 ISR 可进入吗?
    • ISR 可重入吗?
    • 您的变量是否按预期递增?
    • 您的 if 语句是否正常工作?

    祝您好运、
    Cody

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

    您好、Cody、

    1-是的, CpuTimer0.InterruptCount 正在递增。

    2 -是的,如果通过重入,您意味着它将在每个周期(设置为1ms)检查 ISR 条件,则它是可进入和可重入的。

    3 -是的、我的所有变量都在递增。

    4 - ePWM 2工作正常。 在 CPU 定时器 ISR 每1ms 检查一次之后、GPIO6不会变为高电平、也就是说、如果 CpuTimer0.InterruptCount = 5000000、那么将 GPIO 引脚变为 GPIO 输出高电平。 因此、在 CPU 定时器 ISR 中提高到高电平的 GPIO 引脚指令不起作用、因此"IF"语句是否有效令我怀疑。   

    谢谢、此致、

    原始的

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

    sourceish、

    明白。

    程序计数器是否输入了"if"语句?

    此外、请注意、在使用切换 GPIO 之前、通常会设置 GPIO。 然后、当您想要更改其值时、只需写入 GPxSET、GPxCLEAR 或 GPxTOGGLE 即可。

    此致、
    Cody  

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

    您好、Cody、

    非常好。 效果非常好。 非常感谢您的支持。 根据您的建议、我在将 GPIO 初始化设置为高电平之前在 if 语句下进行初始化、它起作用。

    此致、

    原始的