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;
					}
					