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.

[参考译文] TMS320F2.8062万:McBSP作为具有DMA的SPI从属设备,可传输一位移位的数据

Guru**** 2538955 points
Other Parts Discussed in Thread: CONTROLSUITE

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/656475/tms320f28062-mcbsp-as-spi-slave-with-dma-transmits-data-shifted-by-one-bit

部件号:TMS320F2.8062万
主题:controlSUITE中讨论的其他部件

你(们)好  我在SPI模式下使用DMA时遇到问题。  接收端工作正常,但输出数据传输延迟一位。  例如,当我尝试传输0x0022 0x0044 0x0088...的测试数据时,它在电线上显示为0x0011 0x0022 0x0044...

请参阅下面的相关代码。  我已确保XCR2的XDATDLY字段设置为0,因此芯片选择(又称帧同步)后不会有任何延迟。  我还玩过时钟信号(McbspaRegs.pcr.bit.CLKXP)的极性 ,但没有效果。  将停止模式(McbspaRegs.SPCR1.bit.CLKSTP)从2更改为3会中断接收端,因此我很确定我的答案是正确的。

对我做错了什么有什么想法?  此代码的大部分是从以下位置的示例代码复制/修改的: C:\ti\controlSUITE\DEVICE_SUPPORT\f2806x\v151\F2806X_Examples_ccsv5,2806,McBSP_SPI_loopback或McBSP_loop_DMA。

谢谢!

Alex

void main (void)
{
//此处显示不相关的系统初始化

InitMcbsp();
EnableInterrupts();

用于(;;){
	//未详细显示,处理高级协议
		,//以及在触发中断
		//后重新启用DMA通道
HandleSpiCommunications();
}
}

作废InitMcbsp(void){

initDMA();//
	
	启动两个DMA通道
StartSpiRxDmaChannel();
	StartSpiTxDmaChannel();
	
initMcbspa();
}

