FATFS学习

1:FATFS移植

1.1:FATFS配置参数

讲解网址

在这里插入图片描述
1.3 _USE_STRFUNC
用于使能或禁用字符串函数:f_gets、f_putc、f_puts和f_printf

1.5 _USE_MKFS
使能或禁用f_mkfs函数 (格式化函数)

2.1 _CODE_PAGE
设置语言类型

2.2 _USE_LFN
使能或禁用长文件名(LFN)。当使能长文件名后,需要向工程添加包含Unicode支持函数的option/unicode.c文件。工作缓冲区增加(_MAX_LFN + 1) * 2个字节,如果使能exFAT,额外多需要608字节缓存。如果工作缓存使用栈内存,需当心栈溢出;如果工作缓冲使用堆内存,需要向工程添加内存管理函数ff_memalloc和ff_memfree。

2.3 _MAX_LFN
定义长文件名工作缓冲区大小,可以为12~255字节。当禁用长文件名时,此选项无效。

2.4 _LFN_UNICODE
使能或禁用Unicode。如果要使用Unicode(UTF16)字符串路径名,需要使能LFN和设置本选项为1。此选项还影响字符串I/O功能函数。如果禁用长文件名,此选项必须为0。

2.5 _STRF_ENCODE
通过设置_LFN_UNICODE为1使能Unicode API函数时,这个选项定义通过字符串I/O函数读写的文件字符编码。字符串I/O函数有f_gets、f_putc、f_puts和f_printf。当_LFN_UNICODE等于0时,此选项不起作用。

3.1 _VOLUMES
配置可用卷的数目,可设置为1~10。

4.5 _FS_LOCK
使能或禁用文件锁功能。控制重复打开文件和非法打开文件对象。注意:文件锁功能不具有可重入性。只读模式下,这个宏必须为0。

2.2:SDIO的SD卡移植

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
#include “MicroSD.c”

SD_HandleTypeDef        SDCARD_Handler;     		//SD卡句柄
HAL_SD_CardInfoTypeDef  SDCardInfo;             //SD卡信息结构体
uint8_t SD_Init(void)
{
    uint8_t SD_Error;
    
    //初始化时的时钟不能大于400KHZ 
    SDCARD_Handler.Instance=SDIO;
    SDCARD_Handler.Init.ClockEdge=SDIO_CLOCK_EDGE_RISING;          		//上升沿     
    SDCARD_Handler.Init.ClockBypass=SDIO_CLOCK_BYPASS_DISABLE;     		//不使用bypass模式,直接用HCLK进行分频得到SDIO_CK
    SDCARD_Handler.Init.ClockPowerSave=SDIO_CLOCK_POWER_SAVE_DISABLE;   //空闲时不关闭时钟电源
    SDCARD_Handler.Init.BusWide=SDIO_BUS_WIDE_1B;                       //1位数据线
    SDCARD_Handler.Init.HardwareFlowControl=SDIO_HARDWARE_FLOW_CONTROL_ENABLE;//开启硬件流控
    SDCARD_Handler.Init.ClockDiv=10;            		//SD传输时钟频率最大25MHZ
	
    SD_Error=HAL_SD_Init(&SDCARD_Handler);
    if(SD_Error!=HAL_OK) return 1;
	
    SD_Error=HAL_SD_ConfigWideBusOperation(&SDCARD_Handler,SDIO_BUS_WIDE_4B);//使能宽总线模式
    if(SD_Error!=HAL_OK) return 2;
    return 0;
}

//得到卡信息
//cardinfo:卡信息存储区
//返回值:错误状态
u8 SD_GetCardInfo(HAL_SD_CardInfoTypeDef *cardinfo)
{
    u8 sta;
    sta=HAL_SD_GetCardInfo(&SDCARD_Handler,cardinfo);
    return sta;
}

