?? ch375hmp.c
字號:
/* 2004.06.05
****************************************
** Copyright (C) W.ch 1999-2004 **
** Web: http://www.winchiphead.com **
****************************************
** USB Host File Module @CH375 **
** TC2.0@PC, KC7.0@MCS51 **
****************************************
*/
/* U盤文件讀寫模塊, 連接方式: 并口+查詢 */
/* MCS-51單片機C語言示例程序, 僅適用于V2.5及以上版本的模塊 */
/* 因為使用U盤文件讀寫模塊而不是使用U盤文件級子程序庫,所以占用較少的單片機資源,可以使用89C51單片機測試 */
#include <reg51.h>
#include <absacc.h>
#include <string.h>
#include <stdio.h>
#define MAX_PATH_LEN 32 /* 最大路徑長度,含所有斜杠分隔符和小數點間隔符以及路徑結束符00H,CH375模塊支持的最大值是64,最小值是13,并口最大值62 */
#include "..\CH375HM.H"
/* 電路連接方式
單片機 模塊
P0 = D0-D7
RD = RD#
WR = WR#
? = CS# 如果沒有外部RAM,那么CS#=P26,如果有超過16KB的外部RAM,那么CS#=P27 & ! P26 & ...,所以CS#的片選地址為BXXXH
P20 = A0
P15 = STA#
INT0 = INT# 雖然連接到INT0,但是本程序只是查詢模塊的INT#的狀態,所以可以用P1口等普通I/O引腳代替INT0
*/
#define CH375HM_INDEX XBYTE[0xBCF0] /* CH375模塊的索引端口的I/O地址 */
#define CH375HM_DATA XBYTE[0xBDF1] /* CH375模塊的數據端口的I/O地址 */
#define CH375HM_INT_WIRE INT0 /* 假定CH375模塊的INT#引腳連接到單片機的INT0引腳 */
sbit P15 = P1^5;
#define CH375HM_STA P15 /* 假定CH375模塊的STA#引腳連接到單片機的P15引腳 */
/* 假定文件數據緩沖區: ExtRAM: 0000H-7FFFH */
unsigned char xdata DATA_BUF[ 512 * 64 ] _at_ 0x0000; /* 外部RAM的文件數據緩沖區,從該單元開始的緩沖區長度不小于一次讀寫的數據長度,最少為512字節 */
CMD_PARAM mCmdParam; /* 默認情況下該結構將占用64字節的RAM,可以修改MAX_PATH_LEN常量,當修改為32時,只占用32字節的RAM */
unsigned char mIntStatus; /* CH375模塊的中斷狀態或者操作完成狀態 */
sbit LED_OUT = P1^4; /* P1.4 低電平驅動LED顯示,用于監控演示程序的進度 */
/* 對于模擬的并口讀寫時序或者其它并口讀寫方式,請修改以下3個子程序 */
#define CH375HM_INDEX_WR( Index ) { CH375HM_INDEX = (Index); } /* 寫索引地址 */
#define CH375HM_DATA_WR( Data ) { CH375HM_DATA = (Data); } /* 寫數據 */
#define CH375HM_DATA_RD( ) ( CH375HM_DATA ) /* 讀數據 */
/* 以毫秒為單位延時,適用于24MHz時鐘 */
void mDelaymS( unsigned char delay )
{
unsigned char i, j, c;
for ( i = delay; i != 0; i -- ) {
for ( j = 200; j != 0; j -- ) c += 3; /* 在24MHz時鐘下延時500uS */
for ( j = 200; j != 0; j -- ) c += 3; /* 在24MHz時鐘下延時500uS */
}
}
/* 執行命令 */
unsigned char ExecCommandBuf( unsigned char cmd, unsigned char len, unsigned char xdata *bufstart )
/* 輸入命令碼和輸入參數長度,返回操作狀態碼,輸入參數和返回參數都在CMD_PARAM結構中 */
/* 輸入參數bufstart僅用于CMD_FileRead或者CMD_FileWrite命令,指定外部RAM緩沖區的起始地址,可以參考中斷方式C程序采用全局變量buffer的方式 */
{
unsigned char i, status;
#define DataCount status /* 節約一個變量單元 */
unsigned char data *buf;
unsigned char xdata *CurrentBuf;
CH375HM_INDEX_WR( 0 ); /* 索引地址置0 */
CH375HM_DATA_WR( cmd ); /* 向索引地址0寫入命令碼 */
CH375HM_DATA_WR( len ); /* 向索引地址1寫入后續參數的長度 */
if ( len ) { /* 有參數 */
i = len;
buf = (unsigned char *)&mCmdParam; /* 指向輸入參數的起始地址 */
do {
CH375HM_DATA_WR( *buf ); /* 從索引地址2開始,寫入參數 */
buf ++;
} while ( -- i );
}
CH375HM_STA = 0; /* 產生下降沿通知模塊,說明命令包已經寫入,請求開始執行命令 */
CurrentBuf = bufstart; /* 外部RAM緩沖區起始地址,僅用于FileRead或者FileWrite命令 */
while ( 1 ) { /* 處理數據傳輸,直到操作完成才退出 */
while ( CH375HM_INT_WIRE ); /* 等待模塊完成操作產生低電平中斷,最佳檢測方式是對模塊的INT#信號進行下降沿邊沿檢測 */
CH375HM_INDEX_WR( 63 ); /* 寫入索引地址63 */
status = CH375HM_DATA_RD( ); /* 從索引地址63讀取中斷狀態 */
CH375HM_STA = 1; /* 中斷應答,取消來自模塊的中斷請求 */
/* 因為模塊在收到中斷應答后3uS之內才撤消中斷請求,所以,如果是查詢INT#信號的低電平,那么在發出中斷應答后3uS之內不應該再查詢INT#信號的狀態
但是由于51單片機較慢,下面的處理時間已經超過3uS,所以不必另加延時等待模塊撤消中斷請求 */
if ( status == ERR_SUCCESS ) { /* 操作成功 */
CH375HM_INDEX_WR( 1 );
DataCount = CH375HM_DATA_RD( ); /* 從索引地址1讀取返回結果數據的長度,計數 */
if ( DataCount ) { /* 有結果數據 */
buf = (unsigned char *)&mCmdParam; /* 指向輸出參數的起始地址 */
i = 2;
do {
CH375HM_INDEX_WR( i );
i ++;
*buf = CH375HM_DATA_RD( ); /* 從索引地址2開始,讀取結果 */
buf ++;
} while ( -- DataCount );
}
// status = ERR_SUCCESS;
break; /* 操作成功返回 */
}
else if ( status == USB_INT_DISK_READ ) { /* 正在從U盤讀數據塊,請求數據讀出 */
DataCount = 64; /* 計數 */
i = 0;
do { /* 要提高文件數據讀寫速度,這段程序用匯編程序效率更高,在C51中,do+while比for或者while結構效率高 */
CH375HM_INDEX_WR( i );
i ++;
*CurrentBuf = CH375HM_DATA_RD( ); /* 從索引地址0到63依次讀出64字節的數據 */
CurrentBuf ++; /* 讀取的數據保存到外部緩沖區 */
} while ( -- DataCount ); /* 上面這一小段C程序用匯編程序效率要高近一倍 */
CH375HM_STA = 0; /* 產生下降沿通知模塊繼續,說明64字節數據已經讀取完成 */
}
else if ( status == USB_INT_DISK_WRITE ) { /* 正在向U盤寫數據塊,請求數據寫入 */
CH375HM_INDEX_WR( 0 );
i = 64;
do {
CH375HM_DATA_WR( *CurrentBuf ); /* 向索引地址0到63依次寫入64字節的數據 */
CurrentBuf ++; /* 寫入的數據來自外部緩沖區 */
} while ( -- i );
CH375HM_STA = 0; /* 產生下降沿通知模塊繼續,說明64字節數據已經寫入完成 */
}
else if ( status == USB_INT_DISK_RETRY ) { /* 讀寫數據塊失敗重試,應該向回修改緩沖區指針 */
CH375HM_INDEX_WR( 0 );
i = CH375HM_DATA_RD( ); /* 大端模式下為回改指針字節數的高8位,如果是小端模式那么接收到的是回改指針字節數的低8位 */
CH375HM_INDEX_WR( 1 );
DataCount = CH375HM_DATA_RD( ); /* 大端模式下為回改指針字節數的低8位,如果是小端模式那么接收到的是回改指針字節數的高8位 */
CurrentBuf -= ( (unsigned short)i << 8 ) + DataCount; /* 這是大端模式下的回改指針,對于小端模式,應該是( (unsigned short)status << 8 ) + i */
CH375HM_STA = 0; /* 產生下降沿通知模塊繼續,說明重試狀態碼已經處理完成 */
}
else { /* 操作失敗 */
if ( status == ERR_DISK_DISCON || status == ERR_USB_CONNECT ) mDelaymS( 100 ); /* U盤剛剛連接或者斷開,應該延時幾十毫秒再操作 */
break; /* 操作失敗返回 */
}
}
/* while( CH375HM_INT_WIRE == 0 ); 如果單片機速度很快,有可能該程序返回前模塊尚未撤消中斷請求,那么應該等待中斷請求引腳無效 */
return( status );
}
/* 執行命令 */
unsigned char ExecCommand( unsigned char cmd, unsigned char len )
/* 輸入命令碼和輸入參數長度,返回操作狀態碼,輸入參數和返回參數都在CMD_PARAM結構中 */
{
return( ExecCommandBuf( cmd, len, 0 ) ); /* 只有CMD_FileRead或者CMD_FileWrite命令用到輸入參數bufstart,其它命令沒有用到 */
}
/* 檢查操作狀態,如果錯誤則顯示錯誤代碼并停機,應該替換為實際的處理措施 */
void mStopIfError( unsigned char iError )
{
unsigned char led;
if ( iError == ERR_SUCCESS ) return; /* 操作成功 */
printf( "Error: %02X\n", (unsigned short)iError ); /* 顯示錯誤 */
led=0;
while ( 1 ) {
LED_OUT = led&1; /* LED閃爍 */
mDelaymS( 100 );
led^=1;
}
}
/* 為printf和getkey輸入輸出初始化串口 */
void mInitSTDIO( )
{
SCON = 0x50;
PCON = 0x80;
TMOD = 0x20;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -