主题中讨论的其他部件: C2000WARE, controlSUITE
大家好,
我代表客户发布。
我使用的是TMDSPREX2.8335万板。 我正在尝试使用其ADC端口将外部正弦信号(50 Hz的栅电压)转储到控制器中。 信号调节良好,处于0至3伏的安全限值之间。
最初,我将ADC绑定到CPU Timer0中断(每25微秒或40 kHz发生一次),并观察图形窗口中的信号。
CPU TIMER0中断触发的ADC代码如下所示:
包含 "math.h"
#include "IQmathlib.h"
#include "DSP2833x_Device.h" // DSP2833x Headerfile include文件
#include "DSP2833x_examples.h" // DSP2833x examples include File
//本文件中找到的函数的prototype语句。
中断 void CPU_timer0_ISR(void);
//用于绘图,从ADC读取和中断计数的变量
UINT32 计数=1;
Int 样本= 0;
float array_sine[800];
float voltage_grid = 0,vg1 = 0,volt_offset = 0,voft1 = 0;
主要()
{
InitSysCtrl();
// EALLOW;
// SysCtrlRegs.HISPPCP.ALL = 0x3; // HSPCLK = SYSCLKOUT/6
// EDIS;
dint; //禁用CPU中断
InitPieCtrl();// 禁用所有外围设备中断
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC =0;// 停止所有TB时钟
EDIS;
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; //启动所有 同步的计时器
EDIS;
IER = 0x0000; //禁用所有中断
IFR = 0x0000; //清除所有中断的标志
InitPieVectorTable();
//************** ADC初始化和配置开始************ //
InitAdc();// 基本ADC设置(包括校准)
AdcRegs.ADCTRL1.ALL =0; //初始化前清除ADCTRL1
AdcRegs.ADCTRL1.bit.ACQ_PS = 0xF; //采样和保持(15+1)=16个ADC周期
AdcRegs.ADCTRL1.bit.cps = 0; //进一步除以1
ADcRegs.ADCTRL1.bit.SEQ_CASC=1 ; // ADC的级联模式(16状态)
AdcRegs.ADCTRL1.bit.con_run =0; //禁用ADC的连续运行模式
// AdcRegs.ADCTRL2.ALL =0; //初始化前清除ADCTRL2
AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; //在SEQ1上启用中断
AdcRegs.ADCTRL2.bit.INT_MOD_SEQ1 = 0; //在序列的每一端启用中断
AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; //重置SEQ1
AdcRegs.ADCTRL2.bit.so_SEQ1 = 0; //从ePWM1_SOCA触发启动SEQ1
ADcRegs.ADCTRL3.bit.SMODE_SEL = 0; // ADC的连续同步转换
AdcRegs.ADCTRL3.bit.ADCCLKPS = 3;// 3,因为ADC的HSPCLK为75 MHz (150/6);请参阅上文
//来自DSP2833x_sysctrl.c用于ADC的FCLK为75 MHz而不是150 MHz;
//75/(2*3)= 12.5 兆赫
AdcRegs.ADCMAXCONV.ALL = 0x0001; // 2个转换
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x2; //将ADCINA2分配给CONV00
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x3; //将ADCINA3分配给conv01
//************** ADC初始化和配置结束************ //
EALLOW; //这是写入EALLOW保护寄存器所必需的
PieVectorTable.TINT0 =&CPU_timer0_ISR;
EDIS;
InitCpuTimers();
ConfigCpuTimer(&CpuTimer0150,25); //以25 us或40 kHz的频率生成TINT0
CpuTimer0Regs.tcr.all = 0x4001; //禁用 CPU timer0中断(不需要)
IER |=1; //启用所有INT1组
PieCtrlRegs.PIEIER1.bit.INTx7=1 ; //启用ADC INT (组1中的第6个中断)
EINT; //启用全局中断INTM
ERTM; //启用全局 实时 中断DBGM
}
中断 无效 CPU_TIMER0_ISR(void)
{
count++; //检查是否正在生成中断
AdcRegs.ADCTRL2.bit.so_SEQ1 = 1;
volt_grid = AdcRegs.ADCRESULT0>>4;// 从ADC读取
volt_offset = AdcRegs.ADCRESULT1>>4;// 从ADC读取
vg1 = voltage_grid*3/4095; //获取原始值
voft1 = volt_offset*3/4095; //获取原始值
IF (样本> 799)
样本= 0;
array_sine[sample]= vg1;
示例++;
//为下一个ADC序列重新初始化
AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; //重置SEQ1
AdcRegs.ADCST.Bit.INT_SEQ1_CLR = 1; //清除INT SEQ1位
PIECtrlRegs.PIEACK/ALL = PIEACK_Group1; //确认中断到PIE
}
//===========================================================================================================================================
//源代码结束。
//===========================================================================================================================================
与上述代码对应的图形如下所示:

如您所见,(转换的)查看信号中存在不连续性。
然后,我通过从ePWM1中断向ADC发出命令(在相同条件下,即每25微秒或40 kHz)重试一次。 ePWM1中断的ADCSoC代码如下:
/* 目标:
* A)在25 us时使用ePWM1触发ADC中断
* b)级联模式下的ADC
* c) ADC执行顺序采样
* d) ACQ_PS = 0xF (15+1=16个保持周期)
* e) ADC频率为12.5 MHz
* f)观察图解
*/
包含 "math.h"
#include "IQmathlib.h"
#include "DSP2833x_Device.h" // DSP2833x Headerfile include文件
#include "DSP2833x_examples.h" // DSP2833x examples include File
//本文件中找到的函数的prototype语句。
void InitEPwmTimer(void);
中断 无效 ADC_ISR(void);
//用于绘图,从ADC读取和中断计数的变量
UINT32 计数=1;
Int 样本 = 0;
float array_sine[800];
float voltage_grid = 0,vg1 = 0,volt_offset = 0,voft1 = 0;
主要()
{
InitSysCtrl();
// EALLOW;
// SysCtrlRegs.HISPPCP.ALL = 0x3; // HSPCLK = SYSCLKOUT/6
// EDIS;
dint; //禁用CPU中断
InitPieCtrl();// 禁用所有外围设备中断
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC =0;// 停止所有TB时钟
EDIS;
InitEPwmTimer();// 启动所需的ePWM寄存器并配置中断要求
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; //启动所有 同步的计时器
EDIS;
IER = 0x0000; //禁用所有中断
IFR = 0x0000; //清除所有中断的标志
InitPieVectorTable();
//************** ADC初始化和配置开始************ //
InitAdc();// 基本ADC设置(包括校准)
AdcRegs.ADCTRL1.ALL =0; //初始化前清除ADCTRL1
AdcRegs.ADCTRL1.bit.ACQ_PS = 0xF; //采样和保持(15+1)=16个ADC周期
AdcRegs.ADCTRL1.bit.cps = 0; //进一步除以1
ADcRegs.ADCTRL1.bit.SEQ_CASC=1 ; // ADC的级联模式(16状态)
AdcRegs.ADCTRL1.bit.con_run =0; //禁用ADC的连续运行模式
// AdcRegs.ADCTRL2.ALL =0; //初始化前清除ADCTRL2
AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; //在SEQ1上启用中断
AdcRegs.ADCTRL2.bit.INT_MOD_SEQ1 = 0; //在序列的每一端启用中断
AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; //重置SEQ1
AdcRegs.ADCTRL2.bit.ePWM_SOCA_SEQ1 = 1; //从ePWM1_SOCA触发启动SEQ1
ADcRegs.ADCTRL3.bit.SMODE_SEL = 0; // ADC的连续同步转换
AdcRegs.ADCTRL3.bit.ADCCLKPS = 3;// 3,因为ADC的HSPCLK为75 MHz (150/6);请参阅上文
//来自DSP2833x_sysctrl.c用于ADC的FCLK为75 MHz而不是150 MHz;
//75/(2*3)= 12.5 兆赫
AdcRegs.ADCMAXCONV.ALL = 0x0001; // 2个转换
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x2; //将ADCINA2分配给CONV00
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x3; //将ADCINA3分配给conv01
//************** ADC初始化和配置结束************ //
EALLOW; //这是写入EALLOW保护寄存器所必需的
PieVectorTable.ADCINT =&ADC_ISR;
EDIS;
InitCpuTimers();
ConfigCpuTimer(&CpuTimer0150,25); //以25 us或40 kHz的频率生成TINT0
// CpuTimer0Regs.tcr.all = 0x4001; //禁用 CPU timer0中断(不需要)
IER |=1; //启用所有INT1组
PieCtrlRegs.PIEIER1.bit.INTx6=1 ; //启用ADC INT (组1中的第6个中断)
EINT; //启用全局中断INTM
ERTM; //启用全局 实时 中断DBGM
}
void InitEPwmTimer (void)
{
EALLOW;
GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1; // ePWM1A激活
gpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1; // ePWM1B激活
EDIS;
// ePWM 1模块时钟同步已禁用
// ePWM1 TBCTL初始化
EPwm1Regs.TBCTL.bit.FREE_SOFT = 11; //自由运行
EPwm1Regs.TBCTL.bit.PHSDIR = 1; //同步后计数
EPwm1Regs.TBCTL.bit.CLKDIV = 0; // TBCLK = HSPCLK/1
EPwm1Regs.TBCTL.bit.HSPCLKDIV = 1; // HSPCLK = SYSCLK/2
EPwm1Regs.TBCTL.bit.SWFSYNC = 0; //软件同步已禁用
EPwm1Regs.TBCTL.bit.SYNCOSEL = 3; //禁用同步
EPwm1Regs.TBCTL.bit.PRDLD = 0; // CTR上的负载= 0
EPwm1Regs.TBCTL.bit.PHSEN = 0; //禁用相位启用
EPwm1Regs.TBCTL.bit.SYNCOSEL = 3; //禁用同步
EPwm1Regs.TBCTL.bit.CTRMODE = 0; //在上模式下计数
// ePWM1 ETPS初始化
EPwm1Regs.etps.bit.SOCBCNT = 0; //这是只读位
EPwm1Regs.ETPS.bit.SOCBPRD =0; //已禁用,因为中断由ePWM1A生成
EPwm1Regs.etps.bit.SOCACNT = 0; //这是只读位
EPwm1Regs.ETPS.bit.SOCAPRD = 1; //每次ePWM1A都会生成中断
EPwm1Regs.ETPS.bit.INTCNT = 0; //只读位无关紧要
EPwm1Regs.ETPS.bit.INTPRD =1; //生成每个事件的中断
// ePWM1 ETSEL初始化
EPwm1Regs.ETSEL.bit.SOCBEN = 0; //禁用SOCB
EPwm1Regs.ETSEL.bit.SOCBSEL = 0; //因为SOCB已禁用
EPwm1Regs.ETSEL.bit.SOCAEN = 1; //启用SOCA
EPwm1Regs.ETSEL.bit.SOCASEL = 1; //在CTR = 0时生成中断
EPwm1Regs.ETSEL.bit.inten = 0; //禁用PWM中断
EPwm1Regs.ETSEL.bit.INTSEL = 0; //不重要,因为PWM中断已禁用
// ePWM1 ETSEL初始化
EPwm1Regs.TBPRD = 1875; // fpwm = 40 kHz = finterrupt
}
中断 无效 ADC_ISR(void)
{
count++; //检查是否正在生成中断
volt_grid = AdcRegs.ADCRESULT0>>4;// 从ADC读取
volt_offset = AdcRegs.ADCRESULT1>>4;// 从ADC读取
vg1 = voltage_grid*3/4095; //获取原始值
voft1 = volt_offset*3/4095; //获取原始值
IF (样本 > 799)
样本 = 0;
array_sine[sample]= vg1;
示例++;
//为下一个ADC序列重新初始化
AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; //重置SEQ1
AdcRegs.ADCST.Bit.INT_SEQ1_CLR = 1; //清除INT SEQ1位
PIECtrlRegs.PIEACK/ALL = PIEACK_Group1; //确认中断到PIE
}
//===========================================================================================================================================
//源代码结束。
//===========================================================================================================================================
统计图窗口中的相应输出如下所示:

正如您在这两种情况下所看到的(无论是ADC连接到TIMER0中断还是ADC连接到ePWM1中断),即使我正在收集800点(50 Hz =20毫秒,40 kHz =25 us),我也会得到不连续的数据; 20 m /25u = 800点)并绘制所有点。
另一个有趣的事情是,即使ADCTRL2在TIMER0中断的情况下应该显示0x4800或0x2800 (取决于RST =1或SOC =1),或者在ePWM1的SOC的情况下显示0x4900或0x0999 (取决于RST =1或0)。 但是,ACTRL2为TIMER0保留了一个永久值0x0800,为ePWM1保留了一个永久值0x0900。
为什么在这两种情况下统计图窗口中都缺少数据,为什么ADCTRL2保持永久值?
C2000专家能否帮助我调试这些问题,因为我已经尝试解决这个问题几个星期了,但问题仍然存在。
我希望您能提供帮助。
此致,
马文


