⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fat.c

📁 文件系统,运行硬件环境:单片机,软件环境:keilc
💻 C
📖 第 1 页 / 共 5 页
字号:
    return F_OK;
}

/*==============================================================================
函数名: fat_offset_sector
-------------------------------------------------------------------------------
参数:偏移扇区数
-------------------------------------------------------------------------------
函数返回:
-------------------------------------------------------------------------------
函数作用:从当前位置偏移参数要求的扇区数
-------------------------------------------------------------------------------
==============================================================================*/
STATIC UINT8 fat_offset_sector(UINT32 cc)
{
    while(cc)
    {
        fat_count_offset_sector++;
        if (fat_count_offset_sector == fat_sec_perclus)
        {
            fat_count_offset_sector =0;
            fat_count_offset_cluster++;                 /*连续簇的下一个簇*/
            if (chain[fat_chain_index].number ==fat_count_offset_cluster)
            {
                fat_count_offset_cluster =0;
                fat_chain_index++;
            }
            if(fat_chain_index >fat_last_chain_index)   /*不能超过簇,文件剩余扇区数不计*/
            {
                return PARAMETER_CMD_ERR;
            }
        }
        cc--;

        #ifdef FAT_DEBUG
        com_prints("fat_chain_index:",0);
        com_send_arry(&fat_chain_index,1,1);
        com_prints("fat_count_offset_cluster:",0);
        com_send_arry(&fat_count_offset_cluster,1,1);
        com_prints("fat_count_offset_sector:",0);
        com_send_arry(&fat_count_offset_sector,1,1);
        com_send_arry(&cc,2,1);
        #endif

    }
    #ifdef FAT_DEBUG
    com_prints("fat_chain_index:",0);
    com_send_arry(&fat_chain_index,1,1);
    com_prints("fat_count_offset_cluster:",0);
    com_send_arry(&fat_count_offset_cluster,1,1);
    com_prints("fat_count_offset_sector:",0);
    com_send_arry(&fat_count_offset_sector,1,1);
    #endif
    return F_OK;
}

/*==============================================================================
函数名: fat_read_sector
-------------------------------------------------------------------------------
参数:BOOL mode(分为读目录项数据和读文件数据) UINT8 index是在磁盘缓区的偏移*512
-------------------------------------------------------------------------------
函数返回:
-------------------------------------------------------------------------------
函数作用:根据构建的簇链表,读扇区数据到缓冲区
-------------------------------------------------------------------------------
==============================================================================*/
STATIC UINT8 fat_read_sector (BOOL mode, UINT8 index)
{
UINT8 i;
UINT32 next_cluster;

    if((mode==F_OPEN_DIR))
    {                                               /*读目录FAT32与12/16在根目录数有区别*/
        if((fat_type_sign==F_TYPE_FAT32)||(fat_dir_now_l!=1))
        {
            next_cluster =chain[fat_chain_index].cluster + fat_count_offset_cluster-2;
            if (fat_count_offset_sector ==fat_sec_perclus)  /*读完一簇或刚进入*/
            {                                       /*此连续的簇用完,查找下一个连续的簇开始*/
                fat_count_offset_sector =0;
                fat_count_offset_cluster++;
                if (chain[fat_chain_index].number ==fat_count_offset_cluster)
                {
                    fat_chain_index++;
                    fat_count_offset_cluster = 0;
                }
                next_cluster =chain[fat_chain_index].cluster + fat_count_offset_cluster-2;
            }
            fat_current_sect = fat_data_start_sector + fat_count_offset_sector
                + ((UINT32)(next_cluster) * fat_sec_perclus);
            fat_count_offset_sector++;
        }
        else
        {
            fat_current_sect++;                     /*在FAT12/16的根目录下*/
        }
        #ifdef  FAT_DEBUG
        com_prints("fat_chain_index:",0);
        com_send_arry(&fat_chain_index,1,1);
        com_prints("fat_current_sect:",0);
        com_send_arry(&fat_current_sect,4,1);
        #endif
        i=hard_read_sector(fat_current_sect);     /*读下一个扇区*/
        if(i==F_OK)
            return F_OK;
        else
            return READ_DATA_ERR;
    }
    else                                            /*打开文件模式*/
    {
    UINT8  i;
    UINT8  offset;                                  /*用在文件缓冲区里的偏移*/
    UINT16 temp16;
    UINT32 temp32;

                                                    /*计算还有多少个连续的扇区*/
        if(fat_chain_index >fat_last_chain_index)
        {
            fat_cmd.read.sector =0;
            return F_OK;
        }
        offset =0;
        while(index)
        {
            if(fat_chain_index ==fat_last_chain_index)      /*到最后一个连续簇链*/
            {
                i =((fat_file_length + 511) / 512) % fat_sec_perclus;
                if(i ==0)
                    i=fat_sec_perclus;                      /*剩余簇全部为文件数据*/
                i =fat_sec_perclus -i;                      /*计算尾部无效扇区*/
                #ifdef FAT_DEBUG
                com_prints("i:",0);
                com_send_arry(&i,1,1);
                #endif
                temp16 =(chain[fat_chain_index].number -fat_count_offset_cluster) *fat_sec_perclus
                -fat_count_offset_sector -i;                /*剩余连续扇区数*/
                #ifdef FAT_DEBUG
                com_prints("temp16:",0);
                com_send_arry(&temp16,2,1);
                com_prints("fat_count_offset_sector:",0);
                com_send_arry(&fat_count_offset_sector,1,1);
                #endif
                if((temp16) < (UINT16)index)
                {
                    index =(UINT8)temp16;
                    fat_cmd.read.sector =index;             /*计算实际有效扇区数*/
                    if(index ==0)
                        return F_OK;
                }
            }
            else
            {
                temp16 =(chain[fat_chain_index].number -fat_count_offset_cluster) *fat_sec_perclus
                    -fat_count_offset_sector;               /*剩余连续扇区数*/
            }
            #ifdef FAT_DEBUG
            com_prints("temp16:",0);
            com_send_arry(&temp16,2,1);
            com_prints("index:",0);
            com_send_arry(&index,1,1);
            #endif
            if((temp16)>=(UINT16)index)
            {
                temp32 =fat_data_start_sector + (chain[fat_chain_index].cluster + fat_count_offset_cluster - 2)
                    *fat_sec_perclus +fat_count_offset_sector;
                i =hard_read_file_sector(temp32,index,offset);
                if(i!=F_OK)
                    return READ_DATA_ERR;

                fat_current_sect =temp32 +index -1;
                fat_offset_sector(index);           /*偏移扇区*/
                index =0;
            }
            else                                    /*剩余连续扇区较少*/
            {
                i =hard_read_file_sector((fat_data_start_sector +(chain[fat_chain_index].cluster
                    + fat_count_offset_cluster - 2) *fat_sec_perclus +fat_count_offset_sector),(UINT8)temp16,offset);
                if(i!=F_OK)
                    return READ_DATA_ERR;
                fat_offset_sector((UINT8)temp16);
                offset +=(UINT8)temp16;
                index -=(UINT8)temp16;              /*还有多少个扇区没有读*/
            }
            #ifdef FAT_DEBUG
            com_prints("fat_chain_index:",0);
            com_send_arry(&fat_chain_index,1,1);
            com_prints("fat_count_offset_cluster:",0);
            com_send_arry(&fat_count_offset_cluster,1,1);
            com_prints("fat_count_offset_sector:",0);
            com_send_arry(&fat_count_offset_sector,1,1);
            #endif
        }
        return F_OK;
    }
}

