CD播放机经过了多年的发展已是很普及的音响器材了,光盘也成为电脑媒体的重要载体之一,在多数的电脑爱好者手中很多都会有二台或更多的光驱,也许你和我一样新买了支持DVD光盘的光驱,旧的CDROM读盘能力下降,很少再使用了,丢弃了也可惜。在这一期里借着介绍IDE接口的机会我们来尝试把CDROM改装成CD播放机,旧光驱也可以有新用途,当然这里介绍的改装不是指利用CDROM本身所带的播放键(大部分CDROM没有播放键)去改装,而是通过单片机对光驱的ATAPI接口进行对光驱的控制,从而学习一些IDE/ATAPI接口的相关知识和单片机的应用认识。
一、电路原理及编程思路 IDE 是 Integrated Drive Electronics 的缩写,是由 Compaq 和 Western Digital 公司开发,AT架构的计算机出现后,新版的 IDE 命名为 ATA 即 AT bus Attachment,但在更多的时候人们会习惯叫回旧名"IDE",这种接口一直被应用在硬盘的连接上。而ATAPI则是在ATA上扩展出来的,ATAPI是AT Attachment Packet Interface的缩写,意思是AT计算机上附加设备的信息包接口。支持ATAPI的IDE接口可以像连接硬盘一样连接ATAPI设备。目前几乎所有的IDE接口都支持ATAPI,它被广泛应用于光驱,ZIP驱动器等设备上。所说的这三种设备界面都是使用如图1和图2所示的40PIN连接件。像图1的连接件是用于主机板和IDE设备上,是40PIN的针式接头,主板上有两个这样的接口,可以用于连接4个IDE设备。图2则是用于连接主机和IDE设备的40芯IDE线缆,现在也有80芯线缆用于连接更新版的高速ATA。图3则是IDE接口连接件的引脚号定义图。
图1:光驱后面板的接口
图2:连接电缆
图3:引脚号定义图
元件名 |
数 量 |
说 明 |
AT89C51 |
1 |
可以用AT89C52,AT89S51等代换 |
8.2K电阻 |
1 |
|
3K电阻 |
1 |
|
10K排阻 |
1 |
8位 |
LED发光管 |
1 |
|
30pF瓷片电容 |
2 |
|
10uF电解电容 |
1 |
|
11.0592M晶振 |
1 |
可以用6-12M |
40Pin插针式插座 |
1 |
|
40芯IDE连接线 |
1 |
电脑的硬盘或光驱连线 |
小型按钮 |
5 |
|
+12V +5V开关电源 |
1 |
要求+5V+12V都要有1.5A以上电流 |
表一 制作元件表
Pin |
Name |
Dir |
Description |
|
Pin |
Name |
Dir |
Description |
1 |
/RESET |
输入 |
复位 |
|
21 |
DMARQ |
输出 |
DMQ请求 |
2 |
GND |
/ |
地 |
|
22 |
GND |
/ |
地 |
3 |
DD7 |
输入/输出 |
Data 7 |
|
23 |
/DIOW |
输入 |
写控制 |
4 |
DD8 |
输入/输出 |
Data 8 |
|
24 |
GND |
/ |
地 |
5 |
DD6 |
输入/输出 |
Data 6 |
|
25 |
/DIOR |
输入 |
读控制 |
6 |
DD9 |
输入/输出 |
Data 9 |
|
26 |
GND |
/ |
地 |
7 |
DD5 |
输入/输出 |
Data 5 |
|
27 |
IORDY |
输出 |
IO就绪指示 |
8 |
DD10 |
输入/输出 |
Data 10 |
|
28 |
CSEL |
/ |
装置编号 |
9 |
DD4 |
输入/输出 |
Data 4 |
|
29 |
/DMACK |
/ |
输入 |
10 |
DD11 |
输入/输出 |
Data 11 |
|
30 |
GND |
/ |
地 |
11 |
DD3 |
输入/输出 |
Data 3 |
|
31 |
IRQR |
输出 |
中断请求 |
12 |
DD12 |
输入/输出 |
Data 12 |
|
32 |
NC |
/ |
保留 |
13 |
DD2 |
输入/输出 |
Data 2 |
|
33 |
DA1 |
输入 |
寄存器地址A1 |
14 |
DD13 |
输入/输出 |
Data 13 |
|
34 |
/PDIAG |
/ |
自诊断标识 |
15 |
DD1 |
输入/输出 |
Data 1 |
|
35 |
DA0 |
输入 |
寄存器地址A0 |
16 |
DD14 |
输入/输出 |
Data 14 |
|
36 |
DA2 |
输入 |
寄存器地址A2 |
17 |
DD0 |
输入/输出 |
Data 0 |
|
37 |
/CS0 |
输入 |
寄存器选择 |
18 |
DD15 |
输入/输出 |
Data 15 |
|
38 |
/CS1 |
输入 |
寄存器选择 |
19 |
GND |
/ |
地 |
|
39 |
/DASP |
输入 |
装置活动指示 |
20 |
KEY |
/ |
Key |
|
40 |
GND |
/ |
地 |
*注:在引脚名前有"/"的引脚为低电平有效 表2 ATAPI接口的引脚定义说明
图4是电路原理图,表1是元件列表,本实例中使用51单片机做为控制芯片,用它的P1,P2口组成16位的数据输入输出口,连接IDE的D0-D15数据线。P0口用于连接IDE的读写控制、复位和寄存器控制,由于P0口的驱动力比较低,所以用10K的排阻对其上拉。晶振没有什么特别的要求,这里可以选用11.0592M或12M,加上上电复位电路组成典型的单片机最小系统。P3口则用于播放,前进,后退,停止和开关托盘控制按键的输入,P3.7接一个发光二极管是用于显示光驱是否装载了CD光盘或是否出错了,出错或没有光盘时该LED会点亮。电路连接无误后烧录编译好的HEX文件到51芯片上,就可以正常工作了。本文提供的源码只实现这几种功能,在这个基础上可以加上LED数码管或LCD显示曲目时间等信息,也可以加入遥控接收等功能。
图4:原理图
图5是笔者用于实验和调试的电路实物照片。调试时使用自制兼容F-MON51的仿真器和KEIL集成开发环境连接可以方便的进行单步和断点调试,同时也可以查看名RAM和变量的值,这样的查看对于类似这样的制作是很关键的,因为在发送或读取设备的寄存器后,通常设备会有一些状态值返回,程序则要求根据这些值做相应的处理,如果是直接烧片调试则会使得程序的调试过程变得非常的困难。光驱需要的电流比较大,一般要一点几安培的电流,且要用到+5V和+12V两个电压,在制作时可以使用开关电源模块或使用旧电脑上的AT电源(也是开关电源),如果用普通的电压器加7805、7812则不能满足要求。还有一点值得注意的是IDE连接电缆的红色线为一号线,其它则顺序排列到40号,同时要把光驱后面板上的跳线设置为主盘(MASTER)。
像其它电脑接口或单片机应用制作一样,本实例的难点在于单片机控制程序的编写。ATAPI协议是在ATA协议发展出来的,它的控制命令和返回的数据格式十分繁复,用于光驱时对于不同形式的光盘,控制命令的使用方式也不太一样,本文是把光驱改为CD播放器,所以编程的着重点在于CD音频光盘的控制命令如何发送到光驱上的ATAPI接口。ATAPI有许多寄存器,操作这些不同的寄存器便可以实现相应的功能,如读状态寄存器应先设置好CS和DA选定要操作的是状态寄存器,把DIOW拉低,这时就可以读ATAPI的数据线DD了,得到当前的设备状态,再把DIOW拉高完成读取,在本文的源码中可以参看void ReadStatus(void)函数。在发送控制命令时,可以分为二类,分别为ATA Command(ATA命令)和ATAPI Packet Command(ATAPI信息包命令),前者只要先选择要操作的是命令寄存器,再向数据口发一命令字节就可以实现所要的功能,如先选择命令寄存器再发送A1H到数据口,就可以执行识别光驱的自检命令,命令完成后读数据口可以得到光驱的相关信息,如型号、序列号等,源码中可以参看void InitCDROM(void)中的相关语句。后者的使用则相对复杂一些,发送信息包时,先要向传输字节计数寄存器写要发送的字节数,再送A0H信息命令字到命令寄存器通知设备要发送信息包,最后则是向数据寄存器发送信息包。一般信息包为12个字节,第一个字节为命令字,代表不此信息包的功能,其后的是参数,程序实现可以参看void SendPacket(unsigned char SkipDRQ)函数。。
大家也许知道,CDROM播放CD时有一系列的动作,先是上电复位、光盘托盘打开、放入光盘托盘关闭、读取曲目播放。同样使用单片机对光驱进行CD播放控制时也应要有这样的顺序,在本文源码中的主程序中先是调用初始化函数,对光驱进行复位和识别,初始化成功后就会调用读取TOC函数读取曲目和相关值。然后就是对按钮进行判断,做出相应的控制。图6是播放CD时的基本顺序图。
图5:实验电路
图6:CD播放基本顺序
二、IDE(ATAPI)引脚定义
从表一可以看到ATAPI各引脚的定义,下面是几个在实例中要使用的引脚具体说明:
1.DD(15:0)Device Data
DD占用3-18引脚,是一个8位或16位的双向数据线,在用于读写CDROM的寄存器时只使用低8位,而在传送信息包或数据时使用全部16位。
2.CS(1:0)Chip Select CS0,CS1是用于选择指令寄存器芯片的,为低电平有效,它和DA组合就可以选择所要操作的寄存器。
3.DA(2:0)Device Address DA为三位的地址线,和CS组合选取要操作的寄存器。
4.DIOR(Device I/O read) DIOR为控制寄存器或数据口读的引脚,低电平有效。
5.DIOW(Device I/O write) DIOW为控制寄存器或数据口写的引脚,低电平有效。
6.RESET 当此引脚为低电平时CDROM会被复位。
7.INTRQ (Device interrupt) INTRQ为中断请求,当CDROM在读写数据等状态下会在此引脚输出信号以使控制器中断程序得以执行,本实例中没有使用到这个方法。
8.IORDY (I/O channel ready) 这个引脚可判断CDROM的数据口是否就绪,等待数据的输入或输出。同样实例中没有使用到些引脚。
前6种引脚都在实例电路中一一连接在51单片机的IO引脚上,我们可以根据CDROM引脚所要求的电平去实现该引脚的功能,如RESET引脚为低电平有效,连接于单片机的P0.7引脚上,用如下的51C语言就可以实现对CDROM实行复位操作: P0_7 = 0; //拉低P0_7,RESET为低,复位开始 dmsec(100); //调用延时函数延时一段时间 P0_7 = 1; //拉高RESET,复位完成
三、认识ATAPI寄存器
地 址 |
功 能 |
CS0 |
CS1 |
DA2 |
DA1 |
DA0 |
读操作(DIOR) |
写操作(DIOW) |
A |
N |
0 |
0 |
0 |
数 据 |
A |
N |
0 |
0 |
1 |
错误寄存器 |
Features |
A |
N |
0 |
1 |
0 |
ATAPI Interrupt Reason/扇区计数(Sector Number) |
A |
N |
0 |
1 |
1 |
扇区数(Sector Number) |
A |
N |
1 |
0 |
0 |
传输字节计数低8位/Cylinder Low |
A |
N |
1 |
0 |
1 |
传输字节计数高8位/Cylinder High |
A |
N |
1 |
1 |
0 |
驱动器选择(Select) |
A |
N |
1 |
1 |
1 |
状态寄存器 |
命令寄存器 |
表3 ATAPI常用寄存器表
在IDE界面中寄存器的作用可以分二类,一种是用于传送指令和返回数据,一种是用于控制设备和返回控制状态。表3中指明了各ATAPI常用寄存器的地址和功能。地址是用CS和DA组成,CS为寄存器区段的选择,再加上三位地址的DA就可以组合出多个地址编码选择不同的寄存器。在单片机控制程序中可以把P3口IO引脚和DA、CS相连,在程序中控制P3口各引脚的电平状态去选择要操作的寄存器,再通过控制DIOR/ DIOW引脚电平实现读写寄存器。部分的寄存器地址是相同的,如状态寄存器和命令寄存器使用同一个地址,读这个地址时为操作状态寄存器,写这个地址时为操作状态寄存器。下面是本实例中用于控制CDROM用于CD播放时用到的部分寄存器的简单说明。
1.错误(ERROR)寄存器 错误寄存器是返回当前的错误信息或指令的执行状态,它是一个只读寄存器,如写入这个寄存器则是写入到Features寄存器中。在实例中的初始化CDROM的函数中执行驱动器自身诊断命令后,可以读取在错误寄存器中返回的诊断结果并和进行标准值对比判断驱动器是否可用。读取的方法很简单,先查表3,得知错误寄存器的地址后,设置对应的引脚电平,这时就可以在DD中的低8位读取到寄存器中的数据。
2.状态(Status)寄存器 状态寄存器也是一个只读寄存器,读取它时将会在DD中的低8位返回驱动器的当前状态或指令运行的状态。返回数据的每一位定义如下:
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
BSY |
DRDY |
# |
# |
DRQ |
obsolete |
obsolete |
ERR |
表4 状态(Status)寄存器
BSY为1时表示驱动器正处于工作状态--忙。如在驱动器上电时,驱动器复位,这时BSY为1,等到复位完成后BSY为0。当驱动器处于忙状态时将不会响应其它命令,在程序中可以不断的查询BSY位等到变为0时才继续发达命令。
DRDY为1是表示驱动器准备就绪。当这个位为0时驱动器没有就绪这时无法使用。
#号所占的位会根据不同的指令返回的指代表的意思也不同。
DRQ为1时表示数据请求就绪,这时驱动器准备接受数据,如向命令寄存器发送A0H(PACKET命令)后,DRQ位置1,表示驱动器这时可以接受命令信息包了。
Obslete位一般不使用ATAPI,只是部分旧式的ATA设备所使用。
ERR位为1时表示指令执行失败或驱动器存在错误。
3.命令(Command)寄存器 命令寄存器和状态寄存器同一个地址,是只写寄存器。向这个寄存器传送命令字时将会立即被执行。传送的方法是先设置好地址线,再向DD数据口的低8位写入指令字节。
4.Cylinder Low/High寄存器 这两个寄存器是可读也可以写,分别为所要发送或接收的数据长度的高低字节,写入数据值N时表示主设备要向驱动器写入或读出写入N次十六位的数据。这在发送信息包时很重要,信息包的长度一般为12个字节长度,那么就可要求先在Cylinder Low/High寄存器写入0006H(L写入06H,H写入00H),也就是说12个字节会分成6次传送,每次2字节(16位)。具体的C语言实现可以参看实例中的void SendPacket(unsigned char SkipDRQ)函数。
四、ATA命令
ATAPI是在ATA发展而来的,所以仍支持绝大部分的ATA命令。这些命令会直接送到Command寄存器后被ATAPI设备所执行。在这里只说明一下实例程序中所用到的一些相关命令。
1.ATAPI设备软复位命令(08H)
当向命令寄存器写入08H时,驱动器会执行软件复位命令,执行效果和硬件复位差不多。
2. 设备诊断(90H)
执行这个命令时,驱动器会运行自身诊断程序,诊断结束后会返回一个值到错误寄存器,读取错误寄存器值并和标准值比较,当返回值不等于01H或81H时则说明CDROM自身诊断未通过(Device0)。
3.识别信息包功能IDENTIFY PACKET DEVICE(A1H)
这个命令执行后可以返回当前所选择的驱动器的信息包参数和其它相关的参数,如信息包的长度、驱动器的型号、驱动器序列号等等。先向命令寄存器发A1H,然后就可以在DATA寄存器中读取驱动器相关信息,每次可以读取两个字节,应信息串的格式较长这里不再一一说明,可以参考文章结尾的网页地址中资料。
5. 信息包功能 PACKET(AOH)
执行这个命令后驱动器将准备发送信息包命令,在执行这个命令之前应先向 Cylinder Low/High寄存器写入将发送一个值为命令信息包的长度除于2的数值,以让驱动器知道要接收多少次数据。
限于篇幅有限更加详细的说明可以参看"Information Technology AT Attachment with Packet Interface Extension(ATA/ATAPI-4)"的第8章节或"ATA Packet Interface for CD-ROMs SFF-8020i"的第7章节。
五、信息包命令
上面提到发送PACKET命令后就可以发送信息包命令,信息包的格式会是什么样的?信息包又有什么功能?带着这样的问题我们来看看实例中的要用到的信息包命令。
ATAPI是在ATA发展过来的,最大的不同点就是有了针对CDROM等设备的信息包命令,实现两者的兼容。从上文可以得知发送PACKET命令后就可以发送信息包命令了,简单说来就是ATAPI设备在收到PACKET命令后就会进入信息包的接收状态,如信息包正常发送完成后,设备就会执行这个信息包命令。
信息包的格式一般由12字节组成,有些设备是16字节,对于这个值的确定可以用"识别信息包功能"读取信息值。首字节是指令字,以后的字节就是参数。这些字节的发送是这样实现的,选定DATA寄存器,把两个字节加在DD的十六位数据线上,控制DIOW为低,完成写入,再拉高DIOW,后两个字节加上数据线上……如此循环直到所有字节发送完。
文中的实例是针对CDROM中的CD播放功能的,那下面举几个CD播放要用到的信息包命令。
1.READ SUBCHANNEL读次信道命令
这个命令执行后驱动器会返回CD中的次信道信息和播放状态等。这些信息如:当前的MSF地址,当前的音频播放状态和当前的轨道数等。表5是它的格式,表6则是它的返回数据格式。具体的实现可以参考实例程序中的void ReadSub(void)函数。
Byte\Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
0 |
指令字(42H) |
1 |
保 留 |
MSF |
保 留 |
2 |
|
SubQ |
保 留 |
3 |
次信道数据格式 |
4 |
保 留 |
5 |
保 留 |
6 |
轨道数 |
7 |
MSB 分配长度
LSB |
8 |
9 |
保 留 |
10 |
保 留 |
11 |
保 留 |
表5 READ SUBCHANNEL读次信道命令
次信道数据格式字节可以设定返回数据的数式,一般使用01H,这样将返回CDROM当前位置上的次信道数据。返回的数据格式如表六。
Byte\Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
次信道数据报头 |
0 |
保 留 |
1 |
音频状态 |
2 |
MSB 次信道数据长度
LSB |
3 |
CDROM当前位置次信道数据区块 |
4 |
次信道数据格式字(01H) |
5 |
ADR |
Control |
6 |
当前曲目号 |
7 |
当前索引号 |
8 |
MSB 绝对地址
LSB |
9 |
10 |
11 |
12 |
MSB 轨道相对地址
LSB |
13 |
14 |
15 |
表6 次信道返回数据格式
2.READ TOC Command 读轨道TOC命令
TOC是指光盘中轨道的开始地址及其它相关信息,这些信息存在于Q sub-channel(Q子信道)中。当指定要播放一条曲目,就要先知道曲目所在轨道的开始地址和结束地址。这就需要用这个命令去读取光盘中轨道信息,它还将返回CD光盘的曲目数等。
Byte\Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
0 |
指令字(43H) |
1 |
保 留 |
MSF |
保留 |
2 |
保 留 |
返回数据格式 |
3 |
保 留 |
4 |
保 留 |
5 |
保 留 |
6 |
曲目号 |
7 |
MSB 分配长度
LSB |
8 |
9 |
返回数据格式 |
保 留 |
10 |
保 留 |
11 |
保 留 |
表7 读TOC命令
MSF位是要求返地址格式为MSF地址格式,这个位一般要置1。MSF地址格式是指光盘中的数据实际被写入的位置,最小单位是F,75个F字段则为一个S字段,而60个字段则为一个M字段。F字段的有效值范围为0-74,S字段的有效值范围为0-59,M字段的有效值范围为0-99。MSF地址的数据格式由4个字节组成,第一字节为保留字节,第二字节为M字段,第三字节为S字段,第四字节为F字段。
返回数据格式在第二字节和第九字节中,设它为的数值返回的数据形式也不同,在CD光盘播放中一般置零就可以了。
曲目号是指定要返回TOC数据的曲目号,它的有效值为00H-63H,也就是0-99号,当曲目号为AAH时则返回整张光盘的结束MSF地址。具体编程方法可以参看void ReadTOC(unsigned char Track)函数的写法。表八则是返回数据的格式。
Byte\Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
0 |
MSB TOC数据长度 |
1 |
LSB |
2 |
开始曲目号 |
3 |
结束曲目号 |
TOC轨道描述 |
4 |
保 留 |
5 |
ADR |
Control |
6 |
当前曲目号 |
7 |
保 留 |
8 |
MSB 绝对地址
(MSF地址格式)
LSB |
9 |
10 |
11 |
表8 读TOC命令返回数据格式(format字段为00H)
3.PLAY AUDIO MSF Command播放命令 当用读TOC命令得知曲目的MSF开始和结束地址数据后,就可以用播放命令去插放该曲目的音乐了。要播放单个曲子可以先读它的开始MSF地址做为开始地址,再读下一曲子的MSF地址做为结束地址。而播放整个光盘则可以先读首曲目的MSF地址做为开始地址,再用AAH去读最后的结束地址做为结束地址。播放命令的信息包格式如表九。
Byte\Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
0 |
指令字(47H) |
1 |
保 留 |
2 |
保 留 |
3 |
开始M字段 |
4 |
开始S字段 |
5 |
开始F字段 |
6 |
结束M字段 |
7 |
结束S字段 |
8 |
结束F字段 |
9 |
保 留 |
10 |
保 留 |
11 |
保 留 |
表9 PLAY AUDIO MSF Command播放命令
在这里透过简单的制作实例只能简单介绍这几个命令,而ATAPI所拥有的命令是非常丰富的,它里面还包括了CDRW,CDR,CDDA,CDROM等光盘的读写操作命令和设备的操作命令。
本文相关资料下载:demo_cdrom2cdplay.rar
|