wm8960驱动:裸机代码研读

网上已经有基本的wm8960驱动的demo。可以播放特定频率的wav文件。这个程序很具有参考性。
我们知道,初始化wm8960,需要大概的步骤如下:
1.初始化I2C总线,通过I2C接口给wm8960下配置命令。
2.将声音文件加载到memory中
3.初始化I2S,并把内存中的数据通过I2S总线送给wm8960,从而wm8960通过解码播放出声音
我们大概来看一下,这个代码的实现过程:

void main(void)
{
    printf("Audio Testrn");

    int offset = 0x2E;                      // 音频数据开始的地方
    short * p = (short *)0x22000000;        // 音频文件应该位于的位置

    iic_init();                             // 初始化i2c

    wm8960_init();                          // 初始化wm8960

    iis_init();                             // 初始化iis

    // 循环播放音频文件
    while (1)
    {
        // polling  Primary Tx FIFO0 full status indication. 
        while((IISCON & (1<<8)) == (1<<8));

        IISTXD = *(p+offset);               // 每次发送2byte

        offset++;
        if (offset > (WAV_SIZE2-0x2e) /2)       // 有多少个2byte = (文件大小-偏移)/2
            offset = 0x2E;
    }
}

其中 wm8960_init()用来初始化wm8960.具体代码:


void wm8960_init(void)
{
    // bit[7:1]: 0x1a
    // bit[0]:0: write
#define WM8960_DEVICE_ADDR      0x34

    // 重置
    iic_write(WM8960_DEVICE_ADDR, 0xf, 0x0);

    // 设置电源
    iic_write(WM8960_DEVICE_ADDR, 0x19, 1<<8 | 1<<7 | 1<<6);
    iic_write(WM8960_DEVICE_ADDR, 0x1a, 1<<8 | 1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<3);
    iic_write(WM8960_DEVICE_ADDR, 0x2F, 1<<3 | 1<<2);


    // 设置时钟
    //Mclk--div1-->SYSCLK---DIV256--->DAC/ADC sample Freq=11.289(MCLK)/256=44.1KHZ
    iic_write(WM8960_DEVICE_ADDR, 0x4, 0x0);

    // 设置ADC-DAC
    iic_write(WM8960_DEVICE_ADDR, 0x5, 0x0);

    // 设置audio interface
    //I2S format 16 bits word length
    iic_write(WM8960_DEVICE_ADDR, 0x7, 0x2);

    // 设置OUTPUTS
    iic_write(WM8960_DEVICE_ADDR, 0x2, 0xFF | 0x100);
    iic_write(WM8960_DEVICE_ADDR, 0x3, 0xFF | 0x100);

    // 设置DAC VOLUME
    iic_write(WM8960_DEVICE_ADDR, 0xa, 0xFF | 0x100);
    iic_write(WM8960_DEVICE_ADDR, 0xb, 0xFF | 0x100);

    // 设置mixer
    iic_write(WM8960_DEVICE_ADDR, 0x22, 1<<8 | 1<<7);
    iic_write(WM8960_DEVICE_ADDR, 0x25, 1<<8 | 1<<7);

    return;

}

I2S的初始化:

void iis_init(void)
{
    int N;
    // 配置引脚用于i2s功能
    GPICON = 0x22222222;

    // 设置i2s相关时钟
    // step 1: EPLL output 67.7Mhz (see p361 of s5pv210.pdf)
    // EPLL_CON0/ EPLL_CON1, R/W, Address = 0xE010_0110/0xE010_0114)
    // FOUT = (MDIV+K/65536) X FIN / (PDIV X 2SDIV)
    // Fout = (0x43+0.7)*24M / (3*2^3) = 80*24M/24 = 67.7Mhz
#define EPLL_CON0   (*(volatile unsigned int *)0xe0100110)
#define EPLL_CON1   (*(volatile unsigned int *)0xe0100114)
    EPLL_CON0 = 0xa8430303;     // MPLL_FOUT = 67.7Mhz
    EPLL_CON1 = 0xbcee;     // from linux kernel setting


    // step 2: Mux_I2S  AUDIO subsystem clock selection (see P1868 P1875 of s5pv210.pdf)
#define CLK_CON     (*(volatile unsigned int *)0xEEE10000)
    CLK_CON = 0x1;      // 1 = FOUT_EPLL        MUXI2S_A 00 = Main CLK


    // 设置i2s控制器
    // step 3:  Divider of IIS (67.7 -> 11.289Mhz)
    // N + 1 = (67.7Mhz) / (256 * 44.1Khz) = 5.99
    // IISCDCLK  11.289Mhz = 44.1K * 256fs
    // IISSCLK    1.4112Mhz = 44.1K * 32fs
    // IISLRCLK   44.1Khz
    N = 5;
    IISPSR = 1<<15 | N<<8;

    // IIS interface active (start operation).  1 = Active
    IISCON |= 1<<0 | (unsigned)1<<31;

    // [9:8] 10 = Transmit and receive simultaneous mode
    // 1 = Using I2SCLK     (use EPLL)
    IISMOD = 1<<9 | 0<<8 | 1<<10;

}

I2S的初始化,主要完成时钟的初始化.
MPLL_FOUT=67.7Mhz
Codec clock=11.289Mhz—–也称作MCLK=256*fs
I2S SerialCLK(I2SSLK)=1.4122Mhz =2* fs *采样位数
I2S LRCLK ==44.1KHZ

不同采样位数的wav文件,对应的时钟信号有所不同~

相关内容推荐