• GD32F30x_移植FatFs文件系统对外部Flash(GD25Q256DF)进行读写


    一、工具

      1、硬件:GD32F30x系列单片机

      2、编译环境:KEIL

      3、Flash芯片:GD25Q256DF

    二、移植FatFs文件系统到单片机

      关于外部Flash的驱动程序,请看链接:https://www.cnblogs.com/wenhao-Web/p/14052266.html

      关于USB设备模式下把外部Flash模拟成U盘的程序,请看链接:https://www.cnblogs.com/wenhao-Web/p/14052863.html

      1、找到官方提供的固件库中的FatFs文件夹,整体拷贝到自己工程中,如下图所示:

       2、打开自己的工程,创建一个“Fatfs”文件夹并添加上面拷贝的文件夹的部分文件,如下图所示:

    • ff.c文件包含了FatFs文件系统的整个核心内容,包含了操作文件系统的功能函数,不用修改;

    • fattime.c文件是用于获取当前的时间的,该时间用于设定文件的创建或修改时间,有需求的可以进去添加获取实时时间的操作;
    • diskio.c文件属于接口文件,用于和底层读写函数进行衔接的地方,是移植Fatfs文件系统重点修改的地方;
    • ccsbcs.c文件用于不同编码的转换,不用修改;
    • ffconf.h文件是FatFs文件系统的配置文件,用户可根据需求对文件系统进行配置,也是移植Fatfs文件系统重点修改的地方。

      3、修改diskio.c文件

      这三个宏定义代表着三个不同的设备,我只用一个,故删掉。

       修改初始化设备函数,我要放在外面进行初始化,这里就默认初始化成功,如下所示:

    /*-----------------------------------------------------------------------*/
    /* Inicializes a Drive                                                    */
    
    DSTATUS disk_initialize (BYTE drv)    /* Physical drive nmuber (0..) */
    {
      DSTATUS stat = STA_NOINIT;
        
      stat &= ~STA_NOINIT;
      return stat; 
    }

      修改获取状态函数,通过读取外部Flash的ID判断其状态,因为只有一个设备,设备号可以不用管,如下所示:

    /*-----------------------------------------------------------------------*/
    /* Return Disk Status                                                    */
    
    DSTATUS disk_status (
        BYTE drv        /* Physical drive nmuber (0..) */
    )
    {
        DSTATUS stat;
    
        if(gd25q256df_read_id() == 0xC84019)
        {
            stat = RES_OK;
        }
        else
        {
            stat = RES_ERROR;
        }
        return stat;
    }

      修改磁盘读函数,因为只有一个设备,设备号可以不用管,如下所示:

    /*-----------------------------------------------------------------------*/
    /* Read Sector(s)                                                        */
    
    DRESULT disk_read (
        BYTE drv,        /* Physical drive nmuber (0..) */
        BYTE *buff,        /* Data buffer to store read data */
        DWORD sector,    /* Sector address (LBA) */
        BYTE count        /* Number of sectors to read (1..255) */
    )
    {
        DRESULT res;
        gd25q256df_read_data(buff, sector*512, count*512);
        res = RES_OK;
        return res;
    }

      修改磁盘写函数,因为只有一个设备,设备号可以不用管,如下所示:

    /*-----------------------------------------------------------------------*/
    /* Write Sector(s)                                                       */
    
    #if _READONLY == 0
    DRESULT disk_write (
        BYTE drv,            /* Physical drive nmuber (0..) */
        const BYTE *buff,    /* Data to be written */
        DWORD sector,        /* Sector address (LBA) */
        BYTE count            /* Number of sectors to write (1..255) */
    )
    {
        DRESULT res;
        
        gd25q256df_write_data(buff, sector*512, count*512);
        
        res = RES_OK;
        return res;
    }

      修改磁盘I/O控制函数,因为只有一个设备,设备号可以不用管,如下所示:

    /*-----------------------------------------------------------------------*/
    /* Miscellaneous Functions                                               */
    
    DRESULT disk_ioctl (
        BYTE drv,        /* Physical drive nmuber (0..) */
        BYTE ctrl,        /* Control code */
        void *buff        /* Buffer to send/receive control data */
    )
    {
      DRESULT res;
      switch(ctrl)
      {
          case GET_SECTOR_COUNT:
              *(DWORD *)buff = 65536;
              break;
          case GET_SECTOR_SIZE:
              *(WORD *)buff = 512;
              break;
          case GET_BLOCK_SIZE:
              /* 暂时未用 */
              break;
      }
      res = RES_OK;
      return res;
    }

      4、文件系统读写测试

      相关变量定义

    uint32_t flash_id;
    
    FATFS fs;
    FIL file;
    FRESULT res_flash;
    uint8_t g_TestBuf1[] = "12345hello world 今天是个好日子,123456
    ";
    uint8_t g_TestBuf2[] = "hello world
    ";
    uint8_t g_ReadBuf[128];
    uint32_t bw;

      主函数中实现文件的创建和读取,验证FatFs移植是否成功

    /*!
        rief      main function
        param[in]  none
        param[out] none
        
    etval     none
    */
    int main(void)
    {
        /* configure 4 bits pre-emption priority */
        nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
        
        bsp_spi1_init();
        gd25q256df_init();
            
        flash_id = gd25q256df_read_id();
        if(flash_id == 0xC84019)
        {    
            /* 挂载设备 */
            res_flash = f_mount (1, &fs);
            if (res_flash == FR_OK)
            {
                /* 打开或者创建文件 */
                res_flash = f_open(&file, "1:test1.txt", FA_CREATE_ALWAYS | FA_WRITE);
                if(res_flash == FR_OK)
                {
                    /* 向文件件中写数据 */
                    res_flash = f_write(&file, g_TestBuf1, sizeof(g_TestBuf1), &bw);
                    if (res_flash != FR_OK)
                    {
                        while(1);
                    }
                    /* 关闭文件 */
                    f_close(&file);    
                }
                
                /* 打开或者创建文件 */
                res_flash = f_open(&file, "1:test2.txt", FA_CREATE_ALWAYS | FA_WRITE);
                if(res_flash == FR_OK)
                {
                    /* 向文件件中写数据 */
                    res_flash = f_write(&file, g_TestBuf2, sizeof(g_TestBuf2), &bw);
                    if (res_flash != FR_OK)
                    {
                        while(1);
                    }
                    /* 关闭文件 */
                    f_close(&file);    
                }
                /* 以读的方式打开文件 */
                res_flash = f_open(&file, "1:test2.txt", FA_OPEN_EXISTING | FA_READ);     
                if(res_flash == FR_OK)
                {
                    res_flash = f_read(&file, g_ReadBuf, sizeof(g_ReadBuf), &bw); 
                    if(res_flash != FR_OK)
                    {
                        while(1);
                    }    
                    /* 关闭文件 */
                    f_close(&file);    
                }    
            }
            /* 卸载文件 */
            res_flash = f_mount (1, NULL);    
        }    
    }

      通过调试,可以发现是能够成功读取前面创建的文件中的内容,如下图所示:

    四、扩展功能

      为了能够更直观看到文件系统创建的文件和写入的内容,我结合了单片机的USB设备模式,把外部Flash模拟成一个U盘,能够直接在电脑查看创建的文件。

      USB相关变量定义及初始化

    usb_core_handle_struct usbhs_core_dev =
    {
        .dev = 
        {
            .dev_desc = (uint8_t *)&device_descripter,
            .config_desc = (uint8_t *)&configuration_descriptor,    
            .strings = usbd_strings,                                
            .class_init = msc_init,                                    
            .class_deinit = msc_deinit,                                
            .class_req_handler = msc_req_handler,                    
            .class_data_handler = msc_data_handler
        },
    
        .udelay = delay_us,
        .mdelay = delay_ms
    };
    
    void usb_clock_config(void);
    void usb_gpio_config(void);
    void usb_interrupt_config(void);
    
    uint8_t timer_prescaler = 0;
    uint32_t usbfs_prescaler = 0;

      主函数中实现文件的创建并写入数据,写入完成后初始化并启动USB设备

    /*!
        rief      main function
        param[in]  none
        param[out] none
        
    etval     none
    */
    int main(void)
    {
        /* configure 4 bits pre-emption priority */
        nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
        
        bsp_spi1_init();
        gd25q256df_init();
            
        flash_id = gd25q256df_read_id();
        if(flash_id == 0xC84019)
        {    
            /* 挂载设备 */
            res_flash = f_mount (1, &fs);
            if (res_flash == FR_OK)
            {
                /* 打开或者创建文件 */
                res_flash = f_open(&file, "1:test1.txt", FA_CREATE_ALWAYS | FA_WRITE);
                if(res_flash == FR_OK)
                {
                    /* 向文件件中写数据 */
                    res_flash = f_write(&file, g_TestBuf1, sizeof(g_TestBuf1), &bw);
                    if (res_flash != FR_OK)
                    {
                        while(1);
                    }
                    /* 关闭文件 */
                    f_close(&file);    
                }
                
                /* 打开或者创建文件 */
                res_flash = f_open(&file, "1:test2.txt", FA_CREATE_ALWAYS | FA_WRITE);
                if(res_flash == FR_OK)
                {
                    /* 向文件件中写数据 */
                    res_flash = f_write(&file, g_TestBuf2, sizeof(g_TestBuf2), &bw);
                    if (res_flash != FR_OK)
                    {
                        while(1);
                    }
                    /* 关闭文件 */
                    f_close(&file);    
                }            
            }
            /* 卸载文件 */
            res_flash = f_mount (1, NULL);    
        }    
        
        /* configure USB clock */
        usb_clock_config();    
        /* USB timer configure */
        timer_nvic_init();
        /* USB device stack configure */
        usbd_init(&usbhs_core_dev, USB_FS_CORE_ID);
        /* USB interrupt configure */
        usb_interrupt_config();    
        
        /* check if USB device is enumerated successfully */
        while (usbhs_core_dev.dev.status != USB_STATUS_CONFIGURED) {}        
        
        while(1);
    }

      测试结果如下图所示:

    #endif

  • 相关阅读:
    在IIS中浏览网站时出现:无法打开登录所请求的数据库 "***",登录失败
    Java中的深拷贝和浅拷贝(转载)
    Java的Final和C#的Const,Readonly比较分析(转载)
    C#中的Sealed和J#中的Final比较(转载)
    Java全系列帮助文档下载
    The Willpower Instinct(自控力,意志力)
    瓦片地图的前世今生(转载)
    创建CUDA项目
    CUDA warning C4819的消除
    并行调用
  • 原文地址:https://www.cnblogs.com/wenhao-Web/p/14056437.html
Copyright © 2020-2023  润新知