DSP芯片,SPI操作ch376讀寫U盤扇區(qū),整個(gè)過程操作都沒提示出錯(cuò),讀U盤扇區(qū)是正常的,但是寫數(shù)據(jù)到U盤扇區(qū)后無法在PC端文件中查看到數(shù)據(jù),新建一個(gè)文件和打開一個(gè)已有文件結(jié)果是一樣,文件創(chuàng)建正常,還有對于文件,扇區(qū)讀寫和字節(jié)讀寫有什么區(qū)別呢?下面是代碼:
/* 將準(zhǔn)備寫入U(xiǎn)盤的零碎數(shù)據(jù)進(jìn)行集中緩沖,組合成大數(shù)據(jù)塊時(shí)再通過CH376真正寫入U(xiǎn)盤 */
/* 這樣做的好處是: 提高速度(因?yàn)榇髷?shù)據(jù)塊寫入時(shí)效率高), 減少U盤損耗(U盤內(nèi)部的內(nèi)存壽命有限,不宜頻繁擦寫) */
voidmFlushBufferToDisk( UINT8 force )
/* force = 0 則自動(dòng)刷新(檢查緩沖區(qū)中的數(shù)據(jù)長度,滿則寫盤,不滿則暫時(shí)放在緩沖區(qū)中), force != 0 則強(qiáng)制刷新(不管緩沖區(qū)中的數(shù)據(jù)有多少都寫盤,通常在系統(tǒng)關(guān)機(jī)前應(yīng)該強(qiáng)制寫盤) */
{
UINT8s;
if ( force )?
{ ?/* 強(qiáng)制刷新 */
s = ( total + DEF_SECTOR_SIZE - 1 ) / DEF_SECTOR_SIZE; ?/* 將緩沖區(qū)中的字節(jié)數(shù)轉(zhuǎn)換為扇區(qū)數(shù)(除以DEF_SECTOR_SIZE),長度加上DEF_SECTOR_SIZE-1用于確保寫入最后的零頭數(shù)據(jù) */
if ( s )?
{ ?/* 有數(shù)據(jù) */
s = CH376SecWrite( FileDataBuf, s, NULL ); ?/* 以扇區(qū)為單位向文件寫入數(shù)據(jù),寫入緩沖區(qū)中的所有數(shù)據(jù),含最后的零頭 */
mStopIfError( s );
/* 有些U盤可能會(huì)要求在寫數(shù)據(jù)后等待一會(huì)才能繼續(xù)操作,所以,如果在某些U盤中發(fā)生數(shù)據(jù)丟失現(xiàn)象,建議在每次寫入數(shù)據(jù)后稍作延時(shí)再繼續(xù) */
mDelaymS( 1 ); ?/* 寫后延時(shí),可選的,大多數(shù)U盤不需要 */
memcpy( FileDataBuf, & FileDataBuf[ total & ~ ( DEF_SECTOR_SIZE - 1 ) ], total & ( DEF_SECTOR_SIZE - 1 ) ); ?/* 將剛才已寫入U(xiǎn)盤的零頭數(shù)據(jù)復(fù)制到緩沖區(qū)的頭部 */
total &= DEF_SECTOR_SIZE - 1; ?/* 緩沖區(qū)中只剩下剛才已寫入U(xiǎn)盤的零頭數(shù)據(jù),繼續(xù)保留在緩沖區(qū)中是為了方便以后在其后面追加數(shù)據(jù) */
}
NewSize = CH376GetFileSize( ); ?/* 讀取當(dāng)前文件長度,如果沒有零頭數(shù)據(jù),那么文件長度是DEF_SECTOR_SIZE的倍數(shù) */
if ( total ) NewSize -= DEF_SECTOR_SIZE - total; ?/* 以扇區(qū)為單位,有零頭數(shù)據(jù),計(jì)算出真正的文件長度(有效數(shù)據(jù)的長度) */
CH376WriteVar32( VAR_FILE_SIZE, NewSize ); ?/* 將正確的當(dāng)前文件長度寫入CH376內(nèi)存 */
//printf( "Current file size is %ld\n", NewSize );
s = CH376SecWrite( FileDataBuf, 0, NULL ); ?/* 寫0長度,實(shí)際是刷新文件長度,將CH376內(nèi)存中當(dāng)前文件長度信息真正寫入U(xiǎn)盤或者SD卡中 */
mStopIfError( s );
s = CH376SecLocate( 0xFFFFFFFF ); ?/* 重新回到原文件的尾部,以扇區(qū)為單位,所以會(huì)忽略文件尾部的零頭數(shù)據(jù),下面如果再寫入數(shù)據(jù)將覆蓋尾部零頭數(shù)據(jù),不過該零頭數(shù)據(jù)有一份副本保留在緩沖區(qū)中,所以請放心 */
mStopIfError( s );
}
else if ( total >= sizeof( FileDataBuf ) - DEF_SECTOR_SIZE )?
{ ?/* 緩沖區(qū)中的數(shù)據(jù)快要滿了,所以應(yīng)該先將緩沖區(qū)中的原有數(shù)據(jù)寫入U(xiǎn)盤 */
s = CH376SecWrite( FileDataBuf, (UINT8)( total / DEF_SECTOR_SIZE ), NULL ); ?/* 將緩沖區(qū)中的字節(jié)數(shù)轉(zhuǎn)換為扇區(qū)數(shù)(除以DEF_SECTOR_SIZE),最后的零頭數(shù)據(jù)先不管,以扇區(qū)為單位向文件寫入數(shù)據(jù) */
????????????????mStopIfError( s );
memcpy( FileDataBuf, & FileDataBuf[ total & ~ ( DEF_SECTOR_SIZE - 1 ) ], total & ( DEF_SECTOR_SIZE - 1 ) ); ?/* 將剛才未寫入U(xiǎn)盤的零頭數(shù)據(jù)復(fù)制到緩沖區(qū)的頭部 */
total &= DEF_SECTOR_SIZE - 1; ?/* 緩沖區(qū)中只剩下剛才未寫入U(xiǎn)盤的零頭數(shù)據(jù) */
/* 注意,此處U盤或者SD卡中的文件長度仍然是以前的值,即此時(shí)突然斷電,那么雖然物理上的數(shù)據(jù)已在U盤/SD卡中,但文件長度沒有包括這些數(shù)據(jù),導(dǎo)致常歸應(yīng)用程序無法取得數(shù)據(jù) */
}
}
void ch376_main( void )
{ ? ??
mDelaymS( 100 ); ?/* 延時(shí)100毫秒 */
s = mInitCH376Host( ); ?/* 初始化CH376 */
mStopIfError( s );
//global_memset(USB_buf, 'F', 0x4000);
while (1)
{
while ( CH376DiskConnect( ) != USB_INT_SUCCESS )?
{ ?/* 檢查U盤是否連接,等待U盤插入,對于SD卡,可以由單片機(jī)直接查詢SD卡座的插拔狀態(tài)引腳 */
msleep( 10 );
}
msleep( 20 ); ?/* 延時(shí),可選操作,有的USB存儲(chǔ)器需要幾十毫秒的延時(shí) */
/* 對于檢測到USB設(shè)備的,最多等待10*50mS */
for ( s = 0; s < 5; s ++ )?
{ ?/* 重復(fù)5次,每次200mS延遲 */
msleep( 20 );
if ( CH376DiskMount( ) == USB_INT_SUCCESS )?
break; ?/* 初始化磁盤并測試磁盤是否就緒 */
}
s = CH376DiskQuery( (PUINT32)USB_buf ); ?/* 查詢磁盤剩余空間信息,扇區(qū)數(shù) */
mStopIfError( s );
m_USB_size = *(PUINT32)USB_buf /( 1000000 / DEF_SECTOR_SIZE );
/* 如果MY_ADC.TXT文件已經(jīng)存在則添加數(shù)據(jù)到尾部,如果不存在則新建文件 */
s = CH376FileOpen( (PUINT8)"/B-DATA.TXT" ); ?/* 打開文件,該文件在根目錄下 */
if ( s == USB_INT_SUCCESS )?
{ ?/* 文件存在并且已經(jīng)被打開,移動(dòng)文件指針到尾部以便添加數(shù)據(jù) */
NewSize = CH376GetFileSize( ); ?/* 讀取當(dāng)前文件長度,如果沒有零頭數(shù)據(jù),那么文件長度是DEF_SECTOR_SIZE的倍數(shù) */
s = CH376SecLocate( 0xFFFFFFFF ); ?/* 以扇區(qū)為單位移到文件尾部,如果文件尾部有不足一個(gè)扇區(qū)的零頭數(shù)據(jù)則被忽略,如果不做處理那么零頭數(shù)據(jù)將可能被寫入數(shù)據(jù)覆蓋 */
mStopIfError( s );
total = NewSize & ( DEF_SECTOR_SIZE - 1 ); ?/* 上次保存文件時(shí)如果尾部有零頭數(shù)據(jù),那么先取得零頭字節(jié)數(shù),不滿扇區(qū)長度的零碎數(shù)據(jù) */
if ( total )?
{ ?/* 原尾部有零頭數(shù)據(jù),那么先調(diào)入內(nèi)存,以便接著添加數(shù)據(jù) */
s = CH376SecRead( FileDataBuf, 1, NULL ); ?/* 從文件讀取尾部零頭數(shù)據(jù) */
mStopIfError( s );
s = CH376SecLocate( 0xFFFFFFFF ); ?/* 重新回到原文件的尾部,下面如果寫入數(shù)據(jù)將覆蓋原尾部零頭數(shù)據(jù),不過原零頭數(shù)據(jù)剛才已經(jīng)被讀入內(nèi)存,所以請放心 */
mStopIfError( s );
}
}
else if ( s == ERR_MISS_FILE )?
{ ?/* 沒有找到文件,必須新建文件 */
s = CH376FileCreate( NULL ); ?/* 新建文件并打開,如果文件已經(jīng)存在則先刪除后再新建,不必再提供文件名,剛才已經(jīng)提供給CH376FileOpen */
mStopIfError( s );
total = 0; ?/* 此前沒有零頭數(shù)據(jù) */
NewSize = 0;
}
else mStopIfError( s ); ?/* 打開文件時(shí)出錯(cuò) */
//mFlushBufferToDisk( 0 ); ?/* 自動(dòng)刷新緩沖區(qū),檢查緩沖區(qū)是否已滿,滿則寫盤*/
mFlushBufferToDisk( 1 ); ?/* 強(qiáng)制刷新緩沖區(qū),因?yàn)橄到y(tǒng)要退出了,所以必須強(qiáng)制刷新 */
s = CH376FileClose( FALSE ); ?/* 關(guān)閉文件,扇區(qū)模式通常不自動(dòng)更新文件長度,因?yàn)閺?qiáng)制刷新緩沖區(qū)時(shí)已經(jīng)更新了文件長度,所以這里不需要自動(dòng)更新文件長度 */
mStopIfError( s );
while ( CH376DiskConnect( ) == USB_INT_SUCCESS )?
{ ?/* 檢查U盤是否連接,等待U盤拔出 */
msleep( 10 );
}
msleep( 200 );
}
}