(2)创建sdio_sdcard.c文件,并输入以下代码。
#include "sdio_sdcard.h"
#include "string.h"
SD_CardInfo SDCardInfo ; //SD卡信息
u8 CardType=SDIO_STD_CAPACITY_SD_CARD_V1_1 ; //SD卡类型
/***************************************************
Name :SDIO_Clock_Set
Function :SDIO发送命令函数
Paramater :
cmdindex:命令索引,低六位有效
waitrsp:期待的相应
00/10:无响应
01:短响应
11:长响应
arg:参数
Return :错误代码
***************************************************/
void SDIO_Send_Cmd( u8 cmdindex, u8 waitrsp, u32 arg )
{
u32 tmpreg ;
SDIO->ARG = arg ;
tmpreg = SDIO->CMD ;
tmpreg &= 0xFFFFF800 ; //清除index和waitrsp
tmpreg |= cmdindex&0X3F ; //设置新的index
tmpreg |= waitrsp<<6 ; //设置新的wait rsp
tmpreg |= 0<<8 ; //无等待
tmpreg |= 1<<10 ; //命令通道状态机使能
SDIO->CMD = tmpreg ;
}
/***************************************************
Name :SDIO_Send_Data_Cfg
Function :SDIO发送数据配置函数
Paramater :
datatimeout:超时时间设置
datalen:传输数据长度,低25位有效,必须为块大小的整数倍
blksize:块大小.实际大小为:2^blksize字节
dir:数据传输方向
0:控制器到卡
1:卡到控制器
Return :错误代码
***************************************************/
void SDIO_Send_Data_Cfg( u32 datatimeout, u32 datalen, u8 blksize, u8 dir )
{
u32 tmpreg;
SDIO->DTIMER = datatimeout ;
SDIO->DLEN = datalen&0x1FFFFFF ; //低25位有效
tmpreg = SDIO->DCTRL ;
tmpreg &= 0xFFFFFF08 ; //清除之前的设置
tmpreg |= blksize<<4 ; //设置块大小
tmpreg |= 0<<2 ; //块数据传输
tmpreg |= ( dir&0x01 )<<1 ; //方向控制
tmpreg |= 1<<0 ; //数据传输使能,DPSM状态机
SDIO->DCTRL = tmpreg ;
}
/***************************************************
Name :SDIO_Clock_Set
Function :SDIO时钟初始化设置
Paramater :
clkdiv:时钟分频系数
Return :错误代码
***************************************************/
void SDIO_Clock_Set( u8 clkdiv )
{
u32 tmpreg = SDIO->CLKCR ;
tmpreg &= 0xFFFFFF00 ;
tmpreg |= clkdiv;
SDIO->CLKCR = tmpreg ;
}
/***************************************************
Name :CmdError
Function :检查CMD0的执行状态
Paramater :None
Return :错误代码
***************************************************/
SD_Error CmdError()
{
SD_Error errorstatus = SD_OK ;
u32 timeout=SDIO_CMD0TIMEOUT ;
while( timeout-- )
{
//命令已发送(无需响应)
if( SDIO->STA&( 1<<7 ) )
break ;
}
if( timeout==0 )
return SD_CMD_RSP_TIMEOUT ;
SDIO->ICR = 0x5FF ; //清除标记
return errorstatus ;
}
/***************************************************
Name :CmdResp7Error
Function :检查R7响应的错误状态
Paramater :None
Return :错误代码
***************************************************/
SD_Error CmdResp7Error()
{
u32 status ;
u32 timeout = 0x00010000 ;
while( timeout-- )
{
status = SDIO->STA ;
if( ( status&0x45 )!=0 ) //等待接收到应答
break ;
}
//响应超时
if( ( timeout==0 )||( ( status&0x04 )==0x04 ) )
{
//当前卡不是2.0兼容卡,或者不支持设定的电压范围
SDIO->ICR |= 1<<2 ; //清除命令响应超时标志
return SD_CMD_RSP_TIMEOUT ;
}
//成功接收到响应
if( ( status&0x40 )==0x40 )
SDIO->ICR |= 1<<6 ; //清除响应标志
return SD_OK ;
}
/***************************************************
Name :CmdResp1Error
Function :检查R1响应的错误状态
Paramater :
cmd:当前命令
Return :错误代码
***************************************************/
SD_Error CmdResp1Error( u8 cmd )
{
u32 status ;
while( 1 )
{
status = SDIO->STA ;
if( ( status&0x45 )!=0 ) //等待接收到应答
break ;
}
//响应超时
if( ( status&0x04 )==0x04 )
{
SDIO->ICR |= 1<<2 ; //清除命令响应超时标志
return SD_CMD_RSP_TIMEOUT ;
}
//CRC错误
if( ( status&0x01 )==0x01 )
{
SDIO->ICR |= 1<<0; //清除标志
return SD_CMD_CRC_FAIL;
}
if( SDIO->RESPCMD!=cmd )
return SD_ILLEGAL_CMD ; //命令不匹配
SDIO->ICR = 0x5FF ; //清除标记
return ( SD_Error )( SDIO->RESP1&0xFDFFE008 ) ; //返回卡响应
}
/***************************************************
Name :CmdResp3Error
Function :检查R3响应的错误状态
Paramater :None
Return :错误代码
***************************************************/
SD_Error CmdResp3Error()
{
u32 status ;
while( 1 )
{
status = SDIO->STA ;
if( ( status&0x45 )!=0 ) //等待接收到应答
break ;
}
//响应超时
if( ( status&0x04 )==0x04 )
{
SDIO->ICR |= 1<<2 ; //清除命令响应超时标志
return SD_CMD_RSP_TIMEOUT ;
}
SDIO->ICR = 0x5FF ; //清除标记
return SD_OK ;
}
/***************************************************
Name :CmdResp2Error
Function :检查R2响应的错误状态
Paramater :None
Return :错误代码
***************************************************/
SD_Error CmdResp2Error()
{
u32 status ;
u32 timeout = 0x00010000 ;
while( timeout-- )
{
status = SDIO->STA ;
if( ( status&0x45 )!=0 ) //接收到R2响应
break ;
}
//响应超时
if( ( timeout==0 )||( ( status&0x04 )==0x04 ) )
{
SDIO->ICR |= 1<<2 ; //清除命令响应超时标志
return SD_CMD_RSP_TIMEOUT ;
}
//CRC错误
if( ( status&0x01 )==0x01 )
{
SDIO->ICR |= 1<<0 ; //清除响应标志