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.

[参考译文] TMS320F28335:在 F28335 上配置双脉冲

Guru**** 2576195 points
Other Parts Discussed in Thread: C2000WARE

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1572698/tms320f28335-configuring-double-pulse-on-f28335

器件型号:TMS320F28335
主题:C2000WARE 中讨论的其他器件

工具/软件:

嗨、大家好、我是这款 DSP F28335 的新用户。 我尝试在使用 F28335 微控制器的 CC Studio 上配置双脉冲代码、但我不确定发生什么情况。 我有这个示例代码(请参阅随附的代码)、当我将它连接到示波器时、我注意到的是 2 个脉冲、但这不是我预期的那样。 有两个问题、

  1. 在调试之前、直流电压保持恒定的高电平、调试后、我的 t1(假定为高电平)改为低电平、t2(假定为低电平)改为高电平、t3(假定为高电平)改为低电平、在 t3 之后、我希望它一直处于低电平(即我的双脉冲结束)。
  2. 接下来、我试图实现的所需双脉冲时序是 t1 (2.5us)、t2 (1.5us)、t3 (1.5us)、其中 t1 和 t3 为高电平、t2 为低电平。 但当我测量示波器上的时间段时、t1 为 15us、t2、t3 为 7.5us、这与我的代码不同、我不确定为什么?

我的目标是:一旦调试、它在 t1 之前应该处于低电平、在 t1 时应该处于高电平 2.5 μ s、在 t2 时应该处于低电平 1.5 μ s、在 t3 再次处于高电平 1.5 μ s、然后在 t3 之后应该永远处于低电平(即双脉冲结束)。 类似于下图:

是否有人有任何经验或代码可以用于双脉冲生成以进行双脉冲测试? 我的双脉冲代码还应该能够随不同的时间段而变化(例如,如果我希望我的 T1 更改为 4uS,示波器也应该在调试后反映变化)。  

如果有人能在我出错时提供一些输入或帮助我更改代码、我将非常感激。 提前感谢!

 

#include "DSP2833x_Device.h"
#include "DSP2833x_Examples.h"

//================== User-adjustable: pick your EPWM and GPIO ==================
#define USE_EPWM1A_GPIO0   1   // Set 1 to route EPWM1A to GPIO0 (JTAG-friendly boards)
#define SYSCLK_HZ          150000000UL   // F28335 default after InitSysCtrl() (150 MHz)
#define TBCLK_DIV          1             // TBCLK = SYSCLK / (HSPCLKDIV*CLKDIV). We set both to /1.
#define TBCLK_HZ           (SYSCLK_HZ / TBCLK_DIV)

// Convert microseconds to TBCLK ticks (rounded)
static inline Uint32 us_to_ticks(float us)
{
    float ticks = (us * (float)TBCLK_HZ) / 1e6f;
    if (ticks < 1.0f) ticks = 1.0f;
    return (Uint32)(ticks + 0.5f);
}

//================== Double-pulse times (change as you like) ===================
// initial low delay, first high, low gap, second high
volatile float t_pre_us = 2.0f;   // example: 2.0 us "quiet" before t1 starts
volatile float t1_us    = 2.5f;   // first high width
volatile float t2_us    = 1.5f;   // low gap
volatile float t3_us    = 1.5f;   // second high width

//================== State machine ==================
typedef enum {
    DP_EDGE0_PRE = 0,   // at t_pre: force HIGH
    DP_EDGE1_END,       // at t_pre+t1: force LOW
    DP_EDGE2_START,     // at t_pre+t1+t2: force HIGH
    DP_EDGE3_END,       // at t_pre+t1+t2+t3: force LOW and stop
    DP_DONE
} dp_state_e;

volatile dp_state_e dp_state = DP_DONE;
volatile Uint32 t_pre_ticks, t1_ticks, t2_ticks, t3_ticks, total_ticks;

// Forward decl
__interrupt void epwm1_isr(void);

static void route_gpio_epwm1a(void)
{
#if USE_EPWM1A_GPIO0
    EALLOW;
    GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1;  // 1 = EPWM1A
    GpioCtrlRegs.GPADIR.bit.GPIO0  = 1;
    EDIS;
#else
    // If you prefer GPIO1 (EPWM1A), uncomment:
    // EALLOW;
    // GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1;
    // GpioCtrlRegs.GPADIR.bit.GPIO1  = 1;
    // EDIS;
#endif
}

