一、sd和fatfs的配置流程界面
1、选择sd4bits 根据自己的sd卡的硬件插槽进行选择。
2、fatfs配置由于使用的是sd卡所以直接选择sd选项
3、程序中对sd卡的初始化需要进行改动,直接使用默认的参数sd卡是挂载不上的。
4、在sd卡挂载好后,就可以使用文件系统的函数进行操作了。
写入
读取
注意:f_open后写和读取要分开操作,即写完后f_close以保持写入的内容,当需要读取时重新打开文件进行读取。
调试结果显示:
二、sd和fatfs的配置打开dma进行处理的流程界面
在使用f_write和f_read时会调用disk_write和disk_read。
下图就是其调用关系,f_read同理。
默认的disk_write和disk_read没用使用到dma,需要自己编辑对应的dma调用函数。
1、重新编写disk_write和disk_read函数
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to write */
)
//{
// DRESULT res;
// res = disk.drv[pdrv]->disk_write(disk.lun[pdrv], buff, sector, count);
// return res;
//}
{
uint8_t res=0;
if (!count)return RES_PARERR;//count不能等于0,否则返回参数错误
switch(pdrv)
{
case 0://SD卡
res=SD_WriteDisk((uint8_t*)buff,sector,count);
while(res)//写出错
{
MX_SDIO_SD_Init(); //重新初始化SD卡
res=SD_WriteDisk((uint8_t*)buff,sector,count);
//printf("sd wr error:%d\r\n",res);
}
res=0;
break;
default:
res=1;
}
if(res == 0x00)
return RES_OK;
else
return RES_ERROR;
}
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to read */
)
//{
// DRESULT res;
// res = disk.drv[pdrv]->disk_read(disk.lun[pdrv], buff, sector, count);
// return res;
//}
{
uint8_t res=0;
if (!count)return RES_PARERR;//count不能等于0,否则返回参数错误
switch(pdrv)
{
case 0://SD卡
res=SD_ReadDisk(buff,sector,count);
while(res)//读出错
{
MX_SDIO_SD_Init(); //重新初始化SD卡
res=SD_ReadDisk(buff,sector,count);
//printf("sd rd error:%d\r\n",res);
}
res=0;
break;
default:
res=1;
}
if(res==0x00)
return RES_OK;
else
return RES_ERROR;
}
2、编写写sd卡的写入操作函数
//获取SD运行状态
uint8_t SD_GetCardState(void)
{
return((HAL_SD_GetCardState(&hsd)==HAL_SD_CARD_TRANSFER )?SD_TRANSFER_OK:SD_TRANSFER_BUSY);
}
//写SD卡
//buf:写数据缓存区
//sector:扇区地址
//blocksize:扇区大小(一般都是512字节)
//cnt:扇区个数
//返回值:错误状态;0,正常;其他,错误代码;
uint8_t SD_WriteBlocks_DMA(uint32_t *buf,uint64_t sector,uint32_t blocksize,uint32_t cnt)
{
uint8_t err=0;
uint32_t timeout=100000000;
err=HAL_SD_WriteBlocks_DMA(&hsd,(uint8_t*)buf,sector,cnt);//通过DMA写SD卡n个扇区
if(err==0)
{
//等待SD卡写完
while(SD_GetCardState()!=SD_TRANSFER_OK)
{
if(timeout-- == 0)
{
err=SD_TRANSFER_BUSY;
}
}
}
return err;
}
//写SD卡操作
//buf:写数据缓存区
//sector:扇区地址
//cnt:扇区个数
//返回值:错误状态;0,正常;其他,错误代码;
uint8_t SD_WriteDisk(uint8_t *buf,uint32_t sector,uint32_t cnt)
{
uint8_t sta=HAL_OK;
long long lsector=sector;
sta=SD_WriteBlocks_DMA((uint32_t*)buf,lsector,512,cnt);//多个sector的写操作
return sta;
}
3、编写写sd卡的读取操作函数
//通过DMA读取SD卡一个扇区
//buf:读数据缓存区
//sector:扇区地址
//blocksize:扇区大小(一般都是512字节)
//cnt:扇区个数
//返回值:错误状态;0,正常;其他,错误代码;
uint8_t SD_ReadBlocks_DMA(uint32_t *buf,uint64_t sector,uint32_t blocksize,uint32_t cnt)
{
uint8_t err=0;
uint32_t timeout=100000000;
err=HAL_SD_ReadBlocks_DMA(&hsd,(uint8_t*)buf,sector,cnt);//通过DMA读取SD卡n个扇区
if(err==0)
{
//等待SD卡读完
while(SD_GetCardState()!=SD_TRANSFER_OK)
{
if(timeout-- == 0)
{
err=SD_TRANSFER_BUSY;
}
}
}
return err;
}
//读SD卡
//buf:读数据缓存区
//sector:扇区地址
//cnt:扇区个数
//返回值:错误状态;0,正常;其他,错误代码;
uint8_t SD_ReadDisk(uint8_t* buf,uint32_t sector,uint32_t cnt)
{
uint8_t sta=HAL_OK;
long long lsector=sector;
sta=SD_ReadBlocks_DMA((uint32_t*)buf,lsector, 512,cnt);
return sta;
}