//通过串口打印SD卡相关信息
void show_sdcard_info(void)
{
	uint64_t CardCap;	//SD卡容量
	HAL_SD_CardCIDTypeDef SDCard_CID;

	HAL_SD_GetCardCID(&SDCARD_Handler,&SDCard_CID);	//获取CID
	SD_GetCardInfo(&SDCardInfo);                    //获取SD卡信息
	switch(SDCardInfo.CardType)
	{
		case CARD_SDSC:
		{
			if(SDCardInfo.CardVersion == CARD_V1_X)
				printf("Card Type:SDSC V1\r\n");
			else if(SDCardInfo.CardVersion == CARD_V2_X)
				printf("Card Type:SDSC V2\r\n");
		}
		break;
		case CARD_SDHC_SDXC:printf("Card Type:SDHC\r\n");break;
	}	
	CardCap=(uint64_t)(SDCardInfo.LogBlockNbr)*(uint64_t)(SDCardInfo.LogBlockSize);	//计算SD卡容量
  	printf("Card ManufacturerID:%d\r\n",SDCard_CID.ManufacturerID);					//制造商ID
 	printf("Card RCA:%d\r\n",SDCardInfo.RelCardAdd);								//卡相对地址
	printf("LogBlockNbr:%d \r\n",(u32)(SDCardInfo.LogBlockNbr));					//显示逻辑块数量
	printf("LogBlockSize:%d \r\n",(u32)(SDCardInfo.LogBlockSize));					//显示逻辑块大小
	printf("Card Capacity:%d MB\r\n",(u32)(CardCap>>20));							//显示容量
 	printf("Card BlockSize:%d\r\n\r\n",SDCardInfo.BlockSize);						//显示块大小
}

void MicrsSD_Test(void)
{
	
  FRESULT res;                                      
  uint32_t Bw, Br;                    
  uint8_t wtext[] = "Hello Test USB TestTime:2023/07/08 15:42:37";                  
  uint8_t rtext[50];            
	
  char FileName[]="Micro.csv";
	
	/*	1:挂载系统	*/
  res = f_mount(&SDFatFS, (TCHAR const*)SDPath, 1);
  if(res != FR_OK) 
    printf("挂载系统失败 原因: %d", res);
	else
		printf("挂载系统成功");
  printf("在: %s 盘上挂载\r\n", SDPath);

	/*	2:创建文件	*/
  res = f_open(&SDFile, FileName, FA_CREATE_ALWAYS | FA_WRITE);
  if(res != FR_OK)
    printf("创建%s文件失败: %d\r\n", FileName,res);
	else
	  printf("创建%s文件成功\r\n",FileName);

	/*	3:写入内容	*/
  res = f_write(&SDFile, wtext, sizeof(wtext), (void *)&Bw);
  if((Bw == 0) || (res != FR_OK))
    printf("向%s写入 内容%s 失败 原因: %d\r\n",FileName,wtext,res);
	else
		printf("向%s写入 内容%s 成功\r\n",FileName,wtext);
  f_close(&SDFile);

	/*	4:打开文件	*/
  res = f_open(&SDFile, FileName, FA_READ);
  if(res != FR_OK)
    printf("打开%s文件失败 原因: %d\r\n", FileName,res);
	else
		printf("打开%s文件成功\r\n",FileName);

	/*	5:读取文件	*/
  res = f_read(&SDFile, rtext, sizeof(rtext), (void *)&Br);
  if((Br == 0) || (res != FR_OK))
    printf("读取%s文件失败 原因: %d\r\n", FileName,res);
	else
		printf("读取%s文件成功\r\n",FileName);

  f_close(&SDFile);

  if((Br != Bw))
    printf("文件读写不一致\r\n");
	else
		printf("文件读写一致\r\n");

  printf("已将%s文件创建到磁盘%s\r\n",FileName,SDPath);
}

2.3:U盘移植
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2.3:SPI的SD卡读写

0:注意SPI1的速度是SPI2的两倍 本
1:帧格式
2:设置SPI的数据大小:SPI发送接收8位帧结构
3:指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
4:定义波特率预分频的值:波特率预分频值为256
5:串行同步时钟的空闲状态为高电平
6:串行同步时钟的第二个跳变沿(上升或下降)数据被采样
7:关闭硬件CRC校验
8:NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
在这里插入图片描述
diskio.c

#include "diskio.h"
#include "ff_gen_drv.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
extern Disk_drvTypeDef  disk;
#include "mmc_sd.h"
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Gets Disk Status 
  * @param  pdrv: Physical drive number (0..)
  * @retval DSTATUS: Operation status
  */
//获得磁盘状态
DSTATUS disk_status (
	BYTE pdrv		/* Physical drive nmuber to identify the drive */
)
{
	return RES_OK;
}

/**
  * @brief  Initializes a Drive
  * @param  pdrv: Physical drive number (0..)
  * @retval DSTATUS: Operation status
  */
//初始化磁盘
DSTATUS disk_initialize (
	BYTE pdrv				/* Physical drive nmuber to identify the drive */
)
{
	uint8_t res;
//	if(pdrv<=4)//只能初始化SD卡
//	{
		res=SD_Init();	//SD卡初始化 
//	}
	if(res)
		return  STA_NOINIT;
	else
		return 0; //初始化成功 
}

/**
  * @brief  Reads Sector(s) 
  * @param  pdrv: Physical drive number (0..)
  * @param  *buff: Data buffer to store read data
  * @param  sector: Sector address (LBA)
  * @param  count: Number of sectors to read (1..128)
  * @retval DRESULT: Operation result
  */
//读扇区
//pdrv:磁盘编号0~9
//*buff:数据接收缓冲首地址
//sector:扇区地址
//count:需要读取的扇区数
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 */
)
{
	u8 res=0; 
	if (!count)
		return RES_PARERR;//count不能等于0,否则返回参数错误		 	
	
//	if(pdrv<=4)//只能是SD卡
//	{
		res=SD_ReadDisk(buff,sector,count);	 
//	}
	while(res)//读出错
	{
		SD_Init();	//重新初始化SD卡
		res=SD_ReadDisk(buff,sector,count);	
	}
	if(res==0x00)
		return RES_OK;	 
  else 
		return RES_ERROR;	  
	
}

/**
  * @brief  Writes Sector(s)  
  * @param  pdrv: Physical drive number (0..)
  * @param  *buff: Data to be written
  * @param  sector: Sector address (LBA)
  * @param  count: Number of sectors to write (1..128)
  * @retval DRESULT: Operation result
  */
#if _USE_WRITE == 1
//写扇区
//pdrv:磁盘编号0~9
//*buff:发送数据首地址
//sector:扇区地址
//count:需要写入的扇区数 

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 */
)
{
	u8 res=0;  
  if (!count)
		return RES_PARERR;//count不能等于0,否则返回参数错误		 
//	if(pdrv<=4)//只能是SD卡
//	{
		res=SD_WriteDisk((u8*)buff,sector,count);
		while(res)//写出错
		{
			SD_Init();	//重新初始化SD卡
			res=SD_WriteDisk((u8*)buff,sector,count);	
		}
//	}
	if(res == 0x00)
		return RES_OK;	 
  else 
		return RES_ERROR;
	
}
#endif /* _USE_WRITE == 1 */

/**
  * @brief  I/O control operation  
  * @param  pdrv: Physical drive number (0..)
  * @param  cmd: Control code
  * @param  *buff: Buffer to send/receive control data
  * @retval DRESULT: Operation result
  */
#if _USE_IOCTL == 1

//其他表参数的获得
//pdrv:磁盘编号0~9
//ctrl:控制代码
//*buff:发送/接收缓冲区指针 

DRESULT disk_ioctl (
	BYTE pdrv,		/* Physical drive nmuber (0..) */
	BYTE cmd,		/* Control code */
	void *buff		/* Buffer to send/receive control data */
)
{
  DRESULT res;
//	if(pdrv<=4)//只能是SD卡
//	{
		switch(cmd)
		{
			case CTRL_SYNC:
			res = RES_OK; 
					break;	 
			case GET_SECTOR_SIZE:
			*(DWORD*)buff = 512; 
					res = RES_OK;
					break;	 
			case GET_BLOCK_SIZE:
					*(WORD*)buff = 8;
					res = RES_OK;
					break;	 
			case GET_SECTOR_COUNT:
					*(DWORD*)buff = SD_GetSectorCount();
					res = RES_OK;
					break;
			default:
					res = RES_PARERR;
					break;
//		}
	}
	
	return res;
}
#endif /* _USE_IOCTL == 1 */

/**
  * @brief  Gets Time from RTC 
  * @param  None
  * @retval Time in DWORD
  */
__weak DWORD get_fattime (void)
{
return ((2052UL-1980) << 25) /* Year = 2010 */
			| (11UL << 21) /* Month = 11 */
			| (2UL << 16) /* Day = 2 */
			| (15U << 11) /* Hour = 15 */
			| (0U << 5) /* Min = 0 */
			| (0U >> 1) /* Sec = 0 */
;

}

spi.c

#define SDSPI hspi1
//SPI速度设置函数
//SPI速度=fAPB1/分频系数
//@ref SPI_BaudRate_Prescaler:SPI_BAUDRATEPRESCALER_2~SPI_BAUDRATEPRESCALER_2 256
//fAPB1时钟一般为42Mhz:
void SD_SPI_SetSpeed(uint8_t SPI_BaudRatePrescaler)
{
    assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));//判断有效性
    __HAL_SPI_DISABLE(&SDSPI);            //关闭SPI
    SDSPI.Instance->CR1&=0XFFC7;          //位3-5清零,用来设置波特率
    SDSPI.Instance->CR1|=SPI_BaudRatePrescaler;//设置SPI速度
    __HAL_SPI_ENABLE(&SDSPI);             //使能SPI
    
}

//SPI1 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
uint8_t SPI_SD_ReadWriteByte(uint8_t TxData)
{
    uint8_t Rxdata;
    HAL_SPI_TransmitReceive(&SDSPI,&TxData,&Rxdata,1, 1000);       
 	return Rxdata;          		    //返回收到的数据		
}

mmc_sd.c

