当前位置: 首页 > news >正文

S3C2440-IIS放音

哈尔滨理工大学软件工程专业08-7李万鹏原创作品,转载请标明出处

http://blog.csdn.net/woshixingaaa/archive/2011/01/14/6140692.aspx

S3C2440A的Inter-IC Sound(IIS)总线接口作为一个编解码接口连接外部8/16位立体声音频解码IC用于迷你碟机和可携式应用。IIS总线接口支持IIS总线数据格式和MSB-justified数据格式。该接口对FIFO的访问采用了DMA模式取代了中断。它可以在同一时间接受和发送数据。S3C2440一共有5个引脚用于IIS:IISDO,IISDI,IISSCLK,IISLRCK和CDCLK。前两个信号用于数字音频信号的输入输出,另外3个引脚都与音频信号的频率有关,可见要用好IIS,就要把信号频率设置正确。IISSCLK为串行时钟,每一个时钟信号传送一位音频信号,因此IISSCLK的频率=声道数*采样频率*采样位数,如采样频率为44.1kHz,采样的位数为16位,声道数2个(左,右两个声道),则IISSCLK的频率=32fs=1411.2kHz。IISLRCK为帧时钟,用于切换左右声道,如IISLRCK为高电平表示正在传输的是左声道数据,为低表示传输的是右声道数据。因此IISLRCK的频率应该正好等于采样频率。由于IIS只负责数字音频信号的传输,而要真正实现音频信号的放录还需要额外的处理芯片(在这里我们使用UDA1341),CDCLK为该芯片提供系统同步时钟,即编解码时钟,主要用于音频的A/D,D/A采样时的采样时钟,一般CDCLK为256fs或384fs。UDA1341使用L3接口,通过L3接口可以实现UDA1341和S3C2440控制信息的传递。L3指3根线,L3DATA(数据线,用于传输数据),L3MODE(模式线,用于选择模式),L3CLOCK(时钟线,用于传输时钟)。先传输地址模式数据,再传输数据模式数据。L3MODE为低时是地址模式,L3MODE为高时是数据传输模式。L3DATA和L3CLOCK相互作用,完成8位数据的传输,传输的顺序是先低位数据,再高位数据。地址模式用于选择设备和定义目标寄存器,在这种模式下,8位数据的含义是:高6位是设备地址(UDA1341的地址为000101),低两位是后面数据模式的类型(00:DATA0,01:DATA1,10:STATUS)。

下面这个程序完成从WAV音频文件中提取出数组。

#include <stdio.h> #include<stdlib.h> #include <string.h> #include <memory.h> int main(){ FILE *stream, *fp; unsigned char *music; char ch[5]; int start, end, num, t, i, j, r; if(((stream = fopen("D:\\music.wav","rb")) == NULL) || ((fp = fopen("D:\\music.h","wb+")) == NULL)){ printf("%s","cannot open output file.\n"); return 1; } fseek(stream,0,SEEK_SET); start = ftell(stream); //获得文件的起始地址 fseek(stream,0,SEEK_END); end = ftell(stream); //获得文件的结束地址 fseek(stream,0,SEEK_SET); music = (unsigned char *)malloc(end-start); //动态分配一个buffer fwrite("unsigned char music[",1,20,fp); fwrite("]={",1,3,fp); fwrite("\n", 2, 1, fp); num = (end - start - 0x2c) / 16; //m每行16个 t = (end - start - 0x2c) % 16; fread(music, 1, end - start, stream); for(i = 0; i < num; i++){ for(j = 0; j < 16; j++){ memset(ch,0,5); r = (int)music[i*16+j+0x2c]; //从0x2c开始是音频数据 r &= 0xff; sprintf(ch,"0x%02x",r); //先转化成一定格式 fwrite(ch,sizeof(ch),1,fp); fwrite(",",1,1,fp); } fwrite("\n",1,2,fp); } for(i = 0; i < t; i++){ memset(ch,0,5); r = (int)music[i*16+j+0x2c]; r &= 0xff; sprintf(ch,"0x%02x",r); fwrite(ch,sizeof(ch),1,fp); if(i != t-1) fwrite(",",1,1,fp); } fwrite("};",1,2,fp); fclose(stream); fclose(fp); system("pause"); return 0; }

完成音频文件的播放。IISFIFO为16位宽,深度为32。将音频数组中的数据装入IISFIFO,装满后IIS读取IISFIFO中的数据,即放音,然后再将音频数组中的数据读入IISFIFO,周而复始,完成放音。

#include "2440addr.h" #include "music.h" #define L3MODE 1<<2 #define L3DATA 1<<3 #define L3CLOCK 1<<4 void WriteL3(unsigned char data, unsigned int mode){ //mode = 0,地址模式;mode = 1,数据传输模式 int i, k; if(mode == 0){ rGPBDAT = rGPBDAT & ~(L3MODE|L3DATA|L3CLOCK )|L3CLOCK; } else{ rGPBDAT = rGPBDAT & ~(L3MODE|L3DATA|L3CLOCK)|(L3CLOCK|L3MODE); } for(k = 0; k < 5; k++) ; for(i = 0; i < 8; i++){ if(data & 0x1){ rGPBDAT &= ~L3CLOCK; rGPBDAT |= L3DATA; for(k = 0; k < 5; k++) ; rGPBDAT |= L3CLOCK; rGPBDAT |= L3DATA; for(k = 0; k < 5; k++) ; } else{ rGPBDAT &= ~L3CLOCK; rGPBDAT &= ~L3DATA; for(k = 0; k < 5; k++) ; rGPBDAT |= L3CLOCK; rGPBDAT &= ~L3DATA; for(k = 0; k < 5; k++) ; } data >>= 1; } rGPBDAT = rGPBDAT & ~(L3MODE|L3DATA|L3CLOCK)|(L3CLOCK|L3MODE); } void PlayMusic(unsigned char buffer[], unsigned int length){ int i, fifo; //UDA1341 //STATUS模式 rGPBDAT = rGPBDAT & ~(L3MODE|L3DATA|L3CLOCK)|(L3CLOCK|L3MODE); WriteL3(0x14+2,0); //复位 WriteL3(0x60,1); WriteL3(0x14+2,0); //00010000 系统时钟频率384fs WriteL3(0x10,1); WriteL3(0x14+2,0); //11000001 输出增益,ADC关,DAC开 WriteL3(0xc1,1); //IIS //DMA禁止,在接受空闲状态,不产生IISLRCK信号,IIS预分频使能 rIISCON = (0<<5)|(0<<4)|(0<<3)|(1<<2)|(1<<1); //主设备时钟PCLK,主设备模式,发送模式,串行数据16位,主时钟是384fs,串行位时钟32fs rIISMOD = (0<<9)|(0<<8)|(2<<6)|(0<<5)|(0<<4)|(1<<3)|(1<<2)|(1<<0); //预分频都是N=3 rIISPSR = (3<<5)|3; //发送FIFO正常,发送FIFO使能 rIISFCON = (0<<15)|(1<<13); //IIS start rIISCON |= 0x1; for(fifo = 0; fifo <= length; fifo += 64){ while(rIISCON &(1<<7)); for(i = 0; i < 32; i++) rIISFIFO = (buffer[i*2+fifo]) + (buffer[i*2+1+fifo]<<8); } //IIS close rIISCON = 0x0; } int Main(){ rGPBUP = rGPBUP & ~(0x7<<2) | (0x7<<2); //The pull up function is disabled GPB[4:2] 1 1100 rGPBCON = rGPBCON & ~(0x3f<<4) | (0x15<<4); //GPB[4:2]=Output(L3CLOCK):Output(L3DATA):Output(L3MODE) rGPBDAT = 0x1ec; rGPEUP = rGPEUP & ~(0x1f) | 0x1f; //The pull up function is disabled GPE[4:0] 1 1111 rGPECON = rGPECON & ~(0x3ff) | 0x2aa; //GPE[4:0]=I2SSDO:I2SSDI:CDCLK:I2SSCLK:I2SLRCK rMPLLCON = (150<<12)|(5<<4)|(0<<0); PlayMusic(music, sizeof(music)); while(1); return 0; }

相关文章:

  • 记住密码超简单实现(C#)
  • CSS布局居中
  • Servlet和JSP关系浅析
  • selenium 获取某元素的 某属性 的值
  • BestCoder Round #81 (div.2) 1003 String
  • 2010年架构社区回顾:悠长的一年
  • 【VS开发】使用VS2010创建MFC ActiveX工程项目
  • Java Resource路径小结
  • 在ubuntu 15.04下安装VMware Tools
  • ZeroMQ(java)中监控Socket
  • hdu1418 欧拉公式
  • S3C2440-DMA
  • 冲刺第三天
  • 落花流水又一年
  • 九、oracle 事务
  • [译]前端离线指南(上)
  • conda常用的命令
  • JavaScript异步流程控制的前世今生
  • Java编程基础24——递归练习
  • js 实现textarea输入字数提示
  • MYSQL 的 IF 函数
  • nginx(二):进阶配置介绍--rewrite用法,压缩,https虚拟主机等
  • PHP 7 修改了什么呢 -- 2
  • 大型网站性能监测、分析与优化常见问题QA
  • 关键词挖掘技术哪家强(一)基于node.js技术开发一个关键字查询工具
  • 前嗅ForeSpider教程:创建模板
  • 因为阿里,他们成了“杭漂”
  • Mac 上flink的安装与启动
  • raise 与 raise ... from 的区别
  • Redis4.x新特性 -- 萌萌的MEMORY DOCTOR
  • #{} 和 ${}区别
  • (10)STL算法之搜索(二) 二分查找
  • (day 12)JavaScript学习笔记(数组3)
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (二)斐波那契Fabonacci函数
  • (二十一)devops持续集成开发——使用jenkins的Docker Pipeline插件完成docker项目的pipeline流水线发布
  • (附源码)springboot码头作业管理系统 毕业设计 341654
  • (附源码)ssm失物招领系统 毕业设计 182317
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (淘宝无限适配)手机端rem布局详解(转载非原创)
  • (一)Neo4j下载安装以及初次使用
  • (中等) HDU 4370 0 or 1,建模+Dijkstra。
  • (转)ObjectiveC 深浅拷贝学习
  • (转)编辑寄语:因为爱心,所以美丽
  • .dwp和.webpart的区别
  • .NET 8 中引入新的 IHostedLifecycleService 接口 实现定时任务
  • .NET Core/Framework 创建委托以大幅度提高反射调用的性能
  • .NET Standard 的管理策略
  • @Autowired和@Resource的区别
  • @Bean注解详解
  • @Conditional注解详解
  • @Import注解详解
  • @param注解什么意思_9000字,通俗易懂的讲解下Java注解
  • [2013AAA]On a fractional nonlinear hyperbolic equation arising from relative theory
  • [20170705]lsnrctl status LISTENER_SCAN1