本日记使用的是沁恒电子的CH376U盘模块读写, 采用PIC芯片;
我把调试过程简单的介绍下,希望给各位需要设计U盘读写的参考思路。
uint8 UsbSendDataFun( uint8 * u8UsbSendRam ) { //
// 最好关闭中断; 数据采集时候会发生意外的呢;
uint8 u8UsbRamBuf[20]; // 文件名字RAM;
uint8 ucTemp; // 变量;
uint16 uiTemp; // 用于USB 传输范围的 选择;
uint16 retry; // uint16 adc, month, date, hour;
uint8 *ui8BufPtr; // 存16通道 参数的 数组 //
uint16 U16SendPagePtr; // 发送的指针;
uint8 u8FunRet; // 返回发送 报告;
DelayNMs(100); // while ( 1) { // DfDisInter; // 关闭中断;
retry =0; // // 初始化CH376 //
while ( retry< 10 ){ // 10 S ?
u8FunRet= mInitCH376Host( ); // 初始化CH376
if ( u8FunRet== USB_INT_SUCCESS ){ break;} // // // 继续; // OK // return 0xff ; // 报告上层调用的函数,出错了;
else { // 初始化失败; 延时是10S, 通信陈宫;成功,延时大约3S;
retry ++;
DelayNMs( 10);
} //
} // retry++
if ( u8FunRet!= USB_INT_SUCCESS ){ // 初始化失败;
return DfInitCH376HostErr; // ERR_USB_UNKNOWN; // 报告上层调用的函数,出错了;
} //
else{; }
CLRWDT(); // 清看门狗 // 假如N次芯片复位后, 系统还是连不上, 就需要复位PIC 系统! 突然拔掉5V电源;
retry=0;
// 检查U盘是否连接,等待U盘插入,对于SD卡, 可以由单片机直接查询SD卡座的插拔状态引脚 //
while ( CH376DiskConnect( ) != USB_INT_SUCCESS ) { // return 0xff ; //
if ( retry > 10) {// break; // // 关闭U 盘,避免浪费电源; 和意外的发生;就是退出后, U盘写入的文件无法更新;
return DfUSBUnConnect; // ERR_USB_UNKNOWN;
}//
else{ retry ++ ;
DelayNMs(10 ); // 如果没有 U 盘的话; 执行任务 : 否则退出,写U盘;
}
}//
// 检查U盘是否连接, 否则退出,写U盘; // CH375_DelayNms(100); // 延时500ms让U盘准备好
DelayNMs( 100 ); // 延时,可选操作,有的USB存储器需要几十毫秒的延时 //
// 对于检测到USB设备的,最多等待10*50mS //
retry =0;
while ( 1 ) { // 最长等待时间,10*50mS //
CLRWDT(); // 清看门狗 // DelayNMs(20 ); //// printf( "Ready ?\n" ); // 30 S
// 初始化磁盘并测试磁盘是否就绪 //
if ( CH376DiskMount( ) == USB_INT_SUCCESS ) { break; } // // Ok
if ( retry > 10){ // #define DfCH376DiskMountErr 5
return DfUSBDiskMountErr ;// ERR_USB_UNKNOWN;
} //
else { retry ++ ;
DelayNMs(10 ); // 1S
}//
}// 次数超过,也退出;
xWriteCH376Cmd( CMD_SET_FILE_NAME ); // 设置将要操作的文件的文件名,通配符支持所有文件和子目录
xWriteCH376Data( '/' );
xWriteCH376Data( '*' );
xWriteCH376Data( 0 );
xWriteCH376Cmd( CMD_FILE_OPEN ); // 枚举文件和目录
while ( 1 ) {
//s = mWaitInterrupt( );
s =Wait376Interrupt( );
if ( s == USB_INT_DISK_READ ) { // 请求数据读出
xWriteCH376Cmd( CMD01_RD_USB_DATA0 );
printf( "Name: ");
xReadCH376Data( ); // 长度总是sizeof(FAT_DIR_INFO)
for ( s = 0; s != 8+3; s ++ ) printf( "%c", xReadCH376Data( ) );
printf( " (%c)\n", xReadCH376Data( )&ATTR_DIRECTORY?'#':'*' ); // 目录显示#后缀,文件显示*后缀
for ( s = 11; s != sizeof( FAT_DIR_INFO ); s ++ ) xReadCH376Data( ); // 取出后续数据
xWriteCH376Cmd( CMD0H_FILE_ENUM_GO ); // 继续枚举文件和目录 //
}
else if ( s == ERR_MISS_FILE ) break; //没有找到更多的匹配文件,正常结束 //
// else mStopIfError( s ); // 操作出错 //
}
// 列举目录成功! 2011 0127
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 如果USB在线,且有数据可以继续创建文件
memcpy(&u8UsbRamBuf[0],"RECD00.BIN" , 11); // printf("buf = ’%s’\n", buf);
if( ( Gu16SysComAddr >99)||(Gu16SysComAddr<0)) { Gu16SysComAddr=1; }
// 补丁; 如果地址溢出,那么就错误;
u8UsbRamBuf[0+4]=Gu16SysComAddr/10+'0'; // // Show_Numstring8x8( (0)*8,0,&u8UsbRamBuf[0],5 ); // +符号位
u8UsbRamBuf[1+4]=Gu16SysComAddr%10+'0'; // // Show_Numstring8x8( (0)*8,0,&u8UsbRamBuf[0],5 ); // +符号位
// u8UsbRamBuf[0]='0'+1; // GWriteCout%9 // 要在RAM中建立文件名成功了太好了我将工程 CLEAN了 再编译就好了;
u8FunRet= CH376FileCreate( &u8UsbRamBuf[0] ); // 新建 文件并打开
DfenablInter;
// "/ MY_ADC.TXT"NULL新建文件并打开,如果文件已经存在则先删除后再新建,
// 不必再提供文件名,刚才已经提供给CH376FileOpen //
if ( u8FunRet== USB_INT_SUCCESS ) { // 文件名创建成功;
// 调用数据写入程序;
u8FunRet=UsbSendRecdDatFun(u8UsbSendRam );// 正常传送;
if( u8FunRet == USB_INT_SUCCESS ){; // 继续下面的程序;
} else{ return u8FunRet ; }
} // // 继续; // OK ; // return ;
else { // return DfCH376DiskMountErr ;
return u8FunRet;
} // // 报告上层调用的函数,出错了;// ERR_USB_UNKNOWN;
// 所以只用于更新文件的长度,当阶段性写入数据后,可以用这种办法更新文件长度 //
// CH376ByteWrite( buf, 0, NULL ); //以字节为单位向文件写入数据,因为是0字节写入,
// 关闭文件,自动计算文件长度,以字节为单位写文件,建议让程序库关闭文件以便自动更新文件长度 //
// DfDisInter; // 关闭中断;
u8FunRet= CH376FileClose( TRUE ); //
DfenablInter;
DelayNMs(100); // 复位完成;
DelayNMs( 2000 ); // 延时,可选操作
// printf( "Write end\n" ); //
return u8FunRet;
// return USB_INT_SUCCESS; // 成功退出 OK ;
}// end file main;
//////////////////////////////////////////////////////////////模拟出的并口的时序/////////////////////////////////////////////////////////////////////////////////
// 由于使用通用I/O模拟并口读写时序,所以进行初始化 如果模拟出的并口上只有CH376*/
void CH376_PORT_INIT( void )
{
// 实现对A口进行初始化;// // 设置与模拟通道有关的口全部为数字
ADCON1 = 0x0f; // // DfLcd_CtrlOutput();
DirCH376_CD=0;
DirCH376_WR=0;
DirCH376_RD=0; // 输出;
mDelayuS( 4);
CH376_WR = 1;
mDelayuS( 4);
CH376_RD = 1;
mDelayuS( 4);
DfCH376_CD = 0;
mDelayuS( 4);
CH376_DATA_DIR_IN( ); // 设置并口输入 //
DfCH376_CS = 1; // 无效
}
// #define xEndCH376Cmd( ) // 结束CH376命令,仅用于SPI接口方式 //
// 从CH376读状态,仅用于并口方式 //
UINT8 xReadCH376Status( void ) {
UINT8 mData;
// DfPsp_CS=0; // 总的数据线片选;
CH376_DATA_DIR_IN( ); // 设置并口方向为输入 //
DfCH376_CD = 1;
DfCH376_CS = 0;
mDelayuS( 4);
CH376_RD = 0; // 输出有效读控制信号, 读CH376芯片的状态端口 //
DfCH376_CS = 0;
// 该操作无意义,仅作延时,CH376要求读写脉冲宽度大于40nS,强烈建议此处执行一条空指令延时以确保并口有足够时间输入数据 //
mDelayuS( 4);
mData = CH376_DATA_DAT_IN( ); // 从CH376的并口输入数据 //
CH376_RD = 1; // 输出无效的控制信号, 完成操作CH376芯片 //
DfCH376_CS = 1;
DfCH376_CD = 0;
// DfPsp_CS=1; // 总的数据线片选;
DfCH376_CS = 1; // 无效
return( mData );
}
void xWriteCH376Cmd( UINT8 mCmd ){ // 向CH376写命令 //
CH376_DATA_DIR_OUT( ); // 设置并口方向为输出 //
mDelayuS( 5);
CH376_DATA_DAT_OUT( mCmd ); // 向CH376的并口输出数据 // PORTD = mCmd ;
DfCH376_CD = 1;
DfCH376_CS = 0;
CH376_WR = 0; // 输出有效写控制信号, 写CH376芯片的命令端口 //
mDelayuS( 4);
DfCH376_CS = 0; // 该操作无意义,仅作延时,CH376要求读写脉冲宽度大于40nS //
CH376_WR = 1; // 输出无效的控制信号, 完成操作CH376芯片 //
DfCH376_CS = 1;
DfCH376_CD = 0;
mDelayuS( 4);
CH376_DATA_DIR_IN( ); // 禁止数据输出 //
// mDelay0_5uS( ); mDelay0_5uS( ); mDelay0_5uS( );//
// 延时1.5uS确保读写周期大于1.5uS,或者用状态查询代替 //
DfCH376_CS = 1; // 无效
}
void xWriteCH376Data( UINT8 mData ) // 向CH376写数据 //
{
CH376_DATA_DIR_OUT( ); // 设置并口方向为输出 //
mDelayuS( 5);
CH376_DATA_DAT_OUT( mData ); // 向CH376的并口输出数据 //
mDelayuS( 5);
DfCH376_CD = 0;
DfCH376_CS = 0;
CH376_WR = 0; // 输出有效写控制信号, 写CH376芯片的数据端口 //
mDelayuS( 4);
DfCH376_CS = 0; // 该操作无意义,仅作延时,CH376要求读写脉冲宽度大于40nS //
CH376_WR = 1; // 输出无效的控制信号, 完成操作CH376芯片 //
DfCH376_CS = 1;
mDelayuS( 4);
CH376_DATA_DIR_IN( ); // 禁止数据输出 //
// mDelay0_5uS( ); // 确保读写周期大于0.6uS //
DfCH376_CS = 1; // 无效
}
UINT8 xReadCH376Data( void ) // 从CH376读数据 //
{
UINT8 mData;
// mDelay0_5uS( ); // 确保读写周期大于0.6uS // // CH376_WR = 0;
CH376_DATA_DIR_IN( ); // 设置并口方向为输入 //
mDelayuS( 4);
DfCH376_CD = 0;
DfCH376_CS = 0;
CH376_RD = 0; // 输出有效读控制信号, 读CH376芯片的数据端口 //
DfCH376_CS = 0; // 该操作无意义,仅作延时,CH376要求读写脉冲宽度大于40nS,强烈建议此处执行一条空指令延时以确保并口有足够时间输入数据 //
mDelayuS( 4);
mData = CH376_DATA_DAT_IN( ); // 从CH376的并口输入数据 //
CH376_RD = 1; // 输出无效的控制信号, 完成操作CH376芯片 //
DfCH376_CS = 1; // 无效
return( mData );
}
// 查询CH376中断(INT#低电平) //
UINT8 Query376Interrupt( void )
{
#ifdef CH376_INT_WIRE
return( CH376_INT_WIRE ? FALSE : TRUE ); // 如果连接了CH376的中断引脚则直接查询中断引脚
#else
return( xReadCH376Status( ) & PARA_STATE_INTB ? FALSE : TRUE ); // 如果未连接CH376的中断引脚则查询状态端口 //
#endif
// return( xReadCH376Status( ) & PARA_STATE_INTB ? FALSE : TRUE ); // 如果未连接CH376的中断引脚则查询状态端口 //
}
// 初始化CH376 //
UINT8 mInitCH376Host( void ) {
UINT8 res=0;
CH376_PORT_INIT( ); // 接口硬件初始化 //
Gres=res; // 观察的; 中间变量
xWriteCH376Cmd( CMD11_CHECK_EXIST ); // 测试单片机与CH376之间的通讯接口 //
xWriteCH376Data( 0xf0 ); // 那么CH376的输出数据是输入数据的按位取反。~0x65=0x9A
res = xReadCH376Data( );
Gres=res; // 观察的; 中间变量
// xEndCH376Cmd( ); // 并口方式不需要
if ( res != 0x0f ) return( ERR_USB_UNKNOWN ); // 通讯接口不正常,可能原因有:接口连接异常,其它设备影响(片选不唯一),串口波特率,一直在复位,晶振不工作 //
xWriteCH376Cmd( CMD11_SET_USB_MODE ); // 设备USB工作模式 //
xWriteCH376Data( 0x06 );
mDelayuS( 20 );
res = xReadCH376Data( );
Gres=res; // 观察的; 中间变量;
// xEndCH376Cmd( ); // 并口方式不需要
if ( res == CMD_RET_SUCCESS ) return ( USB_INT_SUCCESS );
else return( ERR_USB_UNKNOWN ); // 设置模式错误 //
}
文章评论(0条评论)
登录后参与讨论