📄 ch375hft.c
字号:
xWriteCH375Data( iCount ); /* 后续数据的长度 */
for ( ; iCount != 0; iCount -- ) { /* 根据长度写入数据 */
xWriteCH375Data( *iBuffer ); /* 将数据写入 */
iBuffer ++;
}
}
/* 检查U盘是否写保护, 返回USB_INT_SUCCESS说明可以写,返回0xFF说明只读/写保护,返回其它值说明是错误代码 */
/* 其它BulkOnly传输协议的命令可以参考这个例子处理,修改前必须了解USB MassStorage和SCSI规范 */
UINT8 IsDiskWriteProtect( void )
{
UINT8 mIfSubClass, mLength, mDevSpecParam;
if ( CH375Version2 == 0 ) return( ERR_USB_DISK_ERR ); /* CH375S不支持 */
CH375IntStatus = 0; /* 清中断标志 */
xWriteCH375Cmd( CMD_GET_DESCR ); /* 获取描述符的命令 */
xWriteCH375Data( 2 ); /* 配置描述符 */
xQueryInterrupt( ); /* 查询CH375中断并更新中断状态 */
if ( CH375IntStatus == USB_INT_SUCCESS ) { /* 操作成功 */
ReadUsbData( (UINT8 *)&mCmdParam ); /* 读取描述符,请确保mCmdParam长度MAX_BYTE_IO大于32字节,否则需另选缓冲区 */
mIfSubClass = mCmdParam.Other.mBuffer[9+6]; /* 子类 USB_CFG_DESCR_LONG.itf_descr.bInterfaceSubClass */
mCmdParam.BOC.mCBW.mCBW_DataLen = 0x10; /* 数据传输长度 */
mCmdParam.BOC.mCBW.mCBW_Flag = 0x80; /* 传输方向为输入 */
if ( mIfSubClass == 6 ) { /* 根据子类选择命令码 */
mCmdParam.BOC.mCBW.mCBW_CB_Buf[0] = 0x1A; /* 命令块首字节, MODE SENSE(6) */
mCmdParam.BOC.mCBW.mCBW_CB_Buf[1] = 0x00;
mCmdParam.BOC.mCBW.mCBW_CB_Buf[2] = 0x3F;
mCmdParam.BOC.mCBW.mCBW_CB_Buf[3] = 0x00;
mCmdParam.BOC.mCBW.mCBW_CB_Buf[4] = 0x10;
mCmdParam.BOC.mCBW.mCBW_CB_Buf[5] = 0x00;
}
else {
mCmdParam.BOC.mCBW.mCBW_CB_Buf[0] = 0x5A; /* 命令块首字节, MODE SENSE(10) */
mCmdParam.BOC.mCBW.mCBW_CB_Buf[1] = 0x00;
mCmdParam.BOC.mCBW.mCBW_CB_Buf[2] = 0x3F;
mCmdParam.BOC.mCBW.mCBW_CB_Buf[3] = 0x00;
mCmdParam.BOC.mCBW.mCBW_CB_Buf[4] = 0x00;
mCmdParam.BOC.mCBW.mCBW_CB_Buf[5] = 0x00;
mCmdParam.BOC.mCBW.mCBW_CB_Buf[6] = 0x00;
mCmdParam.BOC.mCBW.mCBW_CB_Buf[7] = 0x00;
mCmdParam.BOC.mCBW.mCBW_CB_Buf[8] = 0x10;
mCmdParam.BOC.mCBW.mCBW_CB_Buf[9] = 0x00;
}
WriteUsbData( (UINT8 *)&mCmdParam, 31 ); /* 向CH375主机端点的发送缓冲区写入CBW数据块,剩余部分CH375自动填补 */
CH375IntStatus = 0;
xWriteCH375Cmd( CMD_DISK_BOC_CMD ); /* 对USB存储器执行BulkOnly传输协议 */
xQueryInterrupt( ); /* 查询CH375中断并更新中断状态 */
if ( CH375IntStatus == USB_INT_SUCCESS ) { /* 操作成功 */
mLength = ReadUsbData( (UINT8 *)&mCmdParam ); /* 从CH375主机端点的接收缓冲区读取数据块 */
if ( mLength > 3 ) { /* MODE SENSE命令返回数据的长度有效 */
if ( mIfSubClass == 6 ) mDevSpecParam = mCmdParam.Other.mBuffer[2]; /* MODE SENSE(6), device specific parameter */
else mDevSpecParam = mCmdParam.Other.mBuffer[3]; /* MODE SENSE(10), device specific parameter */
if ( mDevSpecParam & 0x80 ) return( 0xFF ); /* U盘写保护 */
else return( USB_INT_SUCCESS ); /* U盘没有写保护 */
}
return( ERR_USB_DISK_ERR );
}
mIfSubClass = CH375IntStatus; /* 暂存 */
xWriteCH375Cmd( CMD_DISK_R_SENSE ); /* 检查USB存储器错误 */
xQueryInterrupt( ); /* 查询CH375中断并更新中断状态 */
return( mIfSubClass );
}
return( CH375IntStatus );
}
/* 安全移除U盘, 返回USB_INT_SUCCESS说明可以安全移除,否则说明不能安全移除,只能强行移除 */
/* 在操作完U盘准备让用户拔出U盘前调用, 防止用户过早拔出U盘丢失数据 */
UINT8 SafeRemoveDisk( void )
{
UINT8 i;
for ( i = 0; i < 10; i ++ ) { /* 有的U盘总是返回未准备好,不过可以被忽略 */
mDelaymS( 100 );
if ( CH375DiskReady( ) == ERR_SUCCESS ) break; /* 查询磁盘是否准备好 */
}
mDelaymS( 10 );
xWriteCH375Cmd( CMD_SET_CONFIG ); /* 设置USB配置 */
xWriteCH375Data( 0 ); /* 取消配置,会导致很多U盘的LED灯灭 */
xQueryInterrupt( ); /* 查询CH375中断并更新中断状态 */
mDelaymS( 10 );
if ( i < 5 && CH375IntStatus == USB_INT_SUCCESS ) return( USB_INT_SUCCESS ); /* 操作成功 */
else return( 0xFF );
/* 以下取消SOF包会导致绝大多数U盘的LED灯灭 */
/* 如果此处取消SOF, 那么与此对应, 在检测到U盘插入后应该再恢复为模式6即恢复SOF包 */
// xWriteCH375Cmd( CMD_SET_USB_MODE ); /* 设置USB工作模式 */
// xWriteCH375Data( 5 ); /* 停止发出SOF包,检测到U盘插入后必须用模式6恢复SOF包发出 */
// mDelaymS( 1 );
}
main( ) {
UINT8 i;
LED_OUT_INIT( );
LED_OUT_ACT( ); /* 开机后LED亮一下以示工作 */
mDelaymS( 100 ); /* 延时100毫秒 */
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 ) {
printf( "Wait Udisk\n" );
while ( CH375DiskStatus < DISK_CONNECT ) { /* 查询CH375中断并更新中断状态,等待U盘插入 */
CH375DiskConnect( );
mDelaymS( 100 );
}
LED_OUT_ACT( ); /* LED亮 */
mDelaymS( 200 ); /* 延时,可选操作,有的USB存储器需要几十毫秒的延时 */
/* 检查U盘是否准备好,有些U盘不需要这一步,但是某些U盘必须要执行这一步才能工作 */
for ( i = 0; i < 3; 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 ) 有可能前两个数据相乘后导致溢出, 所以修改成上式
*/
LED_RUN_ACT( ); /* 开始操作U盘 */
printf( "Check Disk Write Protect ? ...\n" );
i = IsDiskWriteProtect( ); /* 检查U盘是否写保护, 返回USB_INT_SUCCESS说明可以写,返回0xFF说明只读/写保护,返回其它值说明是错误代码 */
if ( i != USB_INT_SUCCESS && i != 0xFF ) { /* 操作失败 */
printf( "Again ...\n" );
mDelaymS( 100 );
i = IsDiskWriteProtect( ); /* 再试一次 */
}
if ( i == USB_INT_SUCCESS ) { /* 可以写 */
printf( "... No !\n" );
LED_WR_ACT( ); /* 写操作 */
printf( "Create a File\n" );
mCopyCodeStringToIRAM( mCmdParam.Create.mPathName, "\\NEWFILE.TXT" ); /* 新文件名,在根目录下 */
i = CH375FileCreate( ); /* 新建文件并打开,如果文件已经存在则先删除后再新建 */
mStopIfError( i );
mCmdParam.ByteWrite.mByteBuffer[0] = 'O';
mCmdParam.ByteWrite.mByteBuffer[1] = 'K';
mCmdParam.ByteWrite.mByteCount = 2; /* 写入数据的字符数,单次读写的长度不能超过MAX_BYTE_IO,第二次调用时接着刚才的向后写 */
i = CH375ByteWrite( ); /* 向文件写入数据 */
mStopIfError( i );
printf( "Close\n" );
mCmdParam.Close.mUpdateLen = 0; /* 不需要自动计算文件长度 */
i = CH375FileClose( );
mStopIfError( i );
LED_WR_INACT( );
if ( SafeRemoveDisk( ) == USB_INT_SUCCESS ) { /* 安全移除U盘 */
printf( "Safe Remove !\n" );
}
else {
printf( "Unsafe Remove !\n" );
}
}
else if ( i == 0xFF ) { /* 写保护 */
printf( "... Yes !\n" );
}
else {
mStopIfError( i ); /* 显示错误代码 */
}
LED_RUN_INACT( );
printf( "Take out\n" );
while ( CH375DiskStatus >= DISK_CONNECT ) { /* 查询CH375中断并更新中断状态,等待U盘拔出 */
CH375DiskConnect( );
mDelaymS( 100 );
}
LED_OUT_INACT( ); /* LED灭 */
mDelaymS( 200 );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -