硬盘控制源程序
2012-08-03
邵春伟
标签: 硬盘控制




/*******************************************************************
*           硬盘控制源程序               *
*  创建日期: 2004/3/5                      *
*  版本 : VER 1.0     最近修改日期 : 2004/3/6        *
*  作者:邵春伟      最近修改时间 : 23:48         *
*  编译环境 : KEIL C51 V7.07  支持器件 : AT89C51       *
*          COPYRIGHT (C) 2004              *
/*******************************************************************/

///////////////////预处理/////////////////////////////////////
#include <reg51.h>
#include <absacc.h>
#define uchar unsigned char
#define uint unsigned int
#define KEYPORT P1
#define LCDCOM XBYTE[0x0008]//LCD命令寄存器
#define LCDDATA XBYTE[0x0009]//LCD数据寄存器
#define CDPA XBYTE[0x0004]//8255 PORT A, harddisk D0-D7
#define CDPB XBYTE[0x0005]//8255 PORT B, harddisk D8-D15
#define CDPC XBYTE[0x0006]//8255 PORT C,harddisk address
#define CDCOM XBYTE[0x0007]//8255 命令寄存器
#define FILE0 0x00//硬盘数据寄存器     
#define FILE1 0x01//错误/特征寄存器
#define FILE2 0x02//扇区数寄存器
#define FILE3 0x03//扇区号寄存器
#define FILE4 0x04//柱面号寄存器L
#define FILE5 0x05//柱面号寄存器H
#define FILE6 0x06//驱动器/磁头寄存器
#define FILE7 0x07//状态/命令寄存器
static uchar code LCD1[16] = "TOPLOW DESIGN  ";
static uchar code LCD2[16] = "Copyright(C)2004";
static uchar code ERROR[16] = "ERROR      ";
static uchar code PASS[16] = "PASS      ";
uchar buffer0, buffer1;
uchar buffer[16];
uchar STATUS;
///////////////////位设置///////////////////////////
sbit BFLAG = ACC ^ 7;
sbit BSY = ACC ^ 7;
sbit DRDY = ACC ^ 6;
sbit DRQ = ACC ^ 3;
sbit ERR = ACC ^ 0;
sbit RESET = P3 ^ 5;
sbit READ = P3 ^ 0;
sbit WRITE = P3 ^ 1;
sbit ILT = ACC ^ 0;
sbit INTRQ = P3 ^ 3;
/************************************************************
* 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:命令执行出错。                     *
*************************************************************/
/*******************************************************
*函数名称:void delay(uint time)            *
*函数用途:延迟函数                   *
********************************************************/
void delay(uint time)
{
    uint i, j;
    for (i = 0; i < time; i++)
        for (j = 0; j < 255; j++);
}

/*******************************************************
*函数名称:void putch(unsigned char ch)         *
*函数用途:串口发送程序                 *
********************************************************/
void putch(unsigned char ch)
{
    SBUF = ch;
    TI = 0;
    while (!TI);
}

/*******************************************************
*函数名称:unsigned char getch(void)          *
*函数用途:串口接收程序                 *
********************************************************/
unsigned char getch(void)
{
    uchar temp;
    while (!RI);
    temp = SBUF;
    RI = 0;
    return (temp);
}

/*******************************************************
*函数名称:void wait(void)               *
*函数用途:LCD忙等待                  *
********************************************************/
void wait(void)
{
    do {
        ACC = LCDCOM;
    }
    while (BFLAG == 1);
}

/*******************************************************
*函数名称:void IniLcd(void)              *
*函数用途:LCD初始化函数                *
********************************************************/
void IniLcd(void)
{
    LCDCOM = 0x38;
    wait();
    LCDCOM = 0x08;
    wait();
    LCDCOM = 0x01;
    wait();
    LCDCOM = 0x06;
    wait();
    LCDCOM = 0x0c;
    wait();
}

/***********************************************************************
*函数名称:void LcdDis(uchar FL,uchar Lcd1[16],uchar SL,uchar Lcd2[16]) *
*函数用途:液晶显示函数                         *
************************************************************************/
void LcdDis(uchar FL, uchar Lcd1[16], uchar SL, uchar Lcd2[16])
{
    uchar k;
    LCDCOM = FL | 0x80;
    wait();
    for (k = 0; k < 16; k++) {
        LCDDATA = Lcd1[k];
        wait();
    }
    LCDCOM = SL | 0xc0;
    wait();
    for (k = 0; k < 16; k++) {
        LCDDATA = Lcd2[k];
        wait();
    }
}

/*******************************************************
*函数名称:void ReadReg(uchar ADD)           *
*函数用途:读硬盘非数据寄存器内容,并将结果返回     *
********************************************************/
void ReadReg(uchar ADD)
{
    CDCOM = 0x92;
    CDPC = ADD;
    READ = 0;
    ACC = CDPA;
    STATUS = ACC;
    READ = 1;
}

