如何做bin文件升级以及数据定位——文件操作函数簇!

写在前面

之前自己一直在做芯片上应用程序的升级功能,也就是所谓的Bootloader程序,当然,是Secondery Bootloader程序。

在做芯片升级的BootLoader程序时,我的做法计较简单:一般是接收上位机下发的数据,判断数据协议是否正确,判断正确后将数据写入flash。可是,上位机是如何把数据打包发来的,如何按协议组数据帧,如何在一个bin文件中准确定位数据,自己却一致没有机会接触。

偶然的机会需要在掌机上开发对芯片进行升级的功能,由于下位机代码是自己已经写好的BootLoader程序,协议什么的还算是比较熟悉,便就着这个机会接触到了文件操作函数。

本文包含

  1. 文件指针及文件信息结构
  2. 文件打开
  3. 文件关闭
  4. 文件中数据定位
  5. 文件删除
  6. 文件列表菜单显示

文件指针及结构体定义

c语言库中包含了许多对文件操作的函数库,其中对文件指针的定义为

_FILE *FilePointer

_FILE 由c语言库定义好,我们可以直接定义文件指针,用来保存我们需要操作的文件信息。

文件指针是什么?通俗点讲,我们打开一个文件时,需要一个指针指向该文件,但该指针的类型是FILE型的,不恰当的理解可以为指向的是文件名,当然实际上该指针信息包含的不止文件名。

另一个需要定义的是保存查找到的文件信息的结构体,如下:

typedef __packed struct FINDBLK{
    U16 num;     // 查找到的文件个数
    U8 Cur_S; 
    U8 Index;    
    S8 name[8];  // 文件名,支持8字节长度,可更改
    S8 ext[3];
    S8 dir[65];  // 路径
    U8 ff_ftime[16];   /* file  date_time*/
    U32 ff_fsize;       /* file size */
    S8 ff_name[13];     /* found file name */
    U8 ff_attrib;       /* attribute found */
}FindBlk;

通过上面的结构体,可以定义一个查找到的文件信息的变量,用来进行文件操作。

文件查找

定义完结构体之后,需要去查找并打开文件,用到 findfirst 和 findnext函数,这两个函数功能如其名。

注意: 在打开文件之前需要把文件关闭,断开文件指针与文件的关系后,重新建立联系。

下面是定义一个文件信息并查找打开文件。

    FindBlk fileinfo;
    U8 ret;

    LCDcls();     //清屏
    _fcloseall();//查找打开文件之前关闭所有文件
    _setcurdir("D:\\"); //设置查找文件的目录
    ret = _findfirst("*.bin",&fileinfo);
    // 查找bin文件,用通配符*代替文件名
    line = 3;
    num = 0;
    while(ret==0)
    {
        strncpy(&name[num][0],&fileinfo.ff_name,sizeof(fileinfo.ff_name));
        ret = _findnext(&fileinfo);
        num++;// 个数计数器
    }

    if (num == 0)
    {
        while (1)
        {
            myPutString(4,1,"无文件",1);
            myPutString(4,2,"按确认返回",1);
            if (_bioskey(0) == ENTER)
            {
                LCDcls();
                return;
            }
        }
    }   
... ...

上面代码主要是将符合bin格式的文件查找到,并将文件名保存到定义好的name数组中,并用计数器num记录查找到的文件个数。

文件打开与数据定位

查找到文件后,需要打开该文件,也就是重新建立文件指针与文件的关系。通过索引出需要打开的文件的文件名,利用fopen 、 fseek 、filelength 和 fread 函数定位数据。

LCDcls();
    _fclose(FilePointer);
    FilePointer = _fopen(&name[cn-1][0],"r"); //传入文件名,返回文件指针。

    if (FilePointer != 0)
    //此处不规范,规范为 != NULL ((void *) 0)
    {
        filesize = _filelength(FilePointer); 
        // 传入文件指针,返回该文件的文件长度,字节数。
        filesize_ori = filesize;
        _fseek(FilePointer,0,0);
        // 首先将文件指针定位到 文件的起始位置,起始0偏移0
        memset(data_buffer,0,sizeof(data_buffer));
        //数据缓存区清零
        _fread(data_buffer,filesize,FilePointer);
        // 将文件中的数据读取保存到缓冲区中
        // filesize--需要读取的长度 FilePointer--文件指针
    // 注:每次读取之后,文件指针会自动偏移到读取完的字节后,如读取1024个字节(0-1023),读取后文件指针会指向第1025个字节,即索引为1024的字节。
        memset(&data_buffer[filesize],0x1A,(1024*(filesize/1024+1) - filesize));

        if (filesize % 1024 != 0)
        {
            filesize = 1024*(filesize/1024+1);
        }
        ChooseFile_flag = 1;

        while (1) 
        {   
            myPutString(4,1,"打开成功",1);
            myPutString(4,2,"按确认返回",1);
            if (_bioskey(0) == ENTER)
            {
                LCDcls();
                break;
            }
        }
    }   
    else
    {
        ChooseFile_flag = 0;
        while (1)
        {
            myPutString(4,1,"打开失败",1);
            myPutString(4,2,"按确认返回",1);
            if (_bioskey(0) == ENTER)
            {
                LCDcls();
                break;
            }
        }
    }

通过以上操作便完成了文件的打开以及数据的定位读取。

文件删除

文件删除很简单,调用_filedelete即可。

    do
    {
        ret = _filedelete(&name[cn-1][0]);
    }while(ret != 0);

    LCDcls();

    num--;

_filedelete 传入的是需要删除的文件名,返回为结果0或1,当然,在做删除之前需要关闭文件并设置路径。

    _fcloseall();   /* 必须先关闭所有文件 */
    _setcurdir("D:\\");

一个屏幕显示多文件的小程序

LOOP9:while(1)
    {   
        myPutString(4,1,"--选择删除--",1);
        _setdispcolor(1);


        if((k!=0)||(fist==0))/* 有按键按下 或第一次执行 */
        {
            for(i = 0;i < num;i++)
            { 
                if(i == (cn-head))
                {
                    myPutString(4,3+i,&name[cn-1][0],0);
                }
                else
                {
                    myPutString(4,3+i,&name[i+head-1][0],1);
                }
                if ((i>=7)||(i>=num))
                {
                    break;
                }
            }
            fist = 1;
            k = 0;
        }

        k = _key_time(100);

        if(k==DOWN)
        {
            cn++;
            if (cn > tail) 
            {
                head++;
                tail++;
            }
            Oper_flag = 1;
        }           
        if(k==UP)
        {
            cn--;
            if (cn < head)
            {
                head--;
                tail--;
            }
            Oper_flag = 1;
        }       
        if(k==ENTER)
        {
            res = DeleteInfirm();

            if (res == 0)
            {
                break;
            }
            else
            {
                LCDcls();
                goto LOOP9;
            }   
        }
        if(k==ESC)
        {
            LCDcls();
            return;
        }
        if(cn <= 0)
        {
            cn = num;
            if (num>7)
            {
                head = num-6;
                tail = num;
            }
            else
            {
                head = 1;
                tail = 7;
            }
        }               
        if(cn > num)
        {
            cn = 1;
            head = 1;
            tail = 7;
        }
    }

该程序实现的是在掌机上显示查到的文件名,以列表的形式显示出来。由于屏幕大小的限制,同一屏幕最多显示7个文件,如果文件多余7个,我们需要按上下键来实现文件名的刷新上下移动。这个小程序就是实现这个功能的。

你可能感兴趣的:(BootLoader开发,C)