Ответ: (+)
(«Телесистемы»: Конференция «Микроконтроллеры и их применение»)

миниатюрный аудио-видеорекордер mAVR

Отправлено Max_Fly 15 сентября 2004 г. 09:49
В ответ на: Ответ: Кстати кто-то уже этим занимался - не могу найти ,,,,, отправлено dimafreebsd 15 сентября 2004 г. 09:35


// --------------------------------------- -------------------------------------
// IDE 19960417 CHG
// Маленький и простий интерфейс для "стандарта" IDE соединенния жесткого диска
// с 8051 центральным процессором, в этом случае используется DS5000, но весь другой 8051 совместимый
// центральный процессор мог бы использоваться, если они имеют некоторое внешнее ОЗУ, 1KByte или более
//
// Этот код обеспечивается, как, без ответственности автором!
// То есть. Это - использование на вашем собственном риске!!!!!
//
// Сделанный
// Carsten Groen, OZ9AAR
// Kaervaenget 46, Gl. Единственно
// DK-8722 Hedensted
// Дания
// Email: cgroen image.dk
//
// --------------------------------------- -------------------------------------
#include
#include
#include
#include
#include

//----------------------------------------------------------------------------
// Constants...
//----------------------------------------------------------------------------
#define TRUE 1
#define FALSE 0
#define CTRL 0
#define CMD 1
#define DRIVE0 0

//----------------------------------------------------------------------------
// Types
//----------------------------------------------------------------------------
typedef xdata struct {
unsigned char Heads;
unsigned int Tracks;
unsigned int SectorsPerTrack;
char Model[41];
} tdefDriveInfo;

//----------------------------------------------------------------------------
// I/O definitions...
// The IDE harddisk is just connected DIRECTLY to these I/O ports on the 8051
// See pin numbers on IDC connecter on IDE drive in one of the attached files.
// REMEMBER to make a pullup on the P0 port (ex 4.7 K to vcc from each of the
// 8 P0 pins
//----------------------------------------------------------------------------
#define nCS1FX P0_0
#define nCS3FX P0_1
#define DA0 P0_2
#define DA1 P0_3
#define DA2 P0_4
#define nDASP P0_5
#define LSBDATA P1
#define MSBDATA P2
#define nDIOR P0_6
#define nDIOW P0_7
#define INTRQ P3_2
#define IORDY P3_3
#define RESET P3_4

#define ALLINPUT 0xFF

//----------------------------------------------------------------------------
// Variables...
//----------------------------------------------------------------------------
xdata unsigned int Timer10mSec=0; // General timer, tick is 10 mSec
xdata unsigned char SectorBuffer[512];


//----------------------------------------------------------------------------
// Wait for a specific time in 10 mSec
// Based on a 11.0592 Mhz crystal
//----------------------------------------------------------------------------
void Delay(unsigned char t) {
xdata unsigned int i;
if (t==0) return;
while (t--) for(i=0;i<774; i++);
}

//----------------------------------------------------------------------------
// Dump a buffer as a hex listing
//----------------------------------------------------------------------------
void HexDump( void *Dataa, int Len ) {
xdata unsigned char *Data=Dataa;
xdata unsigned char Line[80], *CurLine, *CurData;
xdata int linelen, j;
xdata unsigned short rc;
xdata unsigned char tmp;

printf( "*************** HEX-DUMP ***************\n" );
while( Len ){
linelen = Len < 16 ? Len : 16;
*Line='\0';
CurLine = Line;

for( CurData=Data, j=0; j tmp=*CurData;
sprintf( CurLine, "%02BX ", tmp);
CurLine+=3; CurData++;
}

for( j=linelen; j<17; j++ ) {
*CurLine =' ';
CurLine[1]=' ';
CurLine[2]=' ';
CurLine+=3;
}

for( j=0; j sprintf( CurLine, "%c ", *Data > ' ' ? *Data : '_' );
Data++;CurLine+=1;
}
printf( Line );
printf("\n");
Len-=linelen;
}
rc = printf( "*************** HEXEND ***************\n" );
}

//----------------------------------------------------------------------------
// Timer 0 interrupt service function
// executes each 10 mSec @ 11.0592 MHz Crystal Clock
//----------------------------------------------------------------------------
void timer0(void) interrupt 1 using 1 {
TH0 = 0xDC; // reload timer again
TL0 = 0x00; // to 10 mSec timeout
TR0 = 1;
if (Timer10mSec) Timer10mSec--;

}

//----------------------------------------------------------------------------
// Show state of nDASP, INTRQ and IORDY signals
//----------------------------------------------------------------------------
void ShowInputs(void) {
printf("Signals from Drive: nDASP=%s, INTRQ=%s, IORDY=%s\n",
nDASP ? "FALSE":"TRUE", INTRQ ? "TRUE":"FALSE", IORDY ? "TRUE":"FALSE");
}

//----------------------------------------------------------------------------
// Select address and CS signals
//----------------------------------------------------------------------------
void SetAddress(unsigned char cs, unsigned char adr) {
DA0=((adr & 0x01)==0x01);
DA1=((adr & 0x02)==0x02);
DA2=((adr & 0x04)==0x04);
if (cs==CTRL) {
nCS1FX=1;
nCS3FX=0;
} else {
nCS1FX=0;
nCS3FX=1;
}
}

//----------------------------------------------------------------------------
// Read data WORD from Drive
//----------------------------------------------------------------------------
unsigned int ReadWORD(unsigned char cs, unsigned char adr) {
xdata unsigned int tmp;
MSBDATA=ALLINPUT;
LSBDATA=ALLINPUT;
SetAddress(cs,adr);
nDIOR=0;
tmp=(MSBDATA<<8)+LSBDATA;
nDIOR=1;
nCS1FX=1;
nCS3FX=1;
return tmp;
}

//----------------------------------------------------------------------------
// Read data BYTE from Drive
//----------------------------------------------------------------------------
unsigned char ReadBYTE(unsigned char cs, unsigned char adr) {
xdata unsigned char tmp;
MSBDATA=ALLINPUT;
LSBDATA=ALLINPUT;
SetAddress(cs,adr);
nDIOR=0;
tmp=LSBDATA;
nDIOR=1;
nCS1FX=1;
nCS3FX=1;
return tmp;
}

//----------------------------------------------------------------------------
// Write data WORD to Drive
//----------------------------------------------------------------------------
void WriteWORD(unsigned char cs, unsigned char adr, unsigned int dat) {
SetAddress(cs,adr);
// OBS MSB/LSB is swapped (see writeSector function)
MSBDATA=dat;
LSBDATA=(dat>>8);
nDIOW=0;
nDIOW=1;
nCS1FX=1;
nCS3FX=1;
}

//----------------------------------------------------------------------------
// Write data BYTE to Drive
//----------------------------------------------------------------------------
void WriteBYTE(unsigned char cs, unsigned char adr, unsigned char dat) {
SetAddress(cs,adr);
MSBDATA=0;
LSBDATA=dat;
nDIOW=0;
nDIOW=1;
nCS1FX=1;
nCS3FX=1;
}

//----------------------------------------------------------------------------
// Send Identify Command to Drive, and fetch resulting data
//----------------------------------------------------------------------------
unsigned char IdentifyDrive(bit DriveNo, unsigned char *Buffer,
tdefDriveInfo *DriveInfo) {
xdata unsigned int i;
xdata unsigned char Tmp;
WriteBYTE(CMD, 6, 0xA0 + (DriveNo ? 0x10:0x00)); // Select drive
WriteBYTE(CMD, 1, 0);
WriteBYTE(CMD, 2, 1);
WriteBYTE(CMD, 3, 1);
WriteBYTE(CMD, 4, 0);
WriteBYTE(CMD, 5, 0);
WriteBYTE(CMD, 7, 0xEC);
Timer10mSec=10000;
while ((ReadBYTE(CMD,7) & 0x08)!=0x08 && Timer10mSec); // Wait for DRQ or timeout
if (Timer10mSec==0) return 0xFF;

// Fetch the data...
MSBDATA=ALLINPUT;
LSBDATA=ALLINPUT;
// Select address and activate CS
SetAddress(CMD, 0);
// Two bytes at a time
for (i=0; i<512; i+=2) {
nDIOR=0;
*(Buffer+i)=LSBDATA;
*(Buffer+i+1)=MSBDATA;
nDIOR=1;
}
// Disable CS
nCS1FX=1;
nCS3FX=1;
// Extract drive info
DriveInfo->Heads = (*(Buffer+7)<<8) + *(Buffer+6);
DriveInfo->Tracks = (*(Buffer+3)<<8) + *(Buffer+2);
DriveInfo->SectorsPerTrack = (*(Buffer+13)<<8) + *(Buffer+12);
// Swap bytes, because of 16 bit transfer...
for (i=0; i<40; i+=2) {
Tmp=*(Buffer+54+i);
*(Buffer+54+i)=*(Buffer+55+i);
*(Buffer+55+i)=Tmp;
}
memcpy(DriveInfo->Model, Buffer+54, 80);
// Terminate string...
DriveInfo->Model[40]='\0';
// Return the error register...
return ReadBYTE(CMD, 1);
}

//----------------------------------------------------------------------------
// Read one sector, identified by drive, head, track and sector
// Returns contents of the Error Register (0x00 is no error detected)
//----------------------------------------------------------------------------
unsigned char ReadSector(unsigned char Drive,
unsigned char Head, unsigned int Track, unsigned char Sector,
unsigned char *Buffer) {
unsigned int i;
// Prepare parameters...
WriteBYTE(CMD,6, 0xA0+(Drive ? 0x10:00)+Head); // CHS mode/Drive/Head
WriteBYTE(CMD,5, Track>>8); // MSB of track
WriteBYTE(CMD,4, Track); // LSB of track
WriteBYTE(CMD,3, Sector); // sector
WriteBYTE(CMD,2, 0x01); // 1 sector
// Issue read sector command...
WriteBYTE(CMD,7, 0x20); // Read sector(s) command
Timer10mSec=10000;
while ((ReadBYTE(CMD,7) & 0x08)!=0x08 && Timer10mSec); // Wait for DRQ or timeout
if (Timer10mSec==0) return 0xFF;

// Fetch the sector...
MSBDATA=ALLINPUT;
LSBDATA=ALLINPUT;
// Select address and activate CS
SetAddress(CMD, 0);
// Two bytes at a time
for (i=0; i<512; i+=2) {
nDIOR=0;
*(Buffer+i)=LSBDATA;
*(Buffer+i+1)=MSBDATA;
nDIOR=1;
}
// Disable CS
nCS1FX=1;
nCS3FX=1;
// Return the error register...
return ReadBYTE(CMD, 1);
}

//----------------------------------------------------------------------------
// Write one sector, identified by drive, head, track and sector
// Returns contents of the Error Register (0x00 is no error detected)
//----------------------------------------------------------------------------
unsigned char WriteSector(unsigned char Drive,
unsigned char Head, unsigned int Track, unsigned char Sector,
unsigned char *Buffer) {
xdata unsigned int i;
// Prepare parameters...
WriteBYTE(CMD,6, 0xA0+(Drive ? 0x10:00)+Head); // CHS mode/Drive/Head
WriteBYTE(CMD,5, Track>>8); // MSB of track
WriteBYTE(CMD,4, Track); // LSB of track
WriteBYTE(CMD,3, Sector); // sector
WriteBYTE(CMD,2, 0x01); // 1 sector
// Issue write sector command...
WriteBYTE(CMD,7, 0x30); // Write sector(s) command
Timer10mSec=10000;
while ((ReadBYTE(CMD,7) & 0x08)!=0x08 && Timer10mSec); // Wait for DRQ or timeout
if (Timer10mSec==0) return 0xFF;

// Select address and activate CS
SetAddress(CMD, 0);
// write sector data...
for (i=0; i<512; i+=2) {
LSBDATA=*(Buffer+i);
MSBDATA=*(Buffer+i+1);
nDIOW=0;
nDIOW=1;
}
// Disable CS
nCS1FX=1;
nCS3FX=1;
Timer10mSec=10000;
while ((ReadBYTE(CMD,7) & 0xC0)!=0x40 && Timer10mSec); // Wait for DRDY and NOT BUSY
if (Timer10mSec==0) return 0xFF; // or timeout

// Return the error register...
return ReadBYTE(CMD, 1);
}

//----------------------------------------------------------------------------
// Set drive mode (STANDBY, IDLE)
//----------------------------------------------------------------------------
#define STANDBY 0
#define IDLE 1
#define SLEEP 2

unsigned char SetMode(bit DriveNo, unsigned char Mode, bit PwrDown) {
WriteBYTE(CMD, 6, 0xA0 + (DriveNo ? 0x10:0x00)); // Select drive
WriteBYTE(CMD, 2, (PwrDown ? 0x01:0x00)); // Enable automatic power down
switch (Mode) {
case STANDBY: WriteBYTE(CMD,7, 0xE2); break;
case IDLE: WriteBYTE(CMD,7, 0xE3); break;
// NOTE: To recover from sleep, either issue a soft or hardware reset !
// (But not on all drives, f.ex seagate ST3655A it's not nessecary to reset
// but only to go in Idle mode, But on a Conner CFA170A it's nessecary with
// a reset)
case SLEEP: WriteBYTE(CMD,7, 0xE6); break;
}
Timer10mSec=10000;
while ((ReadBYTE(CMD,7) & 0xC0)!=0x40 && Timer10mSec); // Wait for DRDY & NOT BUSY
if (Timer10mSec==0) return 0xFF; // or timeout

// Return the error register...
return ReadBYTE(CMD, 1);
}

//----------------------------------------------------------------------------
// Show all IDE registers
//----------------------------------------------------------------------------
void ShowRegisters(bit DriveNo) {
WriteBYTE(CMD,6, 0xA0 + (DriveNo ? 0x10:0x00)); // Select drive
printf("Reg 0=%02BX 1=%02BX 2=%02BX 3=%02BX 4=%02BX 5=%02BX 6=%02BX 7=%02BX \n",
ReadBYTE(CMD, 0), ReadBYTE(CMD, 1), ReadBYTE(CMD, 2), ReadBYTE(CMD, 3),
ReadBYTE(CMD, 4), ReadBYTE(CMD, 5), ReadBYTE(CMD, 6), ReadBYTE(CMD, 7));
}

//----------------------------------------------------------------------------
// Main part
//----------------------------------------------------------------------------
void main()
{
xdata unsigned int i;
xdata char cmdbuf[15];
tdefDriveInfo DriveInfo;
xdata int Head=0, Track=0, Sector=1;

//------------------------------
// Initialize outputs...
//------------------------------
nCS1FX=1;
nCS3FX=1;
DA0 =0;
DA1 =0;
DA2 =0;
nDIOR =1;
nDIOW =1;
RESET =0; // Reset drive
//------------------------------
// configure inputs...
//------------------------------
nDASP =1;
LSBDATA =ALLINPUT;
MSBDATA =ALLINPUT;
INTRQ =1;
IORDY =1;
//------------------------------
// Configure onchip resources...
//------------------------------
TMOD |= 0x01; // TMOD: timer 0, mode 1, 16 timer
TH0 = 0xDC; // Set timeout period for Timer 0
TL0 = 0x00; // to 10 mSec timeout
ET0 = 1; // Enable Timer 0 interrupts
TR0 = 1; // Start timer 0

SCON = 0x50; // SCON: mode 1, 8-bit UART, enable rcvr */
TMOD |= 0x20; // TMOD: timer 1, mode 2, 8-bit reload */
TH1 = 0xFD; // TH1: reload value for 9.6 Kbaud */
PCON = 0x00; // PCON: Double baudrate, 19.2 Kbaud */
TR1 = 1; // TR1: timer 1 run */
//ES = 1; // ES: Enable serial port int */
TI = 1; // TI: set TI to send first char of UART */
EA = 1; // Global int enable

//----------------------------------------------------------------------------
// Let things settle, and after that, remove RESET from drive
//----------------------------------------------------------------------------
Delay(10);
RESET=1; // Remove reset to drive
//----------------------------------------------------------------------------
// ?
//----------------------------------------------------------------------------
printf("--------------------------------------------\n");
printf("---------IDE EXERCISER (c) CHG 1996---------\n");
printf("--------------------------------------------\n");
ShowInputs();

printf("Waiting for Initial DRDY & NOT BUSY from drive\n");
WriteBYTE(CMD,6, 0xA0); // Set drive/Head register, ie. select drive 0
while ((ReadBYTE(CMD,7) & 0xC0)!=0x40); // Wait for DRDY and NOT BUSY
printf("Drive is ready!\n");

printf("Spinning drive up (Going to IDLE mode)\n");
printf("SetMode=%02bX\n", SetMode(DRIVE0, IDLE, TRUE));
printf("Drive is ready!\n");

printf("ReadSector=%02bX\n", ReadSector(DRIVE0, 0, 0, 1, SectorBuffer));
HexDump(SectorBuffer, 512);
for (i=0; i<512; i++) SectorBuffer[i]=i;

printf("WriteSector=%02bX\n", WriteSector(DRIVE0, 0, 0, 1, SectorBuffer));
printf("ReadSector=%02bX\n", ReadSector(DRIVE0, 0, 0, 1, SectorBuffer));
HexDump(SectorBuffer, 512);

while (1) {
printf ("\nCommand: ");
gets (cmdbuf);//, sizeof (cmdbuf));
// gets (cmdbuf, sizeof (cmdbuf));
for (i=0; cmdbuf[i]!=0; i++)cmdbuf[i] = toupper(cmdbuf[i]);
for (i = 0; cmdbuf[i] == ' '; i++); /* skip blanks */

switch (cmdbuf[i]) {
case 'S': SetMode(DRIVE0, STANDBY, TRUE); break;
case 'I': SetMode(DRIVE0, IDLE, TRUE); break;
case 'D': IdentifyDrive(DRIVE0, SectorBuffer, &DriveInfo);
HexDump(SectorBuffer, 256);
printf("Model = %s\n", DriveInfo.Model);
printf("Heads = %bu\n",DriveInfo.Heads);
printf("Tracks = %u\n", DriveInfo.Tracks);
printf("Sectors/Track = %u\n", DriveInfo.SectorsPerTrack);

break;
case 'R': ShowRegisters(DRIVE0); break;
case '?':
printf("--------------------------------------------\n");
printf("---------IDE EXERCISER (c) CHG 1996---------\n");
printf("--------------------------------------------\n");
printf("Commands:\n");
printf(" S go to Standby mode\n");
printf(" I go to Idle mode\n");
printf(" D Identify drive\n");
printf(" R Show all registers\n");
printf(" G ,, Read sector\n");
printf("--------------------------------------------\n");
break;
case 'G':
sscanf (&cmdbuf[i+1], "%d,%d,%d",
&Head, &Track, &Sector);
printf("ReadSector=%02bX\n", ReadSector(DRIVE0, Head, Track, Sector, SectorBuffer));
HexDump(SectorBuffer, 512);
printf("Head=%d, Track=%d, Sector=%d\n", Head, Track, Sector);
break;
}
}
}


Составить ответ  |||  Конференция  |||  Архив

Ответы



Перейти к списку ответов  |||  Конференция  |||  Архив  |||  Главная страница  |||  Содержание  |||  Без кадра

E-mail: info@telesys.ru