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\r\n";
uint8_t g_TestBuf2[] = "hello world\r\n";
uint8_t g_ReadBuf[128];
uint32_t bw;

 

  主函數中實現文件的創建和讀取,驗證FatFs移植是否成功

/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     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設備

/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM