Exemple #1
0
/**
 * @brief  	向SD卡发送一个命令
 * @param	cmd 命令 
			arg 命令参数
			crc crc校验值
 * @retval 	SD卡返回的响应
 */
u8 SD_SendCmd(u8 cmd, u32 arg, u8 crc)
{
    u8 r1;	
	u8 retry = 0; 
	
	SD_DisSelect();		//取消上次片选
	if(!SD_Select())	//重新片选
		return SD_DUMMY_BYTE;	//片选失败
	
	//打包命令、参数以及校验和
	
    SD_SPI_ReadWriteByte(cmd | 0x40);	//8位命令,最高位恒为1
    SD_SPI_ReadWriteByte(arg >> 24);	//将32位的参数拆分成4字节,逐一发送
    SD_SPI_ReadWriteByte(arg >> 16);
    SD_SPI_ReadWriteByte(arg >> 8);
    SD_SPI_ReadWriteByte(arg);	  
    SD_SPI_ReadWriteByte(crc); 			//8位校验和
	
	if(cmd == CMD12)	//对于停止命令,加发空闲数据
		SD_SPI_ReadWriteByte(SD_DUMMY_BYTE);	
	
    //等待响应,或超时退出
	retry = 0X1F;
	do
	{
		r1 = SD_SPI_ReadWriteByte(0xFF);
	}while((r1 & 0X80) && retry--);	 //r1最高位若为1则不是响应,继续等待

    return r1;
}
//读扇区
//drv:磁盘编号0~9
//*buff:数据接收缓冲首地址
//sector:扇区地址
//count:需要读取的扇区数
DRESULT disk_read (
	BYTE pdrv,		/* Physical drive nmuber (0..) */
	BYTE *buff,		/* Data buffer to store read data */
	DWORD sector,	/* Sector address (LBA) */
	UINT count		/* Number of sectors to read (1..128) */
)
{
	u8 res=0; 
    if (!count)return RES_PARERR;//count不能等于0,否则返回参数错误		 	 
	switch(pdrv)
	{
		case SD_CARD://SD卡
			res=SD_ReadDisk(buff,sector,count);	 
		 	if(res)//STM32 SPI的bug,在sd卡操作失败的时候如果不执行下面的语句,可能导致SPI读写异常
			{
				SD_SPI_SpeedLow();
				SD_SPI_ReadWriteByte(0xff);//提供额外的8个时钟
				SD_SPI_SpeedHigh();
			}
			break;
            
		default:
			res=1; 
	}
   //处理返回值,将SPI_SD_driver.c的返回值转成ff.c的返回值
    if(res==0x00)return RES_OK;	 
    else return RES_ERROR;	   
}
Exemple #3
0
/**
 * @brief	取消片选中SD卡
 * @param  
 * @retval 	None
 */
void SD_DisSelect(void)
{
	/* 取消片选设备 */
	SPI_SoftwareSELCmd(HT_SPI0, SPI_SEL_INACTIVE);
	
	//提供额外的8个时钟
 	SD_SPI_ReadWriteByte(SD_DUMMY_BYTE);	
}
Exemple #4
0
/**
 *  @name SD_RecvData
 *	@description 从sd卡读取一定长度的内容,保存到缓冲区buf中
 *	@param 	buf 数据缓存区
			len 要读取的数据长度
 *	@return 1 读取成功
			0 读取失败	
 *  @notice
 */
u8 SD_RecvData(u8 *buf,u16 len)
{			  	  
	//等待SD卡发回数据起始令牌
	if(SD_GetResponse(SD_BEGIN_END_FLAG) != SD_RESPONSE_NO_ERROR)
		return 0;
	
	//开始接收数据
    while(len--)
    {
        *buf = SD_SPI_ReadWriteByte(SD_DUMMY_BYTE);
        buf++;
    }
	
    //下面是2个伪CRC(dummy CRC)
    SD_SPI_ReadWriteByte(0xFF);
    SD_SPI_ReadWriteByte(0xFF);		
	
    return 1;//读取成功
}
Exemple #5
0
/**
 *  @name SD_GetResponse
 *	@description 等待SD卡回应
 *	@param response 要获得的回应
 *	@return	SD_RESPONSE_NO_ERROR 成功得到回应
			SD_RESPONSE_FAILURE 等待回应超时失败或回应不匹配
 *  @notice
 */
u8 SD_GetResponse(u8 response)
{
	u16 Count = 0xFFFF;//等待次数	   						  
	
	while ((SD_SPI_ReadWriteByte(SD_DUMMY_BYTE) != response) && Count)
		Count--;	//等待得到准确的回应  	  
	if(Count == 0)
		return SD_RESPONSE_FAILURE;		//得到回应失败   
	else 
		return SD_RESPONSE_NO_ERROR;	//正确回应
}
Exemple #6
0
/**
 * @brief	等待SD卡准备好
 * @param  
 * @retval 	1 已准备
			0 等待超时
 */
static u8 SD_WaitReady(void)
{
	u32 t = 0;
	
	while(++t < 0XFFFFFF)	//等待 
	{
		if(SD_SPI_ReadWriteByte(SD_DUMMY_BYTE) == SD_DUMMY_BYTE)	//总线空闲		
			return 1;		  	
	}	
	
	return 0;
}
Exemple #7
0
/**
 *  @name SD_SendBlock
 *	@description 向sd卡写入一个数据包的内容,共512字节
 *	@param 	buf 数据缓存区
			cmd 指令
 *	@return 1 发送成功
			0 发送失败	
 *  @notice
 */
u8 SD_SendBlock(u8 *buf, u8 cmd)
{	
	u16 cnt;
	u8 r1;
	
	if(!SD_WaitReady())
		return 0;	//等待准备失效
	
	SD_SPI_ReadWriteByte(cmd);
	
	if(cmd != 0XFD)//不是结束指令
	{
		for(cnt = 0;cnt < 512;cnt++)
			SD_SPI_ReadWriteByte(buf[cnt]);
	    SD_SPI_ReadWriteByte(0xFF);//忽略crc
	    SD_SPI_ReadWriteByte(0xFF);
		r1 = SD_SPI_ReadWriteByte(0xFF);//接收响应
		if((r1 & 0x1F) != 0x05)
			return 0;	//响应错误									  					    
	}						 									  					    
    return 1;	//写入成功
}
//初始化磁盘
DSTATUS disk_initialize (
	BYTE pdrv				/* Physical drive nmuber (0..) */
)
{
	u8 res=0;	    
	switch(pdrv)
	{
		case SD_CARD://SD卡
			res = SD_Initialize();//SD_Initialize() 
		 	if(res)//STM32 SPI的bug,在sd卡操作失败的时候如果不执行下面的语句,可能导致SPI读写异常
			{
				SD_SPI_SpeedLow();
				SD_SPI_ReadWriteByte(0xff);//提供额外的8个时钟
				SD_SPI_SpeedHigh();
			}
  			break;
            
		default:
			res=1; 
	}		 
	if(res)return  STA_NOINIT;
	else return 0; //初始化成功
}  
Exemple #9
0
/**
 * @brief  	初始化SD,使其进入工作模式
 * @param  
 * @retval 	0 卡错误
 */
u8 SD_Init(void)
{
	int i;
	u8 r1;		//存放命令响应
	u16 retry;	//存放超时计数
	u8 buf[4];	//临时缓冲区

	
	/* SD卡初始化阶段,CLK时钟最大不能超过400KHz */
	SD_SPI_SetLowSpeed();
	
	/* 上电延时至少74个时钟周期 */
	for(i = 0; i < 10; ++i)	
		SD_SPI_ReadWriteByte(SD_DUMMY_BYTE);
	retry = 20;
	while((r1 = SD_SendCmd(CMD0, 0, 0x95)) != 0x01 && retry-- > 0)	//进入IDLE状态,等待正确返回
		;
	if(r1 == 0x01)	//进入IDLE状态成功
	{
		//根据SD卡工作电压区分SD卡种类
		if(SD_SendCmd(CMD8, 0x1AA, 0x87) == 1)		//SD V2.0
		{
			for(i = 0;i < 4;i++)
				buf[i] = SD_SPI_ReadWriteByte(SD_DUMMY_BYTE);	//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)	//检查CCS
						SD_Type = SD_TYPE_V2HC;    
					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_SetHighSpeed();	//正常传输设置为高速
	
	if(SD_Type)	//卡错误,返回0
		return 0;
	else if(r1)
		return r1; 
	else
		return 0xaa;	//其他错误	
}