u8  SD_Type=0;//SD卡的类型 
//移植时候的接口
//data:要写入的数据
//返回值:读到的数据
u8 SD_SPI_ReadWriteByte(u8 data)
{
	return SPI_SD_ReadWriteByte(data);
}	  
//SD卡初始化的时候,需要低速
void SD_SPI_SpeedLow(void)
{
 	SD_SPI_SetSpeed(SPI_BAUDRATEPRESCALER_256);//设置到低速模式	
}
//SD卡正常工作的时候,可以高速了
void SD_SPI_SpeedHigh(void)
{
 	SD_SPI_SetSpeed(SPI_BAUDRATEPRESCALER_4);//设置到高速模式	
}
//SPI硬件层初始化
void SD_SPI_Init(void)
{
	MX_SPI1_Init();
	LL_GPIO_SetOutputPin(SD_CS_GPIO_Port, SD_CS_Pin);
}
///
//取消选择,释放SPI总线
void SD_DisSelect(void)
{
	LL_GPIO_SetOutputPin(SD_CS_GPIO_Port, SD_CS_Pin);
 	SD_SPI_ReadWriteByte(0xff);//提供额外的8个时钟
}
//选择sd卡,并且等待卡准备OK
//返回值:0,成功;1,失败;
u8 SD_Select(void)
{
	LL_GPIO_ResetOutputPin(SD_CS_GPIO_Port, SD_CS_Pin);
	if(SD_WaitReady()==0)return 0;//等待成功
	SD_DisSelect();
	return 1;//等待失败
}
//等待卡准备好
//返回值:0,准备好了;其他,错误代码
u8 SD_WaitReady(void)
{
	u32 t=0;
	do
	{
	  
		if(SD_SPI_ReadWriteByte(0XFF)==0XFF)
			return 0;//OK
		t++;		
	}while(t<0XFFFF);//等待 
	RunStada |= errSDFountt; //报告SD卡挂载系统失败
	return 1;
}
//等待SD卡回应
//Response:要得到的回应值
//返回值:0,成功得到了该回应值
//    其他,得到回应值失败
u8 SD_GetResponse(u8 Response)
{
	u16 Count=0xFFFF;//等待次数	   						  
	while ((SD_SPI_ReadWriteByte(0XFF)!=Response)&&Count)Count--;//等待得到准确的回应  	  
	if (Count==0)return MSD_RESPONSE_FAILURE;//得到回应失败   
	else return MSD_RESPONSE_NO_ERROR;//正确回应
}
//从sd卡读取一个数据包的内容
//buf:数据缓存区
//len:要读取的数据长度.
//返回值:0,成功;其他,失败;	
u8 SD_RecvData(u8*buf,u16 len)
{			  	  
	if(SD_GetResponse(0xFE))return 1;//等待SD卡发回数据起始令牌0xFE
    while(len--)//开始接收数据
    {
        *buf=SPI_SD_ReadWriteByte(0xFF);
        buf++;
    }
    //下面是2个伪CRC(dummy CRC)
    SD_SPI_ReadWriteByte(0xFF);
    SD_SPI_ReadWriteByte(0xFF);									  					    
    return 0;//读取成功
}
//向sd卡写入一个数据包的内容 512字节
//buf:数据缓存区
//cmd:指令
//返回值:0,成功;其他,失败;	
u8 SD_SendBlock(u8*buf,u8 cmd)
{	
	u16 t;		  	  
	if(SD_WaitReady())return 1;//等待准备失效
	SD_SPI_ReadWriteByte(cmd);
	if(cmd!=0XFD)//不是结束指令
	{
		for(t=0;t<512;t++)SPI_SD_ReadWriteByte(buf[t]);//提高速度,减少函数传参时间
	    SD_SPI_ReadWriteByte(0xFF);//忽略crc
	    SD_SPI_ReadWriteByte(0xFF);
		t=SD_SPI_ReadWriteByte(0xFF);//接收响应
		if((t&0x1F)!=0x05)return 2;//响应错误									  					    
	}						 									  					    
    return 0;//写入成功
}

//向SD卡发送一个命令
//输入: u8 cmd   命令 
//      u32 arg  命令参数
//      u8 crc   crc校验值	   
//返回值:SD卡返回的响应															  
u8 SD_SendCmd(u8 cmd, u32 arg, u8 crc)
{
    u8 r1;	
	u8 Retry=0; 
	SD_DisSelect();//取消上次片选
	if(SD_Select())return 0XFF;//片选失效 
	//发送
    SD_SPI_ReadWriteByte(cmd | 0x40);//分别写入命令
    SD_SPI_ReadWriteByte(arg >> 24);
    SD_SPI_ReadWriteByte(arg >> 16);
    SD_SPI_ReadWriteByte(arg >> 8);
    SD_SPI_ReadWriteByte(arg);	  
    SD_SPI_ReadWriteByte(crc); 
	if(cmd==CMD12)SD_SPI_ReadWriteByte(0xff);//Skip a stuff byte when stop reading
    //等待响应,或超时退出
	Retry=0X1F;
	do
	{
		r1=SD_SPI_ReadWriteByte(0xFF);
	}while((r1&0X80) && Retry--);	 
	//返回状态值
    return r1;
}		    																			  
//获取SD卡的CID信息,包括制造商信息
//输入: u8 *cid_data(存放CID的内存,至少16Byte)	  
//返回值:0:NO_ERR
//		 1:错误														   
u8 SD_GetCID(u8 *cid_data)
{
    u8 r1;	   
    //发CMD10命令,读CID
    r1=SD_SendCmd(CMD10,0,0x01);
    if(r1==0x00)
	{
		r1=SD_RecvData(cid_data,16);//接收16个字节的数据	 
    }
	SD_DisSelect();//取消片选
	if(r1)return 1;
	else return 0;
}																				  
//获取SD卡的CSD信息,包括容量和速度信息
//输入:u8 *cid_data(存放CID的内存,至少16Byte)	    
//返回值:0:NO_ERR
//		 1:错误														   
u8 SD_GetCSD(u8 *csd_data)
{
    u8 r1;	 
    r1=SD_SendCmd(CMD9,0,0x01);//发CMD9命令,读CSD
    if(r1==0)
	{
    	r1=SD_RecvData(csd_data, 16);//接收16个字节的数据 
    }
	SD_DisSelect();//取消片选
	if(r1)return 1;
	else return 0;
}  
//获取SD卡的总扇区数(扇区数)   
//返回值:0: 取容量出错 
//       其他:SD卡的容量(扇区数/512字节)
//每扇区的字节数必为512,因为如果不是512,则初始化不能通过.														  
u32 SD_GetSectorCount(void)
{
    u8 csd[16];
    u32 Capacity;  
    u8 n;
	u16 csize;  					    
	//取CSD信息,如果期间出错,返回0
    if(SD_GetCSD(csd)!=0) return 0;	    
    //如果为SDHC卡,按照下面方式计算
    if((csd[0]&0xC0)==0x40)	 //V2.00的卡
    {	
		csize = csd[9] + ((u16)csd[8] << 8) + 1;
		Capacity = (u32)csize << 10;//得到扇区数	 		   
    }else//V1.XX的卡
    {	
		n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
		csize = (csd[8] >> 6) + ((u16)csd[7] << 2) + ((u16)(csd[6] & 3) << 10) + 1;
		Capacity= (u32)csize << (n - 9);//得到扇区数   
    }
    return Capacity;
}
//初始化SD卡
u8 SD_Init(void)
{
  u8 r1;      // 存放SD卡的返回值
  u16 retry;  // 用来进行超时计数
  u8 buf[4];  
	u16 i;

	SD_SPI_Init();		//初始化IO
 	SD_SPI_SpeedLow();	//设置到低速模式 
 	for(i=0;i<10;i++)SD_SPI_ReadWriteByte(0XFF);//发送最少74个脉冲
	retry=20;
	do
	{
		r1=SD_SendCmd(CMD0,0,0x95);//进入IDLE状态
	}while((r1!=0X01) && retry--);
 	SD_Type=0;//默认无卡
	if(r1==0X01)
	{
		if(SD_SendCmd(CMD8,0x1AA,0x87)==1)//SD V2.0
		{
			for(i=0;i<4;i++)buf[i]=SD_SPI_ReadWriteByte(0XFF);	//Get trailing return value of R7 resp
			if(buf[2]==0X01&&buf[3]==0XAA)//卡是否支持2.7~3.6V
			{
				retry=0XFFFE;
				do
				{
					SD_SendCmd(CMD55,0,0X01);	//发送CMD55
					r1=SD_SendCmd(CMD41,0x40000000,0X01);//发送CMD41
				}while(r1&&retry--);
				if(retry&&SD_SendCmd(CMD58,0,0X01)==0)//鉴别SD2.0卡版本开始
				{
					for(i=0;i<4;i++)buf[i]=SD_SPI_ReadWriteByte(0XFF);//得到OCR值
					if(buf[0]&0x40)SD_Type=SD_TYPE_V2HC;    //检查CCS
					else SD_Type=SD_TYPE_V2;   
				}
			}
		}else//SD V1.x/ MMC	V3
		{
			SD_SendCmd(CMD55,0,0X01);		//发送CMD55
			r1=SD_SendCmd(CMD41,0,0X01);	//发送CMD41
			if(r1<=1)
			{		
				SD_Type=SD_TYPE_V1;
				retry=0XFFFE;
				do //等待退出IDLE模式
				{
					SD_SendCmd(CMD55,0,0X01);	//发送CMD55
					r1=SD_SendCmd(CMD41,0,0X01);//发送CMD41
				}while(r1&&retry--);
			}else//MMC卡不支持CMD55+CMD41识别
			{
				SD_Type=SD_TYPE_MMC;//MMC V3
				retry=0XFFFE;
				do //等待退出IDLE模式
				{											    
					r1=SD_SendCmd(CMD1,0,0X01);//发送CMD1
				}while(r1&&retry--);  
			}
			if(retry==0||SD_SendCmd(CMD16,512,0X01)!=0)SD_Type=SD_TYPE_ERR;//错误的卡
		}
	}
	SD_DisSelect();//取消片选
	SD_SPI_SpeedHigh();//高速
	if(SD_Type)return 0;
	else if(r1)return r1; 	   
	return 0xaa;//其他错误
}
//读SD卡
//buf:数据缓存区
//sector:扇区
//cnt:扇区数
//返回值:0,ok;其他,失败.
u8 SD_ReadDisk(u8*buf,u32 sector,u8 cnt)
{
	u8 r1;
	if(SD_Type!=SD_TYPE_V2HC)sector <<= 9;//转换为字节地址
	if(cnt==1)
	{
		r1=SD_SendCmd(CMD17,sector,0X01);//读命令
		if(r1==0)//指令发送成功
		{
			r1=SD_RecvData(buf,512);//接收512个字节	   
		}
	}else
	{
		r1=SD_SendCmd(CMD18,sector,0X01);//连续读命令
		do
		{
			r1=SD_RecvData(buf,512);//接收512个字节	 
			buf+=512;  
		}while(--cnt && r1==0); 	
		SD_SendCmd(CMD12,0,0X01);	//发送停止命令
	}   
	SD_DisSelect();//取消片选
	return r1;//
}
//写SD卡
//buf:数据缓存区
//sector:起始扇区
//cnt:扇区数
//返回值:0,ok;其他,失败.
u8 SD_WriteDisk(u8*buf,u32 sector,u8 cnt)
{
	u8 r1;
	if(SD_Type!=SD_TYPE_V2HC)sector *= 512;//转换为字节地址
	if(cnt==1)
	{
		r1=SD_SendCmd(CMD24,sector,0X01);//读命令
		if(r1==0)//指令发送成功
		{
			r1=SD_SendBlock(buf,0xFE);//写512个字节	   
		}
	}else
	{
		if(SD_Type!=SD_TYPE_MMC)
		{
			SD_SendCmd(CMD55,0,0X01);	
			SD_SendCmd(CMD23,cnt,0X01);//发送指令	
		}
 		r1=SD_SendCmd(CMD25,sector,0X01);//连续读命令
		if(r1==0)
		{
			do
			{
				r1=SD_SendBlock(buf,0xFC);//接收512个字节	 
				buf+=512;  
			}while(--cnt && r1==0);
			r1=SD_SendBlock(0,0xFD);//接收512个字节 
		}
	}   
	SD_DisSelect();//取消片选
	return r1;//
}	
// SD卡类型定义  
#define SD_TYPE_ERR     0X00
#define SD_TYPE_MMC     0X01
#define SD_TYPE_V1      0X02
#define SD_TYPE_V2      0X04
#define SD_TYPE_V2HC    0X06	   
// SD卡指令表  	   
#define CMD0    0       //卡复位
#define CMD1    1
#define CMD8    8       //命令8 ,SEND_IF_COND
#define CMD9    9       //命令9 ,读CSD数据
#define CMD10   10      //命令10,读CID数据
#define CMD12   12      //命令12,停止数据传输
#define CMD16   16      //命令16,设置SectorSize 应返回0x00
#define CMD17   17      //命令17,读sector
#define CMD18   18      //命令18,读Multi sector
#define CMD23   23      //命令23,设置多sector写入前预先擦除N个block
#define CMD24   24      //命令24,写sector
#define CMD25   25      //命令25,写Multi sector
#define CMD41   41      //命令41,应返回0x00
#define CMD55   55      //命令55,应返回0x01
#define CMD58   58      //命令58,读OCR信息
#define CMD59   59      //命令59,使能/禁止CRC,应返回0x00
//数据写入回应字意义
#define MSD_DATA_OK                0x05
#define MSD_DATA_CRC_ERROR         0x0B
#define MSD_DATA_WRITE_ERROR       0x0D
#define MSD_DATA_OTHER_ERROR       0xFF
//SD卡回应标记字
#define MSD_RESPONSE_NO_ERROR      0x00
#define MSD_IN_IDLE_STATE          0x01
#define MSD_ERASE_RESET            0x02
#define MSD_ILLEGAL_COMMAND        0x04
#define MSD_COM_CRC_ERROR          0x08
#define MSD_ERASE_SEQUENCE_ERROR   0x10
#define MSD_ADDRESS_ERROR          0x20
#define MSD_PARAMETER_ERROR        0x40
#define MSD_RESPONSE_FAILURE       0xFF


extern u16 LastMinutes;
extern u16 LastMinutes_W;
extern u8 LastHour;
extern u8 LastDay;
//函数申明区 
u8 SD_SPI_ReadWriteByte(u8 data);
void SD_SPI_SpeedLow(void);
void SD_SPI_SpeedHigh(void);
u8 SD_WaitReady(void);							//等待SD卡准备
u8 SD_GetResponse(u8 Response);					//获得相应
u8 SD_Init(void);								//初始化
u8 SD_ReadDisk(u8*buf,u32 sector,u8 cnt);		//读块
u8 SD_WriteDisk(u8*buf,u32 sector,u8 cnt);		//写块
u32 SD_GetSectorCount(void);   					//读扇区数
u8 SD_GetCID(u8 *cid_data);                     //读SD卡CID
u8 SD_GetCSD(u8 *csd_data);                     //读SD卡CSD

mmc_sd.c

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LVGL是一个开源的图形库,用于创建嵌入式GUI应用程序。它提供了丰富的图形元素和交互功能,可以在各种嵌入式平台上使用。在LVGL中,可以使用文件系统抽象模块来读取文件、图片和字体等资源。LVGL支持多种文件系统,其中包括FatFS。 要在LVGL中使用FatFS文件系统,首先需要在项目配置中添加LVGL的文件系统接口。在LVGL的配置文件lv_conf.h中,可以找到以下配置项: ```c // File system interface #define LV_USE_FS_IF 1 #if LV_USE_FS_IF #define LV_FS_IF_FATFS 'S' #define LV_FS_IF_PC '\0' #define LV_FS_IF_POSIX '\0' #endif ``` 将LV_USE_FS_IF配置为1,表示启用LVGL的文件系统接口。然后,将LV_FS_IF_FATFS配置为'S',表示使用FatFS作为文件系统接口。 在项目中,还需要添加相应的解码库来实现图片的显示。LVGL会自动调用文件系统接口来读取文件系统中的文件。 总结起来,要在LVGL中使用FatFS文件系统,需要进行以下步骤: 1. 在LVGL的配置文件lv_conf.h中启用文件系统接口,并将接口配置为FatFS。 2. 添加相应的解码库来实现图片的显示。 希望以上信息对您有帮助! #### 引用[.reference_title] - *1* *2* *3* [ESP32开发学习 LVGL Littlevgl 使用文件系统](https://blog.csdn.net/cnicfhnui/article/details/118972851)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值