void initDMA(void)
{
EALLOW;
DmaRegs.DMACTRL.bit.hardreset =1;
__ASM(" NOP"; //执行硬重置

DmaRegs.PRIORITYCTRL1.bit.CH1PRIORITY = 0后需要nop;// CH 1与其他通道具有相同的优先级(现在)

// Channel 2,McBSPA Transmit
DmaRegs.CH2.mode.bit.CHINTE = 0; //配置通道
DmaRegs.CH2.burst_size.all时禁用中断 = 0; // 1个16位字/burst
DmaRegs.CH2.SRC_burst_step = 0; //使用1个单词/burst
DmaRegs.CH2.dst_burst_step时无效 = 0; //不要更改目标地址;始终写入SPI TX寄存器
DmaRegs.CH2.transfer_size = 7; //中断每个帧(8个突发/传输)
DmaRegs.CH2.SRC_TRANSFER_STEP = 1; //在连字符
DmaRegs.CH2.dst_transfer_step中的每个单词后移至缓冲区中的下一个单词 = 0; //不要移动目标地址
DmaRegs.CH2.SRC_ADDR_shadow =(UINT32) SpiTxData[0]; //起始地址=缓冲
区DmaRegs.CH2.SRC_beG_ADDR_shadow =(UINT32) SpiTxData[0]; //除非使用Wrap函数
DmaRegs.CH2.DST_ADDR_shadow,否则不需要 =(UINT32)&McbspaRegs.DXR1.all; //起始地址= McBSPA DXR
DmaRegs.CH2.DST_Beg_ADDR_shadow =(UINT32)&McbspaRegs.DXR1.all;//除非使用Wrap函数
DmaRegs.CH2.control.bit.PERINTCLR = 1,否则不需要; //清除外设中断事件标志

DmaRegs.CH2.control.bit.ERRCLR = 1; //清除同步错误标记
DmaRegs.CH2.dst_wrap_size = 0xFFFFFF;//置为最大值-不希望目标包装
DmaRegs.CH2.SRC_WLAW_SIZE = 0xFFFFFF;//置为最大值-不希望源包装

DmaRegs.CH2.control.bit.PERINTCLR = 1; //清除任何虚假中断标志
DmaRegs.CH2.mode.bit.OneShot = 0; //每次传输运行1个脉冲串(寄存器命名不当)
DmaRegs.CH2.mode.bit.CHINTE = 1; //启用通道中断
DmaRegs.CH2.mode.bit.OVRINTE = 0; //禁用溢出中断生成
DmaRegs.CH2.mode.bit.continuous = 0; //当transfer_count达到0时,停止DMA并将RUNSTS清除为0
DmaRegs.CH2.mode.bit.CHINTMODE = 1; //传输结束时中断
DmaRegs.CH2.mode.bit.PERINTE = 1; //启用外设中断事件
DmaRegs.CH2.mode.bit.PERINTSEL = DMA_MXEVTA;//外设中断选择= McBSP MXSYNCA
DmaRegs.CH2.control.bit.PERINTCLR = 1; //清除所有杂散中断标志

//通道3,McBSPA接收
DmaRegs.CH3.mode.bit.CHINTE = 0; //配置通道
DmaRegs.CH3.burst_size.all时禁用中断 = 0; // 1个16位字/burst
DmaRegs.CH3.SRC_burst_step = 0; //使用1个单词/burst
DmaRegs.CH3.dst_burst_step时无效 = 0; //使用1个单词/连字符
DmaRegs.CH3.transfer_size时无效 = 7; //每8次突发中断/传输
DmaRegs.CH3.SRC_TRANSFER_STEP = 0; //不要移动源地址
DmaRegs.CH3.DST_TRANSFER_STEP = 1; //在连字符
DmaRegs.CH3.SRC_ADDR_shadow中的每个单词后移到缓冲区中的下一个单词 =(UINT32)&McbspaRegs.DR1.all;//起始地址= McBSPA DRR
DmaRegs.CH3.SRC_Beg_ADDR_shadow =(UINT32)&McbspaRegs.DR1.all;//除非使用Wrap函数
DmaRegs.CH3.DST_ADDR_shadow,否则不需要 =(UINT32) SpiRxData[0]; //起始地址=接收缓冲区(用于McBSPA-A)
DmaRegs.CH3.DST_beG_ADDR_shadow =(UINT32) SpiRxData[0]; //不需要,除非使用Wrap函数
DmaRegs.CH3.control.bit.PERINTCLR =1; //清除外设中断事件标志

DmaRegs.CH3.control.bit.ERRCLR = 1; //清除同步错误标记
DmaRegs.CH3.DST_WLAW_SIZE = 0xFFFF; //置为最大值-不希望目标包装
DmaRegs.CH3.SRC_Wrap大小 = 0xFFFF; //置为最大值-不希望源包DmaRegs.CH3.control.bit.PERINTCLR
= 1; //清除任何虚假中断标志
DmaRegs.CH3.mode.bit.OneShot = 0; //每次传输运行1个脉冲串(寄存器命名不当)
DmaRegs.CH3.mode.bit.CHINTE = 1; //启用通道中断
DmaRegs.CH3.mode.bit.OVRINTE = 0; //禁用溢出中断生成
DmaRegs.CH3.mode.bit.continuous = 0; //当transfer_count达到0时,停止DMA并将RUNSTS清除为0
DmaRegs.CH3.mode.bit.CHINTMODE = 1; //传输结束时中断
DmaRegs.CH3.mode.bit.PERINTE = 1; //启用外设中断事件
DmaRegs.CH3.mode.bit.PERINTSEL = DMA_MREVTA;//外设中断选择= McBSP MRSYNCA
DmaRegs.CH3.control.bit.PERINTCLR = 1; //清除任何寄生中断标志
EDIS;
}//

这三个值是选项
#define CLKSTP_OPT_VAL 2
#define TX_CLK_POLICATY_OPT_VAL 1
#define RX_CLK_POLICATY_OPT_VAL 1

//参考手册
#define CLKXM_REQ_VAL要求这些值 0
#define SCLKME_REQ_VAL 0
#define CLKSM_REQ_VAL 1
#define CLKGDV_REQ_VAL 1
#define FSXM_REQ_VAL 0
#define FSXP_REQ_VAL 1
#define XDATDLY_REQ_VAL 0#define
RDATDLY_REQ_VAL 0

void initMcbspa(void){


// McBBSP-A寄存器设置
McbspaRegs.SPR2.bit.frst = 0; //帧同步已禁用(将在初始化结束时启用)
McbspaRegs.SPCR2.bit.GRST = 0; //采样率发生器被禁用(将在初始化结束时启用)
McbspaRegs.SPR2.bit.XRST = 0; //暂挂复位(暂时;将在初始化结束时清除)
McbspaRegs.SPR2.bit.free = 0; //调试时不释放运行(我认为文档不清楚)
McbspaRegs.SPR2.bit.soft = 0; //在遇到断点时停止时钟(我认为文档不清楚)
McbspaRegs.SPR2.bit.XINTM = 0; //当XRDY (传输就绪)位变高时生成IRQ
McbspaRegs.SPCR2.bit.XSYNCERR = 0; //清除帧同步错误

McbspaRegs.SPCR1.bit.RRST = 0; //暂挂复位(暂时;将在初始化结束时清除)
McbspaRegs.SPCR1.bit.DLB =0; //数字回送模式已禁用
McbspaRegs.SPCR1.bit.RJUST = 0; //右对齐数据,零填充MSB
McbspaRegs.SPCR1.bit.CLKSTP = CLKSTP_OPT_VAL;//时钟停止模式,无时钟延迟
McbspaRegs.SPCR1.bit.DXENA = 0; //传输延迟启用器关闭
McbspaRegs.SPCR1.bit.RINTM = 0; //当RRDY (接收就绪)位变高时生成IRQ。
McbspaRegs.SPCR1.bit.RSYNCERR = 0; //清除帧同步错误

McbspaRegs.MFFINT.ALL = 0; //禁用所有中断

McbspaRegs.RCR2.all = 0; //单相帧
McbspaRegs.RCR2.bit.RFRLN2 = 0; //相位2长度(忽略,仅适用于帧的第二个相位)
McbspaRegs.RCR2.bit.RWDLEN2 = 2; // 16位字(忽略,仅适用于帧的第二阶段)
McbspaRegs.RCR2.bit.RCOMPAND = 0; //没有压扩,MSB先传输
McbspaRegs.RCR2.bit.RFIG =0; //如果出现帧错误,请在SPR1中设置XSYNCERR
McbspaRegs.RCR2.bit.RDATDLY = RDATDLY_REQ_VAL;// 0位数据延迟
McbspaRegs.RCR2.bit.RPHASE = 0; //单相帧

McbspaRegs.RCR1.all = 0;
McbspaRegs.RCR1.bit.RWDLEN1 = 2; // 16位字
McbspaRegs.RCR1.bit.RFRLEN1 = 7; //每帧8个字

McbspaRegs.XCR2.all = 0;
McbspaRegs.XCR2.bit.XFRLEN2 = 0; //相位2长度(忽略,仅适用于帧的第二个相位)
McbspaRegs.XCR2.bit.XWDLEN2 = 2; // 16位字(忽略,仅适用于帧的第二阶段)
McbspaRegs.XCR2.bit.XCOMPAND = 0; //没有压扩,MSB先传输
McbspaRegs.XCR2.bit.XConfig = 0; //如果出现帧错误,请在SPR1中设置XSYNCERR
McbspaRegs.XCR2.bit.XDATDLY = XDATDLY_REQ_VAL;// 0位数据延迟
McbspaRegs.XCR2.bit.XPhase = 0; //单相帧

McbspaRegs.XCR1.all = 0;
McbspaRegs.XCR1.bit.XWDLEN1 =2;// 16位字
McbspaRegs.XCR1.bit.XFRLEN1 = 7;//每个帧8个字

McbspaRegs.preg.all = 0;
McbspaRegs.pcr.bit.CLKXM = CLKXM_REQ_VAL; // McBSP是SPI从属设备
McbspaRegs.pcr.bit.CLKRM = 0; // MCLKR引脚为输入
McbspaRegs.pcr.bit.fsXM = FSXM_REQ_VAL; //帧同步源自TX引脚的外部源
McbspaRegs.pcr.bit.fsrm = 0; //帧同步源自RX引脚的外部源
McbspaRegs.pcr.bit.FSXP = FSXP_REQ_VAL; //传输帧同步处于活动低电平状态
McbspaRegs.pcr.bit.fSRP = 1; //接收帧同步处于活动低电平状态
McbspaRegs.pcr.bit.CLKXP = TX_CLK_POLICATY_OPT_VAL;//在CLK的上升沿采样传输数据
McbspaRegs.pcr.bit.CLKRP = RX_CLK_POLICATY_OPT_VAL;//接收数据在CLK的下降沿采样
McbspaRegs.pcr.bit.SCLKME = SCLKME_REQ_VAL; //从CPU派生的样本时钟,与外部主CLK同步(与CLKSM一起使用)

McbspaRegs.SRGR2.bit.GSYNC = 1; // CLKG已同步到外部时钟输入
McbspaRegs.SRGR2.bit.CLKSM = CLKSM_REQ_VAL;//从CPU派生的样本时钟与外部主CLK同步(与SCLKME一起使用)
McbspaRegs.SRGR2.bit.FSGM = 0; //忽略,因为PCR.FSXM =0
McbspaRegs.SRGR2.bit.FPER =(8*16)-1; //被忽略,因为GSYNC为1

McbspaRegs.SRGR1.bit.FWID = 0; //帧宽度= 1 CLKG周期
McbspaRegs.SRGR1.bit.CLKGDV = CLKGDV_REQ_VAL;// CLKG频率=1/2 LSPCLK频率

delay_loop(); //至少等待2个SRG时钟周期

McbspaRegs.SPCR2.bit.GRST = 1; //启用采样率生成器
clkg_delay_loop(); //至少等待2个CLKG周期

McbspaRegs.SPCR1.bit.RRST = 1; //从重置中释放RX
McbspaRegs.SPR2.bit.XRST = 1; //从复位中释放TX
McbspaRegs.SPCR1.bit.frst = 1; //从RESET释放帧同步
}__interrupt

void spiTxDmaIsr(void){

StopSpiTxDmaChannel(); //当TX缓冲区已满并且我们可以发送时,重新启用DMA

__ASM(" nop");
EALLOW; //需要在ISR内执行EALLOW!!!
PieCtrlRegs.PIEACK.ALL = PIEACK_group7; //要从此PIE组接收更多中断,请确认此中断
EDIS;

SpiTxBufferFull =0;

return;
}

__interrupt void spirxDmaIsr (void)
{
StopSpiRxDmaChannel(); //需要在处理消息后重新启用
__ASM(" nop");
EALLOW; //需要在ISR内执行EALLOW!!!
PieCtrlRegs.PIEACK.ALL = PIEACK_group7;//要接收来自此PIE组的更多中断,请确认此中断
EDIS;

SpiRxBufferFull =1;

返回;
}

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

    很遗憾听到您在使用McBSP时遇到一些问题。

    我对您的数据流感兴趣。 您是否可以尝试传输一些非连续数据? 这可能有助于验证传输未从传输缓冲区获得正确的数据。

    此外,您是否可以从McBSP中取出DMA并手动传输数据? 这可能有助于从图片中消除DMA。

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

    对于非连续数据,我假设您是指使用固定但"随机"的测试字符串,对吗? 如果我尝试发送0x95A6 0x5643 0x0000 ...,我实际上得到了0xCAD3 0x2B21 0x8000... 因此,_most位被右移一位,但第一位是损坏的或重复的。

    我来试试非DMA方法,我还没有尝试过。

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

    标记-

    我按照您的建议禁用了DMA,但我仍然遇到同样的问题。  我在初始化结束时添加了一行代码,内容为“McbspaRegs.DXR1.all = 0x66AA;”。  不会对DXR1执行其他写入操作,但我在输出中看到的数据是0x3355,重复的频率与主控制器提供时钟时的频率相同。  如果我在调试器中运行代码,我仍然在DXR1寄存器中看到0x66AA。

    我现在确信第一位是重复的,好像第一个时钟转换没有兑现。  有关示例,请参见以下图像。  写入DXR1的数据在第一个图像中为0x66AA,在第二个图像中为0xC963。

    -Alex

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Alex,
    因此,您可能需要再次确认时钟配置。 您当前的设置实际上不是有效的配置。 请参阅表15-15。 CLKSTP,CLKXP和CLKRP对SPRUH18中时钟方案的影响,以获取所有可能配置的列表。

    标记
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    谢谢,Mark。 我从表15到表17走了,这是一个限制性较小的地方。 这对我来说是愚蠢的,但不幸的是,这不是(唯一的)问题。 我刚刚再次确认,当我以CLKSTP = 10b,CLKXP = 1,CLKRP = 0运行时,我仍然有相同的问题。

    -Alex
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    嗯,我希望它会是这样的! 现在您已拥有正确的配置,您是否已确认这是与您的主配置匹配的配置? 从您分享的截获量来看,主控的时钟处于非活动状态,而且SIMO正在不断上升。 主样本将在哪个边缘上采样SOMI数据? 我认为是上升的边缘。

    我想你想要CLKSTP =3, CLKXP =0,CLKRP+=1。 这与图15-38相符。 它还与您共享的图像相匹配。

    谢谢!
    标记
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    解决了问题。 非常感谢,Mark,我真的很感激。 我本可以在要求帮助之前宣誓我尝试过,但我猜我错了。

    再次感谢,
    Alex
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我很高兴我们解决了这个问题! 不幸的是,McBSP是模块的野兽。 如果设置不正确,有许多配置位可能会影响行为。

    如果您有任何问题,请在将来立即创建新帖子!

    谢谢!
    标记