使用CH376存在的几个问题

1,等于大于4GU盘无法检测到。 2,不知道是硬件问题还是程序问题,写入程序一段时间后,U盘文件(2G)读取正常,但是当开机一段时间(5H),小部分机器就出现了无法找到文件名。 请各位前辈指点指点一下。 程序: #include "string.h" #include "..\s3c44b0\Target\44b.h" #include "..\s3c44b0\Target\44blib.h" #include "..\s3c44b0\Target\option.h"

#include "..\UCOSII\os_cpu.h" #include "..\UCOSII\includes.h"

#include "CH376.h" #include "FAT16.h" #include "CHFAT.h" #include

#define INT8U unsigned char #define INT16U unsigned short #define INT32U unsigned int /* *********************************************OK**************************************************************** - 函数名称 : void SD_GPIO_Init(void) - 函数说明 : SDA引脚方向处理 - 输入参数 : 1:输入 0:输出 - 输出参数 : 无 ************************************************************************************************************* */ void CH376WriteVar32( INT8U var, INT32U dat ) // 写CH376芯片内部的32位变量 { _USBCmd( CMD50_WRITE_VAR32 ); _USBWrite( var ); _USBWrite( (INT8U)dat ); _USBWrite( (INT8U)( (INT16U)dat >> 8 ) ); _USBWrite( (INT8U)( dat >> 16 ) ); _USBWrite( (INT8U)( dat >> 24 ) ); CH_Cs_H (); } /* *********************************************OK**************************************************************** - 函数名称 : void SD_GPIO_Init(void) - 函数说明 : SDA引脚方向处理 - 输入参数 : 1:输入 0:输出 - 输出参数 : 无 ************************************************************************************************************* */ void CH376SetFileName( char * name ) // 设置将要操作的文件的文件名 { INT8U c; _USBCmd( CMD10_SET_FILE_NAME ); c = *name; _USBWrite( c ); while ( c ) { name ++; c = *name; if ( c == DEF_SEPAR_CHAR1 || c == DEF_SEPAR_CHAR2 ) c = 0; // 强行将文件名截止 _USBWrite( c ); } CH_Cs_H (); } /* *********************************************OK**************************************************************** - 函数名称 : void SD_GPIO_Init(void) - 函数说明 : SDA引脚方向处理 - 输入参数 : 1:输入 0:输出 - 输出参数 : 无 ************************************************************************************************************* */ INT8U CH376FileOpen( char * name ) // 在根目录或者当前目录下打开文件或者目录(文件夹) { unsigned char mIntStatus; CH376SetFileName( name ); // 设置将要操作的文件的文件名 if ( name[0] == DEF_SEPAR_CHAR1 || name[0] == DEF_SEPAR_CHAR2 ) CH376WriteVar32( VAR_CURRENT_CLUST, 0 ); // 等待U盘连接 _USBCmd(CMD0H_FILE_OPEN); CH_Cs_H (); mIntStatus = CH375_WaitInterrupt( ); //Uart_Printf( "mIntStatus=%02X\n", mIntStatus ); return(mIntStatus); } /* *********************************************OK**************************************************************** - 函数名称 : void SD_GPIO_Init(void) - 函数说明 : SDA引脚方向处理 - 输入参数 : 1:输入 0:输出 - 输出参数 : 无 ************************************************************************************************************* */ INT8U CH376ReadBlock( char *buf ) // 从当前主机端点的接收缓冲区读取数据块,返回长度 { INT8U s, l; _USBCmd( CMD01_RD_USB_DATA0 ); s = l = _USBRead( ); // 长度 if ( l ) { do { *buf = _USBRead( ); buf ++; } while ( -- l ); } CH_Cs_H (); return( s ); } /* *********************************************OK**************************************************************** - 函数名称 : void SD_GPIO_Init(void) - 函数说明 : SDA引脚方向处理 - 输入参数 : 1:输入 0:输出 - 输出参数 : 无 ************************************************************************************************************* */ INT8U CH376ByteRead( char *buf, INT16U ReqCount, INT16U * RealCount ) // 以字节为单位从当前位置读取数据块 { INT8U s; _USBCmd( CMD2H_BYTE_READ ); _USBWrite( (INT8U)ReqCount ); _USBWrite( (INT8U)(ReqCount>>8) ); CH_Cs_H (); if ( RealCount ) *RealCount = 0; while ( 1 ) { s = CH375_WaitInterrupt( ); if ( s == USB_INT_DISK_READ ) { s = CH376ReadBlock( buf ); // 从当前主机端点的接收缓冲区读取数据块,返回长度 _USBCmd( CMD0H_BYTE_RD_GO ); CH_Cs_H (); buf += s; if ( RealCount ) *RealCount += s; } else return( s ); // 错误 } } /* *********************************************OK**************************************************************** - 函数名称 : void SD_GPIO_Init(void) - 函数说明 : SDA引脚方向处理 - 输入参数 : 1:输入 0:输出 - 输出参数 : 无 ************************************************************************************************************* */ INT32U CH376Read32bitDat( void ) // 从CH376芯片读取32位的数据并结束命令 { INT8U c0, c1, c2, c3; c0 = _USBRead( ); c1 = _USBRead( ); c2 = _USBRead( ); c3 = _USBRead( ); CH_Cs_H (); return( c0 | (INT16U)c1 << 8 | (INT32U)c2 << 16 | (INT32U)c3 << 24 ); } /* *********************************************OK**************************************************************** - 函数名称 : void SD_GPIO_Init(void) - 函数说明 : SDA引脚方向处理 - 输入参数 : 1:输入 0:输出 - 输出参数 : 无 ************************************************************************************************************* */ INT32U CH376ReadVar32( unsigned char var ) // 读CH376芯片内部的32位变量 { _USBCmd( CMD14_READ_VAR32 ); _USBWrite( var ); return( CH376Read32bitDat( ) ); // 从CH376芯片读取32位的数据并结束命令 } /* *********************************************OK**************************************************************** - 函数名称 : void SD_GPIO_Init(void) - 函数说明 : SDA引脚方向处理 - 输入参数 : 1:输入 0:输出 - 输出参数 : 无 ************************************************************************************************************* */ INT32U CH376GetFileSize( void ) // 读取当前文件长度 { return( CH376ReadVar32( VAR_FILE_SIZE ) ); } /* *********************************************OK**************************************************************** - 函数名称 : void SD_GPIO_Init(void) - 函数说明 : SDA引脚方向处理 - 输入参数 : 1:输入 0:输出 - 输出参数 : 无 ************************************************************************************************************* */ unsigned char Open_File1(unsigned long *U_Size) // 在根目录或者当前目录下打开文件或者目录(文件夹) { INT8U *Buffer_Usb1 = (INT8U *)DFT_DOWNLOAD_ADDR; INT32U TotalCount,Size1; INT8U sta; INT16U RealCount,i; char buf[512]; strcpy( buf,"/CARDLAN.BIN" ); sta = CH376FileOpen( buf ); // 枚举文件和目录 //Uart_Printf( "mIntStatus=%02X\n", s ); if ( sta == ERR_MISS_DIR || sta == ERR_MISS_FILE ) { // Uart_Printf("没有找到文件\n"); return(1); } else { Size1 = 0; // Uart_Printf("找到文件\n"); TotalCount = CH376GetFileSize( ); // Uart_Printf(0,"FileSize = %02d\n",TotalCount); *U_Size = TotalCount; // 准备读取总长度 // printf( "从文件中读出的前%d个字符是:\n",(UINT16)TotalCount ); while ( TotalCount ) { // 如果文件比较大,一次读不完,可以再调用CH376ByteRead继续读取,文件指针自动向后移动 if ( TotalCount > sizeof(buf) ) i = sizeof(buf); // 剩余数据较多,限制单次读写的长度不能超过缓冲区大小 else i = TotalCount; // 最后剩余的字节数 sta = CH376ByteRead(buf, i, &RealCount ); // 以字节为单位读取数据块,单次读写的长度不能超过缓冲区大小,第二次调用时接着刚才的向后读 TotalCount -= (unsigned char)RealCount; // 计数,减去当前实际已经读出的字符数 // for ( s=0; s!=RealCount; s++ ) // Uart_SendByte( buf[s] ); // 显示读出的字符 memcpy(Buffer_Usb1 + Size1,buf,512); Size1 = Size1 +512; if

void CH375_Upan_Updata(void) { INT8U Status; INT8U n,Upan; Upan = 1; n = 1; while(Upan) { switch(n) { case 1: Status = CH375Init_Master(); if(Status == MI_OK)n++; else Upan = 0; break; case 2: //Uart_Printf(0,"硬件初始化成功\n"); Status = DiskReady(); if(Status == MI_OK)n++; else n = 5; break; case 3: //Uart_Printf(0,"有USB连接\n"); SD_USB = 1; Status = mInitDisk(); if(Status == MI_OK)n++; else Upan = 0; break; case 4: //Uart_Printf(0,"U盘初始化成功\n"); SystemUpdating2(); Upan = 0; break; default: Upan = 0; break; } }


/* ************************************************************************************************************* - 函数名称 : uint8 CH375_WaitInterrupt(void) - 函数说明 : 设置CH375为USB主机方式 - 输入参数 : 无 - 输出参数 : 返回中状态 ************************************************************************************************************* */ unsigned char CH375Init_Master(void) { unsigned char i; unsigned char c; unsigned char res; USB_Cmd_Data = 0; xCH376_GPIO_Init(); CH_Cs_H (); CH_CI_H (); _USBCmd( CMD11_CHECK_EXIST ); // 测试单片机与CH376之间的通讯接口 _USBWrite( 0x55 ); c = _USBRead( ); CH_Cs_H (); // 任务一完成 if ( c != 0xaa ) { // CH375出错 for ( i = 100; i != 0; i -- ) { // 强制数据同步 _USBCmd( CMD_RESET_ALL ); // CH375执行硬件复位 c = _USBRead( ); // 延时 CH_Cs_H (); if(c == 0xaa) break; } CH375_DelayNus( 50 ); // 延时至少30mS if ( c != 0xaa ) return(1); } _USBCmd( CMD11_SET_USB_MODE ); // 设备USB工作模式 _USBWrite( 0x06 ); CH375_DelayNus( 200 ); for ( i = 0xff; i != 0; i -- ) // 等待操作成功,通常需要等待10uS-20uS if ( (_USBRead( ) == CMD_RET_SUCCESS)||(USB_Cmd_Data == CMD0H_DISK_CONNECT) ) break; // 操作成功 if ( i != 0 ) { CH_Cs_H (); _USBCmd( CMD20_SET_SDO_INT ); // 设置SPI的SDO引脚的中断方式 _USBWrite( 0x16 ); _USBWrite( 0x90 ); // 输出状态 CH_Cs_H (); if ( res != CMD_RET_SUCCESS ) // 成功 { return( 0x00 ); } else return( 0x02 ); } else { CH_Cs_H (); return( 0xff ); } // 设置模式错误 } 这部分是将CH376初始化成主机模式,现在无论外部是否插有U盘,U盘大小在任何情况下,返回值说明此步骤是成功的,明显问题是在DiskReady()中出现的。


unsigned char DiskReady(void) { unsigned char mIntStatus; unsigned short i; USB_Cmd_Data = 0; for(i = 0 ; i < 600; i++) { // 等待U盘连接 _USBCmd(CMD01_GET_STATUS); CH375_DelayNus(5); mIntStatus = _USBRead( ); CH_Cs_H (); if(mIntStatus == CMD0H_DISK_CONNECT) break; } if(i == 600) { return mIntStatus; } return 0; } 这个是等待程序


建议参考官方提供的例程写程序,到网站上下载CH376EVT.ZIP。 DiskReady()函数没有对U盘进行初始化,也没有检测U盘连接的程序。


用DISK_CONNECT (0x30)检测还是没有反映呢


while ( CH376DiskConnect( ) != USB_INT_SUCCESS ) { mDelaymS( 100 ); } 你们是采用这种死循环方式?但是我不能这样,我是在开机的时候如果有U盘就进行U盘处理程序,没有U盘就处理其它程序。不能死在这里哦。


发送DISK_CONNECT (0x30) 命令,CH376会产生中断,单片机获取中断状态,如果是0x14则说明磁盘连接,否则磁盘未连接, 我们给的程序是死循环的查询,实际应用中,可根据需要进行查询。


/* ************************************************************************************************************* - 函数名称 : uint8 CH375_WaitInterrupt(void) - 函数说明 : 设置CH375为USB主机方式 - 输入参数 : 无 - 输出参数 : 返回中状态 ************************************************************************************************************* */ unsigned char CH375Init_Master(void) { unsigned char i; unsigned char c; unsigned char res; USB_Cmd_Data = 0; xCH376_GPIO_Init(); CH_Cs_H (); CH_CI_H (); _USBCmd( CMD11_CHECK_EXIST ); // 测试单片机与CH376之间的通讯接口 _USBWrite( 0x55 ); c = _USBRead( ); CH_Cs_H (); if ( c != 0xaa ) { // CH375出错 for ( i = 100; i != 0; i -- ) { // 强制数据同步 _USBCmd( CMD_RESET_ALL ); // CH375执行硬件复位 c = _USBRead( ); // 延时 CH_Cs_H (); if(c == 0xaa) break; } CH375_DelayNus( 50 ); // 延时至少30mS if ( c != 0xaa ) return(1); } _USBCmd( CMD11_SET_USB_MODE ); // 设备USB工作模式 _USBWrite( 0x06 ); CH375_DelayNus( 500 ); res = _USBRead( ); CH_Cs_H (); _USBCmd( CMD20_SET_SDO_INT ); // 设置SPI的SDO引脚的中断方式 _USBWrite( 0x16 ); _USBWrite( 0x90 ); CH375_DelayNus( 500 ); Uart_Printf(0,"res = %02X",res); if ( res == CMD_RET_SUCCESS ) // 成功 { return( 0x00 ); } else return( 0x02 ); // 设置模式错误 } 发现有些U盘插上后在这里res不会等于CMD_RET_SUCCESS,这是怎么回事呢?


这段代码还没有涉及到U盘的操作,只是初始化CH376, 怎么会和U盘有关系呢, 在查查其他原因。


对呀,所以奇怪吗?我U盘不插上去可以成功,插上去就不成功了(有些U盘)


是先接U盘在上电,会出现这种情况吗? 在USB接口的VCC处对地接一个100uF的电容试试。


现在是先接U盘再上电出现的这样情况,周边没有大电容


现在接了个大电容,返回正常了,但是还有一个问题,为什么等待U盘连接正常需要这么长的时间呢?


检测U盘连接不需要很长时间,发送30H命令之后就可以检测到,不知道你程序上面是怎么处理的


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