吉吉影音非凡桔子:硬盘ide接口驱动程序——80C51

来源:百度文库 编辑:偶看新闻 时间:2024/04/28 06:39:06
硬盘ide接口驱动程序

/*********************************************************
硬盘ide接口驱动程序
CPU:AT89C51 CLOCK:24M
并行接口:82c55
**********************************************************/

#include
#include
#include "ide_interface.h"
sbit led = P3^5;


/* IDE初始化, 返回0,初始化失败.返回1,成功! */
uchar IDE_Init()
{
uchar status;
uint i=0;
IDE_Write(IDE_HEAD, 0xE0);
do {
status = IDE_Read(IDE_STATUS);
}
while(!(status & 0x40)|(status & 0x80));/* 等待RDY为"1" BSY为"0" */

IDE_Write(IDE_HEAD, 0x20);
IDE_Write(IDE_SECCNT, 64);

IDE_Write(IDE_COMMAND, IDE_CMD_INIT);

IDE_Busy();
//printf("Time out,device error!\n");

IDE_Write(IDE_COMMAND, IDE_CMD_RECAL);
IDE_Busy();
//printf("Time out,device error!\n");
return 1; //初始化成功!
}

/* 从硬盘读取一个扇区,放入到形参指定的内存中 */
void ReadSector(uint *addr, unsigned long LBA)
{
IDE_Busy();/* 等待硬盘空闲 */
WriteLBA(LBA);
IDE_Write(IDE_COMMAND,IDE_CMD_READ);
IDE_Ready();
ReadData(addr);
}


/* 向硬盘写一个扇区,返回零表示成功,否则失败。*/
uchar WriteSector(uint *addr, unsigned long LBA)
{
uchar i;
IDE_Busy();
WriteLBA(LBA);
IDE_Write(IDE_COMMAND,IDE_CMD_WRITE);
IDE_Ready();
WriteData(addr);
i = IDE_Busy();
if((i & 0x01)==0x01) {
i = GetError;
return i; /* 有错误发生,返回错误状态值 */
}
return 0;
}

/* 取得错误号*/
uchar GetError()
{
uchar res;
res = IDE_Read(IDE_ERR); /* 取出低位字节 */
return res;
}


/* 读取硬盘的标识。*/
void GetDriverId(uint *Buffer)
{
IDE_Busy();
IDE_Write(IDE_COMMAND,IDE_CMD_ID);
IDE_Ready();
ReadData(Buffer);
}

/* 激活硬盘(转动)。*/
void SpinUP()
{
IDE_Write(IDE_COMMAND,IDE_CMD_SPINUP);
IDE_Busy();
}

/* 让硬盘休眠(停转)。*/
void SpinDown()
{
IDE_Busy();
IDE_Write(IDE_COMMAND,IDE_CMD_SPINDOWN);
IDE_Busy();
}

 

/* 从硬盘读取512个字节。*/
void ReadData(uint xdata *Buffer)
{
uint i;

for(i = 0; i < 256; i ++)
{
*(Buffer ++) = IDE_Read(IDE_DATA);
}
}

 

/* 向硬盘写入512个字节。 */
void WriteData(uint xdata *Buffer)
{
uint i;

for(i = 0; i < 256; i ++)
{
IDE_Write(IDE_DATA, *(Buffer++));
}
}

 

/* 向设备寄存器写入逻辑块地址*/
void WriteLBA(unsigned long LBA)
{
uint tmp_data = 0;

tmp_data |= ((LBA&0xFF000000) >> 24);
tmp_data &= 0x0F;
tmp_data |= 0xE0;
IDE_Write(IDE_HEAD, tmp_data);

tmp_data = 0;
tmp_data |= ((LBA&0xFF0000) >> 16);
IDE_Write(IDE_MSB, tmp_data);

tmp_data = 0;
tmp_data |= ((LBA&0xFF00) >> 8);
IDE_Write(IDE_LSB, tmp_data);

tmp_data = 0;
tmp_data |= (LBA&0xFF);
IDE_Write(IDE_SECTOR, tmp_data);

IDE_Write(IDE_SECCNT, 1);

}


/* 等待IDE设备空闲,返回设备的状态. */
uchar IDE_Busy()
{
uchar res;
do
{
res = IDE_Read(IDE_STATUS);
}while(res & 0x80);

return res;
}

/* 等待设备空闲直到可以传送数据,返回设备的状态 */
uchar IDE_Ready()
{
uchar res;
do
{
res = IDE_Read(IDE_STATUS);
}while((res & 0x80)|(!(res & 0x08))); /* 等待DRQ=1,BSY=0 */

return res;
}

/* 通过8255读取硬盘数据(一个16位的字)。 */
uint IDE_Read(uchar reg)
{
uint temp; uchar res;
CFG_8255 = RD_IDE_8255; /* 8255为输入模式,读硬盘。*/
IDE_8255_CTL= reg;
reg |= IDE_RD;
IDE_8255_CTL= reg;
_nop_;
temp = IDE_8255_MSB;
temp = (temp<<8) & 0xFF00;
res = IDE_8255_LSB;

temp = temp|res;
IDE_8255_CTL = 0x00; /* 清除控制寄存器。*/
return temp;
}


/* 通过8255向硬盘写入一个字。 */
void IDE_Write(uchar reg,uint wr_data)
{
uchar tmp_data;
CFG_8255 = WR_IDE_8255; /* 8255为输出模式,写硬盘。*/
tmp_data = wr_data;
IDE_8255_LSB = tmp_data;/* 首先写LSB。 */
tmp_data = (wr_data>>8);
IDE_8255_MSB = tmp_data;/* 继续写MSB。 */
IDE_8255_CTL = reg;
reg |= IDE_WR;
IDE_8255_CTL = reg;
_nop_;
IDE_8255_CTL = 0x00;/* 清除控制寄存器。 */
CFG_8255 = RD_IDE_8255; /* 8255为输入模式,读硬盘。*/
}


/* 硬盘复位操作,当初始化结束后需要复位。 */
void IDE_Reset()
{
CFG_8255 = WR_IDE_8255;/* 8255为输出模式,写硬盘。 */
IDE_8255_CTL = IDE_RST;
delay(10);
IDE_8255_CTL = 0x00;/* 清除控制寄存器。 */
}

/* 延时函数,延时ms级别 */
void delay(uint length) {
uint i;
do {
for (i=0;i<500;i++) {
}
length--;
}
while(length>0);
}

//测试程序部分
void main () {
uint i=1; unsigned long CurrentSector;

IDE_Reset();

if(IDE_Init()==1) {
for(i=0;i<3;i++){
led=0;
delay(50);
led=1;
delay(50);
}
}

GetDriverId(0x6000);

CurrentSector=0x00AA0000;
i=0;
do {

ReadSector(0x7000,CurrentSector);
CurrentSector++;
i++;
}
while(i<1953); /* 读1MB的连续文件 */

SpinDown(); /* 硬盘停转 */
for ( ; ; ) {
}
}
/*********************************************************
硬盘ide接口驱动程序
CPU:AT89C51 CLOCK:24M
并行接口:82c55
**********************************************************/

#include
/***************type define****************/
#define uchar unsigned char
#define uint unsigned int
/******************************************/
/*以下是关于8255的一些定义:*/
#defineIDE_8255_LSB XBYTE[0x8000]/* 低8位 */
#defineIDE_8255_MSB XBYTE[0x8001]/* 高8位 */
#defineIDE_8255_CTL XBYTE[0x8002]
#defineCFG_8255 XBYTE[0x8003] /* 控制口 */
#defineRD_IDE_8255 0x92/*10010010b,8255输入 */
#defineWR_IDE_8255 0x80/*10000000b,8255输出 */

/*8255和IDE接口连接*/
#defineIDE_A0 0x01/* 8255和IDE接口直接相连 */
#defineIDE_A1 0x02/* 8255和IDE接口直接相连 */
#defineIDE_A2 0x04/* 8255和IDE接口直接相连 */
#defineIDE_CS0 0x08/* 8255和IDE接口通过74LS04反相后相连 */
#defineIDE_CS1 0x10/* 8255和IDE接口通过74LS04反相后相连 */
#defineIDE_WR 0x20/* 8255和IDE接口通过74LS04反相后相连 */
#defineIDE_RD 0x40/* 8255和IDE接口通过74LS04反相后相连 */
#defineIDE_RST 0x80/* 8255和IDE接口通过74LS04反相后相连 */

#defineIDE_DATAIDE_CS0
#defineIDE_ERRIDE_CS0 + IDE_A0
#defineIDE_SECCNTIDE_CS0 + IDE_A1
#defineIDE_SECTORIDE_CS0 + IDE_A1 + IDE_A0
#defineIDE_LSBIDE_CS0 + IDE_A2
#defineIDE_MSBIDE_CS0 + IDE_A2 + IDE_A0
#defineIDE_HEADIDE_CS0 + IDE_A2 + IDE_A1
#defineIDE_COMMANDIDE_CS0 + IDE_A2 + IDE_A1 + IDE_A0
#defineIDE_STATUSIDE_CS0 + IDE_A2 + IDE_A1 + IDE_A0
#defineIDE_CONTROLIDE_CS1 + IDE_A2 + IDE_A1
#defineIDE_ASTATUSIDE_CS1 + IDE_A2 + IDE_A1 + IDE_A0

/*IDE命令:*/
#defineIDE_CMD_RECAL 0x10
#defineIDE_CMD_READ 0x20
#defineIDE_CMD_WRITE 0x30
#defineIDE_CMD_INIT 0x91
#defineIDE_CMD_ID 0xEC
#defineIDE_CMD_SPINDOWN 0xE0
#defineIDE_CMD_SPINUP 0xE1

/*******************************函数定义*******************************/
uchar IDE_Init();
void ReadSector(uint *addr,unsigned long LBA);
uchar WriteSector(uint *addr, unsigned long LBA);
uchar GetError();
void GetDriverId(uint *Buffer);
void SpinUP();
void SpinDown();
void ReadData(uint xdata *Buffer);
void WriteData(uint xdata *Buffer);
void WriteLBA(unsigned long LBA);
uchar IDE_Busy();
uchar IDE_Ready();
uint IDE_Read(uchar reg);
void IDE_Write(uchar reg,uint wr_data);
void IDE_Reset();
void delay(uint length);
/**************************函数定义结束**********************************/