2009-6-30
				
				 
				
				
				51单片机硬盘控制电路以及源程序
				
				
				
				#include at89x51.h 
				
				
				
				#include 
				/**************************************************
				*                  
				HardDisk Control Demo 
				*     Power BY DDDLZHU
				*    编译环境 : KEIL C51 V7.07    支持器件 
				: AT89C51       
				*                    
				COPYRIGHT (C) 2004                      
				
				 
				***************************************************/
				#define byte unsigned char
				#define uint unsigned int
				/*************************************************
				//线路连接定义。如电路有变直接修改就可以了
				*************************************************/
				#define DataH P1              
				
				#define DataL P0
				#define RegAddr P2
				#define Read P3_4
				#define Write P3_3
				#define Rst P3_2
				/*************************************************
				//线路连接定义。如电路有变直接修改就可以了
				*************************************************/
				//寄存器地址定义
				#define _Status_Control 0x16
				#define _Data 0x8
				#define _Err_Features 0x9
				#define _SecCount 0xa
				#define _SecNum 0xb
				#define _CylinderL 0xc
				#define _CylinderH 0xd
				#define _DeviceAndHead 0xe
				#define _Status_Command 0xf
				//**************************************************************************************/
				/*这里为初始化硬盘的重要参数,每个硬盘的参数都不尽相同。若不正确则读不了盘中的数据。计算方法如下:
				先看清楚你的 硬盘表面标签中的数据,里面有三个重要参数:
				1。柱面数(Cylinder)
				2。磁头数(Head)
				3。磁道数(Sector)
				其中 _MaxHead=0xA+Head
     _MaxSector=Sector
				例如我的130M硬盘(很老吧,哈哈),磁头数为15,十六进制为0xf,所以_MaxHead=0xAF,磁道数为17,所以_MaxSector=0x11
				*/
				#define _MaxHead 0xAF
				#define _MaxSector 0x11
				//************************************************************************************
				byte bdata Status=0x00;
				sbit ERR=Status^0;
				sbit IDX=Status^1;
				sbit CORR=Status^2;
				sbit DRQ=Status^3;
				sbit DSC=Status^4;
				sbit DF=Status^5;
				sbit DRDY=Status^6;
				sbit BSY=Status^7;
				//************************************************************
				* D7   D6   D5   D4   D3   
				D2    D1   D0                    
				*
				BSY  DRDY  DWF  DSC DRQ  CORR  IDX   
				ERR                   
				*
				BSY:驱动器忙;                                             
				*
				DRDY:驱动器准备好;                                        
				*
				DWF:驱动器写失败;                                         
				*
				DSC:寻道结束;                                              
				*
				DRQ:请求服务,驱动器希望通过数据寄存器与CPU交换一字节数据;*
				CORR:当可以纠正的读错误发生时,该位置1,数据传输将继续进行 *
				IDX:收到综引信号;                                         
				*
				ERR:命令执行出错。                                         
				*
				*************************************************************/
				byte Data_bufferH=0x0;
				byte Data_bufferL=0x0;
				//***************串口子程序
				void send_string(unsigned char *word);
				void send_char(unsigned char word);
				unsigned char get_char(void);
				/*******************************************************
				:延迟函数                                   
				
				********************************************************/   
				
				void delay(byte ms)
				{ byte i,j;
				for(i=0;i      for(j=0;j<255;j++);
				}
				/*******************************************************
				*读寄存器
				********************************************************/
				byte ReadReg(byte Addr)
				{
				RegAddr=Addr;
				DataL=0xff;
				Read=0;
				Status=DataL;
				Read=1;
				return Status;
				}
				/*******************************************************
				*等待BSY信号
				********************************************************/
				byte WaitBSY(void)
				{
				byte timeOut=0;
				do{
  ReadReg(_Status_Command);
  timeOut++;
				//  if(timeOut>=254) return(0xff);
				}while(BSY);
				return(1);
				}
				/*****************************************************
				*写寄存器值
				********************************************************/
				void WriteReg(byte Addr,byte Data)
				{
				RegAddr=Addr;
				Write=0;
				DataL=Data;
				Write=1;
				}
				/*******************************************************
				读数据储存器中数据
				********************************************************/
				void ReadData(void)
				{
				DataH=0xff;
				DataL=0xff;
				RegAddr=_Data;
				Read=0;
				Data_bufferL=DataL;
				Data_bufferH=DataH;
				Read=1;
				}
				/*******************************************************
				写数据寄存器中数据
				********************************************************/
				void WriteData(void)
				{
				RegAddr=_Data;
				Write=0;
				DataL=Data_bufferL;
				DataH=Data_bufferH;
				Write=1;
				}
				/**********************************************************
				初始化硬盘                                          
				*
				***********************************************************/
				void Init(void)
				{ do{
  WriteReg(_DeviceAndHead,0xa0);
     ReadReg(_Status_Command);      
				
  }while(!DRDY|BSY);
    WriteReg(_DeviceAndHead,_MaxHead);
    WriteReg(_SecCount,_MaxSector);
    WriteReg(_Status_Command,0x91);
				WaitBSY();
    WriteReg(_Status_Command,0x10);
				WaitBSY();
				} 
				/**********************************************************
				读硬盘参数
				***********************************************************/
				
				void DriverID(void) 
				{
				unsigned int i=512;
				//send_string("Starting read driver ID\n");
				WaitBSY();
				//send_string("Now can read driver ID  \n");
				WriteReg(_Status_Command,0xec);
				//send_string("Waiting..  ");
				do{ReadReg(_Status_Command);}while(BSY|!DRQ);
				//send_string("Now Sending  \n");
				while(i){
				ReadData();
				send_char(Data_bufferH);
				send_char(Data_bufferL);
				i-=2;
				}
				}
				/*********************************************************
				硬盘寻址
				**********************************************************/
				WriteCHS(byte head,uint cylinder,byte sector,byte read_count)
				{
				WaitBSY();
				WriteReg(_DeviceAndHead,0xa0|head);
				WriteReg(_CylinderH,(char)(cylinder>>8)); 
				WriteReg(_CylinderL,(char)(cylinder&0x00ff));
				WriteReg(_SecNum,sector); 
				WriteReg(_SecCount,read_count);
				}
				/**********************************************************
				*用途:将硬盘的返回数据读入BUFFER数组
				***********************************************************/
				void SendData()
				{ uint i;
				i=512*15;
				do{ReadReg(_Status_Command);}while(BSY|!DRQ);
				if(ERR){send_string("\x0d\x0a Error\x0d\x0a");
    }
				while(i){ReadData();send_char(Data_bufferL);send_char(Data_bufferH);i-=2;}
				}
				// 激活硬盘(转动)
				void SpinUP()
				{
				WaitBSY();
  WriteReg(_Status_Command,0xE1);
				}
				// 让硬盘休眠(停转)/
				void SpinDown()
				{
				WaitBSY();
  WriteReg(_Status_Command,0xE0);
				}
				void main(void)
				{
				//Initialize 
				SCON=0x50;  //串口初始化
				TMOD=0x20;   //波特率为57600bps
				TCON=0x40;
				PCON=0x80;
				TH1=0xFf;
				TL1=0xFf;
				TR1=1;
				send_string("IDE Control Demo.     Power By 
				DDDLZHU\x0d\x0a");//send welcome word 
				Rst=0; //IDE 复位
				delay(50);
				Rst=1;
				delay(255);
				send_string("Reset Driver OK...\x0d\x0a");
				Init();   //初始化硬盘
				send_string("Initialize Driver OK,Now Read ID\x0d\x0a");
				send_string("HardDisk ID is ....\x0d\x0a");
				DriverID();  //读硬盘id
				send_string("\n\nNow Read The First Sector On this HardDisk\x0d\x0a\x0d\x0a");
				delay(244);
				delay(244);
				delay(244);
				delay(244);
				WriteCHS(0,0,1,16); //写地址
				WaitBSY();
				WriteReg(_Status_Command,0x20);   //发送读命令
				SendData();
				send_string("\x0d\x0a\x0d\x0a Read OK,Now Shut Down The HardDisk..\x0d\x0a");
				SpinDown();    //硬盘停转     
				
				while(1);
				}
				//**************************************串口子程序
				void send_char(unsigned char word)
				{ 
				TI=0;
				SBUF=word;
				while(TI==0);
				TI=0;
				}
				void send_string(unsigned char *word)
				{ 
				TI=0;
				while(*word!=0)
  {
  SBUF=*word;
  while(TI==0);
  TI=0;
  word++;
  }
				}
				unsigned char get_char(void)
				{ 
				RI=0;
				REN=1;
				while(RI==0);
				return(SBUF);
				RI=0;
				REN=0;
				}
				