硬盘存储在单片机上的应用
扫描二维码
随时随地手机看文章
8031 系列单片机是应用非常广泛的CPU,但随着控制领域不断智能化和复杂化,程序与数据空间可能远远大于64K字节的限制。在8031系列单片机上扩展硬盘接口,使存储容量只受到硬盘容量的限制,可以达到Gbyte级的容量。在需要大容量存储的应用场合,如数据库、图像处理、采样分析等场合,有着广泛的应用。
一、基本知识
1. IDE接口
在PC上,硬盘通过IDE40芯的扁平非屏蔽电缆与主板连接,数据和命令在其上异步传输。详细的信号描述请参照Information Technology -AT Attachment with Packet Interface - 6(ATA/ATAPI-6)协议。
2. 硬盘寄存器描述
与硬盘通信是通过IO寄存器来完成的,访问硬盘上的寄存器是由CS0FX,CS3FX,A2,A1,A0来译码完成的。硬盘的寄存器分为命令寄存器组和控制寄存器组。
详细说明如下:
1) 数据寄存器,在CS3FX为高电平,CS0FX,A2,A1,A0为低电平时选通,其地址为0x8000。单片机通过读写该寄存器与硬盘交互数据。
2) 错误信息寄存器,在CS3FX,A0为高电平,CS0FX,A2,A1为低电平时选通,其地址为0x8001。该寄存器为只读,寄存器位如置1代表不同的错误信息。
3)属性寄存器,在CS3FX,A0为高电平,CS0FX,A2,A1为低电平时选通,其地址为0x8001。该寄存器为只写,对该寄存器的操作可使硬盘工作在不同的模式。由于8031单片机为8位的数据总线,而硬盘默认为16位IO,需要对属性寄存器写0x01,使其工作在8位总线模式。
4) 扇区数目寄存器,在CS3FX,A1为高电平,CS0FX,A2,A0为低电平时选通,其地址为0x8002。其值表示需对硬盘读写的扇区数目,注意对硬盘的操作都是以扇区位单位,每个扇区包含512个字节,即每次对硬盘的数据读写都是512个字节的倍数。
5) LBA低8位地址寄存器,在CS3FX,A1,A0为高电平,CS0FX,A2为低电平时选通,其地址为0x8003。本文中对硬盘的操作是以LBA模式进行,即硬盘上的存储扇区映射成连续的逻辑块地址。要使能LBA模式,需要对模式寄存器的第6位置1。
6) LBA 地址8-15位寄存器,在CS3FX,A2为高电平,CS0FX,A1,A0为低电平时选通,其地址为0x8004。LBA地址共28位表示。
7) LBA 地址16-23位寄存器,在CS3FX,A2,A0为高电平,CS0FX,A1为低电平时选通,其地址为0x8005。
8)模式寄存器,在CS3FX,A2,A1为高电平,CS0FX,A0为低电平时选通,参照原理图1,其地址为0x8006。其低4位为LBA地址的24- 27位,第4位为主从硬盘选择位,若连接J1,则硬盘设为主设备,相应的第4位应为0;若断开J1,则硬盘为从设备,相应的第4位应置1。
9) 状态寄存器,在CS3FX, A2, A1, A0为高电平,CS0FX为低电平时选通,其地址为0x8007。该寄存器为只读。其中第7位若为1,表示硬盘处于忙状态,第3位若为1,表示数据准备好,等待传输。详细的检验程序请参照所附的程序。
10) 命令寄存器,在CS3FX, A2, A1, A0为高电平,CS0FX为低电平时选通,其地址为0x8007。该寄存器为只写。注意硬盘的命令有带参数和不带参数两种,在具有参数的命令操作时,需要首先写入所有的参数到各个寄存器,最后写命令寄存器。
二、硬件连接
8031单片机与硬盘的连接如图1所示。A0 A1 A2经74LS373锁存后,连接到硬盘的A0 A1 A2脚,因其工作在8位模式,硬盘的高8位数据线悬空。
J1用来选择主从硬盘,在连接J1时,该硬盘位主硬盘,否则为从硬盘。8031应检测P1.0上的电平,相应地设置模式寄存器的第4位。
P1.1用于硬复位硬盘,在低电平时有效。因8031不支持DMA模式,硬盘工作于PIO模式,所以DMA请求与应答信号悬空。所附软件工作于查询模式,中断请求信号悬空。
在硬盘读写操作时,DASP脚为低电平,相应的LED指示灯亮。
三、相应软件
以对硬盘写入和读出一个扇区为例,说明8031对硬盘的操作。流程图如图2所示。
现结合具体程序分析。为便于程序阅读,定义了如下的符号:
ReadSctr EQU 20h
WriteSctr EQU 30h
Data_Reg EQU 8000h ; 数据寄存器,可读写
Error_Reg EQU 8001h ; 错误信息寄存器,只读
Features EQU 8001h ; 属性寄存器,只写
Sectr_Cnt EQU 8002h ; 扇区数目寄存器,可读写
LBA0_7 EQU 8003h ; LBA低8位地址寄存器,可读写
LBA8_15 EQU 8004h ; LBA地址8-15位寄存器,可读写
LBA16_24 EQU 8005h ; LBA 地址16-23位寄存器,可读写
Drv_Head EQU 8006h ; 模式寄存器,可读写
Status EQU 8007h ; 状态寄存器, 只读
Command EQU 8007h ; 命令寄存器,只写
1) 检测主从硬盘并设置相应的模式寄存器子程序
功能为检测跳线设置,对模式寄存器写对应值,并置为LBA模式。
Init:
mov B, #11100000b ; D4=0 默认为主硬盘,LBA模式
jnb P1.0, master ; 若P1.0=0,为主硬盘
mov B, #11110000b ; D4=1 为对从硬盘操作
master:
mov dptr, #Drv_Head ; 对模式寄存器写入
mov a, B ;
movx @dptr, a
ret
2) 忙状态检测子程序
功能为,读状态寄存器,在BUSY=0和没有错误时,返回A=0和C=0。
Busy:
mov dptr, #status; 读状态寄存器
movx a, @dptr
jb acc.7, Busy; 在BUSY为高时,等待
jb acc.0, errors; 若第0位为1,表示有错误产生,跳转到error处理
clr a ; A C 为0表示非忙,没有错误
clr C ;
ret ;
errors:
mov dptr, #Error_Reg
movx a, @dptr; A中值表示错误指示
setb C ; C为1,表示有错误产生
ret
3) 等待数据准备好子程序
功能为,读状态寄存器,在BUSY=0,DRQ=1,没有错误时,返回A=0和C=0。
WaitDRQ:
mov dptr, #status; 读状态寄存器
movx a, @dptr
jb acc.7, WaitDRQ ; 在BUSY为高时,等待
jnb acc.3, WaitDRQ ; 在第3位DRQ为0时, 等待
jb acc.0, errors ; 若第0位为1,表示有错误产生,跳转到error处理
clr a
clr C ; A C 为0表示非忙,没有错误,数据已准备好
ret
4) 置硬盘工作在8位数据IO模式子程序
功能设置硬盘属性,使其工作在8位模式,与8031的8位数据总线配合。
Enable8bit:
acall Busy
mov dptr, #Features
mov a, #01h ; 使能8位模式
movx @dptr, a
mov dptr, #COMMAND
mov a, #0EFh; 0xEF为设置硬盘属性命令
movx @dptr, a
ret
5) 填充硬盘寄存器子程序
入口为R2(扇区数目),R3(LBA地址的b0-b7),R4(LBA地址的b8-b15), R5(LBA地址的b16-b23) ,R6(低4位为LBA地址的b24-b27), R7(命令字)
功能为将R2-R7中值写入到硬盘寄存器组。
Function:
acall Busy; 调用Busy子程序,如三.2)所述
mov dptr, #Sectr_Cnt; 扇区数目寄存器
mov a, R2 ; R2中值为扇区数目
movx @dptr, a
mov dptr, #LBA0_7; LBA地址的b0-b7寄存器
mov a, R3 ; R3中值为LBA地址的b0-b7
movx @dptr, a
mov dptr, #LBA8_15; LBA地址的b8-b15寄存器
mov a, R4 ; R4中值为LBA地址的b8-b15
movx @dptr, a
mov dptr, #LBA16_24; LBA地址的b16-b23寄存器
mov a, R5 ; R5中值为LBA地址的b16-b23
movx @dptr, a
mov dptr, #Drv_Head; 模式寄存器
mov a, R6 ; R6中值为低4位为LBA地址的b24-b27
anl a, #00001111b
orl a, B;B在Init子程序中已赋值.
movx @dptr, a
mov dptr, #command; 命令寄存器
mov a, R7 ; R7中值为命令字
movx @dptr, a
ret
6) 写扇区子程序
假定对LBA地址为0x0A的扇区写,
Write_Sctr:
mov R2, #1 ; 对R2-R7填入适当值,调用Function
mov R3, #0Ah ;
mov R4, #0
mov R5, #0
mov R6, #0
mov R7, #WriteSctr
acall Function
acall WaitDRQ
acall Write512
ret
Write512:
mov R0, #high(message) ; 取需写入信息的高位地址
mov R1, #low(message) ; 取需写入信息的低位地址
mov R7, #2 ; 512字节 = 2 * 256
mov R6, #0
write:
mov dph, R0 ;
mov dpl, R1
clr a
movc a, @a+dptr ; 读取信息的内容
inc dptr ; 指针指向下一个字节地址
mov R0, dph ;
mov R1, dpl
mov DPTR, #Data_Reg ; 数据寄存器
movx @dptr, a ; 写一个字节到硬盘
djnz R6, write
djnz R7, write ; 循环直到512个字节全部写完
ret
四、总结
由于篇幅所限,不详细介绍对硬盘的读操作,其流程类似于写操作。感兴趣读者可对照ATA协议规范,编写相应的驱动程序。对硬盘操作的ATA命令很多,可以通过ATA命令进行电源管理,读取硬盘参数,进行多个扇区的读写操作。欲详细了解对硬盘的操作,可参照最新的ATA-6协议。本文中,对硬盘的访问采用轮询模式,也可以使对硬盘的访问工作于中断模式,使其在BUSY=0或DRQ=1时触发中断。
在8031上,硬盘只可以工作在8位IO,PIO模式,依照本文的思路,可使硬盘工作于任何嵌入式系统中,工作于DMA模式或16位IO模式。