📄 usbcontrol.c
字号:
/*******************************************************
ch375hft.c file
u盘系统式读写文件
作者:潘卓贤
建立日期:2006-05-02
修改日期:2006-05-21
版本:V2.9
备注:功能:枚举文件、复制文件、删除文件、循环选择文件、文件全部复制,删除,剪切。查询容量,显示有无文件,文件属性选择与显示文本文件内容。
不同U盘传输数据。按键问题修复,数据采集,文件写入大小调整好,显示文本文件,加入取消按键,退出U盘时候有显示,未选文件按操作键会出错。
增加:复制中断,文件属性内容增加,显示菜单语言改变。
******************************************************/
#include <string.h>
#include <at89x52.h>
#include <stdio.h>
#include "DS1302_18B20.H"
#define LIB_CFG_DISK_IO 2 // 磁盘读写的数据的复制方式,1为"单DPTR复制",2为"双DPTR复制",3为"单DPTR和P2+R0复制"
#define LIB_CFG_FILE_IO 2 // 文件读写的数据的复制方式,0为"外部子程序",1为"单DPTR复制",2为"双DPTR复制",3为"单DPTR和P2+R0复制"
#define LIB_CFG_INT_EN 1 // CH375的INT#引脚连接方式,0为"查询方式",1为"中断方式"
#define CH375_CMD_PORT_ADDR 0x8FFF // CH375命令端口的I/O地址
#define CH375_DAT_PORT_ADDR 0x8EFF // CH375数据端口的I/O地址
// 62256提供的32KB的RAM分为两部分: 0000H-7DFFH为文件读写缓冲区, 7E00H-7FFFH为磁盘数据缓冲区
#define DISK_BASE_BUF_ADDR 0x7A00 // 外部RAM的磁盘数据缓冲区的起始地址,从该单元开始的缓冲区长度为SECTOR_SIZE
#define FILE_DATA_BUF_ADDR 0x0000 // 外部RAM的文件数据缓冲区的起始地址,缓冲区长度不小于一次读写的数据长度
// 由于演示板用的62256只有32K字节,其中CH375子程序用512字节,所以外部RAM剩余长度为32256字节
#define FILE_DATA_BUF_LEN 0x7A00 // 外部RAM的文件数据缓冲区,缓冲区长度不小于一次读写的数据长度
#define CH375_INT_NO 0 // CH375中断号, CH375的中断线INT#引脚连接单片机的INT0引脚
#define CH375_INT_FLAG IE0 // IE0,CH375中断标志
#define CH375_INT_EN EX0 // EX0,CH375中断允许
#include "CH375HF4.H"
#include "LCD_FUN.C"
//////// 延时100毫秒,不精确///////
void mDelay100mS( )
{
UINT8 i, j, c;
for ( i = 200; i != 0; i -- ) for ( j = 200; j != 0; j -- ) c+=3;
}
///////// 将程序空间的字符串复制到内部RAM中,返回字符串长度 ////////
UINT8 mCopyCodeStringToIRAM( UINT8 idata *iDestination, UINT8 code *iSource )
{
UINT8 i = 0;
while ( *iDestination = *iSource )
{
iDestination ++;
iSource ++;
i ++;
}
return( i );
}
///////// 检查操作状态,如果错误则显示错误代码并停机 /////////
void mStopIfError( UINT8 iError )
{
if ( iError == ERR_SUCCESS ) return; // 操作成功
printf( "Error: %02X\n", (UINT16)iError ); // 显示错误
}
//////// 为printf和getkey输入输出初始化串口 ///////
void mInitSTDIO( )
{
SCON = 0x50;
PCON = 0x80;
TMOD = 0x20;
TH1 = 0xCB; // 24MHz晶振, 2400bps
TR1 = 1;
TI = 1;
}
////////////////////窜口中断接收采样数据///////////////
UINT16 onetime;
void uart_isr(void) interrupt 4
{
UINT8 ch;
if(RI)
{
RI=0;
ch=SBUF;
onetime++;
FILE_DATA_BUF[onetime]=ch;
FILE_DATA_BUF[0]=' ';//消除开始时候扰动。
FILE_DATA_BUF[1]=' ';
}
}
//////////////////////////采样数据保存////////////////////////////
void save_data(void)
{
UINT8 i;UINT16 c;
c=onetime/512+1;
strcpy( mCmdParam.Create.mPathName,"\\SAMPLE.TXT"); /* 新文件名,在根目录下 */
i = CH375FileCreate( ); /* 新建文件并打开,如果文件已经存在则先删除后再新建 */
mStopIfError( i );
mCmdParam.Write.mSectorCount =c; /* 写入所有扇区的数据 */
/*current_buffer = & FILE_DATA_BUF[0]; 如果文件读写的数据的复制方式为"外部子程序",那么需要设置存放数据的缓冲区的起始地址 */
i = CH375FileWrite( ); /* 向文件写入数据 */
mStopIfError( i );
mCmdParam.Modify.mFileAttr = 0xff; /* 输入参数: 新的文件属性,为0FFH则不修改 */
mCmdParam.Modify.mFileTime = 0xffff; /* 输入参数: 新的文件时间,为0FFFFH则不修改,使用新建文件产生的默认时间 */
mCmdParam.Modify.mFileDate = MAKE_FILE_DATE( 2006,5, 22); /* 输入参数: 新的文件日期: 2004.05.18 */
mCmdParam.Modify.mFileSize =onetime; /* 输入参数: 如果原文件较小,那么新的文件长度与原文件一样长,否则被RAM所限,如果文件长度大于64KB,那么NewSize必须为UINT32 */
i = CH375FileModify( ); /* 修改当前文件的信息,修改日期和长度 */
mStopIfError( i );
mCmdParam.Close.mUpdateLen = 0; /* 不要自动计算文件长度,如果自动计算,那么该长度总是512的倍数 */
i = CH375FileClose( );
mStopIfError( i );
printf( "OK\n" );
}
///////////////////查询容量//////////////////////
void query_disk(void)
{
UINT8 i;
printf("Query Disk...\n");
i=CH375DiskQuery();
mStopIfError( i );
//printf("Fat=%d/", (UINT16)mCmdParam.Query.mDiskFat);
printf("TotalSector=%ld\n",(UINT32)mCmdParam.Query.mTotalSector);
printf("FreeSector=%ld\n",(UINT32)mCmdParam.Query.mFreeSector);
printf("Total--%ld M\n",((UINT32)mCmdParam.Query.mTotalSector)/2048);
printf("Free--%ld M\n",((UINT32)mCmdParam.Query.mFreeSector)/2048);
}
/////////////////////////查询文件属性////////////////////////////////
void file_attribute(void)
{//前提:已经选择文件名
UINT32 size;
UINT8 i;
UINT8 idata cp[25];
strcpy(cp,mCmdParam.Open.mPathName);
i = CH375FileOpen();
mStopIfError(i);
i=CH375FileQuery( ); /* 查询当前文件的信息 */
// mCmdParam.Modify.mFileSize中是文件的长度,以字节为单位,长度可以是0
//mCmdParam.Modify.mFileDate 中是文件修改时间,格式参考CH375HF?.H 中的说明
//mCmdParam.Modify.mFileTime 中是文件修改时间,格式参考CH375HF?.H 中的说明
//mCmdParam.Modify.mFileAttr 中是文件属性,例如数值01H 说明该文件是只读文件
//printf("Modify time:%ld\n",(UINT16)mCmdParam.Modify.mFileAttr);
//printf("Modify data:%ld\n",(UINT16)mCmdParam.Modify.mFileDate);
//printf("Attribute:%02X",(UINT16)mCmdParam.Modify.mFileAttr);
if(mCmdParam.Modify.mFileAttr==0X20)
printf("Archive\n");
if(mCmdParam.Modify.mFileAttr==0X01)
printf("Read only\n");
if(mCmdParam.Modify.mFileAttr==0X02)
printf("Hidden\n");
if(mCmdParam.Modify.mFileAttr==0x10)
printf("Subdir\n");
if(mCmdParam.Modify.mFileAttr==0x04)
printf("System file\n");
if(mCmdParam.Modify.mFileAttr==0x08)
printf("VOLUME_ID");
size=(UINT32)CH375vFileSize;
if(size!=0)
size=size+1024;
printf("Name:%s\n",cp);
printf("File size:%ldK\n",size/1024);
i = CH375FileClose(); /* 关闭文件 */
strcpy(mCmdParam.Open.mPathName,cp);//文件关闭,自动退出已经选择文件名,需再次指定。
mStopIfError( i );
}
/////////////////////////打开文件并显示部分///////////////////////////////
void file_open_show(void)
{//字节方式读写文件,本例只使用512字节的外部RAM, 同时作为磁盘数据缓冲区和文件数据缓冲区
//前提:已经选择文件名,同Copy_file();函数.
//使速度变慢 mDelay100mS();
UINT8 c,i;
UINT16 TotalCount;//显示64字节内容。
UINT8 idata cp[25];
bit cancel=0;
strcpy(cp,mCmdParam.Open.mPathName);
i = CH375FileOpen( );
mStopIfError( i );
TotalCount=CH375vFileSize;
if(TotalCount==0)
printf("File is NULL\n");
while ( TotalCount )
{ /* 如果文件比较大,一次读不完,可以再调用CH375ByteRead继续读取,文件指针自动向后移动 */
if ( TotalCount > MAX_BYTE_IO )
c = MAX_BYTE_IO; /* 剩余数据较多,限制单次读写的长度不能超过 sizeof( mCmdParam.ByteRead.mByteBuffer ) */
else
c = TotalCount; /* 最后剩余的字节数 */
mCmdParam.ByteRead.mByteCount = c; /* 请求读出几十字节数据 */
i = CH375ByteRead( ); /* 以字节为单位读取数据块,单次读写的长度不能超过MAX_BYTE_IO,第二次调用时接着刚才的向后读 */
mStopIfError( i );
TotalCount -= mCmdParam.ByteRead.mByteCount; /* 计数,减去当前实际已经读出的字符数 */
for ( i=0; i!=mCmdParam.ByteRead.mByteCount; i++ )
{
printf( "%C", mCmdParam.ByteRead.mByteBuffer[i] );
mDelay100mS();
///////////////////////////////////////
if(key_esc)
{key_esc_elim();cancel=1;break;} //中断显示。
///////////////////////////////////////
} /* 显示读出的字符 */
if(cancel)
break;
if ( mCmdParam.ByteRead.mByteCount < c )
{ /* 实际读出的字符数少于要求读出的字符数,说明已经到文件的结尾 */
printf( "\n" );
printf( "End\n" );
break;
}
}
i = CH375FileClose( ); /* 关闭文件 */
printf( "\nClose file\n" );
strcpy(mCmdParam.Open.mPathName,cp);//文件关闭,自动退出已经选择文件名,需再次指定。
mStopIfError( i );
}
//////////////////枚举文件///////////////////////
UINT8 enumer_file(UINT8 code *sou,bit type)//0为刷新文件数目;1为枚举文件;返回为文件数目-1(含0开始)
//void enumer_file(void)
{
UINT8 i;
UINT16 j;
if(type)
printf("Enumer files:\n");
for ( j = 0; j < 255; j ++ ) //最多搜索前255个文件
{
i = mCopyCodeStringToIRAM( mCmdParam.Open.mPathName, sou); //搜索文件名,*为通配符,适用于所有文件或者子目录
mCmdParam.Open.mPathName[ i ] = j; // 根据字符串长度将结束符替换为搜索的序号,从0到255
i = CH375FileOpen(); // 打开文件,如果文件名中含有通配符*,则为搜索文件而不打开
if ( i == ERR_MISS_FILE ) {return(j-1);break;} // 再也搜索不到匹配的文件,已经没有匹配的文件名
if ( i == ERR_FOUND_NAME ) // 搜索到与通配符相匹配的文件名,文件名及其完整路径在命令缓冲区中
{
if(type)
printf( "%03d:%s\n", (unsigned int)j, mCmdParam.Open.mPathName );// 显示序号和搜索到的匹配文件名或者子目录名
continue; //继续搜索下一个匹配的文件名,下次搜索时序号会加1
}
else // 出错
{
mStopIfError( i );
break;
}
}
}
////////////////////删除文件///////////////////////
//void del_file(UINT8 code *sou)
void del_file(void)
{
UINT8 i;
//mCopyCodeStringToIRAM( mCmdParam.Open.mPathName, sou );
i = CH375FileErase();
mStopIfError(i);
printf("Del %s\n",mCmdParam.Open.mPathName);
}
bit cy_cancel=0;
////////////////////复制文件//////////////////////
void copy_file(UINT8 idata *sou)
{
UINT8 idata des[25];
UINT8 i;
UINT16 m,n, c,SecCount ;
UINT32 NewSize;
UINT8 idata cp[23];
// mCopyCodeStringToIRAM(mCmdParam.Open.mPathName,sou); /* 文件名,该文件在C51子目录下 */
i = CH375FileOpen( );/* 打开文件 */
strcpy(cp,sou);
strcpy(des,"\\AA");
strcat(des,cp);
if ( i ==ERR_SUCCESS )
{
printf( "Copy now...\n");
if ( CH375vFileSize > FILE_DATA_BUF_LEN )
{ /* 由于演示板用的62256只有32K字节,其中CH375子程序用512字节,所以只读取不超过63个扇区,也就是不超过32256字节 */
c=FILE_DATA_BUF_LEN / 512; /* 由于演示板用的62256只有32K字节,其中CH375子程序用512字节,所以只读取不超过63个扇区,也就是不超过32256字节 */
}
else
{
c=(CH375vFileSize+511)/ 512;
}
SecCount =(CH375vFileSize+511)/ 512;
m=1;
NewSize=(UINT32)CH375vFileSize;
// printf( "cha xun:%d,%d,%ld\n ",SecCount ,c,(UINT32)CH375vFileSize);
for(n=c;n<=SecCount;m++)
{
n=c*m;
mCmdParam.Locate.mSectorOffset = 0x00000000;
mCmdParam.Locate.mSectorOffset =(n-c);
//printf("指针移动%d\n",n-c);
i = CH375FileLocate( );
mCmdParam.Read.mSectorCount =c;
CH375vFileSize += 511; /* 默认情况下,以扇区方式读取数据时,无法读出文件尾部不足1个扇区的部分,所以必须临时加大文件长度以读取尾部零头 */
i = CH375FileRead( ); /* 从文件读取数据 */
CH375vFileSize -= 511; /* 恢复原文件长度 */
mStopIfError( i );
//printf( "读%d个扇区\n",c);
i = CH375FileClose( ); /* 关闭文件 */
mStopIfError( i );
strcpy( mCmdParam.Create.mPathName, des );
if(n==c)
{
i = CH375FileCreate( );
if(n==0)
break;//空文件的时候只新建一个空文件
}
else
{ i = CH375FileOpen( );}
mCmdParam.Locate.mSectorOffset =0xffffffff;
i = CH375FileLocate( );
mCmdParam.Write.mSectorCount =c;
//printf("写入%d个扇区\n",c);
CH375FileWrite();
////////////////////加入按键中断////////////
if(key_esc)
{
i = CH375FileErase();
printf("Cancel!\n");
cy_cancel=1;
strcpy(mCmdParam.Open.mPathName,cp);//使文件指针再次指向原来目标文件。
return;
}
cy_cancel=0;
////////////////////////////////////////////
i = CH375FileClose( );
mStopIfError( i );
//printf("total sec:%d\n",n);
strcpy(mCmdParam.Open.mPathName,cp); /* 文件名,该文件在C51子目录下 */
i = CH375FileOpen( );
mStopIfError( i );
}
i = CH375FileClose();
mStopIfError( i );
strcpy( mCmdParam.Create.mPathName, des );
i = CH375FileOpen();
mCmdParam.Modify.mFileAttr = 0xff; /* 输入参数: 新的文件属性,为0FFH则不修改 */
mCmdParam.Modify.mFileTime = 0xffff; /* 输入参数: 新的文件时间,为0FFFFH则不修改,使用新建文件产生的默认时间 */
mCmdParam.Modify.mFileDate = MAKE_FILE_DATE( 2006,5, 22 ); /* 输入参数: 新的文件日期: 2004.05.18 */
mCmdParam.Modify.mFileSize =NewSize; /* 输入参数: 如果原文件较小,那么新的文件长度与原文件一样长,否则被RAM所限,如果文件长度大于64KB,那么NewSize必须为UINT32 */
i = CH375FileModify( ); /* 修改当前文件的信息,修改日期和长度 */
mStopIfError( i );
mCmdParam.Close.mUpdateLen =0;
i = CH375FileClose( );
mStopIfError( i );
strcpy(mCmdParam.Open.mPathName,cp);//使文件指针再次指向原来目标文件。
printf("OK to %s\n",des);
}
else
{
printf("%s is a folder\n",sou);
}
}
//////////////////复制/删除全部根目录文件到AA目录下//////////////
void copy_del_cut_enumer(UINT8 code *sou,UINT8 type)//1为复制全部文件到AA,2为删除全部文件,3为剪切文件到AA。4为枚举文件
//void enumer_file(void)
{
UINT8 i;
UINT16 c;
for ( c = 0; c < 255; c ++ )
{
strcpy( mCmdParam.Enumer.mPathName,sou);
i=strlen(mCmdParam.Enumer.mPathName);
mCmdParam.Enumer.mPathName[ i ] = c;
i=CH375FileEnumer( );
if ( i == ERR_MISS_FILE ) break;
if ( i!=ERR_SUCCESS ) break;
if(strcmp(mCmdParam.Enumer.mPathName,"\\AA")==0)
continue;
if(strcmp(mCmdParam.Enumer.mPathName,"\\AA\\.")==0)
continue;
if(strcmp(mCmdParam.Enumer.mPathName,"\\AA\\..")==0)
continue;
if(cy_cancel)
return;
if(type==1)
copy_file(mCmdParam.Enumer.mPathName);
if(type==2)
{del_file();c--;}//del_file()删除文件后,c自动加1,现在不需要此功能。
if(type==3)
{
copy_file(mCmdParam.Enumer.mPathName);
if(!cy_cancel)
del_file();
c--;
}
if(type==4)
{printf( "%03d:%s\n", (unsigned int)c,mCmdParam.Enumer.mPathName);};
}
}
//////////////31K数据写入外部RAM,换U盘后写入/////////////////////////////////
//前提选中文件名
void file_charge(void)
{ UINT8 c,i;
UINT8 idata cp[23]={0};
UINT16 size;
strcpy(cp,mCmdParam.Open.mPathName);
i = CH375FileOpen( );/* 打开文件 */
if ( i ==ERR_SUCCESS )
{
if ( CH375vFileSize > FILE_DATA_BUF_LEN )
{c=FILE_DATA_BUF_LEN / 512;size=c*512;} /* 由于演示板用的62256只有32K字节,其中CH375子程序用512字节,所以只读取不超过63个扇区,也就是不超过32256字节 */
else
{
c=(CH375vFileSize+511)/ 512;
size=CH375vFileSize;
}
CH375vFileSize += 511; /* 默认情况下,以扇区方式读取数据时,无法读出文件尾部不足1个扇区的部分,所以必须临时加大文件长度以读取尾部零头 */
i = CH375FileRead( ); /* 从文件读取数据 */
CH375vFileSize -= 511; /* 恢复原文件长度 */
mStopIfError( i );
i = CH375FileClose( ); /* 关闭文件 */
mStopIfError( i );
printf("Wait other disc\n");
i=1;
while(CH375DiskStatus != DISK_DISCONNECT)
{
mDelay100mS( );
mDelay100mS( );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -