⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sddriver.c

📁 SD/MMC卡文件读写系统(FAT32)
💻 C
📖 第 1 页 / 共 2 页
字号:
{
    U8 i;

    for (i = 0; i < value; i++)
        SPI_TxBYTE(0xFF);	/* 发送0xFF */
}

//=============================================================================================


#if SD_FreeRTOS_EN
	xSemaphoreHandle pSemSD = NULL;	/* 卡访问权限信号量 semaphore that access card */
#endif 

/* SD卡信息结构体变量 the information structure variable of SD Card */
sd_struct sds;			

/* 超时时间单位表(单位:0.000000001ns) timeout unit table */
const U32 time_unit[8] = {1000000000,100000000,10000000,
							 1000000,100000,10000,1000,100};

/* 超时时间表 timeout value table */							 
const U8 time_value[16] = {0,10,12,13,15,20,25,30,
                              35,40,45,50,55,60,70,80};
 
/* 超时时间因数表 timeout factor table */                              
const U8 r2w_fator[8] = {1,2,4,8,16,32,64,128};                           
    

// 初始化SD/MMC卡	   0: 成功,X:错误码
U8 SD_Initialize(void)
{
	U8 recbuf[4],ret;
	
#if SD_FreeRTOS_EN
	if (pSemSD == NULL)
	{
       /* 创建访问SD/MMC卡信号量 create SD/MMC semaphore */ 
    	pSemSD = xSemaphoreCreateMutex();

		if (pSemSD == NULL)					
		 	return SD_ERR_CREATE_SEMSD;
	}				    
#endif	
    
    SD_StartSD();
    SD_HardWareInit();		/* 初始化读写SD卡的硬件条件*/
    
    if (SD_ChkCard_IN() != 1)	/* 检查卡是否插入 */
    {
    	ret = SD_ERR_NO_CARD;   
    	goto SD_ERR;
    }
         
    SPI_CS_Enable();		/* 1. 置CS为低*/  
	SD_SPIDelay(25);		/* 2. 至少延时 74 clock */
    SPI_CS_Disable();		/* 3. 置CS为高 */
    SD_SPIDelay(2);			/* 4. 延时2(8 clock)*/
    
    ret = SD_ResetSD();		/* 5. 发出CMDO命令复位SD卡*/
    if (ret != SD_NO_ERR)
        goto SD_ERR;									
 	
 	ret = SD_ActiveInit();	/* 6. 激活卡进入初始化过程. */
 	if (ret != SD_NO_ERR)
 		goto SD_ERR;
        
   	ret = SD_ReadOCR(4, recbuf);/* 7. 读OCR寄存器,查询卡支持的电压值 */
    if (ret != SD_NO_ERR)
        goto SD_ERR;
    
    if ((recbuf[1] & MSK_OCR_33) != MSK_OCR_33)
    { 
        ret = SD_ERR_VOL_NOTSUSP;	/* 不支持3.3V,返回错误码   */
    	goto SD_ERR;
    }
           
    ret = SD_SetBlockLen(SD_BLOCKSIZE);	/* 9. 设置块的长度: 512Bytes */
    if (ret != SD_NO_ERR)  
        goto SD_ERR;
        
    ret = SD_GetCardInfo();	/* 10. 读CSD寄存器,获取SD卡信息 */    
	if (ret != SD_NO_ERR)
		goto SD_ERR;

	SD_EndSD();		
	return SD_NO_ERR;		/* 初始化成功 */

SD_ERR:	
	SD_EndSD();	
	return ret;
}

// 从SD/MMC卡中读一个块 (块地址,缓冲区-512字节)   0: 成功,X:错误码
U8 SD_ReadBlock(U32 blockaddr, U8 *recbuf)
{
	U8 ret; 
	
	SD_StartSD();	/* 向OS申请访问卡信号量  */
    if (SD_ChkCard_IN() != 1)							
    {
    	SD_EndSD();	
    	return SD_ERR_NO_CARD;  /* 卡没完全插入卡中*/
	}
		
	if (blockaddr > sds.block_num)	
	{
		SD_EndSD();	
		return SD_ERR_OVER_CARDRANGE;	/* 操作超出卡容量范围 */
	}
	
 	ret = SD_BlockCMD(CMD17, CMD17_R, blockaddr);/* 读单块命令 */						
 	if (ret != SD_NO_ERR)
 	{
 		SD_EndSD();									
 		return ret;
 	}
 	
  	ret = SD_ReadBlockData(SD_BLOCKSIZE, recbuf);	/* 读出数据 */	
	SD_EndSD();										/* 归还访问卡信号量 */
	
	return ret;
}

