专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
STM32
求帮看代码,SPI驱动SD卡,调了两天了。。
2019-07-20 18:39
发布
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
站内问答
/
STM32/STM8
2725
13
1072
找了很多F4的例程,都是SDIO驱动SD卡的,手上这块板又做成了SPI驱动的,找到战舰107的SPI驱动SD卡例程,移植过来,却不成功,不知道哪错了,感觉片选这部分有问题,自己试着改了,还是不行。。求帮忙看看代码
友情提示:
此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
13条回答
JAMES
1楼-- · 2019-07-20 23:00
已搞定
加载中...
JAMES
2楼-- · 2019-07-21 01:18
调了两天了,烦死了,求大神支援啊~~
加载中...
JAMES
3楼-- · 2019-07-21 02:30
精彩回答 2 元偷偷看……
加载中...
mygod
4楼-- · 2019-07-21 05:28
要想有进步就自己调试出来,动不动找这个源码找那个代码,你自己问题根源没找到。下次还来做这个,你还是要蒙。
先从硬件上排除,这个简单就不说了。
然后再软件上,把连接SD的 IO都同时拉高,拉低,看有没动作,然后继续 调试,设置断点,看看哪个地方错误。
加载中...
yyx112358
5楼-- · 2019-07-21 10:41
精彩回答 2 元偷偷看……
加载中...
yyx112358
6楼-- · 2019-07-21 15:44
C源文件[mw_shl_code=c,true]#include "sys.h"
#include "spi.h"
#include "mmc_sd.h"
#include "usart.h"
u8 SD_Type=0;//SD卡的类型
static u32 CSD_Tab[4],CID_Tab[4]; //SD卡CSD,CID以及相对地址(RCA)数据
SD_CardInfo SDCardInfo; //SD卡信息
//static DMA_InitTypeDef SD_DMAInitStructure;
////////////////////////////////////移植修改区///////////////////////////////////
//移植时候的接口
//data:要写入的数据
//返回值:读到的数据
u8 SD_SPI_ReadWriteByte(u8 data)
{
return SPI5_ReadWriteByte(data);
}
//SD卡初始化的时候,需要低速
void SD_SPI_SpeedLow(void)
{
SPI5_SetSpeed(SPI_BaudRatePrescaler_256);
}
//SD卡正常工作的时候,可以高速了
void SD_SPI_SpeedHigh(void)
{
SPI5_SetSpeed(SPI_BaudRatePrescaler_4);//【如果出现错误应改为16分频】
}
//SPI硬件层初始化
void SD_SPI_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF|RCC_AHB1Periph_GPIOC, ENABLE);//使能GPIOA时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOF, &GPIO_InitStructure);
SD_CS=1;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_Init(GPIOC, &GPIO_InitStructure);
L3GD20_CS=1;//其件片选引脚置为高以免影响
SPI5_Init();
}
u8 SD_Deinit(void)
{
SPI_DeInit(SPI5);
return 1;
}
u32 SD_UserCallBack(void)
{
SD_Deinit();
return SD_Init();
}
///////////////////////////////////////////////////////////////////////////////////
//取消选择,释放SPI总线
void SD_DisSelect(void)
{
SD_CS=1;
SD_SPI_ReadWriteByte(DUMMYBYTE);//提供额外的8个时钟
}
//选择sd卡,并且等待卡准备OK
//返回值:0,成功;1,失败;
u8 SD_Select(void)
{
SD_CS=0;
if(SD_WaitReady()==0)return 0;//等待成功
SD_DisSelect();
return 1;//等待失败
}
//等待卡准备好
//返回值:0,准备好了;其他,错误代码
u8 SD_WaitReady(void)
{
u32 t=0;
do
{
if(SD_SPI_ReadWriteByte(0XFF)==0XFF)return 0;//OK
t++;
}while(t<0XFFFFF);//等待
return SD_UserCallBack();
}
//等待SD卡回应
//Response:要得到的回应值
//返回值:0,成功得到了该回应值
// 其他,得到回应值失败
u8 SD_GetResponse(u8 Response)
{
u16 Count=0x1000 ;//等待次数
while ((SD_SPI_ReadWriteByte(0XFF)!=Response)&&Count)Count--;//等待得到准确的回应
if (Count==0)return SD_RESPONSE_FAILURE;//得到回应失败
else return SD_RESPONSE_NO_ERROR;//正确回应
}
//向SD卡发送一个命令
//输入: u8 cmd 命令
// u32 arg 命令参数
// u8 crc crc校验值
//返回值:SD卡返回的响应
u8 SD_SendCmd(u8 cmd, u32 arg, u8 crc)
{
u8 r1;
u8 Retry=0;
#if SD_SPI_USE_CRC///SD卡SPI模式下是否使用CRC
//SPI模式下,一般只需要初始化时用于进入SPI模式的CMD0需要CRC,除非使用CMD59打开SPI的CRC
do
{
SD_DisSelect();//取消上次片选
if(SD_Select())return SD_RESPONSE_FAILURE;//片选失效
//发送
SD_SPI_ReadWriteByte(cmd | 0x40);//分别写入命令
SD_SPI_ReadWriteByte(arg >> 24);
SD_SPI_ReadWriteByte(arg >> 16);
SD_SPI_ReadWriteByte(arg >> 8);
SD_SPI_ReadWriteByte(arg);
SD_SPI_ReadWriteByte(crc);
if(cmd==CMD12)SD_SPI_ReadWriteByte(0xff);//Skip a stuff byte when stop reading
//等待响应,或超时退出
Retry=0X1F;
do
{
r1=SD_SPI_ReadWriteByte(0xFF);
}while((r1&0X80) && Retry--);
crc++;
}while(r1&SD_COM_CRC_ERROR);
#if MY_DEBUG
printf("cmd:%d,arg:%x,crc:%x ",cmd,arg,crc-1);
#endif
#else //不使用CRC
SD_DisSelect();//取消上次片选
if(SD_Select())return SD_RESPONSE_FAILURE;//片选失效
//发送
SD_SPI_ReadWriteByte(cmd | 0x40);//分别写入命令
SD_SPI_ReadWriteByte(arg >> 24);
SD_SPI_ReadWriteByte(arg >> 16);
SD_SPI_ReadWriteByte(arg >> 8);
SD_SPI_ReadWriteByte(arg);
SD_SPI_ReadWriteByte(crc);
if(cmd==CMD12)SD_SPI_ReadWriteByte(0xff);//Skip a stuff byte when stop reading
//等待响应,或超时退出
Retry=0X1F;
do
{
r1=SD_SPI_ReadWriteByte(0xFF);
}while((r1&0X80) && Retry--);
#endif
//返回状态值
return r1;
}
//初始化SD卡
u8 SD_Initialize(void)
{
u8 r1; // 存放SD卡的返回值
u16 retry; // 用来进行超时计数
u8 buf[4];
u16 i;
SD_SPI_Init(); //初始化IO
SD_SPI_SpeedLow(); //设置到低速模式
for(i=0;i<10;i++)
SD_SPI_ReadWriteByte(0XFF);//发送最少74个脉冲
retry=20;
do
{
r1=SD_SendCmd(CMD0,0,0x95);////低电平时发送CMD0进入SPI模式
}while((r1!=SD_IN_IDLE_STATE) && retry--);
SD_Type=0;//默认无卡
if(r1!=SD_ILLEGAL_COMMAND)//R1未返回非法命令,说明支持SD2.0标准
{
if(SD_SendCmd(CMD8,0x1AA,0x87)==1)//SD V2.0
{
for(i=0;i<4;i++)
buf
=SD_SPI_ReadWriteByte(0XFF); //Get trailing return value of R7 resp
if(buf[2]==0X01&&buf[3]==0XAA)//卡是否支持2.7~3.6V
{
retry=0XFFFE;
do
{
SD_SendCmd(CMD55,0,0X64); //发送CMD55
r1=SD_SendCmd(CMD41,0x40000000,0X77);//发送CMD41
}while(r1&&retry--);
if(retry&&SD_SendCmd(CMD58,0,0X01)==0)//鉴别SD2.0卡版本开始
{
for(i=0;i<4;i++)buf
=SD_SPI_ReadWriteByte(0XFF);//得到OCR值
if(buf[0]&0x40)SD_Type=SD_TYPE_V2HC; //检查CCS
else SD_Type=SD_TYPE_V2;
}
}
}
else//SD V1.x/ MMC V3
{
SD_SendCmd(CMD55,0,0X64); //发送CMD55
r1=SD_SendCmd(CMD55,0,0X77); //发送CMD41
if(r1<=1)
{
SD_Type=SD_TYPE_V1;
retry=0XFFFE;
do //等待退出IDLE模式
{
SD_SendCmd(CMD55,0,0X64); //发送CMD55
r1=SD_SendCmd(CMD55,0,0X77);//发送CMD41
}while(r1&&retry--);
}else
{
SD_Type=SD_TYPE_MMC;//MMC V3
retry=0X1000;
do //等待退出IDLE模式
{
r1=SD_SendCmd(CMD1,0,0X01);//发送CMD1
}while(r1&&retry--);
}
if(retry==-1||SD_SendCmd(CMD16,512,0X14)!=0)SD_Type=SD_TYPE_ERR;//错误的卡
}
r1=SD_SendCmd(CMD59,0,0x95);
}
SD_DisSelect();//取消片选
SD_SPI_SpeedHigh();//高速
if(SD_Type)return SD_RESPONSE_NO_ERROR;
else if(r1)return r1;
return 0xaa;//其他错误
}
u8 SD_Init(void)
{
u8 r1=SD_RESPONSE_NO_ERROR;
SD_Deinit();
SD_SPI_Init();
r1=SD_Initialize();
if(r1!=SD_RESPONSE_NO_ERROR)
return r1;
r1=SD_GetCID(CID_Tab);
if(r1!=SD_RESPONSE_NO_ERROR)
return r1;
r1=SD_GetCSD(CSD_Tab);
if(r1!=SD_RESPONSE_NO_ERROR)
return r1;
SD_GetCardInfo(&SDCardInfo);
return SD_RESPONSE_NO_ERROR;
}
//从sd卡读取一个数据包的内容
//buf:数据缓存区
//len:要读取的数据长度.
//返回值:0,成功;其他,失败;
u8 SD_RecvData(u8 buf[],u16 len)
{
if(SD_GetResponse(0xFE))return SD_RESPONSE_FAILURE;//等待SD卡发回数据起始令牌0xFE
while(len--)//开始接收数据
{
*buf=SPI5_ReadWriteByte(DUMMYBYTE);
buf++;
}
//下面是2个伪CRC(dummy CRC)
SD_SPI_ReadWriteByte(DUMMYBYTE);
SD_SPI_ReadWriteByte(DUMMYBYTE);
return 0;//读取成功
}
//向sd卡写入一个数据包的内容 512字节
//buf:数据缓存区
//cmd:指令
//返回值:0,成功;其他,失败;
u8 SD_SendBlock(u8*buf,u8 cmd)
{
u16 t;
if(SD_WaitReady())
return SD_RESPONSE_FAILURE;//等待准备失效
SD_SPI_ReadWriteByte(cmd);
if(cmd!=0XFD)//不是结束指令
{
for(t=0;t<512;t++)SPI5_ReadWriteByte(buf[t]);//提高速度,减少函数传参时间
SD_SPI_ReadWriteByte(DUMMYBYTE);//忽略crc
SD_SPI_ReadWriteByte(DUMMYBYTE);
t=SD_SPI_ReadWriteByte(DUMMYBYTE);//接收响应
if((t&0x1F)!=0x05)return 2;//响应错误
}
return 0;//写入成功
}
//获取SD卡的CID信息,包括制造商信息
//输入: u8 *cid_data(存放CID的内存,至少16Byte)
//返回值:0:NO_ERR
// 1:错误
u8 SD_GetCID(u32 *cid_data)
{
u8 r1,temp[16],i=0;
//发CMD10命令,读CID
r1=SD_SendCmd(CMD10,0,0x01);
if(r1==0||r1==SD_COM_CRC_ERROR)
{
r1=SD_RecvData(temp,16);//接收16个字节的数据
}
for(i=0;i<4;i++)//小端模式转化为大端
{
cid_data
=(temp[4*i]<<24)+(temp[4*i+1]<<16)+(temp[4*i+2]<<8)+(temp[4*i+3]);
}
SD_DisSelect();//取消片选
if(r1)return r1;
else return 0;
}
//获取SD卡的CSD信息,包括容量和速度信息
//输入:u8 *cid_data(存放CID的内存,至少16Byte)
//返回值:0:NO_ERR
// 1:错误
u8 SD_GetCSD(u32 *csd_data)
{
u8 r1,temp[16],i=0;
r1=SD_SendCmd(CMD9,0,0xAF);//发CMD9命令,读CSD
if(r1==0||r1==SD_COM_CRC_ERROR)
{
r1=SD_RecvData(temp, 16);//接收16个字节的数据
}
for(i=0;i<4;i++)//小端模式转化为大端
{
csd_data
=(temp[4*i]<<24)+(temp[4*i+1]<<16)+(temp[4*i+2]<<8)+(temp[4*i+3]);
}
SD_DisSelect();//取消片选
if(r1)return r1;
else return 0;
}
////获取SD卡的总扇区数(扇区数)
////返回值:0: 取容量出错
//// 其他:SD卡的容量(扇区数/512字节)
////每扇区的字节数必为512,因为如果不是512,则初始化不能通过.
//u32 SD_GetSectorCount(void)
//{
// u8 csd[16];
// u32 Capacity;
// u8 n;
// u16 csize;
// //取CSD信息,如果期间出错,返回0
// if(SD_GetCSD(csd)!=0) return 0;
// //如果为SDHC卡,按照下面方式计算
// if((csd[0]&0xC0)==0x40) //V2.00的卡
// {
// csize = csd[9] + ((u16)csd[8] << 8) + 1;
// Capacity = (u32)csize << 10;//得到扇区数
// }
// else//V1.XX的卡
// {
// n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
// csize = (csd[8] >> 6) + ((u16)csd[7] << 2) + ((u16)(csd[6] & 3) << 10) + 1;
// Capacity= (u32)csize << (n - 9);//得到扇区数
// }
// return Capacity;
//}
//得到卡信息
//cardinfo:卡信息存储区
//返回值:错误状态
SD_ERRSTATE SD_GetCardInfo(SD_CardInfo *cardinfo)//这个函数是按照
{
SD_ERRSTATE errorstatus=SD_RESPONSE_NO_ERROR;
u8 tmp=0;
cardinfo->CardType=(u8)SD_Type; //卡类型
cardinfo->RCA=(u16)0x01; //卡RCA值
tmp=(u8)((CSD_Tab[0]&0xFF000000)>>24);
cardinfo->SD_csd.CSDStruct=(tmp&0xC0)>>6; //CSD结构
cardinfo->SD_csd.SysSpecVersion=(tmp&0x3C)>>2; //2.0协议还没定义这部分(为保留),应该是后续协议定义的
cardinfo->SD_csd.Reserved1=tmp&0x03; //2个保留位
tmp=(u8)((CSD_Tab[0]&0x00FF0000)>>16); //第1个字节
cardinfo->SD_csd.TAAC=tmp; //数据读时间1
tmp=(u8)((CSD_Tab[0]&0x0000FF00)>>8); //第2个字节
cardinfo->SD_csd.NSAC=tmp; //数据读时间2
tmp=(u8)(CSD_Tab[0]&0x000000FF); //第3个字节
cardinfo->SD_csd.MaxBusClkFrec=tmp; //传输速度
tmp=(u8)((CSD_Tab[1]&0xFF000000)>>24); //第4个字节
cardinfo->SD_csd.CardComdClasses=tmp<<4; //卡指令类高四位
tmp=(u8)((CSD_Tab[1]&0x00FF0000)>>16); //第5个字节
cardinfo->SD_csd.CardComdClasses|=(tmp&0xF0)>>4;//卡指令类低四位
cardinfo->SD_csd.RdBlockLen=tmp&0x0F; //最大读取数据长度
tmp=(u8)((CSD_Tab[1]&0x0000FF00)>>8); //第6个字节
cardinfo->SD_csd.PartBlockRead=(tmp&0x80)>>7; //允许分块读
cardinfo->SD_csd.WrBlockMisalign=(tmp&0x40)>>6; //写块错位
cardinfo->SD_csd.RdBlockMisalign=(tmp&0x20)>>5; //读块错位
cardinfo->SD_csd.DSRImpl=(tmp&0x10)>>4;
cardinfo->SD_csd.Reserved2=0; //保留
if((cardinfo->CardType==SD_TYPE_V1)||(cardinfo->CardType==SD_TYPE_V2)||(cardinfo->CardType==SD_TYPE_MMC))//标准1.1/2.0卡/MMC卡
{
cardinfo->SD_csd.DeviceSize=(tmp&0x03)<<10; //C_SIZE(12位)
tmp=(u8)(CSD_Tab[1]&0x000000FF); //第7个字节
cardinfo->SD_csd.DeviceSize|=(tmp)<<2;
tmp=(u8)((CSD_Tab[2]&0xFF000000)>>24); //第8个字节
cardinfo->SD_csd.DeviceSize|=(tmp&0xC0)>>6;
cardinfo->SD_csd.MaxRdCurrentVDDMin=(tmp&0x38)>>3;
cardinfo->SD_csd.MaxRdCurrentVDDMax=(tmp&0x07);
tmp=(u8)((CSD_Tab[2]&0x00FF0000)>>16); //第9个字节
cardinfo->SD_csd.MaxWrCurrentVDDMin=(tmp&0xE0)>>5;
cardinfo->SD_csd.MaxWrCurrentVDDMax=(tmp&0x1C)>>2;
cardinfo->SD_csd.DeviceSizeMul=(tmp&0x03)<<1;//C_SIZE_MULT
tmp=(u8)((CSD_Tab[2]&0x0000FF00)>>8); //第10个字节
cardinfo->SD_csd.DeviceSizeMul|=(tmp&0x80)>>7;
cardinfo->CardCapacity=(cardinfo->SD_csd.DeviceSize+1);//计算卡容量
cardinfo->CardCapacity*=(1<<(cardinfo->SD_csd.DeviceSizeMul+2));
cardinfo->CardBlockSize=1<<(cardinfo->SD_csd.RdBlockLen);//块大小
cardinfo->CardCapacity*=cardinfo->CardBlockSize;
}
else if(cardinfo->CardType==SD_TYPE_V2HC) //高容量卡
{
tmp=(u8)(CSD_Tab[1]&0x000000FF); //第7个字节
cardinfo->SD_csd.DeviceSize=(tmp&0x3F)<<16;//C_SIZE
tmp=(u8)((CSD_Tab[2]&0xFF000000)>>24); //第8个字节
cardinfo->SD_csd.DeviceSize|=(tmp<<8);
tmp=(u8)((CSD_Tab[2]&0x00FF0000)>>16); //第9个字节
cardinfo->SD_csd.DeviceSize|=(tmp);
tmp=(u8)((CSD_Tab[2]&0x0000FF00)>>8); //第10个字节
cardinfo->CardCapacity=(long long)(cardinfo->SD_csd.DeviceSize+1)*512*1024;//计算卡容量
cardinfo->CardBlockSize=512; //块大小固定为512字节
}
cardinfo->SD_csd.EraseGrSize=(tmp&0x40)>>6;
cardinfo->SD_csd.EraseGrMul=(tmp&0x3F)<<1;
tmp=(u8)(CSD_Tab[2]&0x000000FF); //第11个字节
cardinfo->SD_csd.EraseGrMul|=(tmp&0x80)>>7;
cardinfo->SD_csd.WrProtectGrSize=(tmp&0x7F);
tmp=(u8)((CSD_Tab[3]&0xFF000000)>>24); //第12个字节
cardinfo->SD_csd.WrProtectGrEnable=(tmp&0x80)>>7;
cardinfo->SD_csd.ManDeflECC=(tmp&0x60)>>5;
cardinfo->SD_csd.WrSpeedFact=(tmp&0x1C)>>2;
cardinfo->SD_csd.MaxWrBlockLen=(tmp&0x03)<<2;
tmp=(u8)((CSD_Tab[3]&0x00FF0000)>>16); //第13个字节
cardinfo->SD_csd.MaxWrBlockLen|=(tmp&0xC0)>>6;
cardinfo->SD_csd.WriteBlockPaPartial=(tmp&0x20)>>5;
cardinfo->SD_csd.Reserved3=0;
cardinfo->SD_csd.ContentProtectAppli=(tmp&0x01);
tmp=(u8)((CSD_Tab[3]&0x0000FF00)>>8); //第14个字节
cardinfo->SD_csd.FileFormatGrouop=(tmp&0x80)>>7;
cardinfo->SD_csd.CopyFlag=(tmp&0x40)>>6;
cardinfo->SD_csd.PermWrProtect=(tmp&0x20)>>5;
cardinfo->SD_csd.TempWrProtect=(tmp&0x10)>>4;
cardinfo->SD_csd.FileFormat=(tmp&0x0C)>>2;
cardinfo->SD_csd.ECC=(tmp&0x03);
tmp=(u8)(CSD_Tab[3]&0x000000FF); //第15个字节
cardinfo->SD_csd.CSD_CRC=(tmp&0xFE)>>1;
cardinfo->SD_csd.Reserved4=1;
tmp=(u8)((CID_Tab[0]&0xFF000000)>>24); //第0个字节
cardinfo->SD_cid.ManufacturerID=tmp;
tmp=(u8)((CID_Tab[0]&0x00FF0000)>>16); //第1个字节
cardinfo->SD_cid.OEM_AppliID=tmp<<8;
tmp=(u8)((CID_Tab[0]&0x000000FF00)>>8); //第2个字节
cardinfo->SD_cid.OEM_AppliID|=tmp;
tmp=(u8)(CID_Tab[0]&0x000000FF); //第3个字节
cardinfo->SD_cid.ProdName1=tmp<<24;
tmp=(u8)((CID_Tab[1]&0xFF000000)>>24); //第4个字节
cardinfo->SD_cid.ProdName1|=tmp<<16;
tmp=(u8)((CID_Tab[1]&0x00FF0000)>>16); //第5个字节
cardinfo->SD_cid.ProdName1|=tmp<<8;
tmp=(u8)((CID_Tab[1]&0x0000FF00)>>8); //第6个字节
cardinfo->SD_cid.ProdName1|=tmp;
tmp=(u8)(CID_Tab[1]&0x000000FF); //第7个字节
cardinfo->SD_cid.ProdName2=tmp;
tmp=(u8)((CID_Tab[2]&0xFF000000)>>24); //第8个字节
cardinfo->SD_cid.ProdRev=tmp;
tmp=(u8)((CID_Tab[2]&0x00FF0000)>>16); //第9个字节
cardinfo->SD_cid.ProdSN=tmp<<24;
tmp=(u8)((CID_Tab[2]&0x0000FF00)>>8); //第10个字节
cardinfo->SD_cid.ProdSN|=tmp<<16;
tmp=(u8)(CID_Tab[2]&0x000000FF); //第11个字节
cardinfo->SD_cid.ProdSN|=tmp<<8;
tmp=(u8)((CID_Tab[3]&0xFF000000)>>24); //第12个字节
cardinfo->SD_cid.ProdSN|=tmp;
tmp=(u8)((CID_Tab[3]&0x00FF0000)>>16); //第13个字节
cardinfo->SD_cid.Reserved1|=(tmp&0xF0)>>4;
cardinfo->SD_cid.ManufactDate=(tmp&0x0F)<<8;
tmp=(u8)((CID_Tab[3]&0x0000FF00)>>8); //第14个字节
cardinfo->SD_cid.ManufactDate|=tmp;
tmp=(u8)(CID_Tab[3]&0x000000FF); //第15个字节
cardinfo->SD_cid.CID_CRC=(tmp&0xFE)>>1;
cardinfo->SD_cid.Reserved2=1;
return errorstatus;
}
//读SD卡
//buf:数据缓存区
//sector:扇区
//cnt:扇区数
//返回值:0,ok;其他,失败.
//SPI无DMA下 多块读:约1047K/S 单块读:约623K/S
u8 SD_ReadDisk(u8*buf,u32 sector,u32 cnt)
{
u8 r1;
if((sector+cnt)>(SDCardInfo.SD_csd.DeviceSize+1)*1024) return SD_PARAMETER_ERROR;//超出最大扇区数
if(SD_Type!=SD_TYPE_V2HC)sector <<= 9;//转换为字节地址(每扇区512B)
if(cnt==1)
{
r1=SD_SendCmd(CMD17,sector,0X01);//读命令
if(r1==0||r1==SD_COM_CRC_ERROR)//指令发送成功【由于未进行CRC计算,故R1可能为SD_COM_CRC_ERROR】
{
r1=SD_RecvData(buf,512);//接收512个字节
}
}
else
{
r1=SD_SendCmd(CMD18,sector,0X01);//连续读命令
do
{
r1=SD_RecvData(buf,512);//接收512个字节
buf+=512;
}while(--cnt && (r1==0||r1==SD_COM_CRC_ERROR));
SD_SendCmd(CMD12,0,0X60); //发送停止命令
}
SD_DisSelect();//取消片选
return r1;//
}
//写SD卡
//buf:数据缓存区
//sector:起始扇区
//cnt:扇区数
//返回值:0,ok;其他,失败.
u8 SD_WriteDisk(u8*buf,u32 sector,u32 cnt)
{
u8 r1;
if(buf==NULL) return SD_PARAMETER_ERROR;//空指针
if((sector+cnt)>(SDCardInfo.SD_csd.DeviceSize+1)*1024) return SD_PARAMETER_ERROR;//超出最大扇区数
if(SD_Type!=SD_TYPE_V2HC)sector <<= 9;//转换为字节地址
if(cnt==1)
{
r1=SD_SendCmd(CMD24,sector,0X01);//写命令
if(r1==0||r1==SD_COM_CRC_ERROR)//指令发送成功【由于未进行CRC计算,故R1可能为SD_COM_CRC_ERROR】
{
r1=SD_SendBlock(buf,0xFE);//写512个字节
}
}else
{
if(SD_Type!=SD_TYPE_MMC)
{
SD_SendCmd(CMD55,0,0X64);
SD_SendCmd(CMD23,cnt,0X01);//发送指令
}
r1=SD_SendCmd(CMD25,sector,0X01);//连续写命令
if(r1==0||r1==SD_COM_CRC_ERROR)
{
do
{
r1=SD_SendBlock(buf,0xFC);//接收512个字节
buf+=512;
}while(--cnt && (r1==0||r1==SD_COM_CRC_ERROR));
r1=SD_SendBlock(0,0xFD);//接收512个字节
}
}
SD_DisSelect();//取消片选
return r1;//
}
//擦除指定区间的块
//写之前预先擦除会加快写SD卡速度
u8 SD_EraseDisk(u32 startsector,u32 endsector)
{
u8 r1;
if(SD_Type!=SD_TYPE_V2HC)
{
startsector <<= 9;//转换为字节地址(每扇区512B)
endsector <<=9;
}
r1=SD_SendCmd(CMD32,startsector,0x01);
if(r1!=0&&r1!=SD_COM_CRC_ERROR)
return r1;
r1=SD_SendCmd(CMD33,endsector,0x01);
if(r1!=0&&r1!=SD_COM_CRC_ERROR)
return r1;
r1=SD_SendCmd(CMD33,endsector,0x01);
if(r1!=0&&r1!=SD_COM_CRC_ERROR)
return r1;
return r1;
}
[/mw_shl_code]
加载中...
1
2
3
下一页
一周热门
更多
>
相关问题
STM32F4上I2C(在PROTEUS中模拟)调试不通的问题
6 个回答
芯片供应紧张,准备换个MCU,MM32L系列替换STM32L系列的怎么样?
7 个回答
STM32同时使用两个串口进行数据收发时数据丢包的问题
5 个回答
STM32F103串口通信死机问题
4 个回答
STM32WLE5CC连接SX1268在LoRa模式下能与 SX1278互通吗?
2 个回答
STM32开发板免费用活动
7 个回答
stm32 处理 DHT11占用太多时间,大家程序是怎么设计的
8 个回答
分享一个STM32单片机做的离线编程器代码
9 个回答
相关文章
ST公司第一款无线低功耗单片机模块有效提高物联网设计生产效率
0个评论
如何实现对单片机寄存器的访问
0个评论
通过USB用STM32片内自带Bootloader下载程序及注意事项
0个评论
欲练此功必先自宫之STM32汇编启动,放慢是为了更好的前行
0个评论
×
关闭
采纳回答
向帮助了您的网友说句感谢的话吧!
非常感谢!
确 认
×
关闭
编辑标签
最多设置5个标签!
STM32
保存
关闭
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
关闭
您已邀请
15
人回答
查看邀请
擅长该话题的人
回答过该话题的人
我关注的人
先从硬件上排除,这个简单就不说了。
然后再软件上,把连接SD的 IO都同时拉高,拉低,看有没动作,然后继续 调试,设置断点,看看哪个地方错误。
#include "spi.h"
#include "mmc_sd.h"
#include "usart.h"
u8 SD_Type=0;//SD卡的类型
static u32 CSD_Tab[4],CID_Tab[4]; //SD卡CSD,CID以及相对地址(RCA)数据
SD_CardInfo SDCardInfo; //SD卡信息
//static DMA_InitTypeDef SD_DMAInitStructure;
////////////////////////////////////移植修改区///////////////////////////////////
//移植时候的接口
//data:要写入的数据
//返回值:读到的数据
u8 SD_SPI_ReadWriteByte(u8 data)
{
return SPI5_ReadWriteByte(data);
}
//SD卡初始化的时候,需要低速
void SD_SPI_SpeedLow(void)
{
SPI5_SetSpeed(SPI_BaudRatePrescaler_256);
}
//SD卡正常工作的时候,可以高速了
void SD_SPI_SpeedHigh(void)
{
SPI5_SetSpeed(SPI_BaudRatePrescaler_4);//【如果出现错误应改为16分频】
}
//SPI硬件层初始化
void SD_SPI_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF|RCC_AHB1Periph_GPIOC, ENABLE);//使能GPIOA时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOF, &GPIO_InitStructure);
SD_CS=1;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_Init(GPIOC, &GPIO_InitStructure);
L3GD20_CS=1;//其件片选引脚置为高以免影响
SPI5_Init();
}
u8 SD_Deinit(void)
{
SPI_DeInit(SPI5);
return 1;
}
u32 SD_UserCallBack(void)
{
SD_Deinit();
return SD_Init();
}
///////////////////////////////////////////////////////////////////////////////////
//取消选择,释放SPI总线
void SD_DisSelect(void)
{
SD_CS=1;
SD_SPI_ReadWriteByte(DUMMYBYTE);//提供额外的8个时钟
}
//选择sd卡,并且等待卡准备OK
//返回值:0,成功;1,失败;
u8 SD_Select(void)
{
SD_CS=0;
if(SD_WaitReady()==0)return 0;//等待成功
SD_DisSelect();
return 1;//等待失败
}
//等待卡准备好
//返回值:0,准备好了;其他,错误代码
u8 SD_WaitReady(void)
{
u32 t=0;
do
{
if(SD_SPI_ReadWriteByte(0XFF)==0XFF)return 0;//OK
t++;
}while(t<0XFFFFF);//等待
return SD_UserCallBack();
}
//等待SD卡回应
//Response:要得到的回应值
//返回值:0,成功得到了该回应值
// 其他,得到回应值失败
u8 SD_GetResponse(u8 Response)
{
u16 Count=0x1000 ;//等待次数
while ((SD_SPI_ReadWriteByte(0XFF)!=Response)&&Count)Count--;//等待得到准确的回应
if (Count==0)return SD_RESPONSE_FAILURE;//得到回应失败
else return SD_RESPONSE_NO_ERROR;//正确回应
}
//向SD卡发送一个命令
//输入: u8 cmd 命令
// u32 arg 命令参数
// u8 crc crc校验值
//返回值:SD卡返回的响应
u8 SD_SendCmd(u8 cmd, u32 arg, u8 crc)
{
u8 r1;
u8 Retry=0;
#if SD_SPI_USE_CRC///SD卡SPI模式下是否使用CRC
//SPI模式下,一般只需要初始化时用于进入SPI模式的CMD0需要CRC,除非使用CMD59打开SPI的CRC
do
{
SD_DisSelect();//取消上次片选
if(SD_Select())return SD_RESPONSE_FAILURE;//片选失效
//发送
SD_SPI_ReadWriteByte(cmd | 0x40);//分别写入命令
SD_SPI_ReadWriteByte(arg >> 24);
SD_SPI_ReadWriteByte(arg >> 16);
SD_SPI_ReadWriteByte(arg >> 8);
SD_SPI_ReadWriteByte(arg);
SD_SPI_ReadWriteByte(crc);
if(cmd==CMD12)SD_SPI_ReadWriteByte(0xff);//Skip a stuff byte when stop reading
//等待响应,或超时退出
Retry=0X1F;
do
{
r1=SD_SPI_ReadWriteByte(0xFF);
}while((r1&0X80) && Retry--);
crc++;
}while(r1&SD_COM_CRC_ERROR);
#if MY_DEBUG
printf("cmd:%d,arg:%x,crc:%x ",cmd,arg,crc-1);
#endif
#else //不使用CRC
SD_DisSelect();//取消上次片选
if(SD_Select())return SD_RESPONSE_FAILURE;//片选失效
//发送
SD_SPI_ReadWriteByte(cmd | 0x40);//分别写入命令
SD_SPI_ReadWriteByte(arg >> 24);
SD_SPI_ReadWriteByte(arg >> 16);
SD_SPI_ReadWriteByte(arg >> 8);
SD_SPI_ReadWriteByte(arg);
SD_SPI_ReadWriteByte(crc);
if(cmd==CMD12)SD_SPI_ReadWriteByte(0xff);//Skip a stuff byte when stop reading
//等待响应,或超时退出
Retry=0X1F;
do
{
r1=SD_SPI_ReadWriteByte(0xFF);
}while((r1&0X80) && Retry--);
#endif
//返回状态值
return r1;
}
//初始化SD卡
u8 SD_Initialize(void)
{
u8 r1; // 存放SD卡的返回值
u16 retry; // 用来进行超时计数
u8 buf[4];
u16 i;
SD_SPI_Init(); //初始化IO
SD_SPI_SpeedLow(); //设置到低速模式
for(i=0;i<10;i++)
SD_SPI_ReadWriteByte(0XFF);//发送最少74个脉冲
retry=20;
do
{
r1=SD_SendCmd(CMD0,0,0x95);////低电平时发送CMD0进入SPI模式
}while((r1!=SD_IN_IDLE_STATE) && retry--);
SD_Type=0;//默认无卡
if(r1!=SD_ILLEGAL_COMMAND)//R1未返回非法命令,说明支持SD2.0标准
{
if(SD_SendCmd(CMD8,0x1AA,0x87)==1)//SD V2.0
{
for(i=0;i<4;i++)
buf=SD_SPI_ReadWriteByte(0XFF); //Get trailing return value of R7 resp
if(buf[2]==0X01&&buf[3]==0XAA)//卡是否支持2.7~3.6V
{
retry=0XFFFE;
do
{
SD_SendCmd(CMD55,0,0X64); //发送CMD55
r1=SD_SendCmd(CMD41,0x40000000,0X77);//发送CMD41
}while(r1&&retry--);
if(retry&&SD_SendCmd(CMD58,0,0X01)==0)//鉴别SD2.0卡版本开始
{
for(i=0;i<4;i++)buf=SD_SPI_ReadWriteByte(0XFF);//得到OCR值
if(buf[0]&0x40)SD_Type=SD_TYPE_V2HC; //检查CCS
else SD_Type=SD_TYPE_V2;
}
}
}
else//SD V1.x/ MMC V3
{
SD_SendCmd(CMD55,0,0X64); //发送CMD55
r1=SD_SendCmd(CMD55,0,0X77); //发送CMD41
if(r1<=1)
{
SD_Type=SD_TYPE_V1;
retry=0XFFFE;
do //等待退出IDLE模式
{
SD_SendCmd(CMD55,0,0X64); //发送CMD55
r1=SD_SendCmd(CMD55,0,0X77);//发送CMD41
}while(r1&&retry--);
}else
{
SD_Type=SD_TYPE_MMC;//MMC V3
retry=0X1000;
do //等待退出IDLE模式
{
r1=SD_SendCmd(CMD1,0,0X01);//发送CMD1
}while(r1&&retry--);
}
if(retry==-1||SD_SendCmd(CMD16,512,0X14)!=0)SD_Type=SD_TYPE_ERR;//错误的卡
}
r1=SD_SendCmd(CMD59,0,0x95);
}
SD_DisSelect();//取消片选
SD_SPI_SpeedHigh();//高速
if(SD_Type)return SD_RESPONSE_NO_ERROR;
else if(r1)return r1;
return 0xaa;//其他错误
}
u8 SD_Init(void)
{
u8 r1=SD_RESPONSE_NO_ERROR;
SD_Deinit();
SD_SPI_Init();
r1=SD_Initialize();
if(r1!=SD_RESPONSE_NO_ERROR)
return r1;
r1=SD_GetCID(CID_Tab);
if(r1!=SD_RESPONSE_NO_ERROR)
return r1;
r1=SD_GetCSD(CSD_Tab);
if(r1!=SD_RESPONSE_NO_ERROR)
return r1;
SD_GetCardInfo(&SDCardInfo);
return SD_RESPONSE_NO_ERROR;
}
//从sd卡读取一个数据包的内容
//buf:数据缓存区
//len:要读取的数据长度.
//返回值:0,成功;其他,失败;
u8 SD_RecvData(u8 buf[],u16 len)
{
if(SD_GetResponse(0xFE))return SD_RESPONSE_FAILURE;//等待SD卡发回数据起始令牌0xFE
while(len--)//开始接收数据
{
*buf=SPI5_ReadWriteByte(DUMMYBYTE);
buf++;
}
//下面是2个伪CRC(dummy CRC)
SD_SPI_ReadWriteByte(DUMMYBYTE);
SD_SPI_ReadWriteByte(DUMMYBYTE);
return 0;//读取成功
}
//向sd卡写入一个数据包的内容 512字节
//buf:数据缓存区
//cmd:指令
//返回值:0,成功;其他,失败;
u8 SD_SendBlock(u8*buf,u8 cmd)
{
u16 t;
if(SD_WaitReady())
return SD_RESPONSE_FAILURE;//等待准备失效
SD_SPI_ReadWriteByte(cmd);
if(cmd!=0XFD)//不是结束指令
{
for(t=0;t<512;t++)SPI5_ReadWriteByte(buf[t]);//提高速度,减少函数传参时间
SD_SPI_ReadWriteByte(DUMMYBYTE);//忽略crc
SD_SPI_ReadWriteByte(DUMMYBYTE);
t=SD_SPI_ReadWriteByte(DUMMYBYTE);//接收响应
if((t&0x1F)!=0x05)return 2;//响应错误
}
return 0;//写入成功
}
//获取SD卡的CID信息,包括制造商信息
//输入: u8 *cid_data(存放CID的内存,至少16Byte)
//返回值:0:NO_ERR
// 1:错误
u8 SD_GetCID(u32 *cid_data)
{
u8 r1,temp[16],i=0;
//发CMD10命令,读CID
r1=SD_SendCmd(CMD10,0,0x01);
if(r1==0||r1==SD_COM_CRC_ERROR)
{
r1=SD_RecvData(temp,16);//接收16个字节的数据
}
for(i=0;i<4;i++)//小端模式转化为大端
{
cid_data=(temp[4*i]<<24)+(temp[4*i+1]<<16)+(temp[4*i+2]<<8)+(temp[4*i+3]);
}
SD_DisSelect();//取消片选
if(r1)return r1;
else return 0;
}
//获取SD卡的CSD信息,包括容量和速度信息
//输入:u8 *cid_data(存放CID的内存,至少16Byte)
//返回值:0:NO_ERR
// 1:错误
u8 SD_GetCSD(u32 *csd_data)
{
u8 r1,temp[16],i=0;
r1=SD_SendCmd(CMD9,0,0xAF);//发CMD9命令,读CSD
if(r1==0||r1==SD_COM_CRC_ERROR)
{
r1=SD_RecvData(temp, 16);//接收16个字节的数据
}
for(i=0;i<4;i++)//小端模式转化为大端
{
csd_data=(temp[4*i]<<24)+(temp[4*i+1]<<16)+(temp[4*i+2]<<8)+(temp[4*i+3]);
}
SD_DisSelect();//取消片选
if(r1)return r1;
else return 0;
}
////获取SD卡的总扇区数(扇区数)
////返回值:0: 取容量出错
//// 其他:SD卡的容量(扇区数/512字节)
////每扇区的字节数必为512,因为如果不是512,则初始化不能通过.
//u32 SD_GetSectorCount(void)
//{
// u8 csd[16];
// u32 Capacity;
// u8 n;
// u16 csize;
// //取CSD信息,如果期间出错,返回0
// if(SD_GetCSD(csd)!=0) return 0;
// //如果为SDHC卡,按照下面方式计算
// if((csd[0]&0xC0)==0x40) //V2.00的卡
// {
// csize = csd[9] + ((u16)csd[8] << 8) + 1;
// Capacity = (u32)csize << 10;//得到扇区数
// }
// else//V1.XX的卡
// {
// n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
// csize = (csd[8] >> 6) + ((u16)csd[7] << 2) + ((u16)(csd[6] & 3) << 10) + 1;
// Capacity= (u32)csize << (n - 9);//得到扇区数
// }
// return Capacity;
//}
//得到卡信息
//cardinfo:卡信息存储区
//返回值:错误状态
SD_ERRSTATE SD_GetCardInfo(SD_CardInfo *cardinfo)//这个函数是按照
{
SD_ERRSTATE errorstatus=SD_RESPONSE_NO_ERROR;
u8 tmp=0;
cardinfo->CardType=(u8)SD_Type; //卡类型
cardinfo->RCA=(u16)0x01; //卡RCA值
tmp=(u8)((CSD_Tab[0]&0xFF000000)>>24);
cardinfo->SD_csd.CSDStruct=(tmp&0xC0)>>6; //CSD结构
cardinfo->SD_csd.SysSpecVersion=(tmp&0x3C)>>2; //2.0协议还没定义这部分(为保留),应该是后续协议定义的
cardinfo->SD_csd.Reserved1=tmp&0x03; //2个保留位
tmp=(u8)((CSD_Tab[0]&0x00FF0000)>>16); //第1个字节
cardinfo->SD_csd.TAAC=tmp; //数据读时间1
tmp=(u8)((CSD_Tab[0]&0x0000FF00)>>8); //第2个字节
cardinfo->SD_csd.NSAC=tmp; //数据读时间2
tmp=(u8)(CSD_Tab[0]&0x000000FF); //第3个字节
cardinfo->SD_csd.MaxBusClkFrec=tmp; //传输速度
tmp=(u8)((CSD_Tab[1]&0xFF000000)>>24); //第4个字节
cardinfo->SD_csd.CardComdClasses=tmp<<4; //卡指令类高四位
tmp=(u8)((CSD_Tab[1]&0x00FF0000)>>16); //第5个字节
cardinfo->SD_csd.CardComdClasses|=(tmp&0xF0)>>4;//卡指令类低四位
cardinfo->SD_csd.RdBlockLen=tmp&0x0F; //最大读取数据长度
tmp=(u8)((CSD_Tab[1]&0x0000FF00)>>8); //第6个字节
cardinfo->SD_csd.PartBlockRead=(tmp&0x80)>>7; //允许分块读
cardinfo->SD_csd.WrBlockMisalign=(tmp&0x40)>>6; //写块错位
cardinfo->SD_csd.RdBlockMisalign=(tmp&0x20)>>5; //读块错位
cardinfo->SD_csd.DSRImpl=(tmp&0x10)>>4;
cardinfo->SD_csd.Reserved2=0; //保留
if((cardinfo->CardType==SD_TYPE_V1)||(cardinfo->CardType==SD_TYPE_V2)||(cardinfo->CardType==SD_TYPE_MMC))//标准1.1/2.0卡/MMC卡
{
cardinfo->SD_csd.DeviceSize=(tmp&0x03)<<10; //C_SIZE(12位)
tmp=(u8)(CSD_Tab[1]&0x000000FF); //第7个字节
cardinfo->SD_csd.DeviceSize|=(tmp)<<2;
tmp=(u8)((CSD_Tab[2]&0xFF000000)>>24); //第8个字节
cardinfo->SD_csd.DeviceSize|=(tmp&0xC0)>>6;
cardinfo->SD_csd.MaxRdCurrentVDDMin=(tmp&0x38)>>3;
cardinfo->SD_csd.MaxRdCurrentVDDMax=(tmp&0x07);
tmp=(u8)((CSD_Tab[2]&0x00FF0000)>>16); //第9个字节
cardinfo->SD_csd.MaxWrCurrentVDDMin=(tmp&0xE0)>>5;
cardinfo->SD_csd.MaxWrCurrentVDDMax=(tmp&0x1C)>>2;
cardinfo->SD_csd.DeviceSizeMul=(tmp&0x03)<<1;//C_SIZE_MULT
tmp=(u8)((CSD_Tab[2]&0x0000FF00)>>8); //第10个字节
cardinfo->SD_csd.DeviceSizeMul|=(tmp&0x80)>>7;
cardinfo->CardCapacity=(cardinfo->SD_csd.DeviceSize+1);//计算卡容量
cardinfo->CardCapacity*=(1<<(cardinfo->SD_csd.DeviceSizeMul+2));
cardinfo->CardBlockSize=1<<(cardinfo->SD_csd.RdBlockLen);//块大小
cardinfo->CardCapacity*=cardinfo->CardBlockSize;
}
else if(cardinfo->CardType==SD_TYPE_V2HC) //高容量卡
{
tmp=(u8)(CSD_Tab[1]&0x000000FF); //第7个字节
cardinfo->SD_csd.DeviceSize=(tmp&0x3F)<<16;//C_SIZE
tmp=(u8)((CSD_Tab[2]&0xFF000000)>>24); //第8个字节
cardinfo->SD_csd.DeviceSize|=(tmp<<8);
tmp=(u8)((CSD_Tab[2]&0x00FF0000)>>16); //第9个字节
cardinfo->SD_csd.DeviceSize|=(tmp);
tmp=(u8)((CSD_Tab[2]&0x0000FF00)>>8); //第10个字节
cardinfo->CardCapacity=(long long)(cardinfo->SD_csd.DeviceSize+1)*512*1024;//计算卡容量
cardinfo->CardBlockSize=512; //块大小固定为512字节
}
cardinfo->SD_csd.EraseGrSize=(tmp&0x40)>>6;
cardinfo->SD_csd.EraseGrMul=(tmp&0x3F)<<1;
tmp=(u8)(CSD_Tab[2]&0x000000FF); //第11个字节
cardinfo->SD_csd.EraseGrMul|=(tmp&0x80)>>7;
cardinfo->SD_csd.WrProtectGrSize=(tmp&0x7F);
tmp=(u8)((CSD_Tab[3]&0xFF000000)>>24); //第12个字节
cardinfo->SD_csd.WrProtectGrEnable=(tmp&0x80)>>7;
cardinfo->SD_csd.ManDeflECC=(tmp&0x60)>>5;
cardinfo->SD_csd.WrSpeedFact=(tmp&0x1C)>>2;
cardinfo->SD_csd.MaxWrBlockLen=(tmp&0x03)<<2;
tmp=(u8)((CSD_Tab[3]&0x00FF0000)>>16); //第13个字节
cardinfo->SD_csd.MaxWrBlockLen|=(tmp&0xC0)>>6;
cardinfo->SD_csd.WriteBlockPaPartial=(tmp&0x20)>>5;
cardinfo->SD_csd.Reserved3=0;
cardinfo->SD_csd.ContentProtectAppli=(tmp&0x01);
tmp=(u8)((CSD_Tab[3]&0x0000FF00)>>8); //第14个字节
cardinfo->SD_csd.FileFormatGrouop=(tmp&0x80)>>7;
cardinfo->SD_csd.CopyFlag=(tmp&0x40)>>6;
cardinfo->SD_csd.PermWrProtect=(tmp&0x20)>>5;
cardinfo->SD_csd.TempWrProtect=(tmp&0x10)>>4;
cardinfo->SD_csd.FileFormat=(tmp&0x0C)>>2;
cardinfo->SD_csd.ECC=(tmp&0x03);
tmp=(u8)(CSD_Tab[3]&0x000000FF); //第15个字节
cardinfo->SD_csd.CSD_CRC=(tmp&0xFE)>>1;
cardinfo->SD_csd.Reserved4=1;
tmp=(u8)((CID_Tab[0]&0xFF000000)>>24); //第0个字节
cardinfo->SD_cid.ManufacturerID=tmp;
tmp=(u8)((CID_Tab[0]&0x00FF0000)>>16); //第1个字节
cardinfo->SD_cid.OEM_AppliID=tmp<<8;
tmp=(u8)((CID_Tab[0]&0x000000FF00)>>8); //第2个字节
cardinfo->SD_cid.OEM_AppliID|=tmp;
tmp=(u8)(CID_Tab[0]&0x000000FF); //第3个字节
cardinfo->SD_cid.ProdName1=tmp<<24;
tmp=(u8)((CID_Tab[1]&0xFF000000)>>24); //第4个字节
cardinfo->SD_cid.ProdName1|=tmp<<16;
tmp=(u8)((CID_Tab[1]&0x00FF0000)>>16); //第5个字节
cardinfo->SD_cid.ProdName1|=tmp<<8;
tmp=(u8)((CID_Tab[1]&0x0000FF00)>>8); //第6个字节
cardinfo->SD_cid.ProdName1|=tmp;
tmp=(u8)(CID_Tab[1]&0x000000FF); //第7个字节
cardinfo->SD_cid.ProdName2=tmp;
tmp=(u8)((CID_Tab[2]&0xFF000000)>>24); //第8个字节
cardinfo->SD_cid.ProdRev=tmp;
tmp=(u8)((CID_Tab[2]&0x00FF0000)>>16); //第9个字节
cardinfo->SD_cid.ProdSN=tmp<<24;
tmp=(u8)((CID_Tab[2]&0x0000FF00)>>8); //第10个字节
cardinfo->SD_cid.ProdSN|=tmp<<16;
tmp=(u8)(CID_Tab[2]&0x000000FF); //第11个字节
cardinfo->SD_cid.ProdSN|=tmp<<8;
tmp=(u8)((CID_Tab[3]&0xFF000000)>>24); //第12个字节
cardinfo->SD_cid.ProdSN|=tmp;
tmp=(u8)((CID_Tab[3]&0x00FF0000)>>16); //第13个字节
cardinfo->SD_cid.Reserved1|=(tmp&0xF0)>>4;
cardinfo->SD_cid.ManufactDate=(tmp&0x0F)<<8;
tmp=(u8)((CID_Tab[3]&0x0000FF00)>>8); //第14个字节
cardinfo->SD_cid.ManufactDate|=tmp;
tmp=(u8)(CID_Tab[3]&0x000000FF); //第15个字节
cardinfo->SD_cid.CID_CRC=(tmp&0xFE)>>1;
cardinfo->SD_cid.Reserved2=1;
return errorstatus;
}
//读SD卡
//buf:数据缓存区
//sector:扇区
//cnt:扇区数
//返回值:0,ok;其他,失败.
//SPI无DMA下 多块读:约1047K/S 单块读:约623K/S
u8 SD_ReadDisk(u8*buf,u32 sector,u32 cnt)
{
u8 r1;
if((sector+cnt)>(SDCardInfo.SD_csd.DeviceSize+1)*1024) return SD_PARAMETER_ERROR;//超出最大扇区数
if(SD_Type!=SD_TYPE_V2HC)sector <<= 9;//转换为字节地址(每扇区512B)
if(cnt==1)
{
r1=SD_SendCmd(CMD17,sector,0X01);//读命令
if(r1==0||r1==SD_COM_CRC_ERROR)//指令发送成功【由于未进行CRC计算,故R1可能为SD_COM_CRC_ERROR】
{
r1=SD_RecvData(buf,512);//接收512个字节
}
}
else
{
r1=SD_SendCmd(CMD18,sector,0X01);//连续读命令
do
{
r1=SD_RecvData(buf,512);//接收512个字节
buf+=512;
}while(--cnt && (r1==0||r1==SD_COM_CRC_ERROR));
SD_SendCmd(CMD12,0,0X60); //发送停止命令
}
SD_DisSelect();//取消片选
return r1;//
}
//写SD卡
//buf:数据缓存区
//sector:起始扇区
//cnt:扇区数
//返回值:0,ok;其他,失败.
u8 SD_WriteDisk(u8*buf,u32 sector,u32 cnt)
{
u8 r1;
if(buf==NULL) return SD_PARAMETER_ERROR;//空指针
if((sector+cnt)>(SDCardInfo.SD_csd.DeviceSize+1)*1024) return SD_PARAMETER_ERROR;//超出最大扇区数
if(SD_Type!=SD_TYPE_V2HC)sector <<= 9;//转换为字节地址
if(cnt==1)
{
r1=SD_SendCmd(CMD24,sector,0X01);//写命令
if(r1==0||r1==SD_COM_CRC_ERROR)//指令发送成功【由于未进行CRC计算,故R1可能为SD_COM_CRC_ERROR】
{
r1=SD_SendBlock(buf,0xFE);//写512个字节
}
}else
{
if(SD_Type!=SD_TYPE_MMC)
{
SD_SendCmd(CMD55,0,0X64);
SD_SendCmd(CMD23,cnt,0X01);//发送指令
}
r1=SD_SendCmd(CMD25,sector,0X01);//连续写命令
if(r1==0||r1==SD_COM_CRC_ERROR)
{
do
{
r1=SD_SendBlock(buf,0xFC);//接收512个字节
buf+=512;
}while(--cnt && (r1==0||r1==SD_COM_CRC_ERROR));
r1=SD_SendBlock(0,0xFD);//接收512个字节
}
}
SD_DisSelect();//取消片选
return r1;//
}
//擦除指定区间的块
//写之前预先擦除会加快写SD卡速度
u8 SD_EraseDisk(u32 startsector,u32 endsector)
{
u8 r1;
if(SD_Type!=SD_TYPE_V2HC)
{
startsector <<= 9;//转换为字节地址(每扇区512B)
endsector <<=9;
}
r1=SD_SendCmd(CMD32,startsector,0x01);
if(r1!=0&&r1!=SD_COM_CRC_ERROR)
return r1;
r1=SD_SendCmd(CMD33,endsector,0x01);
if(r1!=0&&r1!=SD_COM_CRC_ERROR)
return r1;
r1=SD_SendCmd(CMD33,endsector,0x01);
if(r1!=0&&r1!=SD_COM_CRC_ERROR)
return r1;
return r1;
}
[/mw_shl_code]
一周热门 更多>