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

📄 sd_drive.c

📁 Atmega64单片机程序(完整工程)
💻 C
📖 第 1 页 / 共 2 页
字号:
    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 + -