STM32学习笔记(三)FATFS读SD卡

blob.png


FATFS文件系统官网下载的最新版是0.13版本了,我的学习也是基于这个版本,到这个版本中,代码结构已经比较清晰了。

在diskio.c中,已经分成3个类别:RAM,MMC,USB,我们要做的只需要实现文件中已经定义好的相关函数就可以了。现在是读SD卡,所以实现MMC相关函数就行了:

MMC_disk_initialize();

MMC_disk_status();

MMC_disk_read(buff, sector, count);

MMC_disk_write(buff, sector, count);

以及disk_ioctl中对应的代码。


/////////////////磁盘初始化函数 disk_initialize//////////////////////////////////////////
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
return stat;
case DEV_MMC :
result = MMC_disk_initialize();
// translate the reslut code here
return stat;
case DEV_USB :
result = USB_disk_initialize();
// translate the reslut code here
return stat;
}
return STA_NOINIT;
}
//////////////////////bsp_sd_card.c源文件///////////////////////////
#include "bsp_sd_card.h"/
static GPIO_InitTypeDef GPIO_InitStruct;
SD_HandleTypeDef hsd;  
HAL_SD_CardInfoTypedef SDCardInfo;
__IO HAL_SD_ErrorTypedef errorstate = SD_OK;
uint32_t RdBuff[512];
//以下是实现diskio.c中的MMC_disk_initialize,初始化SD卡
int MMC_disk_initialize(void)
{
__HAL_RCC_SDIO_CLK_ENABLE(); 
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
GPIO_InitStruct.Mode  = GPIO_MODE_AF_PP;
       GPIO_InitStruct.Pull  = GPIO_PULLUP;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;  
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_2;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
hsd.Instance = SDIO;
hsd.Init.ClockDiv=2;
HAL_SD_DeInit(&hsd);
errorstate=HAL_SD_Init(&hsd,&SDCardInfo);
if(errorstate==SD_OK)
{
  printf("SD Card Bus %d MHz\r\n",SDCardInfo.SD_csd.MaxBusClkFrec);
  errorstate = HAL_SD_WideBusOperation_Config(&hsd, SDIO_BUS_WIDE_4B);  
        if(errorstate != SD_OK)  
        { 
    printf("SD Card Config 4B Fail\r\n");
            return 2;  
        }
else
{
printf("SD Card Bus Wide Set to 4Bit\r\n");
}
}
else
{
printf("SD Card Init Fail\r\n");
        return 1; 
}
       printf("SD Card Init Success \r\n");
printf("SD Card Type %d \r\n",SDCardInfo.CardType);
printf("SD Card Size %lld MB\r\n",SDCardInfo.CardCapacity/1024/1024);
printf("SD Card BlockSize %d \r\n",SDCardInfo.CardBlockSize);
printf("SD Card ClockDiv %d \r\n",hsd.Init.ClockDiv);
errorstate = HAL_SD_ReadBlocks(&hsd, (uint32_t*)&RdBuff, 0*SDCardInfo.CardBlockSize, SDCardInfo.CardBlockSize, 1);
return 0;
}
//以下是实现diskio.c中的MMC_disk_status,读取磁盘状态
int MMC_disk_status(void)
{
HAL_SD_TransferStateTypedef SD_Status;
SD_Status=HAL_SD_GetStatus(&hsd);
return SD_Status;
}
//以下是实现diskio.c中的MMC_disk_read,读SD卡内容
int MMC_disk_read(unsigned char *buff,unsigned long sector, unsigned int count)
{
HAL_SD_ErrorTypedef errorstate = SD_OK;
errorstate = HAL_SD_ReadBlocks(&hsd,(uint32_t *)buff, sector*SDCardInfo.CardBlockSize, SDCardInfo.CardBlockSize, count);
if(errorstate != SD_OK)
  {
 printf("SD Card Read Fail\r\n");
 return 1;
  }
//  printf("SD Card Read OK\r\n");
return 0;
}
//以下是实现diskio.c中的MMC_disk_write,向SD卡中写入内容
int MMC_disk_write(const unsigned char *buff,unsigned long sector, unsigned int count)
{
HAL_SD_ErrorTypedef errorstate = SD_OK;
errorstate = HAL_SD_WriteBlocks(&hsd, (uint32_t *)buff, sector*SDCardInfo.CardBlockSize, SDCardInfo.CardBlockSize, count);
if(errorstate != SD_OK)
  {
 printf("SD Card Write Fail\r\n");
 return 1;
  }
  printf("SD Card Write OK\r\n");
return 0;
}
/////////////////////////////main函数/////////////////////////////////////////////////////
FATFS fs;  
FRESULT res;  
FIL file; 
UINT br;  
BYTE buffer[4096];  
/*****************MAIN********************/
int main(void)
{
 pRxBuffer=aRxBuffer;
  HAL_Init(); 
  /* Configure the system clock to 72 MHz */
SystemInit();
        SystemClock_Config();
  
uart1_init();
    res = f_mount(&fs,"1:",0);  
    //创建data.txt  
    res = f_open(&file,"1:/data.txt",FA_CREATE_NEW| FA_READ |FA_WRITE);   
    if(res!=FR_OK)  
    {  
        printf("\r\n f_open() fail .. \r\n");  
    }else{  
        printf("\r\n f_open() success .. \r\n");  
    } 
res = f_close(&file);
  
while (1);
}


注意:由于FATFS系统里面将MMC定义在第二个,所以要将ffconf.h中的FF_VOLUMES值改为大于2的数,否则在挂载或打开文件时会出错。

#define FF_VOLUMES3


#define DEV_RAM0/* Example: Map Ramdisk to physical drive 0 */

#define DEV_MMC1/* Example: Map MMC/SD card to physical drive 1 */

#define DEV_USB2/* Example: Map USB MSD to physical drive 2 */


出现的错误

1、运行HAL_SD_Init(&hsd,&SDCardInfo)时,进入HardFault_Handler

原因一:是句柄没有初使化,加一句hsd.Instance = SDIO;即可。

原因二:HAL_SD_Init的参数是SD_HandleTypeDef *hsd, HAL_SD_CardInfoTypedef *SDCardInfo,定义这两个参数的时候,不要定义成指针,直接定义成结构,调用的时候加地址符,如下示例:

SD_HandleTypeDef hsd;  

HAL_SD_CardInfoTypedef SDCardInfo;

HAL_SD_Init(&hsd,&SDCardInfo);

2、读SD卡函数HAL_SD_ReadBlocks总是溢出,返回SD_RX_OVERRUN 

初使化的时候加一句hsd.Init.ClockDiv=2;将SDIO的时钟频率降下来就能解决。

3、f_open函数已运行成功,但并没有创建文件

f_open和f_close是成对出现的,加上f_close就能成功创建文件了。


关键词:SDIOSDFATFS

0 条评论

目前没有人发表评论

发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。