?? ch375hft.c
字號:
/* 2004.06.05
****************************************
** Copyright (C) W.ch 1999-2004 **
** Web: http://www.winchiphead.com **
****************************************
** USB Host File Interface for CH375 **
** TC2.0@PC, KC7.0@MCS51 **
****************************************
*/
/* CH375 主機(jī)文件系統(tǒng)接口 */
/* 支持: FAT12/FAT16/FAT32 */
/* MCS-51單片機(jī)C語言的U盤文件讀寫示例程序, 適用于89C52或者更大程序空間的單片機(jī) */
/* 本程序用于演示將ADC模數(shù)采集的數(shù)據(jù)保存到U盤文件MY_ADC.TXT中 */
/* CH375的INT#引腳采用查詢方式處理, 數(shù)據(jù)復(fù)制方式為"單DPTR和P2+R0復(fù)制",速度最快,但是不能用于帶有內(nèi)置XRAM的單片機(jī),
本例適用于V1.6及以上版本的CH375子程序庫,以扇區(qū)為單位讀寫U盤文件,讀寫速度較字節(jié)模式快,
由于扇區(qū)模式以扇區(qū)為基本單位,對于需要處理零碎數(shù)據(jù)的應(yīng)用,不如字節(jié)模式方便,
本范例演示在扇區(qū)模式下處理零碎數(shù)據(jù),同時(shí)兼顧操作方便和較高速度,需要文件數(shù)據(jù)緩沖區(qū)FILE_DATA_BUF */
/* C51 CH375HFT.C */
/* LX51 CH375HFT.OBJ , CH375HF4.LIB 如果將CH375HF4換成CH375HF6就可以支持FAT32 */
/* OHX51 CH375HFT */
#include <reg52.h>
#include <stdio.h>
#include <string.h>
/* 以下定義的詳細(xì)說明請看CH375HF6.H文件 */
#define LIB_CFG_DISK_IO 3 /* 磁盤讀寫的數(shù)據(jù)的復(fù)制方式,1為"單DPTR復(fù)制",2為"雙DPTR復(fù)制",3為"單DPTR和P2+R0復(fù)制" */
#define LIB_CFG_FILE_IO 3 /* 文件讀寫的數(shù)據(jù)的復(fù)制方式,0為"外部子程序",1為"單DPTR復(fù)制",2為"雙DPTR復(fù)制",3為"單DPTR和P2+R0復(fù)制" */
#define LIB_CFG_INT_EN 0 /* CH375的INT#引腳連接方式,0為"查詢方式",1為"中斷方式" */
/*#define LIB_CFG_FILE_IO_DEFAULT 1*/ /* 使用CH375HF6.H提供的默認(rèn)"外部子程序" */
/*#define LIB_CFG_UPD_SIZE 1*/ /* 在添加數(shù)據(jù)后是否自動更新文件長度: 0為"不更新",1為"自動更新" */
/* 默認(rèn)情況下,如果扇區(qū)數(shù)/字節(jié)數(shù)不為0那么CH375FileWrite/CH375ByteWrite只負(fù)責(zé)寫入數(shù)據(jù)而不修改文件長度,
如果需要每次寫完數(shù)據(jù)后會自動修改/更新文件長度,那么可以使全局變量CH375LibConfig的位4為1,
如果長時(shí)間不寫入數(shù)據(jù)則應(yīng)該更新文件長度,防止突然斷電后前面寫入的數(shù)據(jù)與文件長度不相符,
如果確定不會突然斷電或者后面很快有數(shù)據(jù)不斷寫入則不必更新文件長度,可以提高速度并減少U盤損耗(U盤內(nèi)部的內(nèi)存壽命有限,不宜頻繁改寫) */
#define CH375_CMD_PORT_ADDR 0xBDF1 /* CH375命令端口的I/O地址 */
#define CH375_DAT_PORT_ADDR 0xBCF0 /* CH375數(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 DISK_BASE_BUF_LEN 4096 /* 默認(rèn)的磁盤數(shù)據(jù)緩沖區(qū)大小為512字節(jié),建議選擇為2048甚至4096以支持某些大扇區(qū)的U盤,為0則禁止在.H文件中定義緩沖區(qū)并由應(yīng)用程序在pDISK_BASE_BUF中指定 */
/* 如果需要復(fù)用磁盤數(shù)據(jù)緩沖區(qū)以節(jié)約RAM,那么可將DISK_BASE_BUF_LEN定義為0以禁止在.H文件中定義緩沖區(qū),而由應(yīng)用程序在調(diào)用CH375Init之前將與其它程序合用的緩沖區(qū)起始地址置入pDISK_BASE_BUF變量 */
#define FILE_DATA_BUF_ADDR 0x1000 /* 外部RAM的文件數(shù)據(jù)緩沖區(qū)的起始地址,緩沖區(qū)長度不小于一次讀寫的數(shù)據(jù)長度 */
/* 由于演示板用的62256只有32K字節(jié),其中CH375子程序用512字節(jié),所以外部RAM剩余長度為32256字節(jié) */
#define FILE_DATA_BUF_LEN 0x3E00 /* 外部RAM的文件數(shù)據(jù)緩沖區(qū),緩沖區(qū)長度不小于一次讀寫的數(shù)據(jù)長度,本例要求不小于0x400即可 */
/* 如果準(zhǔn)備使用雙緩沖區(qū)交替讀寫,那么不要定義FILE_DATA_BUF_LEN,而是在參數(shù)中指定緩沖區(qū)起址,用CH375FileReadX代替CH375FileRead,用CH375FileWriteX代替CH375FileWrite */
#define CH375_INT_WIRE INT0 /* P3.2, INT0, CH375的中斷線INT#引腳,連接CH375的INT#引腳,用于查詢中斷狀態(tài) */
#define NO_DEFAULT_CH375_F_ENUM 1 /* 未調(diào)用CH375FileEnumer程序故禁止以節(jié)約代碼 */
#define NO_DEFAULT_CH375_F_QUERY 1 /* 未調(diào)用CH375FileQuery程序故禁止以節(jié)約代碼 */
#include "..\CH375HF6.H" /* 如果不需要支持FAT32,那么請選用CH375HF4.H */
/* 在P1.4連接一個(gè)LED用于監(jiān)控演示程序的進(jìn)度,低電平LED亮,當(dāng)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連接一個(gè)LED用于監(jiān)控演示程序的進(jìn)度,低電平LED亮,當(dāng)對U盤操作時(shí)亮 */
#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連接一個(gè)LED用于監(jiān)控演示程序的進(jìn)度,低電平LED亮,當(dāng)對U盤寫操作時(shí)亮 */
#define LED_WR_ACT( ) { P1_6 = 0; } /* P1.6 低電平驅(qū)動LED顯示 */
#define LED_WR_INACT( ) { P1_6 = 1; } /* P1.6 低電平驅(qū)動LED顯示 */
/* 以毫秒為單位延時(shí),不精確,適用于24MHz時(shí)鐘 */
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時(shí)鐘下延時(shí)500uS */
for ( j = 200; j != 0; j -- ) c += 3; /* 在24MHz時(shí)鐘下延時(shí)500uS */
}
}
/* 將程序空間的字符串復(fù)制到內(nèi)部RAM中,返回字符串長度 */
UINT8 mCopyCodeStringToIRAM( UINT8 idata *iDestination, UINT8 code *iSource )
{
UINT8 i = 0;
while ( *iDestination = *iSource ) {
iDestination ++;
iSource ++;
i ++;
}
return( i );
}
/* 檢查操作狀態(tài),如果錯(cuò)誤則顯示錯(cuò)誤代碼并停機(jī) */
void mStopIfError( UINT8 iError )
{
if ( iError == ERR_SUCCESS ) return; /* 操作成功 */
printf( "Error: %02X\n", (UINT16)iError ); /* 顯示錯(cuò)誤 */
while ( 1 ) {
LED_OUT_ACT( ); /* LED閃爍 */
mDelaymS( 200 );
LED_OUT_INACT( );
mDelaymS( 200 );
}
}
/* 為printf和getkey輸入輸出初始化串口 */
void mInitSTDIO( )
{
SCON = 0x50;
PCON = 0x80;
TMOD = 0x21;
TH1 = 0xf3; /* 24MHz晶振, 9600bps */
TR1 = 1;
TI = 1;
}
UINT16 total; /* 記錄當(dāng)前緩沖在FILE_DATA_BUF中的數(shù)據(jù)長度 */
/* 將準(zhǔn)備寫入U(xiǎn)盤的零碎數(shù)據(jù)進(jìn)行集中緩沖,組合成大數(shù)據(jù)塊時(shí)再通過CH375真正寫入U(xiǎn)盤 */
/* 這樣做的好處是: 提高速度(因?yàn)榇髷?shù)據(jù)塊寫入時(shí)效率高), 減少U盤損耗(U盤內(nèi)部的內(nèi)存壽命有限,不宜頻繁擦寫) */
void mFlushBufferToDisk( UINT8 force )
/* force = 0 則自動刷新(檢查緩沖區(qū)中的數(shù)據(jù)長度,滿則寫盤,不滿則暫時(shí)放在緩沖區(qū)中), force != 0 則強(qiáng)制刷新(不管緩沖區(qū)中的數(shù)據(jù)有多少都寫盤,通常在系統(tǒng)關(guān)機(jī)前應(yīng)該強(qiáng)制寫盤) */
{
UINT8 i;
UINT32 NewSize;
if ( force ) { /* 強(qiáng)制刷新 */
mCmdParam.Write.mSectorCount = ( total + CH375vSectorSize - 1 ) / CH375vSectorSize; /* 將緩沖區(qū)中的字節(jié)數(shù)轉(zhuǎn)換為扇區(qū)數(shù)(除以CH375vSectorSize),長度加上CH375vSectorSize-1用于確保寫入最后的零頭數(shù)據(jù) */
i = CH375FileWrite( ); /* 以扇區(qū)為單位向文件寫入數(shù)據(jù),寫入緩沖區(qū)中的所有數(shù)據(jù),含最后的零頭 */
mStopIfError( i );
/* 有些U盤可能會要求在寫數(shù)據(jù)后等待一會才能繼續(xù)操作,所以,如果在某些U盤中發(fā)生數(shù)據(jù)丟失現(xiàn)象,建議在每次寫入數(shù)據(jù)后稍作延時(shí)再繼續(xù) */
mDelaymS( 1 ); /* 寫后延時(shí),可選的,大多數(shù)U盤不需要 */
memcpy( FILE_DATA_BUF+0, FILE_DATA_BUF+(total & ~ ( CH375vSectorSize - 1 ) ), total & ( CH375vSectorSize - 1 ) ); /* 將剛才已寫入U(xiǎn)盤的零頭數(shù)據(jù)復(fù)制到緩沖區(qū)的頭部 */
total &= CH375vSectorSize - 1; /* 緩沖區(qū)中只剩下剛才已寫入U(xiǎn)盤的零頭數(shù)據(jù),繼續(xù)保留在緩沖區(qū)中是為了方便以后在其后面追加數(shù)據(jù) */
if ( total ) NewSize = CH375vFileSize - CH375vSectorSize + total; /* 以扇區(qū)為單位,有零頭數(shù)據(jù),計(jì)算出真正的文件長度(有效數(shù)據(jù)的長度) */
else NewSize = CH375vFileSize; /* 以扇區(qū)為單位,沒有零頭數(shù)據(jù),文件長度是CH375vSectorSize的倍數(shù) */
mCmdParam.Modify.mFileSize = NewSize; /* 輸入?yún)?shù): 新的文件長度,扇區(qū)模式下涉及到零頭數(shù)據(jù)不便自動更新長度 */
mCmdParam.Modify.mFileAttr = 0xff; /* 輸入?yún)?shù): 新的文件屬性,為0FFH則不修改 */
mCmdParam.Modify.mFileTime = 0xffff; /* 輸入?yún)?shù): 新的文件時(shí)間,為0FFH則不修改 */
mCmdParam.Modify.mFileDate = 0xffff; /* 輸入?yún)?shù): 新的文件日期,為0FFH則不修改 */
i = CH375FileModify( ); /* 修改當(dāng)前文件的信息,修改文件長度 */
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -