/* CH376芯片 文件系统层 V1.1 */
/* 提供文件系统常用子程序,提供命令打包 */
/* 不使用的子程序可以注释掉,从而节约单片机的程序ROM空间和数据RAM空间 */
/* 这里的子程序是通过括号中的变量传递参数,如果参数较多,为了节约RAM,也可以参考CH375子程序库改成通过同一全局变量/联合结构CH376_CMD_DATA传递 */
/* name 参数是指短文件名, 可以包括根目录符, 但不含有路径分隔符, 总长度不超过1+8+1+3+1字节 */
/* PathName 参数是指全路径的短文件名, 包括根目录符、多级子目录及路径分隔符、文件名/目录名 */
/* LongName 参数是指长文件名, 以UNICODE小端顺序编码, 以两个0字节结束, 使用长文件名子程序必须先定义全局缓冲区GlobalBuf, 长度不小于64字节, 可以与其它子程序共用 */
/* 定义 NO_DEFAULT_CH376_INT 用于禁止默认的Wait376Interrupt子程序,禁止后,应用程序必须自行定义一个同名子程序 */
/* 定义 DEF_INT_TIMEOUT 用于设置默认的Wait376Interrupt子程序中的等待中断的超时时间/循环计数值, 0则不检查超时而一直等待 */
/* 定义 EN_DIR_CREATE 用于提供新建多级子目录的子程序,默认是不提供 */
/* 定义 EN_DISK_QUERY 用于提供磁盘容量查询和剩余空间查询的子程序,默认是不提供 */
/* 定义 EN_SECTOR_ACCESS 用于提供以扇区为单位读写文件的子程序,默认是不提供 */
/* 定义 EN_LONG_NAME 用于提供支持长文件名的子程序,默认是不提供 */
#include "FILE_SYS.H"
UINT8 CH376ReadBlock( PUINT8 buf ) /* 从当前主机端点的接收缓冲区读取数据块,返回长度 */
{
UINT8 s, l;
xWriteCH376Cmd( CMD01_RD_USB_DATA0 );
s = l = xReadCH376Data( ); /* 长度 */
if ( l ) {
do {
*buf = xReadCH376Data( );
buf ++;
} while ( -- l );
}
xEndCH376Cmd( );
return( s );
}
UINT8 CH376WriteReqBlock( PUINT8 buf ) /* 向内部指定缓冲区写入请求的数据块,返回长度 */
{
UINT8 s, l;
xWriteCH376Cmd( CMD01_WR_REQ_DATA );
s = l = xReadCH376Data( ); /* 长度 */
if ( l ) {
do {
xWriteCH376Data( *buf );
buf ++;
} while ( -- l );
}
xEndCH376Cmd( );
return( s );
}
void CH376WriteHostBlock( PUINT8 buf, UINT8 len ) /* 向USB主机端点的发送缓冲区写入数据块 */
{
xWriteCH376Cmd( CMD10_WR_HOST_DATA );
xWriteCH376Data( len ); /* 长度 */
if ( len ) {
do {
xWriteCH376Data( *buf );
buf ++;
} while ( -- len );
}
xEndCH376Cmd( );
}
void CH376WriteOfsBlock( PUINT8 buf, UINT8 ofs, UINT8 len ) /* 向内部缓冲区指定偏移地址写入数据块 */
{
xWriteCH376Cmd( CMD20_WR_OFS_DATA );
xWriteCH376Data( ofs ); /* 偏移地址 */
xWriteCH376Data( len ); /* 长度 */
if ( len ) {
do {
xWriteCH376Data( *buf );
buf ++;
} while ( -- len );
}
xEndCH376Cmd( );
}
void CH376SetFileName( PUINT8 name ) /* 设置将要操作的文件的文件名 */
{
/* UINT8 i;*/
UINT8 c;
xWriteCH376Cmd( CMD10_SET_FILE_NAME );
/* for ( i = MAX_FILE_NAME_LEN; i != 0; -- i ) {
c = *name;
xWriteCH376Data( c );
if ( c == 0 ) break;
name ++;
}*/
c = *name;
xWriteCH376Data( c );
while ( c ) {
name ++;
c = *name;
if ( c == DEF_SEPAR_CHAR1 || c == DEF_SEPAR_CHAR2 ) c = 0; /* 强行将文件名截止 */
xWriteCH376Data( c );
}
xEndCH376Cmd( );
}
UINT32 CH376Read32bitDat( void ) /* 从CH376芯片读取32位的数据并结束命令 */
{
UINT8 c0, c1, c2, c3;
c0 = xReadCH376Data( );
c1 = xReadCH376Data( );
c2 = xReadCH376Data( );
c3 = xReadCH376Data( );
xEndCH376Cmd( );
return( c0 | (UINT16)c1 << 8 | (UINT32)c2 << 16 | (UINT32)c3 << 24 );
}
UINT8 CH376ReadVar8( UINT8 var ) /* 读CH376芯片内部的8位变量 */
{
UINT8 c0;
xWriteCH376Cmd( CMD11_READ_VAR8 );
xWriteCH376Data( var );
c0 = xReadCH376Data( );
xEndCH376Cmd( );
return( c0 );
}
void CH376WriteVar8( UINT8 var, UINT8 dat ) /* 写CH376芯片内部的8位变量 */
{
xWriteCH376Cmd( CMD20_WRITE_VAR8 );
xWriteCH376Data( var );
xWriteCH376Data( dat );
xEndCH376Cmd( );
}
UINT32 CH376ReadVar32( UINT8 var ) /* 读CH376芯片内部的32位变量 */
{
xWriteCH376Cmd( CMD14_READ_VAR32 );
xWriteCH376Data( var );
return( CH376Read32bitDat( ) ); /* 从CH376芯片读取32位的数据并结束命令 */
}
void CH376WriteVar32( UINT8 var, UINT32 dat ) /* 写CH376芯片内部的32位变量 */
{
xWriteCH376Cmd( CMD50_WRITE_VAR32 );
xWriteCH376Data( var );
xWriteCH376Data( (UINT8)dat );
xWriteCH376Data( (UINT8)( (UINT16)dat >> 8 ) );
xWriteCH376Data( (UINT8)( dat >> 16 ) );
xWriteCH376Data( (UINT8)( dat >> 24 ) );
xEndCH376Cmd( );
}
void CH376EndDirInfo( void ) /* 在调用CH376DirInfoRead获取FAT_DIR_INFO结构之后应该通知CH376结束 */
{
CH376WriteVar8( 0x0D, 0x00 );
}
UINT32 CH376GetFileSize( void ) /* 读取当前文件长度 */
{
return( CH376ReadVar32( VAR_FILE_SIZE ) );
}
UINT8 CH376GetDiskStatus( void ) /* 获取磁盘和文件系统的工作状态 */
{
return( CH376ReadVar8( VAR_DISK_STATUS ) );
}
UINT8 CH376GetIntStatus( void ) /* 获取中断状态并取消中断请求 */
{
UINT8 s;
xWriteCH376Cmd( CMD01_GET_STATUS );
s = xReadCH376Data( );
xEndCH376Cmd( );
return( s );
}
#ifndef NO_DEFAULT_CH376_INT
UINT8 Wait376Interrupt( void ) /* 等待CH376中断(INT#低电平),返回中断状态码, 超时则返回ERR_USB_UNKNOWN */
{
#ifdef DEF_INT_TIMEOUT
#if DEF_INT_TIMEOUT < 1
while ( Query376Interrupt( ) == FALSE ); /* 一直等中断 */
return( CH376GetIntStatus( ) ); /* 检测到中断 */
#else
UINT32 i;
for ( i = 0; i < DEF_INT_TIMEOUT; i ++ ) { /* 计数防止超时 */
if ( Query376Interrupt( ) ) return( CH376GetIntStatus( ) ); /* 检测到中断 */
/* 在等待CH376中断的过程中,可以做些需要及时处理的其它事情 */
}
return( ERR_USB_UNKNOWN ); /* 不应该发生的情况 */
#endif
#else
UINT32 i;
for ( i = 0; i < 5000000; i ++ ) { /* 计数防止超时,默认的超时时间,与单片机主频有关 */
if ( Query376Interrupt( ) ) return( CH376GetIntStatus( ) ); /* 检测到中断 */
/* 在等待CH376中断的过程中,可以做些需要及时处理的其它事情 */
}
return( ERR_USB_UNKNOWN ); /* 不应该发生的情况 */
#endif
}
#endif
UINT8 CH376SendCmdWaitInt( UINT8 mCmd ) /* 发出命令码后,等待中断 */
{
xWriteCH376Cmd( mCmd );
xEndCH376Cmd( );
return( Wait376Interrupt( ) );
}
UINT8 CH376SendCmdDatWaitInt( UINT8 mCmd, UINT8 mDat ) /* 发出命令码和一字节数据后,等待中断 */
{
xWriteCH376Cmd( mCmd );
xWriteCH376Data( mDat );
xEndCH376Cmd( );
return( Wait376Interrupt( ) );
}
UINT8 CH376DiskReqSense( void ) /* 检查USB存储器错误 */
{
UINT8 s;
mDelaymS( 5 );
s = CH376SendCmdWaitInt( CMD0H_DISK_R_SENSE );
mDelaymS( 5 );
return( s );
}
UINT8 CH376DiskConnect( void ) /* 检查U盘是否连接,不支持SD卡 */
{
if ( Query376Interrupt( ) ) CH376GetIntStatus( ); /* 检测到中断 */
return( CH376SendCmdWaitInt( CMD0H_DISK_CONNECT ) );
}
UINT8 CH376DiskMount( void ) /* 初始化磁盘并测试磁盘是否就绪 */
{
return( CH376SendCmdWaitInt( CMD0H_DISK_MOUNT ) );
}
UINT8 CH376FileOpen( PUINT8 name ) /* 在根目录或者当前目录下打开文件或者目录(文件夹) */
{
CH376SetFileName( name ); /* 设置将要操作的文件的文件名 */
if ( name[0] == DEF_SEPAR_CHAR1 || name[0] == DEF_SEPAR_CHAR2 ) CH376WriteVar32( VAR_CURRENT_CLUST, 0 );
return( CH376SendCmdWaitInt( CMD0H_FILE_OPEN ) );
}
UINT8 CH376FileCreate( PUINT8 name ) /* 在根目录或者当前目录下新建文件,如果文件已经存在那么先删除 */
{
if ( name ) CH376SetFileName( name ); /* 设置将要操作的文件的文件名 */
return( CH376SendCmdWaitInt( CMD0H_FILE_CREATE ) );
}
UINT8 CH376DirCreate( PUINT8 name ) /* 在根目录下新建目录(文件夹)并打开,如果目录已经存在那么直接打开 */
{
CH376SetFileName( name ); /* 设置将要操作的文件的文件名 */
if ( name[0] == DEF_SEPAR_CHAR1 || name[0] == DEF_SEPAR_CHAR2 ) CH376WriteVar32( VAR_CURRENT_CLUST, 0 );
return( CH376SendCmdWaitInt( CMD0H_DIR_CREATE ) );
}
UINT8 CH376SeparatePath( PUINT8 path ) /* 从路径中分离出最后一级文件名或者目录(文件夹)名,返回最后一级文件名或者目录名的字节偏移 */
{
PUINT8 pName;
for ( pName = path; *pName != 0; ++ pName ); /* 到文件名字符串结束位置 */
while ( *pName != DEF_SEPAR_CHAR1 && *pName != DEF_SEPAR_CHAR2 && pName != path ) pName --; /* 搜索倒数第一个路径分隔符 */
if ( pName != path ) pName ++; /* 找到了路径分隔符,则修改指向目标文件的最后一级文件名,跳过前面的多级目录名及路径分隔符 */
return( pName - path );
}
UINT8 CH376FileOpenDir( PU
- 1
- 2
- 3
前往页