当前位置:   article > 正文

SWM32系列教程9-SDIO及FatFs文件系统_swm32s

swm32s

SWM32S单片机有1个SDIO接口,支持多媒体卡(MMC)、SD 存储卡、SDIO 卡等设备,可以使用软件方法或者 DMA 方法(SDIO 模块内部 DMA,与芯片 DMA 模块无关)进行数据传输。其特点如下:

f9c6ff06b079e579d518e04da31a2fa8.png

 

 

1.SDIO配置

    SDIO的引脚不像UART和SPI等数字外设一样可以灵活配置,它是固定的几个引脚,如下图

4cd32c5d9da740775fb83404147ac75e.png

    使用起来也比较简单,相关的库函数已经封装好了,直接调用就行。

    首先需要配置一下相关引脚的复用功能为SDIO:            

  1. PORT_Init(PORTB, PIN1, PORTB_PIN1_SD_CLK, 0);
  2. PORT_Init(PORTB, PIN2, PORTB_PIN2_SD_CMD, 1);
  3. PORT_Init(PORTB, PIN3, PORTB_PIN3_SD_D0, 1);
  4. PORT_Init(PORTB, PIN4, PORTB_PIN4_SD_D1, 1);
  5. PORT_Init(PORTB, PIN5, PORTB_PIN5_SD_D2, 1);
  6. PORT_Init(PORTB, PIN6, PORTB_PIN6_SD_D3, 1);

    然后直接调用初始化的函数就行:    

result = SDIO_Init(10000000);

    其中形参为SDIO的时钟频率

    SD卡读写的相关函数也已经封装好了,包括DMA和非DMA方式,直接调用即可:

  1. uint32_t SDIO_BlockWrite(uint32_t block_addr, uint32_t buff[]);
  2. uint32_t SDIO_BlockRead(uint32_t block_addr, uint32_t buff[]);
  3. uint32_t SDIO_MultiBlockWrite(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[]);
  4. uint32_t SDIO_MultiBlockRead(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[]);
  5. uint32_t SDIO_DMABlockWrite(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[]);
  6. uint32_t SDIO_DMABlockRead(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[]);

2.FatFs移植

    底层读写函数有了以后,移植FatFs也就比较简单了,首先将FatFs的相关文件添加到工程中:

51f210e373cb91494b7cd17200ee0d9b.png

    我们需要实现的接口函数在diskio.c文件中,包括至少以下3个函数:

    初始化函数,直接将端口配置、SDIO初始化添加到该函数中:

 

  1. DSTATUS disk_initialize (
  2. BYTE pdrv /* Physical drive nmuber to identify the drive */
  3. )
  4. {
  5. DSTATUS stat;
  6. int result;
  7. switch (pdrv) {
  8. case DEV_RAM :
  9. //result = RAM_disk_initialize();
  10. // translate the reslut code here
  11. stat = STA_NOINIT;
  12. return stat;
  13. case DEV_MMC :
  14. //result = MMC_disk_initialize();
  15.     // translate the reslut code here
  16. PORT_Init(PORTB, PIN1, PORTB_PIN1_SD_CLK, 0);
  17. PORT_Init(PORTB, PIN2, PORTB_PIN2_SD_CMD, 1);
  18. PORT_Init(PORTB, PIN3, PORTB_PIN3_SD_D0, 1);
  19. PORT_Init(PORTB, PIN4, PORTB_PIN4_SD_D1, 1);
  20. PORT_Init(PORTB, PIN5, PORTB_PIN5_SD_D2, 1);
  21.     PORT_Init(PORTB, PIN6, PORTB_PIN6_SD_D3,  1);  
  22. result = SDIO_Init(10000000);
  23. if(result == SD_RES_OK)
  24. {
  25. stat = RES_OK;
  26. sd_initialized = 1;
  27. }
  28. else
  29. {
  30. stat = STA_NOINIT;
  31. sd_initialized = 0;
  32. }
  33. return stat;
  34. case DEV_USB :
  35. //result = USB_disk_initialize();
  36. // translate the reslut code here
  37. stat = STA_NOINIT;
  38. return stat;
  39. }
  40. return STA_NOINIT;
  41. }
    读函数
  1. DRESULT disk_read (
  2. BYTE pdrv, /* Physical drive nmuber to identify the drive */
  3. BYTE *buff, /* Data buffer to store read data */
  4. LBA_t sector, /* Start sector in LBA */
  5. UINT count /* Number of sectors to read */
  6. )
  7. {
  8. DRESULT res;
  9. int result;
  10. switch (pdrv) {
  11. case DEV_RAM :
  12. // translate the arguments here
  13. //result = RAM_disk_read(buff, sector, count);
  14. // translate the reslut code here
  15. res = RES_PARERR;
  16. return res;
  17.   case DEV_MMC :
  18. if(count == 1)
  19. {
  20. result = SDIO_BlockRead(sector, (uint32_t *)buff);
  21. }
  22. else
  23. {
  24. //result = SDIO_MultiBlockRead(sector, count, (uint32_t *)buff);
  25. result = SDIO_DMABlockRead(sector, count, (uint32_t *)buff);//使用DMA或非DMA模式均可
  26. }
  27. if(result == SD_RES_OK)
  28. res = RES_OK;
  29. else
  30. res = RES_ERROR;
  31. return res;
  32. case DEV_USB :
  33. // translate the arguments here
  34. //result = USB_disk_read(buff, sector, count);
  35. // translate the reslut code here
  36. res = RES_PARERR;
  37. return res;
  38. }
  39. return RES_PARERR;
  40. }
    写函数
  1. DRESULT disk_write (
  2. BYTE pdrv, /* Physical drive nmuber to identify the drive */
  3. const BYTE *buff, /* Data to be written */
  4. LBA_t sector, /* Start sector in LBA */
  5. UINT count /* Number of sectors to write */
  6. )
  7. {
  8. DRESULT res;
  9. int result;
  10. switch (pdrv) {
  11. case DEV_RAM :
  12. // translate the arguments here
  13. //result = RAM_disk_write(buff, sector, count);
  14. // translate the reslut code here
  15. res = RES_PARERR;
  16. return res;
  17.   case DEV_MMC :
  18. if(count == 1)
  19. {
  20. result = SDIO_BlockWrite(sector, (uint32_t *)buff);
  21. }
  22. else
  23. {
  24. //result = SDIO_MultiBlockWrite(sector, count, (uint32_t *)buff);
  25. result = SDIO_DMABlockWrite(sector, count, (uint32_t *)buff);//使用DMA或非DMA模式均可
  26. }
  27. if(result == SD_RES_OK)
  28. res = RES_OK;
  29. else
  30. res = RES_ERROR;
  31. return res;
  32. case DEV_USB :
  33. // translate the arguments here
  34. //result = USB_disk_write(buff, sector, count);
  35. // translate the reslut code here
  36. res = RES_PARERR;
  37. return res;
  38. }
  39. return RES_PARERR;
  40. }
  还有一个函数是用户获取SD卡容量等信息的,如下:
  1. DRESULT disk_ioctl (
  2. BYTE pdrv, /* Physical drive nmuber (0..) */
  3. BYTE cmd, /* Control code */
  4. void *buff /* Buffer to send/receive control data */
  5. )
  6. {
  7. DRESULT res;
  8. //int result;
  9. switch (pdrv) {
  10. case DEV_RAM :
  11. // Process of the command for the RAM drive
  12. res = RES_PARERR;
  13. return res;
  14. case DEV_MMC :
  15. switch ( cmd )
  16. { //fatfs内核使用cmd调用
  17. case GET_SECTOR_COUNT: //sector count
  18. *(DWORD*)buff = SD_cardInfo.CardCapacity / 512;
  19. return RES_OK;
  20. case GET_SECTOR_SIZE: //sector size, 传入block size(SD),单位bytes
  21. *(DWORD*)buff = 512;
  22. return RES_OK;
  23. case GET_BLOCK_SIZE: //block size, 由上文可得,对于SD2.0卡最大8192,最小 1
  24. *(DWORD*)buff = 1; //单位为 sector(FatFs)
  25. return RES_OK;
  26. case CTRL_SYNC: //同步命令,貌似FatFs内核用来判断写操作是否完成
  27. return RES_OK;
  28. }
  29. res = RES_OK;
  30. return res;
  31. case DEV_USB :
  32. // Process of the command the USB drive
  33. res = RES_PARERR;
  34. return res;
  35. }
  36. return RES_PARERR;
  37. }
   接口部分实现后,就可以调用相关的函数实现文件的读写了,测试程序如下:
  1. res = f_mount(&fatfs, "sd:"1);
  2. if(res != FR_OK)
  3. {
  4. printf("sdcard init fail!\r\n");
  5. }
  6. res = f_open(&filw, "sd:test.txt", FA_CREATE_ALWAYS | FA_WRITE);
  7. if(res != FR_OK)
  8. {
  9. printf("create file fail!\r\n");
  10. }
  11. res = f_write(&filw, str, strlen(str), &len);
  12. if(res != FR_OK)
  13. {
  14. printf("write file fail!\r\n");
  15. }
  16. f_close(&filw);

    文件系统的配置可以在"ffconf.h"文件中根据实际需求进行修改。

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/482307
推荐阅读
相关标签
  

闽ICP备14008679号