打印
[STC单片机]

STC驱动硬盘

[复制链接]
947|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
changle11sdo5|  楼主 | 2016-8-10 20:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 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;
        }
}

相关帖子

沙发
80x86abc| | 2016-8-26 14:26 | 只看该作者
hao

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

29

主题

697

帖子

5

粉丝