⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbcontrol.c

📁 使用51单片机作为控制器
💻 C
📖 第 1 页 / 共 2 页
字号:
/*******************************************************
  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 + -