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

📄 cjsd.c

📁 没有谁会编写低速模式的下的SDHC驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
** 输   出: 0:   正确    >0:   错误码		  		Output:	  0:  right		>0:  error code
** 注    意: startaddr 和 blocknum 建议为sds.erase_uint的整数倍, 因为有的卡只能以sds.erase_uint为单位进行擦除
*********************************************************************************************************************/
#if SD_EraseBlock_EN
unsigned char SD_EraseBlock(unsigned long startaddr, unsigned long blocknum)
{
	long tmp;
	unsigned char ret;
	
	if ((startaddr + blocknum) > sds.block_num)	
		return SD_ERR_OVER_CARDRANGE;							/* 操作超出卡容量范围 operate over the card range */
		
	if (SD_ChkCardWP() == 1)
		return SD_ERR_WRITE_PROTECT;							/* 卡有写保护 */
		
	tmp = blocknum - sds.erase_unit;	
	while(tmp >= 0)												/* 每次擦除扇区大小 once erase is sector size */
	{	
				
		ret = SD_EraseEndBlock(startaddr + sds.erase_unit - 1);	/* 选择终止块地址 select end address */
		if (ret != SD_NO_ERR)
			return ret;
			
		ret = SD_EraseSelectedBlock();							/* 擦除所选的块 erase blocks selected */
		if (ret != SD_NO_ERR)
			return ret;

		startaddr += sds.erase_unit;							/* 起始地址递增 */
		blocknum  -= sds.erase_unit;
		tmp = blocknum - sds.erase_unit;
	};		
	
	if (blocknum > 0)											/* 擦除不够擦除扇区大小的块 */
	{															/* erase blocks that numbers is not enough a sector */
		ret = SD_EraseStartBlock(startaddr);
		if (ret != SD_NO_ERR)
			return ret;
		
		ret = SD_EraseEndBlock(startaddr + blocknum - 1);
		if (ret != SD_NO_ERR)
			return ret;
			
		ret = SD_EraseSelectedBlock();
		if (ret != SD_NO_ERR)
			return ret;
	}

	return SD_NO_ERR;											/* 返回擦除成功 return erase sucessfully */
}
#endif


/*******************************************************************************************************************
** 函数名称: unsigned char SD_GetCardInfo()				Name:	  unsigned char SD_GetCardInfo()
** 功能描述: 获得SD卡的信息						Function: get the information of SD card
** 输   入: unsigned char cardtype: 卡类型				Input:    unsigned char cardtype: card type	
** 输   出: 0:   正确    >0:   错误码		  	Output:	  0:  right		>0:  error code
*******************************************************************************************************************/
unsigned char SD_GetCardInfo()
{
	unsigned long tmp;
	unsigned char csdbuf[16],ret;
		
	ret = SD_ReadCSD(16,csdbuf);	 								    		/* 读CSD寄存器    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) */
																			
	/* 计算扇区大小 */															/*calculate the size of sector */
	sds.erase_unit = ((csdbuf[SECTOR_SIZE_POS1] & SECTOR_SIZE_MSK1) << 1) +  			
	                 ((csdbuf[SECTOR_SIZE_POS2] & SECTOR_SIZE_MSK2) >> 7) + 1; /* SD (SECTOR_SIZE + 1) */
	    			
	return SD_NO_ERR;															/* 返回执行成功 return perform sucessfully */
}

/*******************************************************************************************************************
** 函数名称: unsigned char SD_CalTimeout()				Name:	  unsigned char SD_CalTimeout()
** 功能描述: 计算读/写/擦超时时间				Function: get the information of SD card
** 输   入: unsigned char cardtype: 卡类型				Input:    unsigned char cardtype: card type	
			 unsigned char *csdbuf : CSD寄存器内容		 	      unsigned char *csdbuf : CSD register content
** 输   出: 0:   正确    >0:   错误码		  	Output:	  0:  right		>0:  error code
*******************************************************************************************************************/
void SD_CalTimeout(unsigned char *csdbuf)
{
	unsigned long tmp;
	unsigned char 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);								/* 读超时时间单位 read timeout unit */
	time_v = (csdbuf[TAAC_POS] & NSAC_MSK) >> 3;						/* 读超时时间值   read timeout value */
	fator = (csdbuf[R2WFACTOR_POS] & R2WFACTOR_MSK) >> 2;				/* 写超时时间因数 write timeout factor */
	
	if(time_v == 0)	return;
	if(fator >= 6) return;
	
	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)*/
	
	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;

	sds.timeout_erase = sds.timeout_write;
}

/*******************************************************************************************************************
** 函数名称: unsigned char SD_CalTimeout()				Name:	  unsigned char SD_CalTimeout()
** 功能描述: 计算读/写/擦超时时间				Function: get the information of SD card
** 输   入: unsigned char *cardtype: 卡类型接收缓冲 	Input:    unsigned char *cardtype: card type receive buff
** 输   出: 0:   正确    >0:   错误码		  	Output:	  0:  right		>0:  error code
** 函数说明: 该命令不断重复发送到SD卡,直到响应R1的Bit0(Idle)位为0,表示SD卡内部初始化处理完成。
		     当响应的Idle位为0时,SD卡就完全进入SPI模式了。当然重复发送命令CMD1是有次数限制的,
		     最大次数为宏定义SD_IDLE_WAIT_MAX.
*******************************************************************************************************************/
unsigned char SD_ActiveInit(void)
{
	unsigned char param[4] = {0,0,0,0},resp[5],ret;
	unsigned long i = 0;

 	do 
    {													/* 发出CMD1, 查询卡的状态, send CMD1 to poll card status */
        ret = SD_SendCmd(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 (i >= SD_IDLE_WAIT_MAX)
        return SD_ERR_TIMEOUT_WAITIDLE;					/* 超时,返回错误 time out,return error */

	return SD_NO_ERR;
}

/*******************************************************************************************************************
** 函数名称: unsigned short SD_GetZLGSDVer()			Name:	  unsigned short SD_GetZLGSDVer()
** 功能描述: 得到ZLG/SD的版本号					Function: get the version of ZLG/SD
** 输   入: 无									Input:    NULL
** 输   出: 版本号								Output:	  Version
*******************************************************************************************************************/
unsigned short SD_GetZLGSDVer(void)
{
	return 0x0100;						/* 版本号为 1.00 */
}




	/**************************************************************
		
		读写SD卡的SPI接口函数: SPI接口设置,发送/接收字节函数	
	
	**************************************************************/

/*******************************************************************************************************************
** 函数名称: void SD_Power()					Name:	  void SD_Power()
** 功能描述: 对卡先下电,再上电					Function: turn off the card's power, and turn on
** 输   入: 无									Input:	  NULL
** 输   出: 无									Output:	  NULL
********************************************************************************************************************/
void SD_Power(void)
{
	unsigned long i;

	SD_POWER_GPIO();
	SD_POWER_OUT();
	SD_POWER_OFF();								/* 关闭 SD 卡电源  turn off power of sd card */
	
	SPI_SCK_GPIO();	
	SPI_SCK_OUT();
	SPI_SCK_CLR();								/* SCK  引脚置低   set SCK to zero */
	
	SPI_MISO_GPIO();
	SPI_MISO_OUT();
	SPI_MISO_CLR();								/* MISO 引脚置低   set MISO to zero */
	
	SPI_MOSI_GPIO();		
	SPI_MOSI_OUT();
	SPI_MOSI_CLR();								/* MOSI 引脚置低   set MOSI to zero */
	
	SPI_CS_GPIO();								
   	SPI_CS_OUT();								
	SPI_CS_CLR();								/* CS 引脚置低	   set CS to zero */
		
	for(i = 0; i < 0x9000; i++);				/* 关闭电源延时    delay after turn off power of sd card */
	SD_POWER_ON();								/* 打开 SD 卡电源  turn on power of sd card */
}

/*******************************************************************************************************************
** 函数名称: void SD_HardWareInit()				Name:	  void SD_HardWareInit()
** 功能描述: 初始化访问SD卡的硬件条件			Function: initialize the hardware condiction that access sd card
** 输   入: 无									Input:	  NULL
** 输   出: 无									Output:	  NULL
********************************************************************************************************************/
void SD_HardWareInit(void)
{ 
	SD_Power();									/* 对卡先下电,再上电  turn off power of card, and turn on it */
	
	SPI_INIT();									/* 初始化SPI接口      initialize SPI interface */	
	
	SD_INSERT_GPIO();
	SD_INSERT_IN();								/* 检测卡完全插入口为输入口   the port checking card is input */
	
	SD_WP_GPIO();								
	SD_WP_IN();									/* 写保护检测口为输入口  	  the port written protect is input */	
		   
   	SPI_CS_SET();								/* CS置高	  				  set CS to high voltage */

 	SPI_Clk400k();								/* 设置SPI频率小于等于400kHZ  set frequency of SPI below 400kHZ */
   
 	SPI_SPCR = (0x01 << 4) + (0x01 << 5);		/* 设置SPI接口模式,MSTR = 1,CPOL = 1,CPHA = 0,LSBF=0 */
}												/* configure SPI interface */


/*******************************************************************************************************************
** 函数名称: void SPI_Clk400k()					Name:	  void SPI_Clk400k()
** 功能描述: 设置SPI的时钟小于400kHZ			Function: set the clock of SPI less than 400kHZ
** 输   入: 无									Input:	  NULL
** 输   出: 无									Output:	  NULL
********************************************************************************************************************/
void SPI_Clk400k(void)
{
	SPI_SPCCR = 128;    						/* 设置SPI时钟分频值为128  Set the value of dividing frequency to 128 */
}


/*******************************************************************************************************************
** 函数名称: void SPI_ClkToMax()				Name:	  void SPI_ClkToMax()
** 功能描述: 设置SPI的clock到最大值				Function: set the clock of SPI to maximum
** 输   入: 无									Input:	  NULL
** 输   出: 无									Output:	  NULL
********************************************************************************************************************/
void SPI_ClkToMax(void)
{
	SPI_SPCCR = 8;								/* 设置SPI时钟分频值为8  Set the value of dividing frequency to 8 */
}


/*******************************************************************************

⌨️ 快捷键说明

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