单片机通过CH375读写U盘文件的问题解答

请问一下,写U盘。 用字节的方式写,速度是多少啊? 用扇区写的话,速度又是多少啊? 资料上只是说扇区比字节略快。。。。


这个和单片机有关系。快速的MCU,多扇区读写速度会快的多。库最多支持255个字节同时写。 支持255个扇区同时写。


关于速度方面的详细说明,请下载CH375EVT.ZIP,参考CH375EVT.PDF中的5.3. 单片机读写U盘


你好,我基本上按照你们的例程用128单片机做的并口操作375芯片,文件好像也新建了,因为打开优盘文件名存在,但是内容好像没有写进去,是不是基础程序有问题?单片机是8m晶体 基础程序如下 void xWriteCH375Cmd( UINT8 mCmd ) /* 外部定义的被CH375程序库调用的子程序,向CH375写命令 */ { mDelay1uS( ); mDelay1uS( ); /* 至少延时1uS */ /* *(volatile unsigned char *)CH375_CMD_PORT_ADDR = mCmd; 通过并口直接读写CH375而非普通I/O模拟 */ //PORTB |= 0x08; /* 输出A0=1 */ SET_CH375_A0; PORTC = mCmd; /* 向CH375的并口输出数据 */ DDRC = 0xFF; /* 并口D0-D7输出 */ /* PORTB &= 0xF9; // 输出有效写控制信号, 写CH375芯片的命令端口, A0=1; CS=0; WR=0; RD=1; DDRA = 0xFF; // 该操作无意义,仅作延时,CH375要求读写脉冲宽度大于100nS PORTB |= 0x07; // 输出无效的控制信号, 完成操作CH375芯片, A0=1; CS=1; WR=1; RD=1; DDRA = 0x00; // 禁止数据输出 PORTB &= 0xF7; // 输出A0=0; 可选操作 */ //写命令的状态 CLR_CH375_WR;// CLR_CH375_CS; SET_CH375_RD; NOP();//延时 mDelay1uS( ); SET_CH375_WR;// SET_CH375_CS; CLR_CH375_RD; DDRC = 0x00; // 禁止数据输出 CLR_CH375_A0; mDelay1uS( ); mDelay1uS( ); /* 至少延时2uS */ }

void xWriteCH375Data( UINT8 mData ) /* 外部定义的被CH375程序库调用的子程序,向CH375写数据 */ { /* *(volatile unsigned char *)CH375_DAT_PORT_ADDR = mData; 通过并口直接读写CH375而非普通I/O模拟 */ CLR_CH375_A0; PORTC = mData; /* 向CH375的并口输出数据 */ DDRC = 0xFF; /* 并口D0-D7输出 */ CLR_CH375_WR;// CLR_CH375_CS; SET_CH375_RD; NOP();//延时 mDelay1uS( ); SET_CH375_WR;// SET_CH375_CS; CLR_CH375_RD; DDRC = 0x00; // 禁止数据输出 /* PORTB &= 0xF1; // 输出有效写控制信号, 写CH375芯片的数据端口, A0=0; CS=0; WR=0; RD=1; DDRA = 0xFF; //该操作无意义,仅作延时,CH375要求读写脉冲宽度大于100nS PORTB |= 0x07;//输出无效的控制信号, 完成操作CH375芯片, A0=0; CS=1; WR=1; RD=1; DDRA = 0x00; //禁止数据输出 */ mDelay1uS( ); //至少延时1.2uS }

UINT8 xReadCH375Data( void ) /* 外部定义的被CH375程序库调用的子程序,从CH375读数据 */ { UINT8 mData; //mData = *(volatile unsigned char *)CH375_DAT_PORT_ADDR; 通过并口直接读写CH375而非普通I/O模拟 */ mDelay1uS( ); /* 至少延时1.2uS */ /* PORTB &= 0xF2; // 输出有效读控制信号, 读CH375芯片的数据端口, A0=0; CS=0; WR=1; RD=0; / DDRA = 0x00; // 该操作无意义,仅作延时,CH375要求读写脉冲宽度大于100nS / mData = PINA; // 从CH375的并口PA输入数据 / PORTB |= 0x07; // 输出无效的控制信号, 完成操作CH375芯片, A0=0; CS=1; WR=1; RD=1; / */ SET_CH375_WR;// CLR_CH375_CS; CLR_CH375_RD; DDRC = 0x00; // 该操作无意义,仅作延时,CH375要求读写脉冲宽度大于100nS / mData = PINC; // 从CH375的并口PA输入数据 / //NOP();//延时 mDelay1uS( ); CLR_CH375_WR;// SET_CH375_CS; SET_CH375_RD; DDRC = 0x00; return( mData ); } 中间的延时是后来加上的,加之前之后都不对,写不进去

主程序如下 void main( ) { UINT8 i, c; UINT16 TotalCount; UINT8 *pCodeStr; //CH375_PORT_INIT( ); mDelaymS( 100 ); /* 延时100毫秒 */ init_devices();//2010-1-19 8:51:18 OPEN_BUZZER; mDelaymS( 100 ); /* 延时100毫秒 */ STOP_BUZZER;//2010-1-18 16:12:33 //LED_OUT_INACT( ); //mInitSTDIO( ); /* 为了让计算机通过串口监控演示过程 */ //printf( "Start\n" );

#if DISK_BASE_BUF_LEN == 0 pDISK_BASE_BUF = &my_buffer[0]; /* 不在.H文件中定义CH375的专用缓冲区,而是用缓冲区指针指向其它应用程序的缓冲区便于合用以节约RAM */ #endif

i = CH375LibInit( ); /* 初始化CH375程序库和CH375芯片,操作成功返回0 */ mStopIfError( i ); /* 其它电路初始化 */

while ( 1 ) { while ( CH375DiskStatus != DISK_CONNECT ) xQueryInterrupt( ); /* 查询CH375中断并更新中断状态,等待U盘插入 */ //LED_OUT_ACT( ); /* LED亮 */ mDelaymS( 200 ); /* 延时,可选操作,有的USB存储器需要几十毫秒的延时 */

/* 检查U盘是否准备好,有些U盘不需要这一步,但是某些U盘必须要执行这一步才能工作 */ for ( i = 0; i < 10; i ++ ) { /* 有的U盘总是返回未准备好,不过可以被忽略 */ mDelaymS( 100 ); //printf( "Ready ?\n" ); if ( CH375DiskReady( ) == ERR_SUCCESS ) break; /* 查询磁盘是否准备好 */ } #if DISK_BASE_BUF_LEN if ( DISK_BASE_BUF_LEN < CH375vSectorSize ) { /* 检查磁盘数据缓冲区是否足够大,CH375vSectorSize是U盘的实际扇区大小 */ //printf( "Too large sector size\n" ); while ( CH375DiskConnect( ) == ERR_SUCCESS ) mDelaymS( 100 ); continue; } #endif /* 查询磁盘物理容量 */ /* printf( "DiskSize\n" ); i = CH375DiskSize( ); mStopIfError( i ); printf( "TotalSize = %u MB \n", (unsigned int)( mCmdParam.DiskSize.mDiskSizeSec * (CH375vSectorSize/512) / 2048 ) ); // 显示为以MB为单位的容量 // 原计算方法 (unsigned int)( mCmdParam.DiskSize.mDiskSizeSec * CH375vSectorSize / 1000000 ) 有可能前两个数据相乘后导致溢出, 所以修改成上式 */

/* 读取原文件 */ //printf( "Open\n" ); strcpy( (char *)mCmdParam.Open.mPathName, (char *)"/345.txt" ); /* 文件名,该文件在C51子目录下 */ i = CH375FileOpen( ); /* 打开文件 */ if ( i == ERR_MISS_DIR || i == ERR_MISS_FILE ) { // 没有找到文件 strcpy( mCmdParam.Create.mPathName, mCmdParam.Open.mPathName ); i = CH375FileCreate( ); /* 新建文件并打开,如果文件已经存在则先删除后再新建 */ mStopIfError( i ); } else { /* 找到文件,说明文件已存在,因为不打算覆盖原数据,所以移动文件指针到末尾,以便追加数据 */ mStopIfError( i ); mCmdParam.ByteLocate.mByteOffset = 0xFFFFFFFF; /* 移动到文件尾,用于在CMD_FileOpen打开文件后,继续追加数据到已打开文件的末尾 */ CH375ByteLocate( ); //i = ExecCommand( CMD_ByteLocate, 4 ); /* 以字节为单位移动文件指针 */ mStopIfError( i ); }

//#ifdef EN_DISK_WRITE /* 子程序库支持写操作 */ /* 产生新文件 */ //pCodeStr = (UINT8 *)"Note: \xd\xa这个程序是以字节为单位进行U盘文件读写,单片机只需要有600字节的RAM\xd\xa"; pCodeStr = (UINT8 *)"1234567iytr7ihff"; //while( 1 ) { /* 分多次写入文件数据 */ //for ( i=0; i for ( i=0; i<18; i++ ) { c = *pCodeStr; mCmdParam.ByteWrite.mByteBuffer[i] = c; if ( c == 0 ) break; /* 源字符串结束 */ pCodeStr++; } //if ( i == 0 ) break; /* 源字符串结束,完成写文件 */ mCmdParam.ByteWrite.mByteCount = i; /* 写入数据的字符数,单次读写的长度不能超过MAX_BYTE_IO,第二次调用时接着刚才的向后写 */ i = CH375ByteWrite( ); /* 向文件写入数据 */ mStopIfError( i ); } /* printf( "Modify\n" ); mCmdParam.Modify.mFileAttr = 0xff; 输入参数: 新的文件属性,为0FFH则不修改 mCmdParam.Modify.mFileTime = 0xffff; 输入参数: 新的文件时间,为0FFFFH则不修改,使用新建文件产生的默认时间 mCmdParam.Modify.mFileDate = MAKE_FILE_DATE( 2004, 5, 18 ); 输入参数: 新的文件日期: 2004.05.18 mCmdParam.Modify.mFileSize = 0xffffffff; 输入参数: 新的文件长度,以字节为单位写文件应该由程序库关闭文件时自动更新长度,所以此处不修改 i = CH375FileModify( ); 修改当前文件的信息,修改日期 mStopIfError( i ); */ //printf( "Close\n" ); mCmdParam.Close.mUpdateLen = 1; /* 自动计算文件长度,以字节为单位写文件,建议让程序库关闭文件以便自动更新文件长度 */ i = CH375FileClose( ); mStopIfError( i );

/* 删除某文件 */ /* printf( "Erase\n" ); strcpy( (char *)mCmdParam.Create.mPathName, "/OLD" ); 将被删除的文件名,在根目录下 i = CH375FileErase( ); 删除文件并关闭 if ( i != ERR_SUCCESS ) printf( "Error: %02X\n", (UINT16)i ); 显示错误 */

/* 查询磁盘信息 */ /* printf( "Disk\n" ); i = CH375DiskQuery( ); mStopIfError( i ); printf( "Fat=%d, Total=%ld, Free=%ld\n", (UINT16)mCmdParam.Query.mDiskFat, mCmdParam.Query.mTotalSector, mCmdParam.Query.mFreeSector ); */

//printf( "Take out\n" ); //while ( CH375DiskStatus != DISK_DISCONNECT ) xQueryInterrupt( ); /* 查询CH375中断并更新中断状态,等待U盘拔出 */ //LED_OUT_INACT( ); /* LED灭 */ OPEN_BUZZER; mDelaymS( 100 ); /* 延时100毫秒 */ STOP_BUZZER;//2010-1-18 16:12:33 mDelaymS( 200 ); while(1); /* i = FILE_DATA_BUF[0]; 因为是以字节为单位读写文件,未用到文件数据缓冲区,为了防止编译器优化掉该缓冲区而用一下缓冲区 */ } }


写完文件后要更新相应的文件长度才可以,目前你发现文件好像写不进去,看下文件大小是多少?是不是你实际的文件长度? 关于如果更新文件长度,请下载CH375EVT.ZIP,里面有CH375HF.PDF,按照上面的方法去更新就可以了。


研究贵公司燃CH374s一个星期了,一点头绪都没有。我用的是软件模拟SPI方式。发送测试字后(发送测试字之前需要发送其他的什么数据或者命令吗?),接收到的数据是0Xff。测试晶振两管脚的电压都是2点多伏。请问我的问题怎么解决?还有怎么区分发送的命令还是数据?


要放假了,祝大家春节快乐,来年工作顺利!


新手学习中


我这个程序实现枚举"\\IMPORT"文件中的"SJ*"文件列表,但不知为什么,只能找到第一个文件,然后就"i==ERR_MISS_FILE"就跳出了,我的文件夹里有好多个文件,如SJ1,SJ23,SJA等,请问,是什么原因? 求助。。。。。

strcpy( mCmdParam.Open.mPathName, "\\IMPORT" ); i = CH375FileOpen(); if(i != ERR_OPEN_DIR) //指定路径未被打开 return(i);

for ( c = 0; c < 254; c ++ ) { /* 最多搜索前254个文件 */ mCmdParam.Open.mPathName[0]='S'; mCmdParam.Open.mPathName[1]='J'; mCmdParam.Open.mPathName[2]='*'; mCmdParam.Open.mPathName[3]=0; i = strlen( (char *)mCmdParam.Open.mPathName ); mCmdParam.Open.mPathName[ i ] = 0; i = CH375FileOpen( ); if ( i == ERR_MISS_FILE ) break; if ( i != ERR_FOUND_NAME ) break; //**显示搜索到的文件名 }


你的这种应用,下载CH375EVT.ZIP,参考CH375HF.PDF中的CH375FileEnumer( ); /* 枚举文件 */


我现在这个程序跟例子一样的,但不知为什么,就是枚举不出其它的文件,麻烦你帮我看一下?


是一样么?你的程序中有枚举序号么,再好好比较一下吧: for ( c=0; c<255; c++ ) { /* 最多搜索前255 个文件 */ strcpy( mCmdParam.Enumer.mPathName, "\\C51\\CH375*" ); /* 在C51 子目录下搜索以CH375 开头的文件名,*为通配符 */ i = strlen( mCmdParam.Enumer.mPathName ); /* 计算文件名长度,指向结束符 */ mCmdParam.Enumer.mPathName[i] = c; /* 将结束符替换为搜索的序号,从0 到254 */ i=CH375FileEnumer( ); /* 文件名中含有通配符*,枚举/搜索文件而不打开 */ if ( i==ERR_MISS_FILE ) break; /* 再也搜索不到匹配文件,已经没有匹配的文件名 */ if ( i!=ERR_SUCCESS ) break; /* 出错 */ printf( "found name %d#: %s\n", (unsigned int)c, mCmdParam.Enumer.mPathName ); /* 搜索到相匹配的文件名,显示序号和搜索到的匹配文件名或者子目录名 */ }


谢谢,搞定了,一直没搞懂 mCmdParam.Enumer.mPathName与 mCmdParam.Open.mPathName的区别,现在明白了,还有那个序号


status = mRecvByte( ); /* 等待模块完成操作并返回操作状态 */ if ( status == ERR_SUCCESS ) { /* 操作成功 */ i = mRecvByte( ); /* 返回结果数据的长度 */ if ( i ) { /* 有结果数据 */ CH375HMS.C中i = mRecvByte( ); /* 返回结果数据的长度 */返回结果数据长度是什么意思?每次发送完模块操作命令,如果成功到底返回什么?例如ExecCommand( CMD_QueryStatus, 0 )之后如果成功返回到串口的数据依次是ERR_SUCCESS+返回结果数据的长度+12个字节的struct Status吗? 还是如CH375HM中说的12个字节的struct Status


1、返回结果数据长度,就是模块应答的数据长度 2、数据组成就是头文件中的结构体所描述的


只有登录才能回复,可以选择微信账号登录