我用CPLD采集AD数据,利用XINTF接口将数据传输到DSP,CCS观察DSP地址数据。系统框图如下所示。
其中28335的XINTF采用16位数据总线连接。
GPIO端口设置如下
void InitGpio(void) //初始化GPIO
{
EALLOW;
//-----------------------------------------------------------------------------------
GpioCtrlRegs.GPBMUX1.all = 0xFFFFFFF0; // 配置 GPIO32-33为I/O口
// 配置 GPIO34 for XREADY 就绪
// 配置 GPIO35 for XR/W 读
// 配置 GPIO36 for XZCS0 片选
// 配置 GPIO37 for XZCS7 片选
// 配置 GPIO38 for XWE0 写
// 配置 GPIO39 for XA16 地址
// 配置 GPIO40 for XA0
// 配置 GPIO41 for XA1
// 配置 GPIO42 for XA2
// 配置 GPIO43 for XA3
// 配置 GPIO44 for XA4
// 配置 GPIO45 for XA5
// 配置 GPIO46 for XA6
// 配置 GPIO47 for XA7
GpioCtrlRegs.GPCMUX1.all = 0xFFFFFFFF; // 配置 GPIO64-GPIO79 for XD15-XD0 数据
GpioCtrlRegs.GPCMUX2.all = 0xFFFFFFFF; // 配置 GPIO80-GPIO87 for XA8-XA15 地址
// GpioCtrlRegs.GPBDIR.all = 0xE0000000; // GPIO32-GPIO60 为输入
GpioCtrlRegs.GPCDIR.all = 0x00000000; // GPI064-GPIO95 为输入
//----------------------------------------------------------------------------------------
GpioCtrlRegs.GPAPUD.all = 0x0100; // 内部上拉 GPIO0-GPIO31
GpioCtrlRegs.GPBPUD.all = 0x0000; // 内部上拉 GPIO32-GPIO63
GpioCtrlRegs.GPCPUD.all = 0x0000; // 内部上拉 GPIO64-GPIO79
EDIS;
}
XINTF访问区域0地址
void InitXintf(void)
{
// 这显示了如何写XINTF寄存器。
// 这里使用了重置后的默认状态值。
// 不同的硬件需要不同的配置。
// 为INTF配置一个例子,在如下目录
// F28335 eZdsp, refer to the examples/run_from_xintf project.
// 任何更改XINTF配置只能从XINTF扩展之外的区域运行代码。
// 所有区域---------------------------------
// 所有区域的基准时间时钟为 XTIMCLK = 1/2 SYSCLKOUT
EALLOW;
SysCtrlRegs.PCLKCR3.bit.XINTFENCLK = 1; //开启XINTF时钟信号
XintfRegs.XINTCNF2.bit.XTIMCLK = 1; //基准时钟XTIMCLK = 1/2 SYSCLKOUT
XintfRegs.XINTCNF2.bit.WRBUFF = 0; //无写缓冲寄存器
XintfRegs.XINTCNF2.bit.CLKOFF = 1; //禁止XCLKOUT
XintfRegs.XINTCNF2.bit.CLKMODE = 1; //XCLKOUT=XTIMCLK/2
XintfRegs.XTIMING0.bit.XWRLEAD = 2; //区域0写建立时间为11b,周期数为6
XintfRegs.XTIMING0.bit.XWRACTIVE = 5; //有效时间为111b,周期数为14
XintfRegs.XTIMING0.bit.XWRTRAIL = 2; //跟踪时间为11b,周期数为6
// Zone read timing
XintfRegs.XTIMING0.bit.XRDLEAD = 2; //区域0读建立时间为11b,周期数为6
XintfRegs.XTIMING0.bit.XRDACTIVE = 5; //有效时间为111b,周期数为14
XintfRegs.XTIMING0.bit.XRDTRAIL = 2; //跟踪时间为11b,周期数为6
// double all Zone read/write lead/active/trail timing
XintfRegs.XTIMING0.bit.X2TIMING = 1; //比值2:1
// Zone will sample XREADY signal
XintfRegs.XTIMING0.bit.USEREADY = 0; //XREADY信号采样
XintfRegs.XTIMING0.bit.READYMODE = 1; //异步采样
XintfRegs.XTIMING0.bit.XSIZE = 3; //数据总线宽度,16位
EDIS;
}
#define FPGA_BASE_ADDR 0X4000 //区域0起始地址
#define HSAD_OUT_CUR_A1 (*(volatile int16 *)(FPGA_BASE_ADDR + 0x0004)) //HSAD采样
#define HSAD_OUT_CUR_B1 (*(volatile int16 *)(FPGA_BASE_ADDR + 0x0005)) //HSAD采样电流
#define HSAD_OUT_CUR_A2 (*(volatile int16 *)(FPGA_BASE_ADDR + 0x0006)) //HSAD采样电流
#define HSAD_OUT_CUR_B2 (*(volatile int16 *)(FPGA_BASE_ADDR + 0x0007)) //HSAD采样电流
#define HSAD_OUT_CUR_A3 (*(volatile int16 *)(FPGA_BASE_ADDR + 0x0008)) //HSAD采样电流
#define HSAD_OUT_CUR_B3 (*(volatile int16 *)(FPGA_BASE_ADDR + 0x0009)) //HSAD采样电流
#define HSAD_OUT_CUR_A4 (*(volatile int16 *)(FPGA_BASE_ADDR + 0x000A)) //HSAD采样电流
#define HSAD_OUT_CUR_A5 (*(volatile int16 *)(FPGA_BASE_ADDR + 0x000B)) //HSAD采样电流
interrupt void XINT1_ISR(void)
{
// ISR代码插入这里
outCurADeal_pSt[0].in_I16 = HSAD_OUT_CUR_A1; //1_A相电流
outCurBDeal_pSt[0].in_I16 = HSAD_OUT_CUR_B1; //1_B相电流
outCurADeal_pSt[1].in_I16 = HSAD_OUT_CUR_A2; //2_A相电流
outCurBDeal_pSt[1].in_I16 = HSAD_OUT_CUR_B2; //2_B相电流
outCurADeal_pSt[2].in_I16 = HSAD_OUT_CUR_A3; //3_A相电流
outCurBDeal_pSt[2].in_I16 = HSAD_OUT_CUR_B3; //3_B相电流
outCurADeal_pSt[3].in_I16 = HSAD_OUT_CUR_A4; //1_A相电流
outCurADeal_pSt[4].in_I16 = HSAD_OUT_CUR_A5; //2_A相电流
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
起初以为是CPLD与AD之间采样时序错误,造成CPLD本身地址上数据错乱,经XINTF传送后,DSP也接收到错乱数据,CPLD程序如下。
always@(posedge SYS_10M_CLK)
begin
cs_r[2] =(XA == BASE_AD_ZONE0 + 16'H0004) &(!rd_filter)&(!XZCS0_N); //0x04 AD1_V1
cs_r[3] =(XA == BASE_AD_ZONE0 + 16'H0005) &(!rd_filter)&(!XZCS0_N); //0x05 AD1_V2
cs_r[4] =(XA == BASE_AD_ZONE0 + 16'H0006) &(!rd_filter)&(!XZCS0_N); //0x06 AD1_V3
cs_r[5] =(XA == BASE_AD_ZONE0 + 16'H0007) &(!rd_filter)&(!XZCS0_N); //0x07 AD1_V4
cs_r[6] =(XA == BASE_AD_ZONE0 + 16'H0008) &(!rd_filter)&(!XZCS0_N); //0x08 AD1_V5
cs_r[7] =(XA == BASE_AD_ZONE0 + 16'H0009) &(!rd_filter)&(!XZCS0_N); //0x09 AD1_V6
cs_r[8] =(XA == BASE_AD_ZONE0 + 16'H000A) &(!rd_filter)&(!XZCS0_N); //0x0A AD2_V1
cs_r[9] =(XA == BASE_AD_ZONE0 + 16'H000B) &(!rd_filter)&(!XZCS0_N); //0x0B AD2_V2
end
always@(posedge SYS_10M_CLK)
case(cs_r)
15'b000_0000_0000_0100: begin dsp_dat_reg = ad1_dout[15:0]; end //30 AD1_V1 1_A相电流
15'b000_0000_0000_1000: begin dsp_dat_reg = ad1_dout[31:16]; end //40 AD1_V2 1_B相电流
15'b000_0000_0001_0000: begin dsp_dat_reg = ad1_dout[47:32]; end //50 AD1_V3 2_A相电流
15'b000_0000_0010_0000: begin dsp_dat_reg = ad1_dout[63:48]; end //60 AD1_V4 2_B相电流
15'b000_0000_0100_0000: begin dsp_dat_reg = ad1_dout[79:64]; end //70 AD1_V5 3_A相电流
15'b000_0000_1000_0000: begin dsp_dat_reg = ad1_dout[95:80]; end //80 AD1_V6 3_B相电流
15'b000_0001_0000_0000: begin dsp_dat_reg = ad2_dout[15:0]; end //110 AD2_V1 1_A相电流
15'b000_0010_0000_0000: begin dsp_dat_reg = ad2_dout[31:16]; end //120 AD2_V2 2_A相电流
default: begin dsp_dat_reg = dsp_dat_reg;end //数据寄存器数据保持
endcase
因CPLD程序无法调试和观察变量,我将CPLD采集程序屏蔽到只剩下一路AD采样,然后再次观察DSP地址变量数据,发现数据正确,单独测试每一路均能正确接收数据,但将多路AD采样通道开启却出现错误,再次检查CPLD与AD芯片采样时序,确保AD采样时序符合最小时序要求,发现还是出现错误。最后将CPLD采样程序屏蔽,直接在地址位上赋常量,如下所示。
always@(posedge SYS_10M_CLK)
begin
cs_r[2] =(XA == BASE_AD_ZONE0 + 16'H0004) &(!rd_filter)&(!XZCS0_N); //0x04 AD1_V1
cs_r[3] =(XA == BASE_AD_ZONE0 + 16'H0005) &(!rd_filter)&(!XZCS0_N); //0x05 AD1_V2
cs_r[4] =(XA == BASE_AD_ZONE0 + 16'H0006) &(!rd_filter)&(!XZCS0_N); //0x06 AD1_V3
cs_r[5] =(XA == BASE_AD_ZONE0 + 16'H0007) &(!rd_filter)&(!XZCS0_N); //0x07 AD1_V4
cs_r[6] =(XA == BASE_AD_ZONE0 + 16'H0008) &(!rd_filter)&(!XZCS0_N); //0x08 AD1_V5
cs_r[7] =(XA == BASE_AD_ZONE0 + 16'H0009) &(!rd_filter)&(!XZCS0_N); //0x09 AD1_V6
cs_r[8] =(XA == BASE_AD_ZONE0 + 16'H000A) &(!rd_filter)&(!XZCS0_N); //0x0A AD2_V1
cs_r[9] =(XA == BASE_AD_ZONE0 + 16'H000B) &(!rd_filter)&(!XZCS0_N); //0x0B AD2_V2
end
always@(posedge SYS_10M_CLK)
case(cs_r)
15'b000_0000_0000_0100: begin dsp_dat_reg = 30; end //30 AD1_V1 1_A相电流
15'b000_0000_0000_1000: begin dsp_dat_reg = 40; end //40 AD1_V2 1_B相电流
15'b000_0000_0001_0000: begin dsp_dat_reg = 50; end //50 AD1_V3 2_A相电流
15'b000_0000_0010_0000: begin dsp_dat_reg = 60; end //60 AD1_V4 2_B相电流
15'b000_0000_0100_0000: begin dsp_dat_reg = 70; end //70 AD1_V5 3_A相电流
15'b000_0000_1000_0000: begin dsp_dat_reg = 80; end //80 AD1_V6 3_B相电流
15'b000_0001_0000_0000: begin dsp_dat_reg = 110; end //110 AD2_V1 1_A相电流
15'b000_0010_0000_0000: begin dsp_dat_reg = 120; end //120 AD2_V2 2_A相电流
default: begin dsp_dat_reg = dsp_dat_reg;end //数据寄存器数据保持
endcase
测试发现DSP地址数据出现跳变错乱,可以判断是CPLD与DSP的xintf通信问题,当时单路测试时正确以为xintf通信已经没有问题,导致花费很多时间测试CPLD与AD之间时序。仔细观察,发现ADC通道1数据串扰到通道2地址上,并影响通道3,怀疑DSP与CPLD通信时序不匹配,DSP速度过快,CPLD速度过慢,通过改变xintf配置寄存器,将建立、有效、跟踪时间调整至最高和最低,如下。
XintfRegs.XTIMING0.bit.XWRLEAD = 1; //区域0写建立时间为1b,周期数为1
XintfRegs.XTIMING0.bit.XWRACTIVE = 1; //有效时间为1b,周期数为1
XintfRegs.XTIMING0.bit.XWRTRAIL = 1; //跟踪时间为1b,周期数为1
// Zone read timing
XintfRegs.XTIMING0.bit.XRDLEAD = 1; //区域0读建立时间为1b,周期数为1
XintfRegs.XTIMING0.bit.XRDACTIVE = 1; //有效时间为1b,周期数为1
XintfRegs.XTIMING0.bit.XRDTRAIL = 1; //跟踪时间为1b,周期数为1
// double all Zone read/write lead/active/trail timing
XintfRegs.XTIMING0.bit.X2TIMING = 0; //比值1:1
发现差别明显,另外通过将DSP系统时钟设置进行降频,发现数据能达到一个比较稳定状态。
//#define DSP28_DIVSEL 0 // Enable /4 for SYSCLKOUT
//#define DSP28_DIVSEL 1 // Enable /4 for SYSCKOUT
#define DSP28_DIVSEL 2 // Enable /2 for SYSCLKOUT
//#define DSP28_DIVSEL 3 // Enable /1 for SYSCLKOUT
#define DSP28_PLLCR 10
//#define DSP28_PLLCR 9
//#define DSP28_PLLCR 8
//#define DSP28_PLLCR 7
//#define DSP28_PLLCR 6
//#define DSP28_PLLCR 5
//#define DSP28_PLLCR 4
//#define DSP28_PLLCR 3
//#define DSP28_PLLCR 2
//#define DSP28_PLLCR 1
//#define DSP28_PLLCR 0 // PPL旁路
void InitSysCtrl(void) //初始化系统控制
{
DisableDog(); //关闭看门狗
InitPll(DSP28_PLLCR,DSP28_DIVSEL); //初始化PLL控制
InitPeripheralClocks(); //初始化外设时钟
}
最后发现DSP晶振为30Mhz,CPLD晶振为10Mhz,导致CPLD数据线上数据变化过慢,当DSP地址改变时,CPLD数据线上的数据还是前一位数据,造成数据延迟,串扰到第一位地址。尝试将xintf接口速度减慢,CPLD芯片无PLL,采用上下沿触发,软件倍频,还是达不到匹配状态。最后只得将CPLD晶振替换为30MHz才正确匹配。