/*==============================================================================
函数名: fat_write_sector
-------------------------------------------------------------------------------
参数:index为扇区数
-------------------------------------------------------------------------------
函数返回:
-------------------------------------------------------------------------------
函数作用:根据构建的簇链表,写扇区数据到缓冲区
-------------------------------------------------------------------------------
==============================================================================*/
#if F_EN_WRITE ==1
STATIC UINT8 fat_write_sector (UINT8 index)
{
UINT8  i;
UINT8  offset;
UINT16 temp16;

    offset =0;
    while(index)
    {
        if(fat_chain_index > fat_last_chain_index)      /*超出文件范围*/
        {
            temp16 =0;
        }
        else
        {
            temp16 =(chain[fat_chain_index].number -fat_count_offset_cluster) *fat_sec_perclus
            -fat_count_offset_sector;                   /*计算当前有多少个连续的扇区*/
        }

        if((temp16) >= (UINT16)index)
        {
            i =hard_write_file_sector((fat_data_start_sector + (chain[fat_chain_index].cluster
                    + fat_count_offset_cluster - 2)*fat_sec_perclus +fat_count_offset_sector),index,offset);
            if(i!=F_OK)
                return WRITE_DATA_ERR;

            i =fat_offset_sector(index);                /*偏移扇区*/
            if(i !=F_OK)
            {
                #if F_EN_ADD_EDN ==1
                if(fat_cmd.write.sector ==0)            /*所有扇区数据写完*/
                    return F_OK;
                i=fat_get_space(F_CONTI_MODE);          /*继续申请磁盘空间*/
                if(i !=F_OK)
                    return i;

                i=fat_update(F_CONTI_MODE);             /*更新此空间的FAT*/
                if(i !=F_OK)
                    return i;

                fat_offset_sector(fat_sec_perclus);    /*偏移文件结束簇*/
                fat_add_bit =F_TRUE;                   /*在文件末尾添加过数据*/
                #else
                return NO_DEF_ADD_ERR;
                #endif
            }
            index =0;
        }
        else                                            /*剩余连续扇区较少*/
        {
            #ifdef FAT_DEBUG
            com_prints("index: ",0);
            com_send_arry(&index,1,1);
            com_prints("temp16: ",0);
            com_send_arry(&temp16,2,1);
            #endif
            if(temp16 !=0)
            {
                i =hard_write_file_sector((fat_data_start_sector +(chain[fat_chain_index].cluster
                    + fat_count_offset_cluster - 2) *fat_sec_perclus +fat_count_offset_sector),(UINT8)temp16,offset);
                if(i!=F_OK)
                    return READ_DATA_ERR;
            }
            index -=(UINT8)temp16;                      /*还有多少个扇区没有写*/
            offset +=(UINT8)temp16;                     /*改写文件缓冲区里偏移*/

            i =fat_offset_sector((UINT8)temp16);
            if((i !=F_OK)||(temp16 ==0))                /*等于0 说明文件偏移到结尾*/
            {
                #if F_EN_ADD_EDN ==1
                fat_cmd.write.sector +=index;           /*申请扇区空间加上剩余未写的*/
                if(fat_cmd.write.sector ==0)            /*所有扇区数据写完*/
                    return F_OK;
                i=fat_get_space(F_CONTI_MODE);          /*继续申请磁盘空间*/
                if(i !=F_OK)
                    return i;
                fat_cmd.write.sector -=index;

                i=fat_update(F_CONTI_MODE);             /*更新此空间的FAT*/
                if(i !=F_OK)
                    return i;
                fat_offset_sector(fat_sec_perclus);    /*偏移文件结束簇*/
                fat_add_bit =F_TRUE;                    /*在文件末尾添加过数据*/
                #else
                return NO_DEF_ADD_ERR;
                #endif
            }
       }
    }
    return F_OK;
}
#endif

/*==============================================================================
函数名: ini_chain_arry
-------------------------------------------------------------------------------
参数:mode分为是否初始化变量
-------------------------------------------------------------------------------
函数返回:此数组包含的总扇区数
-------------------------------------------------------------------------------
函数作用:构建完簇数组后,初始化各变量
-------------------------------------------------------------------------------
==============================================================================*/
STATIC UINT32 ini_chain_arry(BOOL mode)
{
UINT8  i;
UINT32 temp32=0;

    for (i = 0; i <= fat_last_chain_index; i++)
    {
        temp32 += chain[i].number;              /*计算当前目录有多少个簇*/
    }

    if(mode ==F_TRUE)
    {
        fat_chain_index=0;                      /*指向数组开始*/
        fat_count_offset_cluster=0;             /*指向第一个连续簇开始*/
        fat_count_offset_sector=0;              /*指向此簇的第一个扇区*/
    }
    temp32 *=fat_sec_perclus;                   /*得到此目录的总扇区数*/
    return temp32;
}

#if F_EN_LONG_NAME ==1
/*==============================================================================
函数名: chk_file_name_sum
-------------------------------------------------------------------------------
参数:
-------------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -