知識是屬于全人類的。能將自己的成果無條件與人共享是偉大和受人尊敬的,同時也是一件幸福的事。由于我想得到幸福和受人尊敬,所以我也開放我的工作成果。(其實也不算什么工作成果,匆匆忙忙用了一晚寫的,見笑了。在此感謝邵春偉同志,我在研究ata協議的時候參考了他寫的程序) 相信很多人都想用單片機控制硬盤來實現數據的海量儲存和開發一些東西(如硬盤mp3),但網上關于此方面的資料不多,而真正給出原代碼和電路的更是鳳毛麟角,而且就算給出原程序,但不知是因為是失誤或是本身還未理解好ata協議,抑或是出于對知識產權的保護問題,程序中有著或大或少的錯誤。本程序只是一個演示,還不是很完善,只是給你開發ata程序作一個參考,但我保證絕對可以使用。當然你可以修改和擴充一下,變成一個完善的ata驅動程序。 特征與使用 程序中所有與單片機本身硬件有關的參數都在程序開始處作出定義,移植到其他類型單片機時只需修改一下引腳定義就行了。使用時注意根據你的硬盤修改一下相應的參數(在程序中有注解)。 使用步驟與運行效果 連接好電路(很簡單),在把程序燒進芯片。先接通硬盤電源,再打開任意一個串口調試程序,把波特率設置成57600bps,再運行單片機即可。效果與下: 源程序: #include <at89x51.h> /************************************************** *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 D2D1 D0* BSYDRDYDWFDSC DRQCORRIDX 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); //8888888888888888888888 /******************************************************* :延遲函數 ********************************************************/ void delay(byte ms) { byte i,j; for(i=0;i<ms;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; } //88888888888888888888888888888888888888888 |