// 向SD/MMC卡中写入一个块 (块地址,缓冲区-512字节)   0: 成功,X:错误码
U8 SD_WriteBlock(U32 blockaddr, U8 *sendbuf)
{
	U8 ret,tmp[2];
	
	SD_StartSD();	/* 向OS申请访问卡信号量*/
    if (SD_ChkCard_IN() != 1)							
    {
    	SD_EndSD();	
    	return SD_ERR_NO_CARD;  /* 卡没完全插入卡中 */
	}	
	
	if (blockaddr > sds.block_num)	
	{
		SD_EndSD();	
		return SD_ERR_OVER_CARDRANGE;/* 操作超出卡容量范围 */
	}
	
	if (SD_ChkCard_WP() == 1)
	{
		SD_EndSD();
		return SD_ERR_WRITE_PROTECT; /* 卡有写保护 */
	}
	
	ret = SD_BlockCMD(CMD24, CMD24_R, blockaddr); /* 写单块命令 */
	if (ret != SD_NO_ERR)
	{	
		SD_EndSD();
		return ret;
	}
	
	ret = SD_WriteBlockData(0, SD_BLOCKSIZE, sendbuf);/* 写入数据*/
 	if (ret == SD_NO_ERR)	/* 读Card Status寄存器, 检查写入是否成功 */
 	{	
 		ret = SD_ReadCard_Status(2, tmp);
 		if (ret != SD_NO_ERR)
 		{
 			SD_EndSD();
 			return ret;	/* 读寄存器失败*/
		}

 		if((tmp[0] != 0) || (tmp[1] != 0))
 		{
 			SD_EndSD();
			ret = SD_ERR_WRITE_BLK; /* 响应指示写失败*/
 		}
 	}
  
    SD_EndSD();
 	return ret;	/* 返回写入结果 */									
}



	/*****************************************************************
	
	    		下面为子程序
	 
	*****************************************************************/
// 获得SD/MMC卡的信息	 0: 成功    >0:错误码	
U8 SD_GetCardInfo()
{
	U32 tmp;
	U8 csdbuf[16],ret;

	ret = SD_ReadCSD(16, csdbuf);	/* read CSD register */
	if (ret != SD_NO_ERR)	
		return ret;	
		
	SD_CalTimeout(csdbuf);	/*  calculate timeout value */
		
	/* 计算块的最大长度  calculate the size of a sector */
	sds.block_len = 1 << (csdbuf[READ_BL_LEN_POS] & READ_BL_LEN_MSK);  			/* (2 ^ READ_BL_LEN) */
	
	/* 计算卡中块的个数 calculate the sector numbers of the SD Card */
	sds.block_num = ((csdbuf[C_SIZE_POS1] & C_SIZE_MSK1) << 10) +
	      			 (csdbuf[C_SIZE_POS2] << 2) +
	 	 			((csdbuf[C_SIZE_POS3] & C_SIZE_MSK3) >> 6) + 1;				/* (C_SIZE + 1)*/
		 	  															
	tmp = ((csdbuf[C_SIZE_MULT_POS1] & C_SIZE_MULT_MSK1) << 1) +   
	      ((csdbuf[C_SIZE_MULT_POS2] & C_SIZE_MULT_MSK2) >> 7) + 2;				/* (C_SIZE_MULT + 2) */
    	
    /* 获得卡中块的数量 get the block numbers in card */
	sds.block_num = sds.block_num * (1 << tmp);		/* (C_SIZE + 1) * 2 ^ (C_SIZE_MULT + 2) */
																			
	/* 计算擦除的单位(单位: 块) */	
	if (sds.card_type == CARDTYPE_MMC)
	{					    
		tmp  = ((csdbuf[ERASE_GRP_SIZE_POS] & ERASE_GRP_SIZE_MSK) >> 2) + 1;  	/* (ERASE_GRP_SIZE + 1)  */ 
		
		/* (ERASE_GRP_SIZE + 1) * (ERASE_GRP_MULTI + 1) */
		tmp *= ((csdbuf[ERASE_GRP_MULTI_POS1] & ERASE_GRP_MULTI_MSK1) << 3) +
		       ((csdbuf[ERASE_GRP_MULTI_POS2] & ERASE_GRP_MULTI_MSK2) >> 5) + 1;	
	}
	else																		/*calculate the size of sector */
		tmp = ((csdbuf[SECTOR_SIZE_POS1] & SECTOR_SIZE_MSK1) << 1) +  			
	          ((csdbuf[SECTOR_SIZE_POS2] & SECTOR_SIZE_MSK2) >> 7) + 1;			/* SD: SECTOR_SIZE */
	
	sds.erase_unit = tmp;	  /* 擦除单位(块) */ 
	
	return SD_NO_ERR;		/* perform sucessfully */
}

/*******************************************************************************************************************
** 函数名称: U8 SD_CalTimeout()				
** 功能描述: 计算读/写/擦超时时间			
** 输   入: U8 *csdbuf : CSD寄存器内容	
** 输    出: 0:   成功    >0:  错误码		
*******************************************************************************************************************/

U8 SD_CalTimeout(U8 *csdbuf)
{
	U32 tmp;
	U8 time_u,time_v,fator;
	
	sds.timeout_read = READ_TIMEOUT_100MS;								/* 默认读超时为100ms */
	sds.timeout_write = WRITE_TIMEOUT_250MS;							/* 默认写超时为250ms */
	sds.timeout_erase = WRITE_TIMEOUT_250MS;
		
	time_u = (csdbuf[TAAC_POS] & TAAC_MSK);								/* 读超时时间单位 */
	time_v = (csdbuf[TAAC_POS] & NSAC_MSK) >> 3;						/* 读超时时间值   */
	fator = (csdbuf[R2WFACTOR_POS] & R2WFACTOR_MSK) >> 2;				/* 读超时时间因数 */
	
	if(time_v == 0)	return SD_ERR_CARD_PARAM;		/* 卡参数有错误*/
	
	tmp = SPI_CLOCK * time_value[time_v] / 10 / time_unit[time_u];		/* TACC * f (单位 unit: clock) */
	tmp = tmp + csdbuf[NSAC_POS] * 100;									/* TACC * f + NSAC * 100 (单位 unit: clock) */
	
	/* 计算得到的超时值 the timeout value of being calculated */
	sds.timeout_read = tmp;
	sds.timeout_write = tmp * r2w_fator[fator];		/* (TACC * f + NSAC * 100) * R2WFACTOR (单位 unit:clock)*/
	
	if (sds.card_type == CARDTYPE_SD)
	{
		sds.timeout_read  = sds.timeout_read * 100 / 8;	/* 实际值为计算值的100倍 */
		sds.timeout_write = sds.timeout_write * 100 / 8;
		if (sds.timeout_read > READ_TIMEOUT_100MS)		/* 取计算值与默认值中的最小值 */
			sds.timeout_read = READ_TIMEOUT_100MS;
		
		if (sds.timeout_write > WRITE_TIMEOUT_250MS)
			sds.timeout_write = WRITE_TIMEOUT_250MS;
	}
	else
	{
		sds.timeout_read  = sds.timeout_read * 10 / 8;		/* 实际值为计算值的10倍 */
		sds.timeout_write = sds.timeout_write * 10 / 8;
	}
	
	sds.timeout_erase = sds.timeout_write;
	
#if SD_FreeRTOS_EN
	sds.timeout_read = (sds.timeout_read << 3) * configTICK_RATE_HZ / SPI_CLOCK; 
	sds.timeout_write =(sds.timeout_write << 3) * configTICK_RATE_HZ / SPI_CLOCK;
	sds.timeout_erase = sds.timeout_write;		/* (单位 unit: os tick) */
#endif	
	
	return SD_NO_ERR;	
}

/*******************************************************************************************************************
** 函数名称: U8 SD_ActiveInit()		
** 功能描述: 激活卡,并获得卡型	
** 输   入: 无						
** 输    出: 0:   成功    >0:  错误码			
** 函数说明: 该命令不断重复发送到SD卡,直到响应R1的Bit0(Idle)位为0,表示SD卡内部初始化处理完成。
		     当响应的Idle位为0时,SD卡就完全进入SPI模式了。当然重复发送命令CMD1是有次数限制的,
		     最大次数为宏定义SD_IDLE_WAIT_MAX.
*******************************************************************************************************************/
U8 SD_ActiveInit(void)
{
	U8 param[4] = {0,0,0,0},resp[5],ret;
	U32 i = 0;
	
 	do 
    {														/* 发出CMD1, 查询卡的状态, send CMD1 to poll card status */
        ret = SD_TxCMD(CMD1, param, CMD1_R, resp);
        if (ret != SD_NO_ERR)
       		return ret;
        i ++;
    }while (((resp[0] & MSK_IDLE) == MSK_IDLE) && (i <= SD_IDLE_WAIT_MAX));
    														/* 如果响应R1的最低位Idle位为1,则继续循环 */
    														/* if response R1 Idle bit is 1,continue recycle */    
    if (i >= SD_IDLE_WAIT_MAX)
        return SD_ERR_TIMEOUT_WAITIDLE;						/* 超时,返回错误 time out,return error */	
	
    ret = SD_TxCMD(CMD55, param, CMD55_R, resp);
    if (ret != SD_NO_ERR)
       	return ret;
       	
    ret = SD_TxCMD(ACMD41, param, ACMD41_R, resp);		/* 激活内部初始化命令 active card to initialize process internal */
    if (ret != SD_NO_ERR)	
    	return SD_ERR_UNKNOWN_CARD;
    
    if ((resp[0] & 0xFE) == 0)
      	sds.card_type = CARDTYPE_SD;						/* 是SD卡 the card is SD card */	
    else	
    	sds.card_type = CARDTYPE_MMC;						/* 是MMC卡 the card is MMC card */

	return SD_NO_ERR;
}

// 向操作系统申请访问SD卡的权限
void SD_StartSD(void)
{
#if SD_FreeRTOS_EN
    /* 等待访问卡信号量可用 wait for semaphore that accessed Card */	
    xQueueTakeMutexRecursive(pSemSD,(portTickType)10);   
#endif
}

// 访问SD卡的权限归还操作系统
void SD_EndSD(void)
{
#if SD_FreeRTOS_EN
  /* 将访问卡信号量还给操作系统 return the semaphore accessing Card to OS */
    xQueueGiveMutexRecursive(pSemSD);
#endif
}	










⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -