|
本帖最后由 Tobacco 于 2013-4-12 06:44 编辑
大家好,新人一枚拜上 有个问题想请教一下大家
最近参考论坛上的mp3例子,自己也学着用mega16+ch376+vs1053做了一个简单的mp3。其中枚举文件的功能是由ch376官方例程修改而来的,函数如下,其中listAll调用了listfile:- typedef struct _FILE_NAME {
- UINT32 DirStartClust; /* 文件所在目录的起始簇号 */
- // UINT32 Size; /* 文件长度 */
- UINT8 Name[8+1+3+1]; /* 文件名,共8+3字节,分隔符,结束符,因为未包含上级目录名所以是相对路径 */
- UINT8 Attr; /* 文件属性 */
- } FILE_NAME;
- #define MAX_FILE_COUNT 15
- FILE_NAME FileNameBuffer[MAX_FILE_COUNT]; /* 文件名结构 */
- UINT16 FileCount;
- UINT8 ListFile( UINT8 index )
- /* 输入参数index是指目录在结构中的序号 */
- {
- UINT8 buf[64];
- UINT8 s;
- P_FAT_DIR_INFO pDir;
- UINT8 *pNameBuf;
- UINT32 CurrentDirStartClust; /* 保存当前目录的起始簇号,用于加快文件枚举和打开速度 */
- CH376WriteVar32( VAR_START_CLUSTER, FileNameBuffer[ index ].DirStartClust ); /* 将当前目录的上级目录的起始簇号设置为当前簇号,相当于打开上级目录 */
- // printf( "List Directory: %s\n", FileNameBuffer[ index ].Name ); /* 显示当前要列举的目录名 */
- s = CH376FileOpen( FileNameBuffer[ index ].Name ); /* 打开目录,仅为了获取目录的起始簇号以提高速度 */
- if ( s == USB_INT_SUCCESS ) return( ERR_FOUND_NAME ); /* 应该是打开了目录,但是返回结果是打开了文件 */
- else if ( s != ERR_OPEN_DIR ) return( s ); /* ERR_OPEN_DIR指定路径的目录(文件夹)被打开 ,用在这里代表正确打开目录而非错误*/
- if ( index ) CurrentDirStartClust = CH376ReadVar32( VAR_START_CLUSTER ); /* 不是根目录,获取目录的起始簇号 */
- else CurrentDirStartClust = 0; /* 是根目录 */
- CH376FileClose( FALSE ); /* 对于根目录一定要关闭 */
- CH376WriteVar32( VAR_START_CLUSTER, CurrentDirStartClust ); /* 当前目录的起始簇号,相当于打开当前目录 */
- CH376SetFileName( "*" ); /* 设置将要操作的文件的文件名,通配符支持所有文件和子目录 */
- xWriteCH376Cmd( CMD0H_FILE_OPEN ); /* 枚举文件和目录 */
- xEndCH376Cmd( );
- while ( 1 ) {
- s = Wait376Interrupt( );
- if ( s == USB_INT_DISK_READ ) { /* 请求数据读出 */
- /* 在文件枚举过程中,不能执行其它可能产生中断的操作命令,例如,如果需要获取长文件名,那么可以将枚举出的文件名保存并在枚举结束后获取其长文件名 */
- CH376ReadBlock( buf ); /* 读取枚举到的文件的FAT_DIR_INFO结构,返回长度总是sizeof( FAT_DIR_INFO ) */
- xWriteCH376Cmd( CMD0H_FILE_ENUM_GO ); /* 继续枚举文件和目录,先发出下一个命令再分析上行读出的数据可以让CH376与单片机分别同时工作,提高速度 */
- xEndCH376Cmd( );
- pDir = (P_FAT_DIR_INFO)buf; /* 当前文件目录信息 */
- if ( pDir -> DIR_Name[0] != '.' ) { /* 不是本级或者上级目录名则继续,否则必须丢弃不处理 */
- if ( pDir -> DIR_Name[0] == 0x05 ) pDir -> DIR_Name[0] = 0xE5; /* 特殊字符替换 */
- //if ( pDir -> DIR_Name[8] == 'H' && pDir -> DIR_Name[9] == ' ' /* 比较文件扩展名分析文件类型的范例 */
- // || pDir -> DIR_Name[8] == 'E' && pDir -> DIR_Name[9] == 'X' && pDir -> DIR_Name[10] == 'E' ) {
- // printf( "This is a .H or .EXE file\n" );
- //}
- if ( FileCount < MAX_FILE_COUNT ) { /* 文件名结构缓冲区足够 */
- pNameBuf = FileNameBuffer[ FileCount ].Name; /* 文件名结构中的文件名缓冲区 */
- for ( s = 0; s < 11; s ++ ) { /* 复制文件名,长度为11个字符 */
- if ( pDir -> DIR_Name[ s ] != 0x20 ) { /* 有效字符 */
- if ( s == 8 ) { /* 处理扩展名 */
- *pNameBuf = '.'; /* 分隔符 */
- pNameBuf ++;
- }
- *pNameBuf = pDir -> DIR_Name[ s ]; /* 复制文件名的一个字符 */
- pNameBuf ++;
- }
- }
- *pNameBuf = 0; /* 当前文件名完整路径的结束符 */
- FileNameBuffer[ FileCount ].DirStartClust = CurrentDirStartClust; /* 记录当前目录的起始簇号,用于加快文件打开速度 */
- FileNameBuffer[ FileCount ].Attr = pDir -> DIR_Attr; /* 记录文件属性 */
- // if ( pDir -> DIR_Attr & ATTR_DIRECTORY ) printf( "Dir %4d#: %s\n", FileCount, FileNameBuffer[ FileCount ].Name ); /* 判断是目录名 */
- // else printf( "File%4d#: %s\n", FileCount, FileNameBuffer[ FileCount ].Name ); /* 判断是文件名 */
- FileCount ++; /* 子目录计数 */
- }
- else { /* 文件名结构缓冲区太小,结构数量不足 */
- // printf( "FileName Structure Full\n" );
- s = Wait376Interrupt( );
- CH376EndDirInfo( ); /* 获取完FAT_DIR_INFO结构 */
- break; /* 强行终止枚举 */
- }
- }
- }
- else {
- if ( s == ERR_MISS_FILE ) s = USB_INT_SUCCESS; /* 没有找到更多的匹配文件 */
- break;
- }
- }
- /* if ( s == USB_INT_SUCCESS ) return( s );*/ /* 操作成功 */
- return( s );
- }
- UINT8 ListAll( void ) /* 以广度优先的算法枚举整个U盘中的所有文件及目录 */
- {
- UINT8 s;
- UINT16 OldFileCount;
- //UINT16 RealReadCount;
- FileNameBuffer[ 0 ].Name[0] = '/'; /* 根目录,是完整路径名,除根目录是绝对路径之外都是相对路径 */
- FileNameBuffer[ 0 ].Name[1] = 0;
- FileNameBuffer[ 0 ].DirStartClust = 0; /* 根目录的起始簇号 */
- FileNameBuffer[ 0 ].Attr = ATTR_DIRECTORY; /* 根目录也是目录,作为第一个记录保存 */
- for ( OldFileCount = 0, FileCount = 1; OldFileCount < FileCount; OldFileCount ++ )
- { /* 尚有新枚举到的文件名结构未进行分析,FileCount处于变化之中 */
- if ( FileNameBuffer[ OldFileCount ].Attr & ATTR_DIRECTORY ) /* 是目录则继续进行深度搜索 */
- {
- s = ListFile( OldFileCount ); /* 枚举目录,记录保存到结构中,FileCount可能会改变 */
- if ( s != USB_INT_SUCCESS ) return( s );
- }
- }
复制代码 我遇到一个难题,就是mega16的内存只有1k,而vs1053的送数程序已经占用了512byte缓冲,也就是说其实能用的内存只有一半。再看看上面的函数,是利用结构体FileNameBuffer[MAX_FILE_COUNT]来存储枚举出来的文件列表的,一个文件的信息就占用了18byte,20首歌就占用了360byte;所以我现在只敢枚举20首歌(感觉很挫~囧~明明用了ch376已经省下了FAT文件系统的负担了)……我看到论坛上有些大神也是用mega16+vs1003来做mp3的,不但做好了液晶显示歌曲列表,而且fat文件系统还是由mega16实现的,这太霸道了吧!内存怎么够用?真心请教各位,怎么才能罗列更多的歌曲?
|
阿莫论坛20周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|