SD卡音乐播放器.docx
《SD卡音乐播放器.docx》由会员分享,可在线阅读,更多相关《SD卡音乐播放器.docx(71页珍藏版)》请在冰豆网上搜索。
SD卡音乐播放器
基于FPGA的SD卡音乐
播放器设计
实习项目:
基于FPGA的SD卡音乐播放器设计
课程名称:
电子系统设计
实习日期:
班级:
学号:
姓名:
目录
一、实习系统简介-1-
SD卡操作简介-3-
1.1简介-3-
1.2功能介绍-4-
1.3SD总线模式-4-
二、SD卡接口描述-7-
2.1SD模式引脚-7-
2.2SPI模式引脚-7-
2.3寄存器-8-
2.4SD卡总线拓扑-8-
2.5电气接口上电-9-
2.6寄存器-9-
三、SD卡协议-11-
3.1SD总线协议-11-
3.2协议功能描述-14-
3.3卡识别模式-14-
3.4数据传输模式-15-
四、音频模块-16-
1.内部结构-17-
2.引脚定义-17-
3.典型操作时序-18-
4.音频输入原理图-18-
5.MIC输出原理图-19-
五、实习用到主要程序-20-
1.音频驱动程序-20-
2.SD卡驱动程序-28-
3.主程序-36-
六、实习心得-49-
一、实习系统简介
许多商业媒体/音频播放器使用一个大的外部存储设备,比如一个SD卡或CF卡,来存储音乐或视频文件。
这样的设备还包括高质量的DAC设备可以产生良好的音频质量。
DE-2-70板提供的硬件和软件需要SD卡访问和专业的音频性能,这样它可以使用DE-2-70板设计先进的多媒体产品。
在此演示中,我们展示了如何实现一个SD卡音乐播放器在DE-2-70板运行,音乐文件存储在SD卡和DE-2-70板可以通过它播放音乐文件通过cd品质的音频DAC电路。
我们使用NiosII处理器读音乐中存储的数据SD卡和使用沃尔夫森WM8731音频编解码器播放音乐。
图1.1显示了硬件框图。
这个系统需要一个50MHZ时钟提供DE-2-70板。
锁相环生成一个100-mhz时钟为NIOSII处理器
和其他控制器提供时钟。
音频芯片是由音频控制器一个用户定义的SOPC组件。
这个音频控制器需要一个输入时钟运行在18.432MHZ。
在这个设计中,时钟是由锁相环块组成。
音频控制器需要音频芯片工作在主模式,所以串行位(井底油嘴)和左/右通道钟(LRCK)提供音频芯片。
这个7段显示控制的SEG7控制器也是一个用户定义的SOPC组件。
两个PIO针连接到I2C总线。
I2C协议是由软件实现。
四个PIO针连接到SD卡套接字。
SD比特模式是用于访问SD卡,由软件实现。
所有的其他组件在SOPC框图是内置组件SOPC的组成成分。
图1.1方框图的SD音乐播放器
图2显示了这个演示的软件堆栈。
SD比特模块实现了比特模式协议对阅读记忆原始数据的SD卡。
FAT16的块实现FAT16文件系统读波文件存储在SD卡。
在这个块,只有实现阅读功能。
波自由块实现波文件解码函数接从波文件收音频信号。
I2C块实现了I2C协议配置音频芯片。
实现显示功能的SEG7块显示运行时间。
音频块实现了音频FIFO检查功能和音频信号发送/接收功能。
图2。
软件堆栈的SD音乐播放器
音频芯片应该配置在发送之前音频信号的音频芯片。
主要程序使用I2C协议配置音频芯片工作在主模式中,音频接口作为与16位每通道I2S采样率根据波文件内容。
在音频循环,主程序读取512字节的音频数据从SD卡,然后写数据DACFIFO的音频控制器。
在写数据到FIFO,程序确保先进先出不完整。
该设计还混合了音频信号从麦克风在和输出的卡拉ok风格效果,使用到旁路和SITETONE功能音频芯片。
最后,用户可以获得SD音乐播放器的状态从2x16液晶模块、7段显示器和发光二极管。
顶部和底部排液晶模块将显示文件音乐的名字和音乐音量波,7段显示器将显示音乐文件已打开多久了。
LED将指示音频信号的强度。
SD卡操作简介
1.1简介
SD卡是基于flash的存储卡。
SD卡和MMC卡的区别在于初始化过程不同
SD卡的通信协议包括SD和SPI两类。
SD卡使用卡内智能控制模块进行FLASH操作控制,包括协议、安全算法、数据存取、
ECC算法、缺陷处理和分析、电源管理、时钟管理
1.2功能介绍
1)主机无关的FLASH内存擦除和编程
读或写数据,主机只要发送一个带地址的命令,然后等待命令完成,主机无需关心具
体操作的完成。
当采用新型的FLASH时,主机代码无需更新。
2)缺陷管理
3)错误恢复
4)电源管理
Flash每个扇区有大约10万次的写寿命,读没有限制。
擦除操作可以加速写操作,因为在写之前会进行擦除。
1.3SD总线模式
当主机定义了SD卡不支持的电压范围时,SD卡将处于非活动状态,将忽略所有的总
线传输。
要退出非活动状态唯一的方法就是重新上电。
(1)SD卡获取和识别
SD卡总线采用的是单主多从结构,总线上所有卡共用时钟和电源线。
主机依次分别访
问每个卡,每个卡的CID寄存器中已预编程了一个唯一的卡标识号,用来区分不同的卡。
主机通过READ_CID命令读取CID寄存器。
CID寄存器在SD卡生产过程中的测试和
格式化时被编程,主机只能读取该号。
DAT3线上内置的上拉电阻用来侦测卡。
在数据传输时电阻断开(使用ACMD42)。
(2)卡状态
卡状态分别存放在下面两个区域:
卡状态(CardStatus),存放在一个32位状态寄存器,在卡响应主机命令时作为数据传
送给主机。
SD状态(SD_Status),当主机使用SD_STATUS(ACMD13)命令时,512位以一个数
据块的方式发送给主机。
SD_STATUS还包括了和BUS_WIDTH、安全相关位和扩展位等
扩展状态位。
(3)内存组织
数据读写的基本单元是一个字节,可以按要求组织成不同的块。
Block:
块大小可以固定,也可以改变,允许的块大小是实际大小等信息存储在CSD寄
存器。
Sector:
和擦除命令相关,由几个块组成。
Sector的大小对每个设备是固定的,大小信息
存储在CSD寄存器。
WPGroup:
写保护单位。
大小包括几个group,写保护由一位决定,对每个设备大小是
固定的,存储在CSD寄存器。
(4)读写操作
SingleBlockMode:
主机根据事先定义的长度读写一个数据块。
由发送模块产生一个16
位的CRC校验码,接受端根据校验码进行检验。
读操作的块长度受设备sector大小(512
bytes)的限制,但是可以最小为一个字节。
不对齐的访问是不允许的,每个数据块必须位于
单个物理sector内。
写操作的大小必须为sector大小,起始地址必须与sector边界对齐。
MultipleBlockMode:
主机可以读写多个数据块(相同长度),根据命令中的地址读取或
写入连续的内存地址。
操作通过一个停止传输命令结束。
写操作必须地址对齐。
(5)数据擦除
SD卡数据擦除的最小单位是sector。
为了加速擦除操作,多个sector可以同时擦除。
为了方便选择,第一个指令包含起始地址,第二个指令包含结束地址,在地址范围内的所
有sector将被擦除。
(6)写保护
两种写保护方式可供选择,永久保护和临时保护,两种方式都可以通过PROGRAM_CSD指令进行设置。
永久保护位一旦设置将无法清除。
3.10拷贝位
通过CSD寄存器中的拷贝位(copybit)设置SD卡中的数据是原始数据还是拷贝数据。
拷贝位一旦设置
将无法清除,在测试和格式化时使用。
(7)CSD寄存器
所有SD卡的配置信息存储在CSD寄存器。
通过SEND_CSD读取,PROGRAM_CSD修改
二、SD卡接口描述
引脚和寄存器
连主机通过9个引脚和SD卡相
2.1SD模式引脚
有DAT0使用扩展数据线(DAT1-DAT3)上电后为输入,SET_BUS_WIDTH命令执行后作为数据线。
即使只
,所有数据线都和外部上拉电阻连接,否则DAT1&DAT2(如果未被使用)
的振荡输入将引起非期望的高电流损耗。
上电后,数据线输入50K(+/-20K)欧姆的上拉(用来进行卡侦测和SPI模式选择)。
用
户可以在常规数据传输时,通过SET_CLR_CARD_DETECT(ACMD42)命令分离上拉。
2.2SPI模式引脚
2.3寄存器
主机通过重新上电来重置(reset)卡。
卡有它自身检测上电的电路,当上电后卡状态切换到idle状态。
也可以通过GO_IDLE(CMD0)指令来重置。
2.4SD卡总线拓扑
SD总线有6根通信线和三根电源供应线:
CMD——命令线是双向信号线。
主机和卡通过pushpull模式工作。
DAT0-3——数据线是双向信号线。
主机和卡通过pushpull模式工作。
CLK——时钟是从主机到卡的信号。
CLK通过pushpull模式操作。
VDD—VDD是所有卡的电源供应线。
VSS[1:
2]—VSS是2根地线。
在初始化的时候,向每个卡分别发送命令,允许应用检测卡并给物理槽(physicalslot)
分配逻辑地址。
数据通常分别传输给每个卡。
然后,为了方便处理卡堆栈,初始化后所有
命令同时发送给所有卡,在命令数据包中包含了操作地址。
SD总线允许动态配置数据线数目。
上电后默认SD卡只用DAT0作为数据传输线。
初始
化后,主机可以改变总线宽度。
这个特性使得在硬件开销和系统性能间取得平衡。
2.5电气接口上电
上电后,包括热插入,卡进入idle状态。
在该状态SD卡忽略所有总线操作直到接收到
ACMD41命令。
ACMD41命令是一个特殊的同步命令,用来协商操作电压范围,并轮询所
有的卡。
除了操作电压信息,ACMD41的响应还包括一个忙标志,表明卡还在power-up过
程工作,还没有准备好识别操作,即告诉主机卡还没有就绪。
主机等待(继续轮询)直到忙标
志清除。
单个卡的最大上电时间不能操作1秒。
上电后,主机开始时钟并在CMD线上发送初始化序列,初始化序列由连续的逻辑“1
组成。
序列长度为最大1毫秒,74个时钟或supply-ramp-up时间。
额外的10个时钟(64个
时钟后卡已准备就绪)用来实现同步。
每个总线控制器必须能执行ACMD41和CMD1。
CMD1要求MMC卡发送操作条件。
在任何情况下,ACMD41或CMD1必须通过各自的CMD线分别发送给每个卡。
2.6寄存器
2.6.1OCR(OperatingConditionsRegister)
32位的操作条件寄存器存储了VDD电压范围。
SD卡操作电压范围为2~3.6V。
然而从内存中访问数据的电压是2.7~3.6V。
OCR显示了卡数据访问电压范围,结构如下表所示。
OCR结构如下图所示。
如果第32位(busybit)置位,表明卡上电过程已结束
2.6.2CID(Cardntification)
CID寄存器长度为16个字节的卡唯一标识号,该号在卡生产厂家编程后无法修改。
SD
和MMC卡的CID寄存器结构不一样。
三、SD卡协议
3.1SD总线协议
SD总线通信是基于命令和数据位流方式的,由一个起始位开始,以一个停止位结束:
命令——命令是开始开始操作的标记。
命令从主机发送一个卡(寻址命令)或所有连
接的卡(广播命令)。
命令在CMD线上串行传送。
响应——响应是从寻址卡或所有连接的卡(同步)发送给主机用来响应接受到的命令
的标记。
命令在CMD线上串行传送。
数据——数据可以通过数据线在卡和主机间双向传送。
卡寻址通过会话地址方式实现,地址在初始化的时候分配给卡。
SD总线上的基本操作
是command/response。
数据传送采用块方式,数据块后接CRC校验位,操作包括单数据块和多数据块。
多数据
块更适合快速写操作,多数据块传输当在CMD线出现停止命令时结束。
数据传输可以在主
机端设置采用单数据线或多数据线方式。
块写操作在DAT0数据线写操作期间使用忙信号,无论用来传输的信号线数目是多少。
命令格式如下所示:
响应标记(token)根据内容不同具有四种格式,标记长度。
长度为48位或136位。
数
据块的CRC算法采用16位的CCITT多项式。
在命令行中,MSB位首先传送,LSB位最后传送。
当使用宽总线模式时,数据同时在4根数据线上传输。
开始位、结束位和CRC在每根数
据线上传送。
CRC对每根数据线单独计算。
CRC状态响应和Busy信号只通过DAT0由卡发送给主机。
3.2协议功能描述
所有主机和SD卡间的通信由主机控制。
主机发送下述两类命令:
广播命令——广播命令发送给所有SD卡,有些命令需要响应。
寻址(点对点)命令——寻址命令只发送给具有相应地址的卡,并需要从卡返回一个响应。
对卡而言也有两类操作:
卡识别模式——在重置(reset)后当主机查找总线上的新卡时,处于卡识别模式。
重置后
SD卡将始终处于该模式,直到收到SEND_RCA命令(CMD3)。
数据传输模式——一旦卡的REC发布后,将进入数据传输模式。
主机一旦识别了所有总线
上的卡后,将进入数据传输模式。
操作模式与卡状态关系:
3.3卡识别模式
在卡识别模式,主机重置所有处于卡识别模式的SD卡,检验操作电压范围,识别卡并
请求卡发送相对卡地址RCA。
操作对每个卡在各自的CMD线上单独进行,所有的数据传送只使用CMD线。
3.4数据传输模式
直到主机知道所有CSD寄存器的内容,fpp时钟速率必须保持在fOD,因为一些卡有操作频率限制。
主机发送SEND_CSD(CMD9)获取卡定义数据(CardSpecificData,CSD寄
存器),如块大小、卡存储容量、最大时钟速率等。
CMD7用来选择一个卡并将它置于传输状态(Transferstate),在任何时间只能有一个卡处于传输状态。
如果已有一个卡处于传输状态,它和主机的连接将释放,并返回到Stand-by
状态。
当CMD7以保留相对地址“0x0000”发送时,所有卡将返回到Stand-by状态。
这可
以用来识别新的卡而不重置其他已注册的卡。
在这种状态下已有一个RCA地址的卡不响应
识别命令(ACMD41,CMD2,CMD3)。
注意:
当卡接收到一个带有不匹配RCA的CMD7时,卡将取消选中。
在公用CM线
时,选中一个卡时将自动不选中其他卡。
因此,在SD卡系统中,主机具有如下功能:
初始化完成后,在公用CMD线时,不选中卡是自动完成的。
如果使用单独的CMD线,需要关注不选中卡的操作在主机和选择的SD卡之间的所有数据通信是点对点的方式。
所有寻址命令都需要响应。
不同数据传输模式的关系如图4-8所示,使用如下步骤:
所有读数据命令可以在任何时候通过停止命令(stopcommand,CMD12)中止。
数
据传输将中止,卡回到传输状态(TransferState)。
读命令有:
块读命令(CMD17),
多块读命令(CMD18),发送读保护(CMD30),发送scr(ACMD51),以及读模式
的通用命令(CMD56)。
所有写数据命令可以在任何时候通过停止命令(stopcommand,CMD12)中止。
在不选中卡命令CMD7前写命令必须停止。
写命令有:
块写命令(CMD24andCMD25),写CID(CMD26),写CSD(CMD27),lock/unlock命令(CMD42)以及写模式通用命令(CMD56)。
一旦数据传输完成,卡将退出数据写状态并进入ProgrammingState(传输成功)或TransferState(传输失败)。
如果一个快写操作停止,而且最后一块块长度和CRC是有效的,那么数据可以被操作(programmed)卡可能提供块写缓冲。
这意味着在前一块数据被操作时,下一块数据可以传送给卡。
如果所有卡写缓冲已满,只要卡在ProgrammingState,DAT0将保持低电平(BUSY)。
写CSD、CID、写保护和擦除时没有缓冲。
这表明在卡因这些命令而处于忙时,不再接收其他数据传输命令。
在卡忙时DAT0保持低电平,并处于ProgrammingState。
实际上如果CMD和DAT0线分离,而且主机占有的忙DAT0线和其他DAT0线分开,那么在卡忙时,主机可以访问其他卡。
在卡被编程(programming)时,禁止参数设置命令。
参数设置命令包括:
设置块长度(CMD16),擦除块开始(CMD32)和擦除块结束(CMD33)。
卡在操作时不允许读命令。
使用CMD7指令把另一个卡从Stand-by状态转移到Transfer状态不会中止擦除和编程(programming)操作。
卡将切换到Disconnect状态并释放DAT线使用CMD7指令可以不选中处于Disconnect状态的卡。
卡将进入Programming状态,重新激活忙指示。
使用CMD0或CMD15重置卡将中止所有挂起和活动的编程(programming)操作。
这可能会破坏卡上的数据内容,需要主机保证避免这样的操作。
四、音频模块
该系统采用了沃尔夫森WM8731音频编解码器。
使用I2C协议进行传输。
1.内部结构
2.引脚定义
3.典型操作时序
4.音频输入原理图
模拟量输入
MIC输入
5.MIC输出原理图
五、实习用到主要程序
1.音频驱动程序
#include"my_includes.h"
#include"I2C.h"
#include"AUDIO.h"
#include"AUDIO_REG.h"
#ifdefDEBUG_AUDIO
#defineAUDIO_DEBUG(x)DEBUG(x)
#else
#defineAUDIO_DEBUG(x)
#endif
booladuio_RegWrite(alt_u8reg_index,alt_u16data16);
staticalt_u16reg_file[10+10];
boolAUDIO_Init(void){
boolbSuccess=TRUE;
AUDIO_DEBUG(("[AUDIO]AUDIO_Init...\r\n"));
if(bSuccess)
bSuccess=aduio_RegWrite(15,0x0000);//reset
if(bSuccess)
bSuccess=aduio_RegWrite(9,0x0000);//inactiveinterface
//usleep(20*1000);
if(bSuccess)
bSuccess=aduio_RegWrite(0,0x0017);//LeftLineIn:
setleftlineinvolume
if(bSuccess)
bSuccess=aduio_RegWrite(1,0x0017);//RightLineIn:
setrightlineinvolume
if(bSuccess)
bSuccess=aduio_RegWrite(2,0x005B);//LeftHeadphoneOut:
setleftlineoutvolume
if(bSuccess)
bSuccess=aduio_RegWrite(3,0x005B);//RightHeadphoneOut:
setrightlineoutvolume
if(bSuccess)//enablemic-boost,bypassandsidetone
bSuccess=aduio_RegWrite(4,0x0015|0x20|0x08|0x01);//AnalogueAudioPathControl:
setmicasinputandboostit,andenabledac
//bSuccess=aduio_RegWrite(4,0x0015);//AnalogueAudioPathControl:
setmicasinputandboostit,andenabledac
if(bSuccess)
bSuccess=aduio_RegWrite(5,0x0000);//DigitalAudioPathControl:
disablesoftmute
if(bSuccess)
bSuccess=aduio_RegWrite(6,0);//powerdowncontrol:
poweronall
if(bSuccess)
bSuccess=aduio_RegWrite(7,0x0042);//I2S,iwl=16-bits,EnableMasterMode
//bSuccess=aduio_RegWrite(7,0x0041);//MSB-First,leftjustified,iwl=16-bits,EnableMasterMode
if(bSuccess)
bSuccess=aduio_RegWrite(8,0x0002);//Normal,BaseOVer-SampleingRate384fs(BOSR=1)
if(bSuccess)
bSuccess=aduio_RegWrite(9,0x0001);//activeinterface
AUDIO_DEBUG(("[AUDIO]AUDIO_Init%s\r\n",bSuccess?
"success":
"fail"));
returnbSuccess;
}
boolAUDIO_InterfaceActive(boolbActive){
boolbSuccess;
bSuccess=aduio_RegWrite(9,bActive?
0x0001:
0x0000);
returnbSuccess;
}
boolAUDIO_MicBoost(boolbBoost){
boolbSuccess;
alt_u16control;
control=reg_file[4];
if(bBoost)
control|=0x0001;
else
control&=0xFFFE;
bSuccess=aduio_RegWrite(4,control);//LeftLineIn:
setleftlineinvolume
returnbSuccess;
}
boolAUDI