主题: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;
返回;
}

