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.

C6747的McAsp与DA电路的连接问题



在C6747核心板的基础上,自己设计了一块板子,主要完成对音频信号的采样及输出。DA芯片是单通道16位,跟DSP的引脚连接如下:

AFSX-----DA芯片的SYNC引脚;ACLKX-------DA芯片的sclk引脚;AXR0[0]----DA的Din

问题:对McAsp进行配置后,用示波器测试不到ACLKX的输出信号,并且仅发送2次数据后就发生了underrun,因为在这方面是初学者,现在是黔驴技穷了,请大家帮忙指教。非常感谢。

/***************************************
* 初始化McAsp0 ,此时仅测试发送*
**************************************/
void mcaspinit(void)
{
/********step1:复位*************************/
McAsp_GBLCTL = 0; //全局控制寄存器,复位
McAsp_RGBLCTL = 0; //接收全局控制寄存器,复位收
McAsp_XGBLCTL = 0; //接收全局控制寄存器,复位发
//McAsp_PWRDEMU = 1; //power down 和emulation管理寄存器,自由运行
/******step2:配置其他寄存器******************/
//接收寄存器配置
McAsp_RMASK =0xFFFFFFFF; //接收到的数据直接给CPU或DMA,不填充
McAsp_RFMT =0 //接收数据的格式,16位数据(0x80b8)
| (0x0<<16) //0延时
| (1 <<15) //先接收MSB
| (0x0<<13) //pad extra bits with 0
| (0x0<<8) //pad with bite 0 value
| (0xB<<4) //接收slot的长度为24位
| (1 <<3) //读取的XRBUF源于外围引脚接口,忽略DMA
| (0 <<0); //不进行向右旋转
McAsp_AFSRCTL=0 //帧同步控制寄存器,
| (0x3<<7) //2个时隙TDM模式,
| (1<<4) //接收帧长一个字,
| (1<<1) //内部产生接收帧同步信号,
| (1<<0); //AFSR的下降沿代表一个帧的开始
McAsp_ACLKRCTL=0x00000024; //接收时钟控制寄存器,下降沿接收,内部接收时钟源
//来自ACLKR引脚,AHCLKR/5=ACLKR
McAsp_AHCLKRCTL=0x00008000;//AHCLK来自内部,不反转,AUXCLK/1=AHCLK=24M;
McAsp_RTDM =0x00000004;//在第2个时隙接收数据,第一个时隙不用
McAsp_RINTCTL =0x00000000;//接收中断控制寄存器,禁止中断
McAsp_RCLKCHK =0x00FF000F;//接收时钟确认控制寄存器,不用
//开始配置发送寄存器
McAsp_XMASK =0xffffffff; //发送的数据直接来自CPU或DMA,不填充
McAsp_XFMT =0 //发送数据的格式,24位数据
| (0x0<<16) //0延时
| (1 <<15) //先接收MSB
| (0x0<<13) //pad extra bits with 0
| (0x0<<8) //pad with bite 0 value
| (0xB<<4) //发送slot的长度为24位
| (1 <<3) //读取的RRBUF源于外围引脚接口,忽略DMA
| (0 <<0); //不进行向右旋转
McAsp_AFSXCTL=0 //帧同步控制寄存器,
| (0x3<<7) //2个时隙TDM模式,
| (1<<4) //接收帧长一个字,
| (1<<1) //内部产生发送帧同步信号,
| (1<<0); //AFSX的下降沿代表一个帧的开始
McAsp_ACLKXCTL=0x000000E0; //发送时钟控制寄存器,下降沿接收,不同步,内部发送时钟源
//来自ACLKX引脚,AHCLKX/1=ACLKX
McAsp_AHCLKXCTL=0x00008000;//AHCLK来自内部,AUXCLK/1=AHCLKX=24M;
McAsp_XTDM =0x00000004;//在第2个时隙发送数据,第一个时隙不用
McAsp_XINTCTL =0x00000000;//发送中断控制寄存器,禁止中断
McAsp_XCLKCHK =0x00FF000F;//发送时钟确认控制寄存器,不用
//开始配置串行器寄存器
McAsp_SRCTL1 =0x0001; //McAsp0.AXR0[1]-->DIN,当串并转换器没有工作时
//AXR0引脚为3-state状态,串并转换器是发送方
McAsp_SRCTL0 =0x0002; //McAsp0.AXR0[0]<--DOUT,当串并转换器没有工作时,
//AXR0引脚为3-state状态,串并转换器是接收方
//McAsp_SRCTL2 =0x0002;//McAsp0.AXR0[2]<--DOUT,串行引脚高电平有用,
//串行线是接收方
//配置全局寄存器
McAsp_PFUNC =0; //所有相关引脚都用作McAsp,而不是GPIO
McAsp_PDIR =0xB4000002;//引脚方向寄存器,AFSR/X、ACLKR/X、AXR0[1]输出,
McAsp_DITCTL =0x00000000;//DIT模式控制寄存器,不使用DIT模式
McAsp_DLBCTL =0x00000000;//数字回送控制寄存器,loopback禁止
McAsp_AMUTE =0x00000000;//静音控制寄存器
//对于DIT 模式的操作,要启动寄存器DITCSRA[n]、 DITCSRB[n]、
//DITUDRA[n]和 DITUDRB[n],此程序并不使用DIT模式,故略
/**********step3:启动高频时钟AHCLKX或AHCLKR************/
McAsp_XGBLCTL |=GBLCTL_XHCLKRST_ON; //将GBLCTL的XHCLKRST置1
//使内部的高频时钟分频器退出复位状态
while((McAsp_XGBLCTL&GBLCTL_XHCLKRST_ON)!=
GBLCTL_XHCLKRST_ON);
//McAsp_RGBLCTL |=GBLCTL_RHCLKRST_ON; //将GBLCTL的RHCLKRST置1
//使内部的高频时钟分频器退出复位状态
//while((McAsp_RGBLCTL&GBLCTL_RHCLKRST_ON)!=
// GBLCTL_RHCLKRST_ON);
/*********step4:启动串行时钟ACLKX或ACLKR***********/
McAsp_XGBLCTL |=GBLCTL_XCLKRST_ON; //将GBLCTL的XCLKRST置1
//使内部的时钟分频器退出复位状态
while((McAsp_XGBLCTL&GBLCTL_XCLKRST_ON)!=
GBLCTL_XCLKRST_ON);
//McAsp_RGBLCTL |=GBLCTL_RCLKRST_ON; //将GBLCTL的RCLKRST置1
//使内部的时钟分频器退出复位状态
//while((McAsp_RGBLCTL&GBLCTL_RCLKRST_ON)!=
// GBLCTL_RCLKRST_ON);
/*********step5: 启动数据获取********/
//设置接口与DSP之间的数据传输方式,此时选用CPU
//直接进行数据读取,故不作设置.若采用EDMA或CPU
//中断来传递数据,则要启动EDMA或使能发送/接收中断
//...

/********step6:启动串并转换器************/
McAsp_XSTAT=0xFFFF; //清除发送状态寄存器
McAsp_RSTAT=0xFFFF; //清除接收状态寄存器

McAsp_XGBLCTL |=GBLCTL_XSRCLR_ON; //将GBLCTL中XSRCTL置1
//使串并转换器退出复位
while((McAsp_XGBLCTL&GBLCTL_XSRCLR_ON)!=
GBLCTL_XSRCLR_ON);
//McAsp_RGBLCTL |=GBLCTL_RSRCLR_ON; //将GBLCTL中XSRCTL置1
//使串并转换器退出复位
//while((McAsp_RGBLCTL&GBLCTL_RSRCLR_ON)!=
// GBLCTL_RSRCLR_ON);
/********step7:确保所有的发送缓冲器在工作 ************/
McAsp_RBUF0=0;
McAsp_XBUF1=0;
// McAsp_RBUF1=0;

/********step8:将状态机退出复位状态*************/
McAsp_XGBLCTL |=GBLCTL_XSMRST_ON; //将GBLCTL的XSMRST置1
//使状态机退出复位状态
while((McAsp_XGBLCTL&GBLCTL_XSMRST_ON)!=
GBLCTL_XSMRST_ON);
// McAsp_RGBLCTL |=GBLCTL_RSMRST_ON; //将GBLCTL的RSMRST置1
//使状态机退出复位状态
//while((McAsp_RGBLCTL&GBLCTL_RSMRST_ON)!=
// GBLCTL_RSMRST_ON);
/********step9:将帧同步发生器退出复位状态*********/
McAsp_XGBLCTL |=GBLCTL_XFRST_ON; //将GBLCTL的RFRST置1
//使帧同步发生器退出复位状态
while((McAsp_XGBLCTL&GBLCTL_XFRST_ON)!=
GBLCTL_XFRST_ON);
//McAsp_RGBLCTL |=GBLCTL_RFRST_ON; //将GBLCTL的RFRST置1
//使帧同步发生器退出复位状态
//while((McAsp_RGBLCTL&GBLCTL_RFRST_ON)!=
// GBLCTL_RFRST_ON);

//主函数

int main(void)
{

Int16 data_buffer[512]={0};
Int16 index=0;
/* 初始化6747核 */
C6747_init( );

while(index<256)
{
data_buffer[index]=index+1;
while(!(McAsp_SRCTL1 & 0x10)); //XBUF为空,可以写入数据
McAsp_XBUF1=data_buffer[index];
printf("xbuf is %d\n",McAsp_XBUF1);

index = index+1;
}
/*Close McAsp*/
McAsp_SRCTL0=0;
McAsp_SRCTL1=0;
McAsp_GBLCTL=0;
return 0;
}

  • xifei Lin 说:

    while(index<256)
    {
    data_buffer[index]=index+1;
    while(!(McAsp_SRCTL1 & 0x10)); //XBUF为空,可以写入数据
    McAsp_XBUF1=data_buffer[index];
    printf("xbuf is %d\n",McAsp_XBUF1);

    index = index+1;
    }

    不要在这种对时间敏感的地址随便加printf,这个操作很耗时的。

    还有即使想知道发送了什么数,也不要去读发送数据寄存器,读原始数据就好了。 

  • 谢谢Tony Tang大神的指正,我会注意的。还想请教下,为什么我的ACLKX信号明明已经设置为输出,却仍旧在引脚上测不到信号?

  • http://support.spectrumdigital.com/boards/evmomapl137/revg/

    上面链接是L137, c6747 EVM板的网页,下载其测试代码对比一下吧。http://support.spectrumdigital.com/boards/evmomapl137/revg/files/revg_EVMOMAPL137_BSL.zip

    你也提到可以发送出个数据,那么在这2个数据期间也是应该有时钟的啊。

  • 引脚上一直都测不到时钟,对比了测试代码之后,并没有发现程序有什么问题。程序运行时,XSTAT显示存在发送帧状态错误和发送tdm时间片错误。请问这些错误是如何引起的?是否有相关资料?