老莫

ZedBoard板体验(四)——无奈的音频……

0
阅读(31671)

 继上一篇OLED点亮已经有一段时间了,一直在调着音频接口,当然由于最近各种事情各种忙,所以调试的时间也是有限的,又由于对软件的不熟悉出现了一些问题,同时也得到了一些经验。下面与大家分享分享,在问题上也一起探讨探讨。

1、硬件配置框图

         基于测评的目标是实现音频信号分析仪,在完成了OLED的显示后,这次主要目的是实现音频的控制和数据读写。

表1中给出了ADAU1761 codec具体的接口信号,其中分为三种连接信号,串行数据I2S接口(4线)、系统控制I2C(2线)或者SPI(4线)接口和一个主时钟输入MCLK。

表1 接口信号功能描述

Signal Name

Description

Zed pin

ADAU1761 pin

Type

AC-MCLK

Master Clock Input

AB2

MCKI

D_IN

AC-GPIO2

Digital Audio Bit Clock Input/Output

AA6

BCLK/GPIO2

D_IO

AC-GPIO3

Digital Audio Left-Right Clock Input/Output

Y6

LRCLK/GPIO3

D_IO

AC-GPIO0

DAC Serial Input Data/General Purpose Input and Output

Y8

DAC_SDATA/GPIO0

D_IO

AC-GPIO1

ADC Serial Output Data/General Purpose Input and Output

AA7

ADC_SDATA/GPIO1

D_IO

AC-ADR0

I2C Address Bit 0/SPI Latch Signal

AB1

ADDR0/CDATA

D_IN

AC-ADR1

I2C Address Bit 1/SPI Data Input

Y5

ADDR1/CLATCH

D_IN

AC-SDA

I2C Data/SPI Data Output

AB5

SDA/COUT

D_IO

AC-SCK

I2C Clock/SPI Clock.

AB4

SCL/CCLK

D_IN

硬件配置框图如下:

由上图可以看出,IIC控制总线由PS的I2C接口通过EMIO接出连接到ADAU1761,MCLK时钟信号由PL中的clock Generator生成,其余接口线均有PL中的GPIO实现。

就在硬件配置的时候出现了一个严重问题,就是在加行clock generator后综合时,总是报这个错:

各种纠结呀,是什么问题呢,因为是加上clock generator后才报的,所以问题肯定是出在这个地方,我就各种修改,先是核对了它的输入时钟100MHz跟ps_clk0一致没有问题。有检查了输入输出的连接,什么复位等信号都OK,于是凌乱了,到底什么问题呢?后来发现我设置的输出作为MCLK为12.228MHz,所以输入12228000,但是我改为12000000后没有问题了。Why?难道不识别MHz一下的!!

在这里先解释下为什么输出为12.228MHz,有ADAU1761内部寄存器R0(0x4000)设置为default模式,本着尽量简单的运用原则,关闭了PLL,所以就有了MCLK=256×fS  当然在default模式下 fS为48K。

但是出现了这样的问题,只能输入12MHz了,没事输入12MHz我就启用PLL嘛,根据下面表格配置,同样OK啦

  

2、软件驱动

         配好了硬件,bitstream也生成了,那就开始写应用驱动了。哎,个人的弱项表现得凌厉精致啊。在各种资料的搜索整理后,开始动手了。当然最开始的必然是对于ADAU1761的一个初始化,根据数据手册给出的初始化步骤:

首先初始化时钟和PLL:

     iic_write (IicPs, ZC702_IIC_WRITE_ADDR,ADAU_CLKCTRL,(CLKCTRL_SRC_PLL | CLKCTRL_FRQ_1024 | CLKCTRL_DISABLE));     //设置MCLK和PLL

typedef struct {

     u16 Reg;

     u8 Data;

     u8 Init;

} Zed_I2C_CONFIG;

Zed_I2C_CONFIG PLL_Config[6] =