static void epwm1_setup_for_double_pulse(void)
{
    // Compute ticks from the (possibly modified) microsecond values
    t_pre_ticks  = us_to_ticks(t_pre_us);
    t1_ticks     = us_to_ticks(t1_us);
    t2_ticks     = us_to_ticks(t2_us);
    t3_ticks     = us_to_ticks(t3_us);
    total_ticks  = t_pre_ticks + t1_ticks + t2_ticks + t3_ticks;

    // Time-base clock prescalers -> /1 so TBCLK = SYSCLK
    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; // stop TBCLK while we configure
    EDIS;

    EPwm1Regs.TBCTL.all = 0;
    EPwm1Regs.TBCTL.bit.CTRMODE   = TB_COUNT_UP;   // up count one-shot frame
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;
    EPwm1Regs.TBCTL.bit.CLKDIV    = TB_DIV1;

    EPwm1Regs.TBCTR  = 0;                // start at 0
    EPwm1Regs.TBPRD  = total_ticks + 4;  // a touch of margin beyond last edge

    // No automatic AQ actions on compare; we'll software-force in ISR.
    EPwm1Regs.AQCTLA.all = 0;

    // Start LOW
    EPwm1Regs.AQCSFRC.bit.CSFA = AQ_CLEAR;  // force low

    // First interrupt will be at CMPA-up == t_pre
    EPwm1Regs.CMPA.half.CMPA = t_pre_ticks;

    // Enable interrupt on CMPA-up; fire every event
    EPwm1Regs.ETSEL.bit.INTSEL = ET_CTRU_CMPA;  // INT on up-count CMPA match
    EPwm1Regs.ETSEL.bit.INTEN  = 1;
    EPwm1Regs.ETPS.bit.INTPRD  = ET_1ST;        // interrupt on every event

    // Clear any stale flags
    EPwm1Regs.ETCLR.bit.INT = 1;

    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // restart TBCLKs
    EDIS;

    dp_state = DP_EDGE0_PRE;
}

static void pie_enable_epwm1_isr(void)
{
    EALLOW;
    PieVectTable.EPWM1_INT = &epwm1_isr;
    EDIS;

    PieCtrlRegs.PIECTRL.bit.ENPIE = 1;
    PieCtrlRegs.PIEIER3.bit.INTx1 = 1;  // ePWM1 INT
    IER |= M_INT3;                      // CPU int group 3
    EINT;  // Enable Global interrupt INTM
    ERTM;  // Enable realtime DBGM
}

void start_double_pulse(void)
{
    // Reset and configure EPWM1 for a fresh one-shot sequence
    epwm1_setup_for_double_pulse();
    // EPWM starts counting immediately (TBCLKSYNC=1), ISR will drive edges
}

__interrupt void epwm1_isr(void)
{
    switch (dp_state)
    {
        case DP_EDGE0_PRE:
            // t = t_pre: go HIGH, arm next edge at t_pre + t1
            EPwm1Regs.AQCSFRC.bit.CSFA = AQ_SET;  // force high
            EPwm1Regs.CMPA.half.CMPA   = t_pre_ticks + t1_ticks;
            dp_state = DP_EDGE1_END;
            break;

        case DP_EDGE1_END:
            // t = t_pre + t1: go LOW, arm next edge at + t2
            EPwm1Regs.AQCSFRC.bit.CSFA = AQ_CLEAR;  // force low
            EPwm1Regs.CMPA.half.CMPA   = t_pre_ticks + t1_ticks + t2_ticks;
            dp_state = DP_EDGE2_START;
            break;

        case DP_EDGE2_START:
            // t = t_pre + t1 + t2: go HIGH, arm final edge at + t3
            EPwm1Regs.AQCSFRC.bit.CSFA = AQ_SET;  // force high
            EPwm1Regs.CMPA.half.CMPA   = t_pre_ticks + t1_ticks + t2_ticks + t3_ticks;
            dp_state = DP_EDGE3_END;
            break;

        case DP_EDGE3_END:
            // t = total: go LOW and STOP everything
            EPwm1Regs.AQCSFRC.bit.CSFA = AQ_CLEAR;    // final low
            EPwm1Regs.ETSEL.bit.INTEN  = 0;           // no more INTs

            // Freeze the counter so the frame is one-shot and done.
            EPwm1Regs.TBCTL.bit.CTRMODE = TB_FREEZE;
            dp_state = DP_DONE;
            break;

        default:
            break;
    }

    EPwm1Regs.ETCLR.bit.INT = 1;   // ack module INT flag
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
}

//================== Typical C2000 startup ==================
void main(void)
{
    InitSysCtrl();       // 150 MHz, enable peripheral clocks
    DINT;
    InitPieCtrl();
    IER = 0;
    IFR = 0;
    InitPieVectTable();

    // Route EPWM1A pin
    InitGpio();
    route_gpio_epwm1a();

    // Make sure EPWM clock is on
    EALLOW;
    SysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK = 1;
    EDIS;

    pie_enable_epwm1_isr();

    // ---- START THE DOUBLE PULSE ----
    // Set your times (us). You can change these before calling start_double_pulse(). !!!THIS PART TO CHANGE YOUR PULSE TIMINGS!!!
    t_pre_us = 2.0f;   // initial low delay
    t1_us    = 2.5f;   // first high
    t2_us    = 1.5f;   // low gap
    t3_us    = 1.5f;   // second high

    start_double_pulse();

    // Idle here; the ISR will run four times to produce the sequence, then stop.
    for(;;) { asm(" NOP"); }
}

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

    您好:

    是否要在一个周期内产生两个脉冲、或者双脉冲实现中所指的是什么? 以下示例可以参考 C2000Ware 位字段 ePWM 示例以获得更多帮助: C:\ti\c2000\C2000Ware_5_05_00_00\device_support\F2833x\examples。  

    希望这有所帮助。