• WM8960音频播放


    第一节 音频播放原理
    首先需要申明一下,本章的代码来自网络,参考了亚嵌教育李明老师(论坛ID:limingth)的帖子:

    http://www.arm9home.net/read.php?tid=20515&page=1#175657

    image
    S5PV210通过i2s和i2c与音频编解码芯片wm8960进行交互,其中i2s负责只传输声音数据,而i2c负责传输控制信息(如音量调节、静音等),wm8960负责编解码。
    要驱动wm8960,我们需要做三件事:(1)初始化i2s,(2)初始化i2c,(3)初始化wm8960。
    Mini210S相关的原理图如下:

    image
    第二节 程序详细讲解
    完整代码见目录详细代码下载链接。
    1. Makefile
    在makefile中,我们将程序的链接地址设置为0x21000000,也就是说程序只有
    位于0x21000000才能正常运行,所有我们的程序一开始就必须被下载到内存0x21000000处。
    2. main.c
    代码如下:
    void main(void)
    {
        printf("Audio Test ");
        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 > (882046-0x2e) /2) // 有多少个2byte = (文件大小-偏移)/2
            offset = 0x2E;
        }
    }
    main函数共做了4件事:
    第一步 调用iic_init()初始化i2c;
    第二步 调用wm8960_init()初始化wm8960;
    第三步 调用iis_init()初始化i2s;
    第四步 用i2s中发出声音数据,循环播放音频文件;
    3. audio.c
    audio.c里有几个核心的函数,下面我们来逐个分析。
    函数一 iic_init(),代码如下:
    void iic_init(void)
    {
        GPD1CON |= 0x22; // 配置引脚
        GPD1PUD |= 0x5;
        I2CCON0 = (1<<7) | (0<<6) | (1<<5) | (0xe);
        I2CSTAT0 = 0x10;
    }
    初始化i2c很简单,分三步:
    第一步 配置引脚用于i2c功能;
    第二步 配置i2c控制器,包括设置时钟,使能ack等;
    第三步 使能接收和发送功能;
    函数二 iic_write (),代码如下:
    void iic_write(int slave_addr, int addr, int data)
    {
        // 地址
        I2CDS0 = slave_addr;
        // 发送s信号和地址
        I2CSTAT0 = 0xf0;
        // 等待
        while ((I2CCON0 & 0x10) == 0); // 等待数据发送
        while ((I2CSTAT0 & 0x1)); // 等待从机发来ACK
        // 发7bit地址和9bit数据
        I2CDS0 = addr<<1 | ((data>>8) & 0x0001);
        I2CCON0 &= ~(1<<4); // 清中断
        while ((I2CCON0 & 0x10) == 0); // 等待数据发送
        while ((I2CSTAT0 & 0x1)); // 等待从机发来ACK
        I2CDS0 = (data & 0x00FF);
        I2CCON0 &= ~(1<<4); // 清中断
        while ((I2CCON0 & 0x10) == 0); // 等待数据发送
        while ((I2CSTAT0 & 0x1)); // 等待从机发来ACK
        // 发p信息
        I2CSTAT0 = 0xd0;
        I2CCON0 &= ~(1<<4); // 清中断
        // 延时等待
        int i=0;
        for(i=0; i<50; i++);
        return;
    }
    i2c的写操作也不难,整体上分三步:
    第一步 发s信号和设备地址, slave_addr的bit[0:6]是7bit的设备地址,bit[7]=0,表示发送;
    然后需等待数据发送完成和等待ack应答;
    第二步 发16bit的数据,其中前7bit是寄存器偏移地址,后9bit是寄存器的值;
    第三步 发p信号,表示结束;
    第四步 延时,等待p信号发送成功;
    函数三 wm8960_init (),核心代码如下:
    void wm8960_init(void)
    {
        #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); // 设置时钟
        iic_write(WM8960_DEVICE_ADDR, 0x4, 0x0); // 设置ADC-DAC
        iic_write(WM8960_DEVICE_ADDR, 0x5, 0x0);
        …
    }
    wm8960_init()主要是调用了iic_write()来初始化wm8960芯片,具体的初始化步骤需要自行详细阅读wm8960的芯片手册,
    这里只是简单了整理了网友limingth的初始化步骤:
    第一步 确定wm8960的设备地址,查看wm8960的芯片手册可知其设备地址为0x1a,左移1位且低位补0(表示发送)后,WM8960_DEVICE_ADDR = 0x34,reset;
    第二步 设置power1 2 3;
    第三步 设置时钟;
    第四步 设置ADC-DAC,注意设置非静音;
    第五步 设置audio interface;
    第六步 设置volume;
    第七步 设置mixer;
    这些都是wm8960芯片手册里相关的内容,需自行阅读该芯片手册。
    函数四 iis_init (),核心代码如下:
    void iis_init(void)
    {
        int N;
        // 配置引脚用于i2s功能
        GPICON = 0x22222222;
        // 设置i2s相关时钟
        EPLL_CON0 = 0xa8430303; // MPLL_FOUT = 67.7Mhz
        EPLL_CON1 = 0xbcee;  // from linux kernel setting
        CLK_SRC0 = 0x10001111;
        CLK_CON = 0x1; // 1 = FOUT_EPLL MUXI2S_A 00 = Main CLK
        // 设置i2s控制器
        N = 5;
        IISPSR = 1<<15 | N<<8;
        IISCON |= 1<<0 | (unsigned)1<<31;
        IISMOD = 1<<9 | 0<<8 | 1<<10;
    }
    i2s的初始化整体上分为三个步骤:
    第一步 配置引脚用于i2s功能;
    第二步 设置i2s相关时钟,具体包括设置EPLL_CON0、1使EPLL输出67.7Mhz,设置时钟开关CLK_SRC0;
    第三步 设置i2s控制器,具体包括设置分频,时钟选择和发送接收模式;
    第三节 实验现象
    往开发板上插入耳机,就能重复地听到windows xp启动时的音乐了。

    详细代码下载链接:http://down.51cto.com/data/933023

    http://download.csdn.net/detail/klcf0220/6045039

  • 相关阅读:
    月半小夜曲下的畅想--DOCTYPE模式
    css模块化思想(一)--------命名是个技术活
    聊聊css盒子模型
    【随笔】借鉴 & KPI式设计
    【转载】社交的蒸发冷却效应
    【随笔】写在闪电孵化器分享会之后
    【随笔】微信删除加载动画
    【随笔】微信支付有感 续
    【转载】如何把产品做简单
    【随笔】写在2014年的第一天
  • 原文地址:https://www.cnblogs.com/klcf0220/p/3208792.html
Copyright © 2020-2023  润新知