通过DSP向音频芯片TLV320AIC23B发送数据,从而实现声音的播放。DSP选型为TMS320DM642,DSP与AIC23B通过DM642的音频端口McASP进行连接。设计中使用1片AIC23B,设计的目的是通过McASP的AXR[0](设计中AXR[0]引脚配置为输出,发送数据)向AIC23B发送数据从而达到AIC23B输出报警声的目的。具体到实程序设计中就是查询XSTATE寄存器中的XDATA字段:若XDATA为1,向XBUF[0]发送新的数据;否则进行等待。
在调试的过程中发现在对McASP进行配置并第一次写入数据后,XDATA字段就一直为0(XSTAT的值一直为155H或15DH),使得后续数据不能写入。不知道哪位大神遇到过类似的情况,能告知问题的所在和解决方案。
最后附注一下:设计中的TLV320AIC23B工作在主模式下,位时钟和帧信号由AIC23B生成。在McASP配置前,利用I2C接口对AIC23B进行寄存器配置。通过示波器对位时钟和帧信号进行测试,显示AIC23B的配置是有效的。
Shine:
你的问题是第一次McASP能发送数据,后面就不能发送了?XSTAT一直为0?
yanbin Ren:
回复 Shine:
是的!McASP配置后只能写一次数据,XSTAT寄存器的之后XDATA字段一直为0,但是整个XSTAT的值为155H或者15DH。而且我发现McASP口利用MCASP_OPEN()打开后,XSTAT寄存器的值为10CH(根据我的理解,打开后该寄存器难道不应该为0000H吗?)。
Shine:
回复 yanbin Ren:
XUNDRN置位了:underrun,表示没有及时给数,同时XDATA又不置1,是不是使能了不只一条数据线,但只送了一次数据?
yanbin Ren:
回复 Shine:
没有啊!我在MCASP_ConfigSrctl结构体中只激活了作为数据发送的SRCTL0和作为数据接收的SRCTL0。
yanbin Ren:
回复 yanbin Ren:
上面说错了,是作为数据发送的SRCTL0和作为数据接收的SRCTL1。
Shine:
回复 yanbin Ren:
检查一下是否按照下面McASP user guide上的步骤配置的。3.1.1 Transmit/Receive Section Initializationhttp://www.ti.com/lit/ug/spru041j/spru041j.pdf
yanbin Ren:
回复 Shine:
给你看一下我的配置过程:
MCASP_ConfigGbl mcaspCfgDataGbl = { 0x00000000, // PFUNC – All pins as McASP ,所有的管脚均为McAPS功能 0x00000001, // PDIR – 0,2,4,6 transmit,为output;1,3,5,7 receive,为input 0x00000000, // DITCTL – DIT mode disable 0x00000000, // DLBCTL – Loopback disabled 0x00000000 // AMUTE – Never drive AMUTE };
MCASP_ConfigRcv mcaspCfgDataRcv = { 0xffffffff, // RMASK – Use all 32 bits,左声道与右声道各16位 0x00018078, // RFMT – 1bit 延时,高位在前,0填充,slot为16位,配置总线读数据 0x00000200, // AFSRCTL – TDM模式,4 slots,帧同步高电平为1bit,外部帧同步信号输入,帧信号上升沿表明帧开始 0x00000080, // ACLKRCTL – 接收器在串行时钟上升沿采集数据,外部输入接收时钟 0x00000000, // AHCLKRCTL – 外部高频时钟 0x00000003, // RTDM – slot0,1 active 0x00000000, // RINTCTL – interrupts disable 0x00000000 // RCLKCHK – Not used };
MCASP_ConfigXmt mcaspCfgDataXmt = { 0xffffffff, // XMASK – Use all 32 bits,左声道与右声道各16位 0x00018078, // XFMT – 1bit 延时,高位在前,0填充,slot为16位,配置总线写数据 0x00000200, // AFSXCTL – TDM模式,4 slots,帧同步高电平为1bit,外部帧同步信号输入,帧信号上升沿表明帧开始 0x000000c0, // ACLKXCTL – 发送器在串行时钟的下降沿发送数据,发送与接收异步,外部输入发送时钟 0x00000000, // AHCLKXCTL – 外部高频时钟 0x00000003, // XTDM – slot0,1 active 0x00000000, // XINTCTL – interrupts disable 0x00000000 // XCLKCHK – Not used };
MCASP_ConfigSrctl mcaspCfgDataSrctl = { 0x0000000d, // SRCTL0 – transmit, active high 0x0000000e, // SRCTL1 – receive, active high 0x00000000, // SRCTL2 – transmit 0x00000000, // SRCTL3 – receive 0x00000000, // SRCTL4 – transmit 0x00000000, // SRCTL5 – receive 0x00000000, // SRCTL6 – transmit 0x00000000 // SRCTL7 – receive};
MCASP_Handle VMD642_AIC23_openCodec(){ Uint32 regval=0xffff; MCASP_Handle hMcasp; //打开McASP端口 hMcasp = MCASP_open(MCASP_DEV0, MCASP_OPEN_RESET); //下面开始按照McASP端口初始化步骤配置McASP //step1:通过设置GBLCTL=0使McASP复位到默认值 MCASP_reset(hMcasp); //step2:配置除了GBLCTL外的McASP寄存器// MCASP_config(hMcasp,&mcaspCfgData); MCASP_configRcv(hMcasp, &mcaspCfgDataRcv); MCASP_configXmt(hMcasp, &mcaspCfgDataXmt); MCASP_configSrctl(hMcasp, &mcaspCfgDataSrctl); MCASP_configGbl(hMcasp, &mcaspCfgDataGbl);
//step3:启动相应的高频串行时钟AHCLKX和/或AHCLKR并进行回读检查 //不管使用外部还是内部产生高频时钟,该步都是必须的 MCASP_enableHclk(hMcasp,MCASP_XMTRCV); while(!MCASP_FGETH(hMcasp, GBLCTL, XHCLKRST)); while(!MCASP_FGETH(hMcasp, GBLCTL, RHCLKRST)); //step4:启动相应的串行时钟ACLKX和/或ACLKR并进行回读检查 //如果使用外部时钟,该步可以忽略 MCASP_enableClk(hMcasp,MCASP_XMTRCV); while(!MCASP_FGETH(hMcasp, GBLCTL, XCLKRST)); while(!MCASP_FGETH(hMcasp, GBLCTL, RCLKRST)); //step5:根据需要设置数据获取方式 //本程序使用CPU查询方式,该步可以忽略;其他方式需要进行设置
//step6:激活串行器 //a.开始前,通过向XSTAT和RSTAT寄存器写FFFFH达到清零发送和接收状态寄存器的目的 /********************************* MCASP_RSETH(hMcasp,XSTAT,0xFFFF); MCASP_RSETH(hMcasp,RSTAT,0xFFFF); **********************************/ *((unsigned long *)(0x01B4C0C0)) =regval; *((unsigned long *)(0x01B4C080)) =regval; //MCASP_FSETH(hMcasp ,XSTAT ,XERR ,1); //MCASP_FSETH(hMcasp ,XSTAT ,XDMAERR ,1); //MCASP_FSETH(hMcasp ,XSTAT ,XSTAFRM ,1); //MCASP_FSETH(hMcasp ,XSTAT ,XDATA ,1); //MCASP_FSETH(hMcasp ,XSTAT ,XLAST ,1); //MCASP_FSETH(hMcasp ,XSTAT ,XTDMSLOT ,1); //MCASP_FSETH(hMcasp ,XSTAT ,XCKFAIL ,1); //MCASP_FSETH(hMcasp ,XSTAT ,XSYNCERR ,1); //MCASP_FSETH(hMcasp ,XSTAT ,XUNDRN ,1); //b.激活相应的发送和接收串行器并进行回读检查 MCASP_enableSers(hMcasp, MCASP_XMTRCV); while(!MCASP_FGETH(hMcasp, GBLCTL, XSRCLR)); while(!MCASP_FGETH(hMcasp, GBLCTL, RSRCLR));
//step7:验证发送串行在工作状态 //发送串行器一旦激活,XSTAT寄存器中的XDATA字段被置位,表明串行缓冲区为空,等待数据的写入 while(!MCASP_FGETH(hMcasp, XSTAT, XDATA)); //如果使用CPU查询方式,XBUF应当在这步写入数据 //MCASP_RSETH(hMcasp, XBUF0, 5000);
//step8:激活状态机并回读检查 MCASP_enableSm(hMcasp,MCASP_XMTRCV); while(!MCASP_FGETH(hMcasp, GBLCTL, XSMRST)); while(!MCASP_FGETH(hMcasp, GBLCTL, RSMRST));
//step9:激活帧同步产生器并回读检查 //即使帧同步信号由外部输入,该步也是必须的 MCASP_enableFsync(hMcasp,MCASP_XMTRCV); while(!MCASP_FGETH(hMcasp, GBLCTL, XFRST)); while(!MCASP_FGETH(hMcasp, GBLCTL, RFRST)); //返回McASP模块句柄 return hMcasp;}