電子產(chǎn)業(yè)一站式賦能平臺

PCB聯(lián)盟網(wǎng)

搜索
查看: 55|回復(fù): 0
收起左側(cè)

SWM32系列教程9--SDIO及FatFs文件系統(tǒng)

[復(fù)制鏈接]

451

主題

451

帖子

2461

積分

三級會員

Rank: 3Rank: 3

積分
2461
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2022-9-23 08:00:00 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
SWM32S單片機有1個SDIO接口,支持多媒體卡(MMC)、SD 存儲卡、SDIO 卡等設(shè)備,可以使用軟件方法或者 DMA 方法(SDIO 模塊內(nèi)部 DMA,與芯片 DMA 模塊無關(guān))進行數(shù)據(jù)傳輸。其特點如下:



1.SDIO配置    SDIO的引腳不像UART和SPI等數(shù)字外設(shè)一樣可以靈活配置,它是固定的幾個引腳,如下圖

    使用起來也比較簡單,相關(guān)的庫函數(shù)已經(jīng)封裝好了,直接調(diào)用就行。    首先需要配置一下相關(guān)引腳的復(fù)用功能為SDIO:            
  •   PORT_Init(PORTB, PIN1, PORTB_PIN1_SD_CLK, 0);  PORT_Init(PORTB, PIN2, PORTB_PIN2_SD_CMD, 1);  PORT_Init(PORTB, PIN3, PORTB_PIN3_SD_D0,  1);  PORT_Init(PORTB, PIN4, PORTB_PIN4_SD_D1,  1);  PORT_Init(PORTB, PIN5, PORTB_PIN5_SD_D2,  1);  PORT_Init(PORTB, PIN6, PORTB_PIN6_SD_D3,  1);
        然后直接調(diào)用初始化的函數(shù)就行:   
  • result = SDIO_Init(10000000);
        其中形參為SDIO的時鐘頻率。    SD卡讀寫的相關(guān)函數(shù)也已經(jīng)封裝好了,包括DMA和非DMA方式,直接調(diào)用即可:
  • uint32_t SDIO_BlockWrite(uint32_t block_addr, uint32_t buff[]);uint32_t SDIO_BlockRead(uint32_t block_addr, uint32_t buff[]);uint32_t SDIO_MultiBlockWrite(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[]);uint32_t SDIO_MultiBlockRead(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[]);uint32_t SDIO_DMABlockWrite(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[]);uint32_t SDIO_DMABlockRead(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[]);
    2.FatFs移植    底層讀寫函數(shù)有了以后,移植FatFs也就比較簡單了,首先將FatFs的相關(guān)文件添加到工程中:

        我們需要實現(xiàn)的接口函數(shù)在diskio.c文件中,包括至少以下3個函數(shù):    初始化函數(shù),直接將端口配置、SDIO初始化添加到該函數(shù)中:
  • DSTATUS disk_initialize (  BYTE pdrv        /* Physical drive nmuber to identify the drive */){  DSTATUS stat;  int result;
      switch (pdrv) {  case DEV_RAM :    //result = RAM_disk_initialize();    // translate the reslut code here    stat = STA_NOINIT;    return stat;  case DEV_MMC :    //result = MMC_disk_initialize();    // translate the reslut code here    PORT_Init(PORTB, PIN1, PORTB_PIN1_SD_CLK, 0);    PORT_Init(PORTB, PIN2, PORTB_PIN2_SD_CMD, 1);    PORT_Init(PORTB, PIN3, PORTB_PIN3_SD_D0,  1);    PORT_Init(PORTB, PIN4, PORTB_PIN4_SD_D1,  1);    PORT_Init(PORTB, PIN5, PORTB_PIN5_SD_D2,  1);    PORT_Init(PORTB, PIN6, PORTB_PIN6_SD_D3,  1);      result = SDIO_Init(10000000);    if(result == SD_RES_OK)    {      stat = RES_OK;      sd_initialized = 1;    }    else    {      stat = STA_NOINIT;      sd_initialized = 0;    }    return stat;  case DEV_USB :    //result = USB_disk_initialize();    // translate the reslut code here    stat = STA_NOINIT;    return stat;  }  return STA_NOINIT;}    讀函數(shù)
  • DRESULT disk_read (  BYTE pdrv,    /* Physical drive nmuber to identify the drive */  BYTE *buff,    /* Data buffer to store read data */  LBA_t sector,  /* Start sector in LBA */  UINT count    /* Number of sectors to read */){  DRESULT res;  int result;
      switch (pdrv) {  case DEV_RAM :    // translate the arguments here    //result = RAM_disk_read(buff, sector, count);    // translate the reslut code here    res = RES_PARERR;    return res;  case DEV_MMC :
        if(count == 1)    {      result = SDIO_BlockRead(sector, (uint32_t *)buff);    }    else    {      //result = SDIO_MultiBlockRead(sector, count, (uint32_t *)buff);        result = SDIO_DMABlockRead(sector, count, (uint32_t *)buff);//使用DMA或非DMA模式均可    }      if(result == SD_RES_OK)      res = RES_OK;    else      res = RES_ERROR;        return res;  case DEV_USB :    // translate the arguments here    //result = USB_disk_read(buff, sector, count);    // translate the reslut code here      res = RES_PARERR;    return res;  }  return RES_PARERR;}    寫函數(shù)
  • DRESULT disk_write (  BYTE pdrv,      /* Physical drive nmuber to identify the drive */  const BYTE *buff,  /* Data to be written */  LBA_t sector,    /* Start sector in LBA */  UINT count      /* Number of sectors to write */){  DRESULT res;  int result;
      switch (pdrv) {  case DEV_RAM :    // translate the arguments here    //result = RAM_disk_write(buff, sector, count);    // translate the reslut code here    res = RES_PARERR;    return res;  case DEV_MMC :    if(count == 1)    {      result = SDIO_BlockWrite(sector, (uint32_t *)buff);    }    else    {      //result = SDIO_MultiBlockWrite(sector, count, (uint32_t *)buff);      result = SDIO_DMABlockWrite(sector, count, (uint32_t *)buff);//使用DMA或非DMA模式均可    }    if(result == SD_RES_OK)      res = RES_OK;    else      res = RES_ERROR;    return res;  case DEV_USB :    // translate the arguments here    //result = USB_disk_write(buff, sector, count);    // translate the reslut code here    res = RES_PARERR;    return res;  }  return RES_PARERR;}    還有一個函數(shù)是用戶獲取SD卡容量等信息的,如下:
  • DRESULT disk_ioctl (  BYTE pdrv,    /* Physical drive nmuber (0..) */  BYTE cmd,    /* Control code */  void *buff    /* Buffer to send/receive control data */){  DRESULT res;  //int result;
      switch (pdrv) {  case DEV_RAM :    // Process of the command for the RAM drive    res = RES_PARERR;    return res;  case DEV_MMC :    switch ( cmd )     {      //fatfs內(nèi)核使用cmd調(diào)用      case GET_SECTOR_COUNT:  //sector count          *(DWORD*)buff = SD_cardInfo.CardCapacity / 512;          return RES_OK;      case GET_SECTOR_SIZE:  //sector size, 傳入block size(SD),單位bytes          *(DWORD*)buff = 512;          return RES_OK;      case GET_BLOCK_SIZE:  //block size, 由上文可得,對于SD2.0卡最大8192,最小 1          *(DWORD*)buff = 1;  //單位為 sector(FatFs)          return RES_OK;      case CTRL_SYNC:      //同步命令,貌似FatFs內(nèi)核用來判斷寫操作是否完成          return RES_OK;    }    res = RES_OK;    return res;  case DEV_USB :    // Process of the command the USB drive    res = RES_PARERR;    return res;  }  return RES_PARERR;}    接口部分實現(xiàn)后,就可以調(diào)用相關(guān)的函數(shù)實現(xiàn)文件的讀寫了,測試程序如下:
  • res = f_mount(&fatfs, "sd:", 1);if(res != FR_OK){  printf("sdcard init fail!\r
    ");}res = f_open(&filw, "sd:test.txt", FA_CREATE_ALWAYS | FA_WRITE);if(res != FR_OK){  printf("create file fail!\r
    ");}res = f_write(&filw, str, strlen(str), &len);if(res != FR_OK){  printf("write file fail!\r
    ");}f_close(&filw);
        文件系統(tǒng)的配置可以在"ffconf.h"文件中根據(jù)實際需求進行修改。

    推薦閱讀:
    STM32使用HAL庫驅(qū)動W5500
    SWM32系列教程1-了解一下硬件
    不會寫B(tài)ootloader?看這里,現(xiàn)成的!
    盤點一些國產(chǎn)“有特點”的單片機

    歡迎關(guān)注公眾號"嵌入式技術(shù)開發(fā)",大家可以后臺給我留言溝通交流。如果覺得該公眾號對你有所幫助,也歡迎推薦分享給其他人。
  • 回復(fù)

    使用道具 舉報

    發(fā)表回復(fù)

    您需要登錄后才可以回帖 登錄 | 立即注冊

    本版積分規(guī)則

    關(guān)閉

    站長推薦上一條 /1 下一條


    聯(lián)系客服 關(guān)注微信 下載APP 返回頂部 返回列表