📄 sd_drive.c
字号:
INT8U ret ;
if((blockaddr+blocknum)>sds.block_num)
return SD_ERR_OVER_CARDRANGE ;
/* 操作超出卡容量范围 operate over the card range */
if(SD_ChkCardWP()==1)
return SD_ERR_WRITE_PROTECT ;
/* 卡有写保护 */
ret=SD_WriteMultipleBlock(blockaddr);
/* 写多块命令 write multiple blocks command */
if(ret!=SD_NO_ERR)
return ret ;
for(i=0;i<blocknum;i++)
{
ret=SD_WriteBlockData(1,SD_BLOCKSIZE,sendbuf);
/* 写入数据 write data */
if(ret==SD_NO_ERR)
sendbuf=sendbuf+SD_BLOCKSIZE ;
else
{
/* 写失败 write fail */
SD_StopTransmission();
/* 停止数据传输 stop data transmission */
SD_WaitBusy(SD_WAIT_WRITE);
/* 等待 waiting */
return ret ;
}
}
SD_StopMultiToken();
/* 发送数据停止令牌 send data stop token */
ret=SD_WaitBusy(SD_WAIT_WRITE);
/* 等待写入的完成 wait for finishing writing */
if(ret!=SD_NO_ERR)
return SD_ERR_TIMEOUT_WRITE ;
ret=SD_GetNumWRBlcoks(&i);
/* 读正确写入的块数 read the blocks that be written correctly */
if(ret!=SD_NO_ERR)
return ret ;
if(i!=blocknum)
return SD_ERR_WRITE_BLKNUMS ;
/* 正确写入块数错误 the blocks that be written correctly is error */
return SD_NO_ERR ;
/* 返回写入成功 return write sucessfully */
}
#endif
/*******************************************************************************
** 函数名称: INT8U SD_EraseBlock()
** 功能描述: 擦除SD卡中的块
** 输 入: INT32U startaddr: 起始地址
INT32U endaddr : 终止地址
** 输 出: 0: 正确 >0: 错误码
** 注 意: startaddr 和 blocknum 建议为sds.erase_uint的整数倍,
因为有的卡只能以sds.erase_uint为单位进行擦除
*******************************************************************************/
#if SD_EraseBlock_EN
INT8U SD_EraseBlock(INT32U startaddr,INT32U blocknum)
{
INT32S tmp ;
INT8U 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 ;
/* 每次擦除扇区大小 once erase is sector size */
while(tmp>=0)
{
ret=SD_EraseStartBlock(startaddr);
/* 选择起始块地址 select start address */
if(ret!=SD_NO_ERR)
return ret ;
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
/*******************************************************************************
** 函数名称: INT8U SD_GetCardInfo()
** 功能描述: 获得SD卡的信息
** 输 入: INT8U cardtype: 卡类型
** 输 出: 0: 正确 >0: 错误码 O
*******************************************************************************/
INT8U SD_GetCardInfo(void)
{
INT32U tmp ;
INT8U csdbuf[16],ret ;
ret=SD_ReadCSD(16,csdbuf);/* 读CSD寄存器 */
if(ret!=SD_NO_ERR)
return ret ;
SD_CalTimeout(csdbuf);/* 计算超时时间值 */
/* 计算块的最大长度 */
/* 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=((INT32U)(csdbuf[C_SIZE_POS1]&C_SIZE_MSK1)<<10)+((INT32U)csdbuf[C_SIZE_POS2]<<2)+((csdbuf[C_SIZE_POS3]&C_SIZE_MSK3)>>6)+1 ;
/* (C_SIZE + 1)*/
tmp=((INT32U)(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=((INT32U)(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 */
}
/*******************************************************************************
** 函数名称: INT8U SD_CalTimeout()
** 功能描述: 计算读/写/擦超时时间
** 输 入: INT8U cardtype: 卡类型
INT8U *csdbuf : CSD寄存器内容
** 输 出: 0: 正确 >0: 错误码
*******************************************************************************/
void SD_CalTimeout(INT8U *csdbuf)
{
INT32U tmp ;
INT8U 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+(INT32U)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 ;
}
/*******************************************************************************
** 函数名称: INT8U SD_CalTimeout()
** 功能描述: 计算读/写/擦超时时间
** 输 入: INT8U *cardtype: 卡类型接收缓冲
** 输 出: 0: 正确 >0: 错误码
** 函数说明: 该命令不断重复发送到SD卡,直到响应R1的Bit0(Idle)位为0
当响应的Idle位为0时,SD卡就完全进入SPI模式了。当然重复发送命令CMD1
是有次数限制的,最大次数为宏定义SD_IDLE_WAIT_MAX.
*******************************************************************************/
INT8U SD_ActiveInit(void)
{
INT8U param[4]={0,0,0,0},resp[5],ret ;
INT32U 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 ;
}
/*******************************************************************************
** 函数名称: INT16U SD_GetSDVer()
** 功能描述: 得到SD的版本号
** 输 入: 无
** 输 出: 版本号
*******************************************************************************/
INT16U SD_GetSDVer(void)
{
return 0x0100 ;
/* 版本号为 1.00 */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -