?? ch374hft.c
字號:
/* 2004.06.05
****************************************
** Copyright (C) W.ch 1999-2004 **
** Web: http://www.winchiphead.com **
****************************************
** USB Host File Interface for CH374 **
** TC2.0@PC, KC7.0@MCS51 **
****************************************
*/
/* CH374 主機文件系統(tǒng)接口 */
/* 支持: FAT12/FAT16/FAT32 */
/* MCS-51單片機C語言的U盤文件讀寫示例程序, 適用于89C52或者更大程序空間的單片機 */
/* 本程序用于演示列出指定目錄下的所有文件,以及用于搜索/枚舉文件名 */
/* CH374的INT#引腳采用查詢方式處理, 數(shù)據(jù)復制方式為"單DPTR復制", 所以速度較慢, 適用于所有MCS51單片機 */
/* C51 CH374HFT.C */
/* LX51 CH374HFT.OBJ , CH374HF6.LIB, C51DPTR1.LIB */
/* OHX51 CH374HFT */
#include <reg52.h>
#include <stdio.h>
#include <string.h>
/* 以下定義的詳細說明請看CH374HF6.H文件 */
#define LIB_CFG_INT_EN 0 /* CH374的INT#引腳連接方式,0為"查詢方式",1為"中斷方式" */
#define CH374_IDX_PORT_ADDR 0xBDF1 /* CH374索引端口的I/O地址 */
#define CH374_DAT_PORT_ADDR 0xBCF0 /* CH374數(shù)據(jù)端口的I/O地址 */
/* 62256提供的32KB的RAM分為兩部分: 0000H-01FFH為磁盤讀寫緩沖區(qū), 0200H-7FFFH為文件數(shù)據(jù)緩沖區(qū) */
#define DISK_BASE_BUF_ADDR 0x0000 /* 外部RAM的磁盤數(shù)據(jù)緩沖區(qū)的起始地址,從該單元開始的緩沖區(qū)長度為SECTOR_SIZE */
#define CH374_INT_WIRE INT0 /* P3.2, INT0, CH374的中斷線INT#引腳,連接CH374的INT#引腳,用于查詢中斷狀態(tài) */
/* 如果未連接CH374的中斷引腳,那么應該去掉上述定義,自動使用寄存器查詢方式 */
#define DISK_BASE_BUF_LEN 2048 /* 默認的磁盤數(shù)據(jù)緩沖區(qū)大小為512字節(jié),建議選擇為2048甚至4096以支持某些大扇區(qū)的U盤,為0則禁止在.H文件中定義緩沖區(qū)并由應用程序在pDISK_BASE_BUF中指定 */
/* 如果需要復用磁盤數(shù)據(jù)緩沖區(qū)以節(jié)約RAM,那么可將DISK_BASE_BUF_LEN定義為0以禁止在.H文件中定義緩沖區(qū),而由應用程序在調(diào)用CH375Init之前將與其它程序合用的緩沖區(qū)起始地址置入pDISK_BASE_BUF變量 */
#define NO_DEFAULT_CH374_F_ENUM 1 /* 未調(diào)用CH374FileEnumer程序故禁止以節(jié)約代碼 */
#define NO_DEFAULT_CH374_F_QUERY 1 /* 未調(diào)用CH374FileQuery程序故禁止以節(jié)約代碼 */
#define NO_DEFAULT_CH374_RESET 1 /* 未調(diào)用CH374Reset程序故禁止以節(jié)約代碼 */
#define NO_DEFAULT_FILE_ENUMER 1 /* 禁止默認的文件名枚舉回調(diào)程序,下面用自行編寫的程序代替它 */
#include "..\CH374HF6.H" /* 如果不需要支持FAT32,那么請選用CH374HF6.H */
/* 在P1.4連接一個LED用于監(jiān)控演示程序的進度,低電平LED亮,當U盤插入后亮 */
sbit P1_4 = P1^4;
#define LED_OUT_INIT( ) { P1_4 = 1; } /* P1.4 高電平 */
#define LED_OUT_ACT( ) { P1_4 = 0; } /* P1.4 低電平驅(qū)動LED顯示 */
#define LED_OUT_INACT( ) { P1_4 = 1; } /* P1.4 低電平驅(qū)動LED顯示 */
sbit P1_5 = P1^5;
/* 在P1.5連接一個LED用于監(jiān)控演示程序的進度,低電平LED亮,當對U盤操作時亮 */
#define LED_RUN_ACT( ) { P1_5 = 0; } /* P1.5 低電平驅(qū)動LED顯示 */
#define LED_RUN_INACT( ) { P1_5 = 1; } /* P1.5 低電平驅(qū)動LED顯示 */
sbit P1_6 = P1^6;
/* 在P1.6連接一個LED用于監(jiān)控演示程序的進度,低電平LED亮,當對U盤寫操作時亮 */
#define LED_WR_ACT( ) { P1_6 = 0; } /* P1.6 低電平驅(qū)動LED顯示 */
#define LED_WR_INACT( ) { P1_6 = 1; } /* P1.6 低電平驅(qū)動LED顯示 */
/* 檢查操作狀態(tài),如果錯誤則顯示錯誤代碼并停機,應該替換為實際的處理措施 */
void mStopIfError( UINT8 iError )
{
if ( iError == ERR_SUCCESS ) return; /* 操作成功 */
printf( "Error: %02X\n", (UINT16)iError ); /* 顯示錯誤 */
/* 遇到錯誤后,應該分析錯誤碼以及CH374DiskStatus狀態(tài),例如調(diào)用CH374DiskConnect查詢當前U盤是否連接,如果U盤已斷開那么就重新等待U盤插上再操作,
建議出錯后的處理步驟:
1、調(diào)用一次CH374DiskReady,成功則繼續(xù)操作,例如Open,Read/Write等,在CH374DiskReady中會自動調(diào)用CH374DiskConnect,不必另外調(diào)用
2、如果CH374DiskReady不成功,那么強行將CH374DiskStatus置為DISK_CONNECT狀態(tài),然后從頭開始操作(等待U盤連接CH374DiskConnect,CH374DiskReady等) */
while ( 1 ) {
LED_OUT_ACT( ); /* LED閃爍 */
CH374DelaymS( 200 );
LED_OUT_INACT( );
CH374DelaymS( 200 );
}
}
/* 為printf和getkey輸入輸出初始化串口 */
void mInitSTDIO( )
{
SCON = 0x50;
PCON = 0x80;
TMOD = 0x21;
TH1 = 0xf3; /* 24MHz晶振, 9600bps */
TR1 = 1;
TI = 1;
}
typedef struct _FILE_NAME {
UINT32 DirStartClust; /* 文件所在目錄的起始簇號 */
// UINT32 Size; /* 文件長度 */
UINT8 Name[8+3+1+1]; /* 文件名,共8+3字節(jié),分隔符,結束符,因為未包含目錄名所以是相對路徑 */
UINT8 Attr; /* 文件屬性 */
} FILE_NAME;
#define MAX_FILE_COUNT 200
FILE_NAME xdata FileNameBuffer[ MAX_FILE_COUNT ]; /* 文件名結構 */
UINT16 FileCount;
UINT32 CurrentDirStartClust; /* 保存當前目錄的起始簇號,用于加快文件枚舉和打開速度 */
/* 例子:列舉指定目錄下的所有文件 */
UINT8 ListFile( void )
// 輸入?yún)?shù)mCmdParam.Open.mPathName[]為目錄名字符串,形式與文件名相同,單個斜線則代表根目錄
{
UINT8 i;
printf( "List Directory: %s\n", mCmdParam.Open.mPathName ); /* 顯示目錄名 */
// for ( i = 0; i < MAX_PATH_LEN; i ++ ) { /* 找目錄名的結束符 */
// if ( mCmdParam.Open.mPathName[i] == 0 ) break;
// }
i = strlen( mCmdParam.Open.mPathName ); /* 計算路徑的長度,找目錄名的結束符 */
if ( i && mCmdParam.Open.mPathName[i-1] == '/' ) { } /* 是根目錄,或者是已經(jīng)有路徑分隔符 */
else mCmdParam.Open.mPathName[i++] = '/'; /* 在當前目錄下進行枚舉,除根目錄外都是相對路徑,不是根目錄則加路徑分隔符 */
mCmdParam.Open.mPathName[i++] = '*'; /* 枚舉通配符,完整的路徑例如"\*"或者"\C51\*"或者"\C51\CH374*"等 */
mCmdParam.Open.mPathName[i] = 0xFF; /* 0xFF指定枚舉序號在CH374vFileSize中 */
CH374vFileSize = 0xFFFFFFFF; /* 快速連續(xù)枚舉,每找到一個文件調(diào)用一次xFileNameEnumer回調(diào)子程序,如果值小于0x80000000則每次只枚舉一個文件太慢 */
i = CH374FileOpen( ); /* 枚舉,由回調(diào)程序xFileNameEnumer產(chǎn)生記錄保存到結構中 */
if ( i == ERR_SUCCESS || i == ERR_FOUND_NAME || i == ERR_MISS_FILE ) { /* 操作成功,通常不會返回ERR_SUCCESS,僅在xFileNameEnumer提前退出時才會返回ERR_FOUND_NAME */
printf( "Success, new FileCount = %d\n", FileCount );
return( ERR_SUCCESS );
}
else {
printf( "Failed, new FileCount = %d\n", FileCount );
return( i );
}
}
UINT8 ListAll( void ) /* 以廣度優(yōu)先的算法枚舉整個U盤中的所有文件及目錄 */
{
UINT8 i;
UINT16 OldFileCount;
OldFileCount = FileCount = 0; /* 清文件結構計數(shù) */
FileNameBuffer[ 0 ].Name[0] = '/'; /* 根目錄,是完整路徑名,除根目錄是絕對路徑之外都是相對路徑 */
FileNameBuffer[ 0 ].Name[1] = 0;
FileNameBuffer[ 0 ].DirStartClust = 0; /* 根目錄的這個參數(shù)無意義 */
FileNameBuffer[ 0 ].Attr = ATTR_DIRECTORY; /* 根目錄也是目錄,作為第一個記錄保存 */
for ( FileCount = 1; OldFileCount < FileCount; OldFileCount ++ ) { /* 尚有新枚舉到的文件名結構未進行分析 */
if ( FileNameBuffer[ OldFileCount ].Attr & ATTR_DIRECTORY ) { /* 是目錄則繼續(xù)進行深度搜索 */
strcpy( mCmdParam.Open.mPathName, FileNameBuffer[ OldFileCount ].Name ); /* 目錄名,除根目錄外都是相對路徑 */
CH374vStartCluster = FileNameBuffer[ OldFileCount ].DirStartClust; /* 當前目錄的上級目錄的起始簇號,便于用相對路徑打開,比完整路徑名速度快 */
i = CH374FileOpen( ); /* 打開目錄,僅為了獲取目錄的起始簇號以提高速度 */
if ( i == ERR_SUCCESS ) return( ERR_MISS_DIR ); /* 應該是打開了目錄,但是返回結果是打開了文件 */
if ( i != ERR_OPEN_DIR ) return( i );
if ( OldFileCount ) CurrentDirStartClust = CH374vStartCluster; /* 不是根目錄,獲取目錄的起始簇號 */
else { /* 是根目錄,獲取根目錄的起始簇號 */
if ( CH374vDiskFat == DISK_FAT32 ) CurrentDirStartClust = CH374vDiskRoot; /* FAT32根目錄 */
else CurrentDirStartClust = 0; /* FAT12/FAT16根目錄 */
}
CH374FileClose( ); /* 對于根目錄一定要關閉 */
// strcpy( mCmdParam.Open.mPathName, FileNameBuffer[ OldFileCount ].Name ); /* 目錄名,由于mPathName未被修改所以無需再復制 */
CH374vStartCluster = FileNameBuffer[ OldFileCount ].DirStartClust; /* 當前目錄的上級目錄的起始簇號,便于用相對路徑打開,比完整路徑名速度快 */
i = ListFile( ); /* 枚舉目錄,由回調(diào)程序xFileNameEnumer產(chǎn)生記錄保存到結構中 */
if ( i != ERR_SUCCESS ) return( i );
}
}
// U盤中的文件及目錄全部枚舉完畢,下面開始根據(jù)結構記錄依次打開文件 */
printf( "Total file&dir = %d, Open every file:\n", FileCount );
for ( OldFileCount = 0; OldFileCount < FileCount; OldFileCount ++ ) {
if ( ( FileNameBuffer[ OldFileCount ].Attr & ATTR_DIRECTORY ) == 0 ) { /* 是文件則打開,目錄則跳過 */
printf( "Open file: %s\n", FileNameBuffer[ OldFileCount ].Name );
strcpy( mCmdParam.Open.mPathName, FileNameBuffer[ OldFileCount ].Name ); /* 相對路徑 */
CH374vStartCluster = FileNameBuffer[ OldFileCount ].DirStartClust; /* 當前文件的上級目錄的起始簇號,便于用相對路徑打開,比完整路徑名速度快 */
i = CH374FileOpen( ); /* 打開文件 */
if ( i == ERR_SUCCESS ) { /* 成功打開了文件 */
mCmdParam.ReadX.mDataBuffer = 0x2000; /* 指向文件數(shù)據(jù)緩沖區(qū)的起始地址 */
mCmdParam.ReadX.mSectorCount = 1; /* 讀取扇區(qū)數(shù) */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -