求助CH376 由短文件名创建长文件名出错

unsigned char file_Shortname = "TEST-1~2.FAP";

unsigned char FileName_Now = "TEST-12345-0200P";


unsigned int Creat_LongFile_Name(unsigned char *file_Shortname,unsigned char *ModelName) 

{

    unsigned int j;     

    unsigned int s; 

    for ( j = 0; ModelName[j] != 0; j++ ) 

    {  // 复制并转换长文件名到LongNameBuf长文件名缓冲区 

      LongNameBuf[j*2] = ModelName[j]; // 将英文字符转换为两字节的小端UNICODE编码 

      LongNameBuf[j*2 + 1] = 0x00;

    }   

    LongNameBuf[j*2] = 0x00;   // 末尾用两个0表示结束

    LongNameBuf[j*2 + 1] = 0x00; // 复制该长文件名的ANSI编码的全路径的短文件名(8+3格式),短文件名由长文件名生成(只要不冲突,其实随便定)

   s = CH376CreateLongName( file_Shortname,LongNameBuf ); // 新建具有长文件名的文件 L_NAME

   return (s);      

}


unsigned int   CH376CreateLongName( unsigned char * PathName, unsigned char * LongName )

{

   unsigned int i,s;

   unsigned char   DirBlockCnt;  /* 长文件名占用文件目录结构的个数 */

   unsigned int16  count;      /* 临时变量,用于计数,用于字节读文件方式下实际读取的字节数 */

   unsigned int16  NameCount;    /* 长文件名字节计数 */

   unsigned int32  NewFileLoc;   /* 当前文件目录信息在上级目录中的起始位置,偏移地址 */ 

   for ( count = 0; count < LONG_NAME_BUF_LEN; count += 2 )

   {

      if ( *(unsigned int16 *)(&LongName[count]) == 0 )  break;  /* 到结束位置 */

   }  

   if ( count == 0 || count >= LONG_NAME_BUF_LEN || count > LONE_NAME_MAX_CHAR ) 

   {

      return( ERR_LONG_NAME_ERR );   /* 长文件名无效 */

   } 

   DirBlockCnt = count / LONG_NAME_PER_DIR;   /* 长文件名占用文件目录结构的个数 */ 

   i = count - DirBlockCnt * LONG_NAME_PER_DIR;

   if ( i )           /* 有零头 */

   {

      if ( ++ DirBlockCnt * LONG_NAME_PER_DIR > LONG_NAME_BUF_LEN ) 

      {

        return( ERR_LONG_BUF_OVER );     /* 缓冲区溢出 */

      }

      count += 2;                  /* 加上0结束符后的长度 */

      i += 2;     

      if ( i < LONG_NAME_PER_DIR ) /* 最末的文件目录结构不满 */

      {  

        while ( i++ < LONG_NAME_PER_DIR ) 

        {

          LongName[count++] = 0xFF;  /* 把剩余数据填为0xFF */

        }

      }

   }  

   // s = CH376FileOpenPath( PathName ); /* 打开多级目录下的文件 */ 

 

   CH376FileOpen( C_connect );   // unsigned C_connect[2]="/"; 

   s = CH376FileOpen(PathName ); /* 打开多级目录下的文件 */

 

   if ( s != USB_INT_SUCCESS )  return( s );    

   i = CH376ReadVar8( VAR_FILE_DIR_INDEX ); /* 临时用于保存当前文件目录信息在扇区内的索引号 */

   s = CH376LocateInUpDir( PathName ); /* 在上级目录中移动文件指针到当前文件目录信息所在的扇区 */

   if ( s != USB_INT_SUCCESS )                       

   {

      goto CH376CreateLongNameE;/* 没有直接返回是因为如果打开了根目录那么必须要关闭后才能返回 */

   }  

   NewFileLoc = CH376ReadVar32( VAR_CURRENT_OFFSET ) + i * sizeof(FAT_DIR_INFO);/* 计算当前文件目录信息在上级目录中的起始位置,偏移地址 */

   s = CH376ByteLocate( NewFileLoc );  /* 在上级目录中移动文件指针到当前文件目录信息的位置 */

   if ( s != USB_INT_SUCCESS ) goto CH376CreateLongNameE;

   s = CH376ByteRead( &GlobalBuf[ sizeof(FAT_DIR_INFO) ], sizeof(FAT_DIR_INFO),0 );/* 以字节为单位读取数据,获得当前文件的目录信息FAT_DIR_INFO */

   if ( s != USB_INT_SUCCESS )  goto CH376CreateLongNameE;

   for ( i = DirBlockCnt; i != 0; -- i ) /* 搜索空闲的文件目录结构用于存放长文件名 */

   {  

      s = CH376ByteRead( GlobalBuf, sizeof(FAT_DIR_INFO), &count );/* 以字节为单位读取数据,获得下一个文件目录信息FAT_DIR_INFO */

      if ( s != USB_INT_SUCCESS )    goto CH376CreateLongNameE;

      if ( count == 0 ) {break; }    

      if ( GlobalBuf[0] && GlobalBuf[0] != 0xE5 )  /* 后面有正在使用的文件目录结构,由于长文件名必须连接存放,所以空间不够,必须放弃当前位置并向后转移 */

      {  

        s = CH376ByteLocate(NewFileLoc);/* 在上级目录中移动文件指针到当前文件目录信息的位置 */

         if ( s != USB_INT_SUCCESS )     goto CH376CreateLongNameE;

         GlobalBuf[ 0 ] = 0xE5;              /* 文件删除标志 */

         for ( s = 1; s != sizeof(FAT_DIR_INFO); s ++ ) 

         {

             GlobalBuf[ s ] = GlobalBuf[ sizeof(FAT_DIR_INFO) + s ];

         }

         s = CH376LongNameWrite( GlobalBuf, sizeof(FAT_DIR_INFO) ); 

        /* 写入一个文件目录结构,用于删除之前新建的文件,实际上稍后会将之转移到目录的最末位置 */

         if ( s != USB_INT_SUCCESS )    goto CH376CreateLongNameE;

         while ( count && GlobalBuf[0] ) 

/* 如果仍然是正在使用的文件目录结构则继续向后搜索,直到上级目录结束或者有尚未使用过的文件目录结构 */

        {  

           s = CH376ByteRead( GlobalBuf, sizeof(FAT_DIR_INFO), &count );  

           /* 以字节为单位读取数据,获得下一个文件目录信息FAT_DIR_INFO */           

           if ( s != USB_INT_SUCCESS )  goto CH376CreateLongNameE;

        }         

        NewFileLoc = CH376ReadVar32( VAR_CURRENT_OFFSET );

        /* 用上级目录的当前文件指针作为当前文件目录信息在上级目录中的起始位置 */

        i =DirBlockCnt+1;/* 需要的空闲的文件目录结构的个数,包括短文件名本身一个和长文件名 */

        if ( count == 0 )  break;      /* 无法读出数据,上级目录结束了 */

        NewFileLoc -= sizeof(FAT_DIR_INFO);/* 倒回到刚才搜索到的空闲的文件目录结构的起始位置 */

      }

   }

   if (i) /* 空闲的文件目录结构不足以存放长文件名,原因是上级目录结束了,下面增加上级目录的长度 */

   {  

      s = CH376ReadVar8( VAR_SEC_PER_CLUS );  /* 每簇扇区数 */      

      if ( s == 128 )  /* FAT12/FAT16的根目录,容量是固定的,无法增加文件目录结构 */    

       {  

         s = ERR_FDT_OVER;    /* FAT12/FAT16根目录下的文件数应该少于512个,需要磁盘整理 */

         goto CH376CreateLongNameE;

      }    

      count = s * DEF_SECTOR_SIZE;     /* 每簇字节数 */

      if ( count < i * sizeof(FAT_DIR_INFO) ) 

      {

        count <<= 1;     /* 一簇不够则增加一簇,这种情况只会发生于每簇为512字节的情况下 */

      }

      s=CH376LongNameWrite(NULL,count);/*以字节为单位向当前位置写入全0数据块,清空新增加的文件目录簇 */   

      if ( s != USB_INT_SUCCESS ) goto CH376CreateLongNameE;

   }  

   s = CH376ByteLocate( NewFileLoc ); /* 在上级目录中移动文件指针到当前文件目录信息的位置 */

   if ( s != USB_INT_SUCCESS )    goto CH376CreateLongNameE;  

   GlobalBuf[11] = ATTR_LONG_NAME;

   GlobalBuf[12] = 0x00;

   GlobalBuf[13]=CH376CheckNameSum(&GlobalBuf[sizeof(FAT_DIR_INFO)]);/*计算长文件名的短文件名检验和 */

   GlobalBuf[26] = 0x00;

   GlobalBuf[27] = 0x00;

   for ( s = 0; DirBlockCnt != 0; )     /* 长文件名占用的文件目录结构计数 */

   {  

      GlobalBuf[0] = s ? DirBlockCnt : DirBlockCnt | 0x40;  /* 首次要置长文件名入口标志 */

      DirBlockCnt --;

      NameCount = DirBlockCnt * LONG_NAME_PER_DIR; 

      for(s =1;s

      {  

         if ( s == 1 + 5 * 2 ) 

         {

            s = 14;        /* 从长文件名的第一组1-5个字符跳到第二组6-11个字符 */

         }

         else if ( s == 14 + 6 * 2 ) 

         {

           s = 28;      /* 从长文件名的第二组6-11个字符跳到第三组12-13个字符 */

         }

         GlobalBuf[ s ] = LongName[ NameCount++ ];

         GlobalBuf[ s + 1 ] = LongName[ NameCount++ ];

      }

      s=CH376LongNameWrite(GlobalBuf,sizeof(FAT_DIR_INFO));

      /* 以字节为单位写入一个文件目录结构,长文件名 */        

      if ( s != USB_INT_SUCCESS )    goto CH376CreateLongNameE;

   }

   s = CH376LongNameWrite(&GlobalBuf[sizeof(FAT_DIR_INFO)],sizeof(FAT_DIR_INFO)); 

    /* 以字节为单位写入一个文件目录结构,这是转移来的之前新建的文件的目录信息 */


CH376CreateLongNameE: 

   CH376FileClose( FALSE );     /* 对于根目录则必须要关闭 */

   return( s );

}



unsigned int CH376LocateInUpDir( unsigned char * PathName_s) 

{

   unsigned int   s,c;

   unsigned char  BufData1[64];

   xWriteCH376Cmd( CMD14_READ_VAR32 );

   xWriteCH376Data( VAR_FAT_DIR_LBA );   /* 当前文件目录信息所在的扇区LBA地址 */

   for ( s = 4; s != 8; s ++ ) 

   {

     BufData1[s] = xReadCH376Data( ); /* 临时保存于全局缓冲区中,节约RAM */

   }  

   s = CH376SeparatePath(PathName_s);

   /*从路径中分离出最后一级文件名或者目录名,返回最后一级文件名或者目录名的偏移 */

   if ( s )

   {

      s=CH376FileOpenDir(PathName_s,s);/*多级目录,打开多级目录下最后一级目录,即打开文件的上级目录*/

   }

   else 

   {

      s = CH376FileOpen("/");      /* 根目录下的文件,则打开根目录 */

   }

   if ( s != ERR_OPEN_DIR )  //  ERR_OPEN_DIR = 0x41;

   {

       return( s );

   }

   *(unsigned int32 *)( &BufData1[0] )= 0;  /*目录扇区偏移扇区数,保存在全局缓冲区中,节约RAM */

   while(1)  /* 不断移动文件指针,直到与当前文件目录信息所在的扇区LBA地址匹配 */

   {  

    s=CH376SecLocate(*(unsigned int32*)(&BufData1[0]));/*以扇区为单位在上级目录中移动文件指针 */

      if ( s != USB_INT_SUCCESS )  return( s );

      CH376ReadBlock( &BufData1[8] ); /*从内存缓冲区读取CH376_CMD_DATA.SectorLocate.mSectorLba数据块,返回长度总是sizeof(CH376_CMD_DATA.SectorLocate) */ 

      if ( *(unsigned int32 *)(&BufData1[8]) == *(unsigned int32 *)(&BufData1[4]) ) 

      {

        return( USB_INT_SUCCESS );     /* 已到当前文件目录信息扇区 */

      }

      xWriteCH376Cmd( CMD50_WRITE_VAR32 );

      xWriteCH376Data( VAR_FAT_DIR_LBA );/* 得到前一个扇区,设置为新的文件目录信息扇区LBA地址 */

      for ( s = 8; s != 12; s ++ ) 

      {

        c = BufData1[s];

        xWriteCH376Data(c);

      }

      ++ *(unsigned int32 *)(&BufData1[0]);

   }

}


unsigned int   CH376SeparatePath( unsigned char *path )

{

  unsigned char *pName;

  for ( pName = path; *pName != 0; ++pName );    /* 到文件名字符串结束位置 */

  while ( *pName != DEF_SEPAR_CHAR1 && *pName != DEF_SEPAR_CHAR2 && pName != path ) 

  {   

    pName --;         /*  搜索倒数第一个路径分隔符 */   

  }

  if ( pName != path ) 

  {

   pName++;/*找到路径分隔符,则修改指向目标文件的最后一级文件名,跳过前面的多级目录名及路径分隔符*/

  }

  return((unsigned int)(pName - path));

}


SPI方式 

PIC24EP256GU814   16位单片机调用s=Creat_LongFile_Name(file_Shortname,FileName_Now);运行到红色字体处出错,s = CH376FileOpen("/"); 返回S = 0X42;急求大神们帮忙


你的短文件名不是全路径的  试试unsigned char file_Shortname = "/TEST-1~2.FAP";


谢谢您的回复,我程序中是有分两步的,见程序中蓝色字体部分

CH376FileOpen( C_connect );           // unsigned C_connect[2]="/"; 

s = CH376FileOpen(PathName );       /* 打开多级目录下的文件 */

之前在PIC 8位单片机中运行是没问题的,现在用的是16位单片机,分析了好久,不知道是什么原因,急求帮忙


你的TEST-1~2.FAP文件在执行程序之前必须是已经存在于根目录的,比较有局限性。建议使用FILE_SYS.C提供的长文件处理函数。如果程序里只执行s = CH376FileOpen("/"); 会报S = 0X42吗?尝试把CH376FileOpen("/")改成CH376FileOpen("/\0") 试一下。


收藏


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