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

📄 sd_init.c

📁 SD卡与ARM7在SPI模式下进行数据读写原代码
💻 C
字号:
#ifndef SD_INIT_C
#define SD_INIT_C
/**************************************START OF THE FILE****************************************************************/
/************************************************************************************/
/*																					*/
/*	Copyright (C) 2004 Medeli Electric Industry Co., LTD.							*/
/*																					*/
/*	System Name	:	IC-1000															*/
/*	File   Name	:	sd_init.c														*/
/*	Revision	:	1.00															*/
/*	Date		:	2006/4/6														*/
/*					Initial version													*/
/*					Joe's work														*/
/************************************************************************************/
/*******************************Constants************************************/
/**************************Variable Declaration******************************/

/********************************Locoal**************************************/
CUWORD sd_to_unit[8]=
{/* 超时时间单位表(单位:0.000000001ns) timeout unit table */
	1000000000,100000000,10000000,1000000,100000,10000,1000,100
};
CUBYTE sd_to_value[16]=
{/* 超时时间表 timeout value table */
	0,10,12,13,15,20,25,30,35,40,45,50,55,60,70,80
};
/*******************************External*************************************/
/**************************Function Declaration******************************/
/********************************Locoal**************************************/
/*******************************External*************************************/
/***************************Start of program*********************************/
/****************************************************************************/
/*	initial sd card interface												*/
/*	Function : init_sd														*/
/*		Parameters															*/
/*			Input	:	Nothing												*/
/*			Output	:	Nothing												*/
/****************************************************************************/
UBYTE sd_card_initial(void)
{
	UBYTE ini_trys;
	
	UBYTE ret=SD_ERROR;
	
	sio_set_baudrate(SIO_BAUDRATE_INI);
	
	for(ini_trys=0;ini_trys<3;ini_trys++)
	{
		sd_interface_init();
		
		if(sd_enter_idle() == SD_OK)
		{
			if(sd_card_activate() == SD_OK)
			{
				break;
			}
		}
	}
	if((ini_trys<3)&&(sd_read_ocr() == SD_OK))
	{
		if((sd_vars.ocr[1]&MSK_OCR_33) == MSK_OCR_33)
		{
			sio_set_baudrate(SIO_BAUDRATE_WORK);
			
			if(sd_set_crc(0) == SD_OK)
			{
				if(sd_set_block_length(SD_BLOCK_LENGTH) == SD_OK)
				{
					if(sd_get_card_info() == SD_OK)
					{
						ret=SD_OK;
					}
				}
			}
		}
	}
	SD_CS_DEASSERT;
	
	return ret;
}
/****************************************************************************/
/*	initial sd card interface												*/
/*	Function : init_sd														*/
/*		Parameters															*/
/*			Input	:	Nothing												*/
/*			Output	:	Nothing												*/
/****************************************************************************/
UBYTE sd_card_activate(void)
{
	UBYTE ret=SD_OK;

	UWORD i=0;

	sd_write_com_para(0,0,0,0);

	for(i=0;(i<SD_IDLE_WAIT_MAX);i++)
	{/* 如果响应R1的最低位Idle位为1,则继续循环 */
		if(sd_send_cmd_idle(CMD55,sd_vars.com_para,0,sd_vars.resp)==SD_OK)
		{
			if(sd_send_cmd_idle(ACMD41,sd_vars.com_para,1,sd_vars.resp)==SD_OK)
			{
				if(!sd_vars.resp[0])
				{
					break;
				}
			}
		}
	}
    if(i>= SD_IDLE_WAIT_MAX)
	{/* 超时,返回错误 time out,return error */
		ret=SD_ERROR;
	}
	return ret;
}
/****************************************************************************/
/*	initial sd card interface												*/
/*	Function : init_sd														*/
/*		Parameters															*/
/*			Input	:	Nothing												*/
/*			Output	:	Nothing												*/
/****************************************************************************/
UBYTE sd_read_ocr(void)
{
    UBYTE i,ret=SD_ERROR;

	sd_write_com_para(0,0,0,0);

    if(sd_send_cmd(CMD58,sd_vars.com_para,0,sd_vars.resp) == SD_OK)/* 读 OCR 寄存器命令 */
    {
    	if(!sd_vars.resp[0])
    	{
    		for(i=0;i<4;i++)
    		{
    			sd_vars.ocr[i]=sd_vars.resp[i+1];
    		}
    		ret = SD_OK;
    	}
    }
	return ret;
}
/****************************************************************************/
/*	initial sd card interface												*/
/*	Function : init_sd														*/
/*		Parameters															*/
/*			Input	:	Nothing												*/
/*			Output	:	Nothing												*/
/****************************************************************************/
UBYTE sd_set_crc(UBYTE enable)
{
	UBYTE ret=SD_ERROR;

	sd_write_com_para((enable)? 1:0,0,0,0);

	if(sd_send_cmd(CMD59,sd_vars.com_para,0,sd_vars.resp)==SD_OK)
	{/* "使能/禁止CRC"命令 */
		if(!sd_vars.resp[0])
		{
			ret=SD_OK;
		}
	}
	return ret;
}
/****************************************************************************/
/*	initial sd card interface												*/
/*	Function : init_sd														*/
/*		Parameters															*/
/*			Input	:	Nothing												*/
/*			Output	:	Nothing												*/
/****************************************************************************/
UBYTE sd_set_block_length(UWORD block_length)
{
	UBYTE ret=SD_ERROR;

    sd_pack_com_para(sd_vars.com_para,block_length);					
	/* 将参数转化为字节形式 */
    if(sd_send_cmd(CMD16,sd_vars.com_para,0,sd_vars.resp)==SD_OK)
    {
    	if(!sd_vars.resp[0])
    	{
    		ret=SD_OK;
    	}
    }
	return ret;
}
/****************************************************************************/
/*	initial sd card interface												*/
/*	Function : init_sd														*/
/*		Parameters															*/
/*			Input	:	Nothing												*/
/*			Output	:	Nothing												*/
/****************************************************************************/
UBYTE sd_read_register(UWORD len,UBYTE *save_pt)
{
	UWORD i=0;

	UHWORD crc16;

	UBYTE ret=SD_ERROR;

	do
	{/* 等待数据起始令牌 wait for data start token */
		sd_vars.resp[0] = sd_get_byte();

		i++;

	}while((sd_vars.resp[0]==0xff) && (i<SD_READREG_TIMEOUT));

	if(i<SD_READREG_TIMEOUT)
	{
	   	if (sd_vars.resp[0]!=SD_TOK_READ_STARTBLOCK)
	   	{/* 不是收到数据起始令牌 not receive data start token */
			save_pt[0]=sd_vars.resp[0];

			i=1;/* 还有len - 1个字节要接收 still len - 1 bytes will be received */
	   	}
	   	else
	   	{/* 收到数据起始令牌,还有len个字节要接收 received data start token,still len bytes will be received */
	   		i=0;
	   	}
	    for( ; i<len; i++)
	    {/* 接收数据 receive data */
	   		save_pt[i]=sd_get_byte();
	   	}
	   	/* 下面读取16位CRC get 16-bit CRC */
	    crc16=sd_get_byte();

	    crc16=(crc16<<8)+sd_get_byte();

#if SD_CRC_ENABLED

	   	if (crc16==sd_get_crc16(save_pt,len))
	   	{/* CRC校验正确 CRC check is correct */
	   		ret=SD_OK;
	  	}
#else
		ret=SD_OK;
#endif
	}
	sd_send_byte(0xff);
	/* 返回之前发送8个clock  clock out 8 clk before return */
	return ret;
}
/****************************************************************************/
/*	initial sd card interface												*/
/*	Function : init_sd														*/
/*		Parameters															*/
/*			Input	:	Nothing												*/
/*			Output	:	Nothing												*/
/****************************************************************************/
UBYTE sd_read_csd(UBYTE csdlen, UBYTE *csd_pt)
{
	UBYTE ret=SD_ERROR;

	sd_write_com_para(0,0,0,0);

    if(sd_send_cmd(CMD9,sd_vars.com_para,0,sd_vars.resp) == SD_OK)
	{/* 读CSD寄存器命令 command that read CSD register */
		if(!sd_vars.resp[0])
		{
			return (sd_read_register(csdlen, csd_pt));
		}
	}
	return ret;
}
/****************************************************************************/
/*	initial sd card interface												*/
/*	Function : init_sd														*/
/*		Parameters															*/
/*			Input	:	Nothing												*/
/*			Output	:	Nothing												*/
/****************************************************************************/
void sd_calc_timeout(UBYTE *csd_pt)
{
	UWORD temp;

	UBYTE time_u,time_v,fator;

	sd_vars.timeout_read=READ_TIMEOUT_100MS;
	/* 默认读超时为100ms */
	sd_vars.timeout_write=WRITE_TIMEOUT_250MS;
	/* 默认写超时为250ms */
	sd_vars.timeout_erase=WRITE_TIMEOUT_250MS;
	/* 默认擦除超时为250ms */
	time_u=(sd_vars.csd[TAAC_POS]&TAAC_MSK);
	/* 读超时时间单位 read timeout unit */
	time_v=(sd_vars.csd[TAAC_POS]&NSAC_MSK) >> 3;
	/* 读超时时间值 read timeout value */
	fator=(sd_vars.csd[R2WFACTOR_POS]&R2WFACTOR_MSK)>>2;
	/* 写超时时间因数 write timeout factor */
	if((time_v)&&(fator<6))
	{
		temp=SIO_BAUDRATE_WORK * sd_to_value[time_v]/10/ sd_to_unit[time_u];
		/* TACC * f (单位 unit: clock) */
		temp=temp+csd_pt[NSAC_POS] * 100;
		/* TACC * f + NSAC * 100 (单位 unit: clock) */
		sd_vars.timeout_read=temp;
		/* 计算得到的超时值 the timeout value of being calculated */
		sd_vars.timeout_write=temp<<fator;
		/* (TACC * f + NSAC * 100) * R2WFACTOR (单位 unit:clock)*/
		sd_vars.timeout_read =sd_vars.timeout_read * 100/8;
		/* 实际值为计算值的100倍 */
		sd_vars.timeout_write=sd_vars.timeout_write * 100/8;

		if(sd_vars.timeout_read>READ_TIMEOUT_100MS)
		{/* 取计算值与默认值中的最小值 */
			sd_vars.timeout_read=READ_TIMEOUT_100MS;
		}
		if(sd_vars.timeout_write>WRITE_TIMEOUT_250MS)
		{/* 取计算值与默认值中的最小值 */
			sd_vars.timeout_write=WRITE_TIMEOUT_250MS;
		}
		sd_vars.timeout_erase=sd_vars.timeout_write;
	}
	return;
}
/****************************************************************************/
/*	initial sd card interface												*/
/*	Function : init_sd														*/
/*		Parameters															*/
/*			Input	:	Nothing												*/
/*			Output	:	Nothing												*/
/****************************************************************************/
UBYTE sd_get_card_info(void)
{
	UBYTE i,ret=SD_ERROR;

	UWORD temp;

	if((ret=sd_read_csd(16,sd_vars.csd)) == SD_OK)
	{/* 读CSD寄存器    read CSD register */
		sd_calc_timeout(sd_vars.csd);
		/* 计算超时时间值 calculate timeout value */
		sd_vars.trans_speed=((sd_vars.csd[TRANS_SPEED_POS]&0x7f)>>3)*100000;
		/* 计算传速 calculate the transfering speed of the card */
		for((i=sd_vars.csd[TRANS_SPEED_POS]&0x07);i;i--)
		{
			sd_vars.trans_speed*=10;
		}
		sd_vars.block_len=1<<(sd_vars.csd[READ_BL_LEN_POS]&READ_BL_LEN_MSK);
		/* 计算块的最大长度 calculate the size of a sector *//* (2 ^ READ_BL_LEN) */
		sd_vars.block_num = ((sd_vars.csd[C_SIZE_POS1]&C_SIZE_MSK1)<<10) + (sd_vars.csd[C_SIZE_POS2]<<2) + ((sd_vars.csd[C_SIZE_POS3]&C_SIZE_MSK3)>>6) + 1;/* (C_SIZE + 1)*/
		/* 计算卡中块的个数 calculate the sector numbers of the SD Card */
		temp=((sd_vars.csd[C_SIZE_MULT_POS1]&C_SIZE_MULT_MSK1)<<1) +((sd_vars.csd[C_SIZE_MULT_POS2]&C_SIZE_MULT_MSK2)>>7)+2;/* (C_SIZE_MULT + 2) */
	    /* 获得卡中块的数量 get the block numbers in card */
		sd_vars.block_num=sd_vars.block_num * (1<<temp);
		/* (C_SIZE + 1) * 2 ^ (C_SIZE_MULT + 2) */
		sd_vars.erase_unit=((sd_vars.csd[SECTOR_SIZE_POS1]&SECTOR_SIZE_MSK1)<<1) + ((sd_vars.csd[SECTOR_SIZE_POS2]&SECTOR_SIZE_MSK2)>>7) + 1;/* SD (SECTOR_SIZE + 1) */
		/* 计算扇区大小 calculate the size of sector */
	}
	return ret;
}
/****************************************************************************/
/*	initial sd card interface												*/
/*	Function : init_sd														*/
/*		Parameters															*/
/*			Input	:	Nothing												*/
/*			Output	:	Nothing												*/
/****************************************************************************/
void sd_interface_init(void)
{
	rPDATE&=~(1<<8);/* 对卡断电 */
	
	sd_vars.timer=0;
	
	rPDATC|=(1<<15);/* 245 cs deassert */
	
	SD_CS_DEASSERT;
	
	sio_set_baudrate(SIO_BAUDRATE_INI);
	
	while(sd_vars.timer<5);
	
	rPDATE|=(1<<8);/* 对卡上电 */
	
	sd_vars.timer=0;
	
	rPDATC&=~(1<<15);/* 245 cs assert */
	
	while(sd_vars.timer<5);
	
	SD_CS_ASSERT;
	
	sd_delay(250);
	
	SD_CS_DEASSERT;
	
	sd_delay(100);
	
	SD_CS_ASSERT;
	
	sd_vars.timer=0;
	
	rPDATC&=~(1<<15);/* 245 cs assert */
	
	while(sd_vars.timer<5);
	
	return;
}
/****************************************************************************/
/*	initial sd card interface												*/
/*	Function : init_sd														*/
/*		Parameters															*/
/*			Input	:	Nothing												*/
/*			Output	:	Nothing												*/
/****************************************************************************/
UBYTE sd_enter_idle(void)
{
	UBYTE ret=SD_ERROR;
	
	if(sd_send_cmd_idle(CMD0,sd_vars.com_para,0,sd_vars.resp)==SD_OK)
	{
		if(sd_vars.resp[0]==B_MSK_IDLE)
		{
			ret=SD_OK;
		}
	}
	return ret;
}
/****************************************END OF THE FILE****************************************************************/
#endif

⌨️ 快捷键说明

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