主题:C2000WARE 中讨论的其他器件
工具/软件:
嗨、大家好、我是这款 DSP F28335 的新用户。 我尝试在使用 F28335 微控制器的 CC Studio 上配置双脉冲代码、但我不确定发生什么情况。 我有这个示例代码(请参阅随附的代码)、当我将它连接到示波器时、我注意到的是 2 个脉冲、但这不是我预期的那样。 有两个问题、
- 在调试之前、直流电压保持恒定的高电平、调试后、我的 t1(假定为高电平)改为低电平、t2(假定为低电平)改为高电平、t3(假定为高电平)改为低电平、在 t3 之后、我希望它一直处于低电平(即我的双脉冲结束)。
- 接下来、我试图实现的所需双脉冲时序是 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"); }
}