本帖最后由 changle11sdo5 于 2016-8-10 21:01 编辑
/***********************************
硬盘扇区读写驱动
STC12C5A60S2 *
晶振频率:11.0592Mhz *
***********************************/
#include <at89x52.h>
#include <intrins.h>
#include <string.h>
/*以下声明数据类型*/
#define u8 unsigned char
#define u16 unsigned int
#define u32 unsigned long
/*以下定义硬盘控制线 */
sbit CS0=P1^0;
sbit CS1=P1^1;
sbit DA0=P1^2;
sbit DA1=P1^3;
sbit DA2=P1^4;
sbit DataRead=P1^5;
sbit DataWrite=P1^6;
sbit HDD_Rst=P1^7;
/*以下声明硬盘的数据线接口*/
#define DataH P2
#define DataL P0
/*51单片机IO做输入时置高*/
#define IsInput 0xFF
//******************************************************************************
//ATA命令
// CB_ERR ERROR REGISTER BITS
#define ATA_ER_BBK 0x80 // ATA 坏块
#define ATA_ER_UNC 0x40 // ATA 错误校正
#define ATA_ER_MC 0x20 // ATA 媒介变化
#define ATA_ER_IDNF 0x10 // ATA 未找到ID号
#define ATA_ER_MCR 0x08 // ATA 媒体变更请求
#define ATA_ER_ABRT 0x04 // ATA 命令中止
#define ATA_ER_NTK0 0x02 // ATA 磁道0找不到
#define ATA_ER_NDAM 0x01 // ATA 地址标记未找到
// CB_DH bits 7-4 OF THE DEVICE/HEAD REGISTER
#define ATA_DH_DEV0 0xE0 // 选择设备0 LBA模式
#define ATA_DH_DEV1 0xF0 // 选择设备1 LBA模式
//ATA 命令 (来自 ATA-3),
#define CMD_CFA_ERASE_SECTORS 0xC0
#define CMD_CFA_REQUEST_EXT_ERR_CODE 0x03
#define CMD_CFA_TRANSLATE_SECTOR 0x87
#define CMD_CFA_WRITE_MULTIPLE_WO_ERASE 0xCD
#define CMD_CFA_WRITE_SECTORS_WO_ERASE 0x38
#define CMD_CHECK_POWER_MODE1 0xE5
#define CMD_CHECK_POWER_MODE2 0x98
#define CMD_DEVICE_RESET 0x08
#define CMD_EXECUTE_DEVICE_DIAGNOSTIC 0x90
#define CMD_FLUSH_CACHE 0xE7
#define CMD_FORMAT_TRACK 0x50
#define CMD_IDENTIFY_DEVICE 0xEC
#define CMD_IDENTIFY_DEVICE_PACKET 0xA1
#define CMD_IDENTIFY_PACKET_DEVICE 0xA1
#define CMD_IDLE1 0xE3
#define CMD_IDLE2 0x97
#define CMD_IDLE_IMMEDIATE1 0xE1
#define CMD_IDLE_IMMEDIATE2 0x95
#define CMD_INITIALIZE_DRIVE_PARAMETERS 0x91
#define CMD_INITIALIZE_DEVICE_PARAMETERS 0x91
#define CMD_NOP 0x00
#define CMD_PACKET 0xA0
#define CMD_READ_BUFFER 0xE4
#define CMD_READ_DMA 0xC8
#define CMD_READ_DMA_QUEUED 0xC7
#define CMD_READ_MULTIPLE 0xC4
#define CMD_READ_SECTORS 0x20
#define CMD_READ_VERIFY_SECTORS 0x40
#define CMD_RECALIBRATE 0x10
#define CMD_SEEK 0x70
#define CMD_SET_FEATURES 0xEF
#define CMD_SET_MULTIPLE_MODE 0xC6
#define CMD_SLEEP1 0xE6
#define CMD_SLEEP2 0x99
#define CMD_STANDBY1 0xE2
#define CMD_STANDBY2 0x96
#define CMD_STANDBY_IMMEDIATE1 0xE0
#define CMD_STANDBY_IMMEDIATE2 0x94
#define CMD_WRITE_BUFFER 0xE8
#define CMD_WRITE_DMA 0xCA
#define CMD_WRITE_DMA_QUEUED 0xCC
#define CMD_WRITE_MULTIPLE 0xC5
#define CMD_WRITE_SECTORS 0x30
#define CMD_WRITE_VERIFY 0x3C
//******************************************************************************
//硬盘状态寄存器地址定义
#define _Data 0x0
#define _Err_Features 0x1
#define _SecCount 0x2
#define _SecNum 0x3
#define _CylinderL 0x4
#define _CylinderH 0x5
#define _DeviceAndHead 0x6
#define _Status_AND_Command 0x7
/************************************************************
* D7 D6 D5 D4 D3 D2 D1 D0 *
BSY DRDY DWF DSC DRQ CORR IDX ERR *
BSY:驱动器忙; 1:忙 *
DRDY:驱动器准备好; 1:准备好 *
DWF:驱动器写失败; *
DSC:寻道结束; *
DRQ:请求服务,驱动器希望通过数据寄存器与CPU交换一字节数据 *
CORR:当可以纠正的读错误发生时,该位置1,数据传输将继续进行 *
IDX:收到综引信号; *
ERR:命令执行出错。 *
*************************************************************/
u8 bdata HDstate;
sbit BSY =HDstate ^7;
sbit DRDY =HDstate ^6;
sbit DWF =HDstate ^5;
sbit DSC =HDstate ^4;
sbit DRQ =HDstate ^3;
sbit CORR =HDstate ^2;
sbit IDX =HDstate ^1;
sbit ERR =HDstate ^0;
u8 HDDATAL;
u8 HDDATAH;
/*
以下是提供给用户调用的接口
*/
void DelayXms(u16 xms); //延时n毫秒
void HDD_Init(void); //硬盘初始化
void HDD_Reset(void); //硬盘复位
void HDRunning(void); //使硬盘运行
void HDStop(void); //使硬盘停止运行
void Read_HDD_ID(u8 *HDDBuffer); //读取硬盘ID
void WriteSectorData(u32 longSectorAddr, u8 *DataBuffer);//写一个扇区数据(512 byte)
void ReadSectorData(u32 longSectorAddr, u8 *DataBuffer); //读一个扇区数据(512 byte)
/*
以下函数用户不需要直接调用
*/
void Delay1ms();
void LBA(u32 lba);
void WriteCHS(u16 iCylinder,u8 byHead,u8 bySector,u8 byReadCount);
u8 WaitBsy(void);
u8 WaitDRQ(void);
u8 ReadReg(u8 RegAddr);
void ReadData(void);
void WriteReg(u8 RegAddr, u8 RegData);
void WriteData(u8 wDataL, u8 wDataH);
void RegAddrToPhysics(u8 RegAddr);
void Serial_Init();
void SendStr(u8 *str);
void SendByte(u8 byt);
#define BUF_SIZE 512
#define Dat_Addr 100
u8 buf[BUF_SIZE];
u8 com;
void main(void)
{
int i;
Serial_Init();
SendStr("即将开始测试硬盘... \r\n");
HDD_Reset(); //硬盘复位
SendStr("硬盘复位成功... \r\n");
DelayXms(1000);
DelayXms(1000);
// HDRunning();
// SendStr("开始运行硬盘\r\n");
// HDStop();
// SendStr("停止运行硬盘...\r\n");
HDD_Init(); //硬盘初始化
SendStr("硬盘初始化成功\r\n");
for(i=0;i<BUF_SIZE;i++)
{
buf=128;
}
SendStr("填充数据缓冲成功\r\n");
WriteSectorData(Dat_Addr, buf);
SendStr("写入扇区数据成功\r\n");
for(i=0;i<BUF_SIZE;i++)
{
buf=0;
}
SendStr("清空数据缓冲成功...\r\n");
DelayXms(10);
ReadSectorData(Dat_Addr,buf);
SendStr("读取扇区数据成功\r\n");
SendStr(buf);
while(1)
{
P3_7=1;
P3_6=1;
if(P3_7==0)
{
while(P3_7==0);
HDRunning();
}
if(P3_6==0)
{
while(P3_6==0);
HDStop();
}
}
}
void Serial_Init() // 11.0592Mhz
{
TMOD=0X20; //定时器T1使用方式2
TH1=253; //设定初值
TL1=253;
// TH1=250; //设定初值
// TL1=250;
// PCON=0X80; //SMOD=1,波特率加倍
TR1=1; //启动定时器T1
SCON=0X50; //串口工作方式1,波特率9600bit/s ,REN=1允许接收
REN=1;
ES=1; //打开/关闭串口中断
TI=0;
//PS=1;
EA=1;
}
void SendStr(u8 *str)
{
unsigned int i,sLEN=strlen(str);
for(i=0;i<sLEN;i++)
{
ES=0;
SBUF=str;
while(!TI);
TI=0;
ES=1;
}
}
void SendByte(u8 byt)
{
ES=0;
SBUF=byt;
while(!TI);
TI=0;
ES=1;
}
void Delay1ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
void DelayXms(u16 xms)
{
while((xms--)!=0)
{
Delay1ms();
}
}
void RegAddrToPhysics(u8 RegAddr)
{
CS0=0;
CS1=1;
switch(RegAddr)
{
case _Data: DA0=0; DA1=0; DA2=0; break;
case _Err_Features: DA0=1; DA1=0; DA2=0; break;
case _SecCount: DA0=0; DA1=1; DA2=0; break;
case _SecNum: DA0=1; DA1=1; DA2=0; break;
case _CylinderL: DA0=0; DA1=0; DA2=1; break;
case _CylinderH: DA0=1; DA1=0; DA2=1; break;
case _DeviceAndHead: DA0=0; DA1=1; DA2=1; break;
case _Status_AND_Command: DA0=1; DA1=1; DA2=1; break;
}
}
void WriteReg(u8 RegAddr, u8 RegData)
{
RegAddrToPhysics(RegAddr);
DataL=RegData;
DataWrite=0;
_nop_(); _nop_(); _nop_(); _nop_();
DataWrite=1;
}
void WriteData(u8 wDataL, u8 wDataH)
{
RegAddrToPhysics(_Data);
DataL=wDataL;
DataH=wDataH;
DataWrite=0;
_nop_(); _nop_(); _nop_(); _nop_();
DataWrite=1;
}
u8 ReadReg(u8 RegAddr)
{
u8 temp;
RegAddrToPhysics(RegAddr);
DataRead=0;
_nop_(); _nop_(); _nop_(); _nop_();
temp=DataL;
_nop_(); _nop_(); _nop_(); _nop_();
DataRead=1;
return temp;
}
void ReadData(void)
{
// DataH=IsInput;
// DataL=IsInput;
RegAddrToPhysics(_Data);
DataRead=0;
_nop_(); _nop_(); _nop_(); _nop_();
HDDATAL=DataL;
HDDATAH=DataH;
DataRead=1;
}
void Read_HDD_ID(u8 *HDDBuffer)
{
u16 i,b;
do{
HDstate=ReadReg(_Status_AND_Command);
}while(BSY);
do{
HDstate=ReadReg(_Status_AND_Command);
}while((!DRQ)||BSY);
for(i=0;i<256;i++)
{
WaitDRQ();
ReadData();
HDDBuffer[b++]=HDDATAL;
HDDBuffer[b++]=HDDATAH;
}
}
u8 WaitBsy(void)
{
do{
HDstate= ReadReg(_Status_AND_Command);
}while(BSY);
return (1);
}
u8 WaitDRQ(void)
{
do{
HDstate=ReadReg(_Status_AND_Command);
}while(DRQ);
return (1);
}
void HDRunning(void)
{
u8 temp;
temp=WaitBsy();
if(1==temp)
{
WriteReg(_Status_AND_Command,0xE1);
}
}
void HDStop(void)
{
u8 temp;
temp= WaitBsy();
if(1==temp)
{
WriteReg(_Status_AND_Command,0xE0);
}
}
void LBA(u32 lba)
{
WriteReg(6,0xe0+(lba>>24));
WriteReg(5,(lba>>16));
WriteReg(4,(lba>>8));
WriteReg(3,(lba));
WriteReg(2,1);
}
void WriteCHS(u16 iCylinder,u8 byHead,u8 bySector,u8 byReadCount)
{
WaitBsy();
WriteReg(_DeviceAndHead,0x40|byHead);
WriteReg(_CylinderH,(u8)(iCylinder>>8));
WriteReg(_CylinderL,(u8)(iCylinder&0x00ff));
WriteReg(_SecNum,bySector);
WriteReg(_SecCount,byReadCount);
}
void ReadSectorData(u32 longSectorAddr, u8 *DataBuffer)
{
u16 i,bAddend=0;
LBA(longSectrAddr);
WriteReg(_Status_AND_Command,CMD_READ_SECTORS);//0x20 读扇区数据命令
for(i=0;i<256;i++)
{
WaitDRQ();
ReadData();
DataBuffer[bAddend++]=HDDATAL;
DataBuffer[bAddend++]=HDDATAH;
}
}
void WriteSectorData(u32 longSectorAddr, u8 *DataBuffer)
{
u16 i,bAddend=0;
LBA(longSectorAddr);
WriteReg(_Status_AND_Command,CMD_WRITE_SECTORS);//Ox30 写扇区数据命令
for(i=0;i<256;i++)
{
HDDATAL=DataBuffer[bAddend++];
HDDATAH=DataBuffer[bAddend++];
WaitDRQ();
WriteData(HDDATAL,HDDATAH);
}
}
void HDD_Reset(void)
{
DelayXms(1O);
HDD_Rst=O;
DelayXms(4O);
HDD_Rst=1;
DelayXms(1O);
}
void HDD_Init(void)
{
u8 temp;
DataWrite=1;
DataRead=1;
// CS0=1;
// CS1=0;
// 控制寄存器
CS0=0;
CS1=1;
//命令寄存器
WriteReg(_DeviceAndHead,0xa0);
SendStr("Write DeviceAndHead Suc \r\n");
do{
WriteReg(_DeviceAndHead,0xa0);
HDstate= ReadReg(_Status_AND_Command);
}while((!DRDY)|BSY);
if(BSY)
{
SendStr("硬盘忙\r\n");
}
if(!DRDY)
{
SendStr("硬盘没有准备好\r\n");
}
SendStr("硬盘不忙了...\r\n");
WriteReg(_DeviceAndHead,0x40); //磁头数 需要根据实际硬盘参数填写
WriteReg(_SecCount,0x3c); //磁道数 需要根据实际硬盘参数填写
WriteReg(_Status_AND_Command,CMD_INITIALIZE_DRIVE_PARAMETERS); //0x91
WaitBsy();
WriteReg(_Status_AND_Command,CMD_RECALIBRATE); //0x10
WaitBsy();
}
void usart() interrupt 4
{
if(RI)
{
RI=0;
com=SBUF;
if(com==1){
com=0;
HDRunning();
}else if(com==2)
{
com=0;
HDStop();
}else if(com==3)
{
SendByte(HDstate);
}
}else{
TI=0;
}
}
|
|