{

{0x4002, 0x00, 0x00},

    {0x4003, 0x00, 0x7D},

    {0x4004, 0x00, 0x00},

    {0x4005, 0x00, 0x0C},

    {0x4006, 0x00, 0x21},

{0x4007, 0x00, 0x01},

}

for ( i = 0; i < 6; i++ ) //配置PLL

{

printf("ready to write register %d\n\r", i);

iic_write(IicPs, ZC702_IIC_WRITE_ADDR, PLL_Config[i].Reg, PLL_Config[i].Init);

printf("finish to write register %d\n\r", i);

}

Delay_ms(4); //延迟4ms,等待PLL锁定

 

下面就是对于寄存器的配置:

/*

 * Default Mode

 * Analog microphones, ADC capture/DAC playback, dsp core disabled

*/

static struct Zed_I2C_CONFIG adau1761_mode0[MODE_REGISTER_COUNT] = {

     /* mute outputs */

     {ADAU_PLBHPVL, 0x00, 0x03},

     {ADAU_PLBHPVR, 0x00, 0x03},

     {ADAU_PLBLOVL, 0x00, 0x02},

     {ADAU_PLBLOVR, 0x00, 0x02},

     {ADAU_PLBMNOC, 0x00, 0xE5},

     { ADAU_INP_ROT, 0x00, 0x01},

     { ADAU_OUT_ROT, 0x00, 0x01},

     {ADAU_CLK_EN0, 0x00, 0x5F},

     {ADAU_CLK_EN1, 0x00, 0x01},

     /*analog mic*/

     {ADAU_RECVLCL, 0x00, 0x82},

     {ADAU_RECVLCR, 0x00, 0x82},

     {ADAU_MICCTRL, 0x00, 0x00},

};

         这些都是要进行配置的寄存器,都是通过I2C进行输入。写的I2C写入函数如下:

//iic写函数

//IicPs:iic接口指针

//Address:接在iic上的slave设备地址

//Register:slave中寄存器地址

//Data:写入寄存器中的值

static int iic_write( XIicPs *IicPs, u16 Address, u16 Register, u8 Data )

{

     u8 WriteBuffer[3];

     int Status;

     /*

      * A temporary write buffer must be used which contains both the address

      * and the data to be written, put the address in first

      */

     WriteBuffer[0] = Register>>8;

     WriteBuffer[1] = Register;

     WriteBuffer[2] = Data;

       printf("the WriteBuffer %d\n\r", WriteBuffer[0]);

       printf("the WriteBuffer %d\n\r", WriteBuffer[1]);

       printf("the WriteBuffer %d\n\r", WriteBuffer[2]);

     /*

      * Wait until bus is idle to start another transfer.

      */

     while (XIicPs_BusIsBusy(IicPs)) {

         /* NOP */

     }

     /*

      * Send the buffer using the IIC and check for errors.

      */

     print("IIC is not busy\n\r");

     printf("Device is ready %d\n\r", IicPs->IsReady);

     Status = XIicPs_MasterSendPolled(IicPs, WriteBuffer, 3, Address);

     if (Status != XST_SUCCESS) {

         print("XIicPs_MasterSendPolled error!\n\r");

         return XST_FAILURE;

     }

     else          print("XIicPs_MasterSendPolled ok!\n\r");

     return XST_SUCCESS;

}

         此处可以看出主要写函数就是XIicPs_MasterSendPolled(IicPs, WriteBuffer, 3, Address),问题也在这个地方,下板子后的打印信息就一直卡在这里:

         各种检查,得到的答案就是,这条语句就没有执行。这里面的四个参数都是严格按照库函数intXIicPs_MasterSendPolled(XIicPs*InstancePtr, u8*MsgPtr,

        intByteCount, u16SlaveAddr)的格式来定义的,为什么会出现这样的问题呢?还在继续排查问题中。

         在此先写出这篇文章,一来算是调试文档日志,二来提出问题和经验给大家一起分享和探讨。毕竟测评就是一个排除问题的过程。