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

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


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


第二节 程序详细讲解
完整代码见目录详细代码下载链接。
1. Makefile
在makefile中,我们将程序的链接地址设置为0x21000000,也就是说程序只有
位于0x21000000才能正常运行,所有我们的程序一开始就必须被下载到内存0x21000000处。
2. main.c
代码如下:
void main(void)
{
    printf("Audio Test\r\n");
    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

WM8960音频播放的更多相关文章

  1. iOS开发系列--音频播放、录音、视频播放、拍照、视频录制

    --iOS多媒体 概览 随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制, ...

  2. HTML5 音频播放器-Javascript代码(短小精悍)

    直接上干货咯! //HTML5 音频播放器 lzpong 2015/01/19 var wavPlayer = function () { if(window.parent.wavPlayer) re ...

  3. IOS开发之简单音频播放器

    今天第一次接触IOS开发的UI部分,之前学OC的时候一直在模拟的使用Target-Action回调模式,今天算是真正的用了一次.为了熟悉一下基本控件的使用方法,和UI部分的回调,下面开发了一个特别简易 ...

  4. ios原声音频播放AVAudioSession 总结

    //音频播放/*英译:record:录音 */ 1 导入头文件#import<AVFoundation/AVFoundation.h>//AVAudioSession是一个单例模式.在IO ...

  5. 微信小程序-图片、录音、音频播放、音乐播放、视屏、文件

    图片: wx.chooseImage(OBJECT) 从本地相册选择图片或使用相机拍照. OBJECT参数说明: 注:文件的临时路径,在小程序本次启动期间可以正常使用,如需持久保存,需在主动调用 wx ...

  6. Android音频播放之SoundPool

    SoundPool 一.基本概念 在Android应用程序的开发过程中,经常需要播放多媒体文件,也许最先想到的会是MediaPlayer类了,该类提供了播放.暂停.停止及重复播放等功能性方法(该类位于 ...

  7. iOS开发----音频播放、录音、视频播放、拍照、视频录制

    随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制,还是对麦克风.摄像头的操 ...

  8. [Cocos2D-x For WP8]CocosDenshion音频播放

    Cocos2D-x的音频分为长时间的背景音乐和短的音效两种,我们可以通过SimpleAudioEngine::sharedEngine()方法来获取音频播放的引擎,然后调用对音频相关的操作方法就可以了 ...

  9. 【jquery】一款不错的音频播放器——Amazing Audio Player

    前段时间分享了一款视频播放器,点击这里.今天介绍一款不错的音频播放器——Amazing Audio Player. 介绍: Amazing Audio Player 是一个使用很方便的 Windows ...

随机推荐

  1. 洛谷P1044 栈

    之前看这题还是一头雾水,现在看:啊啊啊lydnb! 思考了一段时间,发现可以用DP. 令f[i]表示有i辆车时的方案数. 我一开始考虑的是在后面加车,可是这样搞不出状态转移方程来. 然后我考虑从前面加 ...

  2. [luogu3398][仓鼠找sugar]

    luogu3398 思路: 假设松鼠a要从a1去a2,松鼠b要从b1去b2,ks表示lca(a1,a2)和lca(b1,b2)中深度较深的那个.那么,若要使得两只松鼠可能相遇,则只要满足lca(a1, ...

  3. 11:SSM框架下各个层的解释说明

    具体见网址:http://blog.csdn.net/lutianfeiml/article/details/51864160

  4. Error configuring application listener of

    最近在做spring+struts2+IbatIS的项目,昨天eclipse启动服务器正常,结果今天来了就总是报错,错误如下:严重: Error configuring application lis ...

  5. Class对象、反射机制、获取Constructor构造方法

    1.Class对象的三种创建方法(Class首字母大写) public class Demo { public static void main(String[] args){ Object obj= ...

  6. ping的作用

    Ping是潜水艇人员的专用术语,表示回应的声纳脉冲,在网络中Ping 是一个十分好用的TCP/IP工具.它主要的功能是用来检测网络的连通情况和分析网络速度. Ping有好的善的一面也有恶的一面.先说一 ...

  7. CodeForces911D 逆序对

    http://codeforces.com/problemset/problem/911/D 题意 给你一个长度为N的序列,有M次操作.每次翻转[l,r]的区间,每次操作后询问序列逆序对个数的奇偶性 ...

  8. 怎样解决Myeclipse内存溢出?

    打开myeclipse 10安装目录下的myeclipse.ini文件 打开文件,将文件圈圈中的内容设置如下图: 上面是其中一种解决方案,下面介绍第二种解决方案 设置Default VM Argume ...

  9. keepalive的工作原理和如何做到健康检查

    keepalived是以VRRP协议为实现基础的,VRRP全称Virtual Router Redundancy Protocol,即虚拟路由冗余协议. 虚拟路由冗余协议,可以认为是实现路由器高可用的 ...

  10. php循环删除文件夹和目录

    一定要注意文件夹中的两个目录---->   .(当前目录)  ..(上级目录) 需要对这两个目录进行过滤, 否则在删除或者遍历是会一直,对于..甚至会向你指定的文件夹的上级目录循环操作,删除重要 ...