/*******************************************************
*函数名称:void WriteReg(uchar ADD,uchar DATA)     *
*函数用途:写硬盘非数据寄存器内容            *
********************************************************/
void WriteReg(uchar ADD, uchar DATA)
{
    CDCOM = 0x80;
    CDPC = ADD;
    WRITE = 0;
    CDPA = DATA;
    WRITE = 1;
}

/*******************************************************
*函数名称:void ReadData()               *
*函数用途:读硬盘数据寄存器内容             *
********************************************************/
void ReadData()
{
    CDCOM = 0x92;
    CDPC = FILE0;
    READ = 0;
    buffer0 = CDPA;
    buffer1 = CDPB;
    READ = 1;
}

/*******************************************************
*函数名称:void WriteData(uchar Data0,uchar Data1)   *
*函数用途:写硬盘数据寄存器内容             *
********************************************************/
void WriteData(uchar Data0, uchar Data1)
{
    CDCOM = 0x80;
    CDPC = FILE0;
    WRITE = 0;
    CDPA = Data0;
    CDPB = Data1;
    WRITE = 1;
}

/*********************************************************
*函数名称:WriteCHS(uint cylinder,uchar head,uchar sector)*
*函数用途:写CHS信息(地址信息)              *
**********************************************************/
WriteCHS(uchar head, uint cylinder, uchar sector)
{
    do {
        ReadReg(FILE7);
    }
    while (BSY);
    WriteReg(FILE6, 0xe0 & head);
    WriteReg(FILE5, cylinder >> 8); //high 2-bit cylinder
    WriteReg(FILE4, cylinder & 0x00ff); //low 8-bit cylinder
    WriteReg(FILE3, sector); //start sector
    WriteReg(FILE2, 0x01); //sector counter
}

/*********************************************************
*函数名称:WriteCommand(command)             *
*函数用途:写命令                     *
**********************************************************/
WriteCommand(command)
{
    do {
        ReadReg(FILE7);
    }
    while (BSY);
    WriteReg(FILE7, command);
}

/**********************************************************
*函数名称:GetData()                    *
*用途:将硬盘的返回数据读入BUFFER数组           *
***********************************************************/
void GetData()
{
    uint i = 512;
    do {
        ReadReg(FILE7);
    }
    while (BSY | !DRQ);
    if (ERR) {
        LcdDis(0, ERROR, 0, LCD2);
        putch(255);
    }
    while (i) {
        ReadData();
        putch(buffer0);
        putch(buffer1);
        i -= 2;
    }
}

/**********************************************************
*函数名称:void IniHard(void)               *
*用途:初始化硬盘                     *
***********************************************************/
void IniHard(void)
{
    do {
        WriteReg(FILE6, 0xa0);
        ReadReg(FILE7);
    }
    while (!DRDY | BSY);
    WriteReg(FILE6, 0x20);
    WriteReg(FILE2, 64);
    WriteReg(FILE7, 0x91);
    do {
        ReadReg(FILE7);
    }
    while (BSY);
    WriteReg(FILE7, 0x10);
    do {
        ReadReg(FILE7);
    }
    while (BSY);
}

/**********************************************************
*函数名称:void DriveID(void)               *
*用途:读硬盘ID                      *
***********************************************************/
void DriveID(void)
{
    uint i = 512;
    do {
        ReadReg(FILE7);
    }
    while (BSY);
    WriteReg(FILE7, 0xec);
    do {
        ReadReg(FILE7);
    }
    while (BSY | !DRQ);
    while (i) {
        ReadData();
        putch(buffer0);
        putch(buffer1);
        i -= 2;
    }
}

/*******************************************************
*函数名称:主函数                    *
*函数用途:                       *
********************************************************/
void HardDiskControl(void)
{
    uint i;
    SCON = 0x50; //方式1,串行口接收允许位
    TMOD = 0x21; //定时器1用于串行通信波特率发生,定时器0用于REMOTE接收判断0,1时间
    PCON = 0x80; //串行波特率加倍位
    TCON = 0x51; //启动计数器0,计数器1
    EA = 1; //中断允许
    EX0 = 0; //外部中断0不允许
    TH1 = 0xD0;
    TL1 = 0xD0;
    TI = 1;

    RESET = 0;
    delay(50);
    RESET = 1;
    delay(255);

    IniHard();
    //DriveID();
    WriteCHS(0, 0, 0);
    WriteCommand(0x20);
    GetData();

    IniLcd();
    LcdDis(0, LCD1, 0, LCD2);

    for (i = 0; i < 512; i++) {
        putch(i);
        delay(255);
    }

    while (1);
}

void main(void)
{
    HardDiskControl();
}


可能会用到的工具/仪表
相关文章
推荐文章
热门文章
章节目录
本站简介 | 意见建议 | 免责声明 | 版权声明 | 联系我们
CopyRight@2024-2039 嵌入式资源网
蜀ICP备2021025729号