问题是这样的:利用mcbsp将DM642配置成SPI协议的从机,主机用FPGA实现。现在主机端发送出来的数据和波形用示波器和逻辑分析仪看都是正常的,但是在DSP端就是无法正确接收。主机FPGA发送的数据格式是:帧头(AA)+8字节数据。DSP首先检测帧头AA是否正确,如果正确,则接收8字节数据,否则不接收。
下图是FPGA端发送出来的波形图,
采用的模式是CLKSTP=11,CLKXP=1这种模式,DM642芯片手册上的时序图如下所示,
下面是我的DSP端的配置:
static MCBSP_Config myConfig =
{
MCBSP_SPCR_RMK //Serial Port Control Register (SPCR)
( MCBSP_SPCR_FREE_YES, // Serial clock free running mode(FREE) MCBSP_SPCR_SOFT_YES, // Serial clock emulation mode(SOFT)
MCBSP_SPCR_FRST_YES, // Frame sync generator reset(FRST)
MCBSP_SPCR_GRST_YES, // Sample rate generator reset(GRST)
MCBSP_SPCR_XINTM_XRDY, // Transmit interrupt mode(XINTM) MCBSP_SPCR_XSYNCERR_NO, // Transmit synchronization error MCBSP_SPCR_XRST_YES, // Transmitter reset(XRST) MCBSP_SPCR_DLB_OFF, // Digital loopback(DLB) mode MCBSP_SPCR_RJUST_RZF, // Receive data sign-extension and
// justification mode(RJUST)
MCBSP_SPCR_CLKSTP_DEFAULT, // Clock stop(CLKSTP) mode 0
MCBSP_SPCR_DXENA_OFF, // DX Enabler(DXENA) -Extra delay for
// DX turn-on time.
MCBSP_SPCR_RINTM_RRDY, // Receive interrupt(RINT) mode
MCBSP_SPCR_RSYNCERR_NO, // Receive synchronization error(RSYNCERR)
MCBSP_SPCR_RRST_YES // Receiver reset(RRST)
),
MCBSP_RCR_RMK // Receive Control Register (RCR)
( MCBSP_RCR_RPHASE_SINGLE, // Receive phases MCBSP_RCR_RFRLEN2_OF(0), // Receive frame length // in phase 2(RFRLEN2) MCBSP_RCR_RWDLEN2_8BIT, // Receive element length // in phase 2(RWDLEN2) MCBSP_RCR_RCOMPAND_MSB, // Receive companding mode (RCOMPAND) MCBSP_RCR_RFIG_YES, // Receive frame ignore(RFIG)
MCBSP_RCR_RDATDLY_0BIT, // Receive data delay(RDATDLY)
MCBSP_RCR_RFRLEN1_OF(0), // Receive frame length // in phase 1(RFRLEN1)
MCBSP_RCR_RWDLEN1_8BIT, // Receive element length // in phase 1(RWDLEN1)
MCBSP_RCR_RWDREVRS_DISABLE // Receive 32-bit bit reversal // feature.(RWDREVRS)
),
MCBSP_XCR_RMK //Transmit Control Register (XCR)
( MCBSP_XCR_XPHASE_SINGLE, // Transmit phases
MCBSP_XCR_XFRLEN2_OF(0), // Transmit frame length // in phase 2(XFRLEN2) MCBSP_XCR_XWDLEN2_8BIT, // Transmit element length
// in phase 2
MCBSP_XCR_XCOMPAND_MSB, // Transmit companding mode(XCOMPAND)
MCBSP_XCR_XFIG_YES, // Transmit frame ignore(XFIG)
MCBSP_XCR_XDATDLY_0BIT, // Transmit data delay(XDATDLY)
MCBSP_XCR_XFRLEN1_OF(0), // Transmit frame length // in phase 1(XFRLEN1)
MCBSP_XCR_XWDLEN1_8BIT, // Transmit element length // in phase 1(XWDLEN1)
MCBSP_XCR_XWDREVRS_DISABLE // Transmit 32-bit bit reversal feature
),
MCBSP_SRGR_RMK //serial port sample rate generator register(SRGR)
( MCBSP_SRGR_GSYNC_FREE, // Sample rate generator clock // synchronization(GSYNC).
MCBSP_SRGR_CLKSP_RISING, // CLKS polarity clock edge select(CLKSP)
MCBSP_SRGR_CLKSM_INTERNAL, // MCBSP sample rate generator clock
// mode(CLKSM)
MCBSP_SRGR_FSGM_DXR2XSR, // Sample rate generator transmit frame
// synchronization
MCBSP_SRGR_FPER_OF(8), // Frame period(FPER)
MCBSP_SRGR_FWID_OF(0), // Frame width(FWID)
MCBSP_SRGR_CLKGDV_OF(1) // Sample rate generator clock
// divider(CLKGDV)
),
MCBSP_MCR_DEFAULT, // Using default value of MCR register
MCBSP_RCERE0_DEFAULT, // Using default value of RCERE registers
MCBSP_RCERE1_DEFAULT,
MCBSP_RCERE2_DEFAULT,
MCBSP_RCERE3_DEFAULT,
MCBSP_XCERE0_DEFAULT, // Using default value of XCERE registers
MCBSP_XCERE1_DEFAULT,
MCBSP_XCERE2_DEFAULT,
MCBSP_XCERE3_DEFAULT,
MCBSP_PCR_RMK //serial port pin control register(PCR)
( MCBSP_PCR_XIOEN_SP, // Transmitter in general-purpose I/O mode
MCBSP_PCR_RIOEN_SP, // Receiver in general-purpose I/O mode
MCBSP_PCR_FSXM_EXTERNAL, // Transmit frame synchronization mode
MCBSP_PCR_FSRM_EXTERNAL, // Receive frame synchronization mode
MCBSP_PCR_CLKXM_INPUT, // Transmitter clock mode (CLKXM)
MCBSP_PCR_CLKRM_INPUT, // Receiver clock mode (CLKRM)
MCBSP_PCR_CLKSSTAT_0, // CLKS pin status(CLKSSTAT)
MCBSP_PCR_DXSTAT_0, // DX pin status(DXSTAT)
MCBSP_PCR_FSXP_ACTIVELOW, // Transmit frame synchronization polarity(FSXP)
MCBSP_PCR_FSRP_ACTIVELOW, // Receive frame synchronization polarity(FSRP)
MCBSP_PCR_CLKXP_FALLING, // Transmit clock polarity(CLKXP)Transmit data sampled on falling edge of CLKX
MCBSP_PCR_CLKRP_FALLING // Receive clock polarity(CLKRP)
)
// MCBSP_enableSrgr(hMcbsp); // 修改时我加上的!!!
};
求各位老师指点哪来有问题,谢谢!
Chris Meng:
你好,
FPGA是在时钟下降沿发出的数据,所以DM642的Mcbsp应该在时钟上升沿采集数据,你下面的配置是否需要修改一下?
weizhi zhangMCBSP_PCR_CLKRP_FALLING // Receive clock polarity(CLKRP)
另,注意FPGA输出的时钟频率,需要在mcbsp的spec范围内,不能太快。
weizhi zhang:
回复 Chris Meng:
您好,
我找您所说,将MCBSP_PCR_CLKRP_FALLING // Receive clock polarity(CLKRP)改为了RISING,
因为我FPGA端发的数据是AA(帧头)+8字节数据。所以我的主函数里这样写的:
while(1){
receive_send_1_byte(0x00);//接收帧头, if (head_in==0xAA)//如果帧头是AA,那么下一步 { receive_send_8_byte(data_in,data_out);//接收8字节数据。 // 关SPI MCBSP_FSETSH(hMcbsp,SPCR,XRST,YES); // 串口发送器被禁止,并处于复位状态 MCBSP_FSETSH(hMcbsp,SPCR,RRST,YES); // 串口接收器被禁止,并处于复位状态
} else {; } } // 与while(1) 对应
//读帧头函数
void receive_send_1_byte(Uint8 head_out){ while (!MCBSP_rrdy(hMcbsp)); //等待读准备好 head_in=MCBSP_read(hMcbsp);//读进来的8字节数据放入head_in
while (!MCBSP_xrdy(hMcbsp)); //判断写准备好 MCBSP_write(hMcbsp,head_out);
}
//读写8字节函数
void receive_send_8_byte(Uint8 *data_out){ int i=0; // 接收8个字节数据,并发送八个字节数据
for (i=0;i<8;i++) { while (!MCBSP_rrdy(hMcbsp)); //判断准备好 data8_in[i]= MCBSP_read(hMcbsp);//读数据
while (!MCBSP_xrdy(hMcbsp)); MCBSP_write(hMcbsp,data_out[i]); }
}
现在问题是我在判断帧头的时候receive_send_1_byte,可以顺利通过,然后进入receive_send_8_byte函数后,会一直卡在
while (!MCBSP_rrdy(hMcbsp)); //判断读准备好
这一步,不知道为什么在receive_send_1_byte里面没有卡在判断读准备好这一步,进入receive_send_8_byte函数后就卡在这一步,
请老师指教,谢谢!
Chris Meng:
回复 weizhi zhang:
weizhi zhang
void receive_send_1_byte(Uint8 head_out){ while (!MCBSP_rrdy(hMcbsp)); //等待读准备好 head_in=MCBSP_read(hMcbsp);//读进来的8字节数据放入head_in
while (!MCBSP_xrdy(hMcbsp)); //判断写准备好 MCBSP_write(hMcbsp,head_out);
}
第一个8bit数据全部都读到了么? 正确么?
为什么还有写的动作?
weizhi zhang:
回复 Chris Meng:
您好,
在没改RISING的时候,第一个8bit的数据(也就是帧头0xAA)读不正确,改了后,大多数情况可以读正确,但是还是有时候会不正确;
写的话当时认为这个SPI是全双工的,有读的地方就有写,所以就加了写,这样不对吗?
这里有个很奇怪的问题,原来呢整个程序是通的,因为当时是跟另一个人合作的,在当时我们调通这个程序后,我的工作完成了,他接着自己改了改DSP端的程序,
后来发给我目前这个程序,说是最后改好的,我当时没在意。结果现在我拿出来重新要用的时候发现程序不通,导致我现在重新开始调,也联系不到他了目前,
他跟我一样完全是新手,所以怀疑是他最后改的什么地方又改错了。
Chris Meng:
回复 weizhi zhang:
Zhang Weizhi,
你原来的代码还在么?可以尝试一下是否能正常工作。
请问FPGA的代码是否有改动过?我之前提到的“FPGA输出的时钟频率,需要在mcbsp的spec范围内,不能太快。”是否有关注过?
先调试到采集正确。
weizhi zhang:
回复 Chris Meng:
原来的DSP代码不能正确接收,也不能正确发送。
FPGA代码改动过其中一个module,但是不涉及SPI协议这个模块,是整个系统中的一个模块。
FPGA输出的时钟频率我设置的是1M。
原来的代码的主要配置如下:
1、FPGA端(主机):
always @(negedge spi_clk)…//主机发送
always @(negedge spi_clk)…//主机接收
2、DSP端(从机):
MCBSP_PCR_CLKXP_FALLING, // Transmit clock polarity(CLKXP)Transmit data sampled on falling edge of CLKX(FALLING-1,RISING-0)
MCBSP_SPCR_CLKSTP_DEFAULT, // Clock stop(CLKSTP) mode 0(DEFAULT-00)
MCBSP_PCR_CLKRP_FALLING // Receive clock polarity(CLKRP)(FALLING-0,RISING-1)
这里有个疑问,我们做之前沟通是按照CLKSTP=11,CLKXP=1来做的,就是第四种模式,但是我当初的小伙伴配置的却是CLKISTP=00.我问过这个问题,她说是
后面有这么一句MCBSP_FSETSH(hMcbsp,SPCR,CLKSTP,DELAY);主要看这个,DELAY-11,所以最后还是对应的是第四种模式。
最后,关于您所说的”FPGA输出的时钟频率,需要在mcbsp的spec范围内,不能太快”这点,我设置的时钟是1M,算不得快,老师麻烦您再给看看哪里有问题,谢谢!
weizhi zhang:
回复 Chris Meng:
考虑到硬件问题,所以把FPGA板子和DSP板子都换了,还是没用。
昨晚上将几种模式又重新试了一遍,目前出现两种情况:
第一种就是:数据的低位不能正确接收,比如我发AA,DSP收到的是AB,我发A9,DSP收到A7之类。(这种情况居多。将帧头检测忽略不判断是否为AA后,直接进入接收8字节的函数后,就会出现下面所说的第二种情况)
第二种是:帧头正确接收后,卡在
void receive_send_1_byte(Uint8 head_out)//收帧头{ while (!MCBSP_rrdy(hMcbsp)); head_in=MCBSP_read(hMcbsp); while (!MCBSP_xrdy(hMcbsp)); MCBSP_write(hMcbsp,head_out); }
void receive_send_8_byte(Uint8 *data_out)//收8字节数据{ int i=0; for (i=0;i<8;i++) { while (!MCBSP_rrdy(hMcbsp)); //卡在这一步 data8_in[i]= MCBSP_read(hMcbsp); while (!MCBSP_xrdy(hMcbsp)); MCBSP_write(hMcbsp,data8_out[i]); cnt++; } }
Chris Meng:
回复 weizhi zhang:
weizhi zhang
原来的DSP代码不能正确接收,也不能正确发送。
FPGA代码改动过其中一个module,但是不涉及SPI协议这个模块,是整个系统中的一个模块。
之前不是正常工作的么?能否找找现在不能工作的原因?
是否有测量过SPI信号,是否有毛刺,干扰?降低spi clk的频率能否有改善?
weizhi zhang:
回复 Chris Meng:
去年8月份确实可以正常工作,在这之后发生的事就是:
1、优化了一下FPGA其中一个模块
2、FPGA的一个管脚坏了,重新配置了一个
用逻辑分析仪测过SPI信号,没有问题,而CLK频率我查了看2812的MCBSP好像最高可以达到28M,1M算是非常低的速度了,再低的话数据处理跟不上
weizhi zhang:
回复 Chris Meng:
您好,
我这几天调试的结果发现规律就是:DSP端在读入第一个字节后,就不能继续执行下去了,比如:
void receive_send_1_byte(Uint8 head_out)//收发一个字节,并判断是否是期望的帧头,如果是则进入下面的收发8字节的函数,否则就继续判断{ while (!MCBSP_rrdy(hMcbsp)); head_in=MCBSP_read(hMcbsp); while (!MCBSP_xrdy(hMcbsp)); MCBSP_write(hMcbsp,head_out);
}
void receive_send_8_byte(Uint8 *data_out)//收发8个字节{
for (i=0;i<8;i++) { while (!MCBSP_rrdy(hMcbsp)); data8_in[i]= MCBSP_read(hMcbsp); while (!MCBSP_xrdy(hMcbsp)); MCBSP_write(hMcbsp,data8_out[i]); }
}
假如void receive_send_1_byte判断通过,那么在进入收发8字节 的函数后,会卡在while (!MCBSP_rrdy(hMcbsp)); 这里,
假如void receive_send_1_byte判断未通过,那么则继续停留在void receive_send_1_byte函数中,这时候仍然会卡在while (!MCBSP_rrdy(hMcbsp));
总结就是,无论如何都会卡在第二个字节的接收这一步。复位之后的第一个字节无论对错都能正确收到,但是到第二个字节的时候就会一直卡在
while (!MCBSP_rrdy(hMcbsp)); 这里。这是什么原因,请您指教,谢谢!