OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5771|回复: 16

真是要抓狂了,一个SD卡的SPI让我痛不欲生

[复制链接]

4

主题

34

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
220
金钱
220
注册时间
2013-6-28
在线时间
0 小时
发表于 2013-11-16 22:38:08 | 显示全部楼层 |阅读模式

                 这几天一直在想用软件模拟SD卡的SPI通信,但是一直不成功,研究了SPI时序好几天,找不出是哪里的问题,但是模拟SPI Flash的又完全没问题,有没有谁有写好的SD卡 SPI 驱动,发我一份,参考一下,感激不尽,以下是我的SPI时序代码


 

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165516
金钱
165516
注册时间
2010-12-1
在线时间
2116 小时
发表于 2013-11-16 23:18:39 | 显示全部楼层
模拟的??
有点蛋疼啊。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2013-11-17 11:03:53 | 显示全部楼层
我的是这样写的,你参考下,打算用他来驱动下SD卡,呵呵






现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复 支持 反对

使用道具 举报

5

主题

154

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
205
金钱
205
注册时间
2013-6-8
在线时间
2 小时
发表于 2013-11-17 15:04:58 | 显示全部楼层
我用的一直模拟的啊,可以用啊
#ifdef SD_USE_HARDWARE_SPI
#define SD_SPI_RWByte(dat) SPI2_RWByte(dat)
#else
//io口模拟SPI时序读写一个字节
u8 SD_SPI_RWByte(u8 dat)
{
u8 rcv=0, i=0;
for(i=0; i<8; i++)
{
if(dat&0x80)
SD_DI_H;
else
SD_DI_L;
SD_CK_L;//前沿数据输出
__delay(__speed);
SD_CK_H;//后沿数据输入
rcv<<=1;
if(SD_DO_is1)
rcv|=0x01;
dat<<=1;
}
return rcv;
}
#endif
即使爬到最高的山上,一次也只能脚踏实地地迈一步。
回复 支持 反对

使用道具 举报

0

主题

12

帖子

0

精华

新手上路

积分
32
金钱
32
注册时间
2013-11-7
在线时间
0 小时
发表于 2013-11-18 10:40:07 | 显示全部楼层
回复【3楼】Badu_Space:
---------------------------------
我觉得楼主这个SPI用来初始化SD卡,可能是速度太快了。
初始化SD卡的时候SPI要使用低速模式。下面是我自己使用的51模拟SPI,可以使用你可以参考一下
回复 支持 反对

使用道具 举报

0

主题

12

帖子

0

精华

新手上路

积分
32
金钱
32
注册时间
2013-11-7
在线时间
0 小时
发表于 2013-11-18 10:43:34 | 显示全部楼层
/*******************************************************************************
* 函 数 名 : SD_SPI_Start
* 函数功能 : 初始化SPI的IO
* 输    入 : 无
* 输    出 : 无
*******************************************************************************/

void SD_SPI_Start(void)
{
TOUCH_CS = 1;        //因为触摸和SD共用SPI接口,所以先将触摸的关闭掉
SD_SPI_CLK = 1;
SD_SPI_MI = 1;
SD_SPI_MO = 1;
}
/*******************************************************************************
* 函 数 名 : SD_SPI_WriteData
* 函数功能 : 使用SPI写入一个数据
* 输    入 : dat:要输入的数据
* 输    出 : 无
*******************************************************************************/

void SD_SPI_WriteData(uchar dat)
{
uchar i;

for(i=0; i<8; i++)   //发送8位数
{
SD_SPI_MO = dat >> 7;  //先发送最高位
dat <<= 1;   //发送完最高位,将最高位移走

SD_SPI_CLK = 0;   //写入时序
if(SPI_LOWMODE)
{
SD_Delay();
SD_Delay();
}
SD_SPI_CLK = 1;
if(SPI_LOWMODE)
{
SD_Delay();
SD_Delay();
}
}
SD_SPI_MO = 1;
}

/*******************************************************************************
* 函 数 名 : SD_SPI_ReadData
* 函数功能 : 使用SPI读取一个数据
* 输    入 : 无
* 输    出 : readValue:读取到的数据
*******************************************************************************/

uchar SD_SPI_ReadData(void)
{
uchar i, readValue = 0;

SD_SPI_MI = 1;
for(i=0; i<8; i++)   //接收8位数据
{
SD_SPI_CLK = 0;
if(SPI_LOWMODE)
{
SD_Delay();
}
SD_SPI_CLK = 1;
if(SPI_LOWMODE)
{
SD_Delay();
}

readValue <<=1;   //将最低位移走
readValue |= SD_SPI_MI;//将读取到的数值放置到最低位
}
return readValue;     
}

回复 支持 反对

使用道具 举报

0

主题

12

帖子

0

精华

新手上路

积分
32
金钱
32
注册时间
2013-11-7
在线时间
0 小时
发表于 2013-11-18 10:44:30 | 显示全部楼层

/*******************************************************************************
* 函 数 名 : SD_WriteCmd
* 函数功能 : 向SD卡写入一个命令
* 输    入 : cmd:命令;
*          * dat: 命令参数
*          * crc: CRC效验
* 输    出 : r1:SD卡返回的数据
*          * 0xFF:表示发送失败
* 备    注 :SD卡一个命令格式包括8位命令,32位命令参数和7位CRC效验位,最后一位为1
*******************************************************************************/

uchar SD_WriteCmd(uchar cmd, ulong dat, uchar crc)
{
uint i, r1 = 0;

//--复位SD卡--//
SD_CS = 1;
SD_SPI_Start();
SD_SPI_WriteData(0xFF); //额外提供8个时钟
SD_CS = 0;
while(SD_SPI_ReadData() != 0xFF) //等待卡是否准备好
{
i++;
if(i > 200)
{
return 0xFF;                 //等待失败返回
}
}

//--发送数据--//
SD_SPI_WriteData(cmd | 0x40);

SD_SPI_WriteData(dat >> 24);     //发送Dat的最高8位
SD_SPI_WriteData(dat >> 16);
SD_SPI_WriteData(dat >> 8);
SD_SPI_WriteData(dat & 0x00FF);

SD_SPI_WriteData(crc);

if(cmd == SD_CMD12) //如果是停止数据传输命令,额外多发一个时钟
{
SD_SPI_WriteData(0xFF);
}

i = 0;
do
{
r1 = SD_SPI_ReadData();
i++;
if(i > 200)
{
return 0xFF;
}
}
while((r1 & 0x80) != 0);   //发送成功的最高位是0 

return r1;
}

/*******************************************************************************
* 函 数 名 : SD_Init
* 函数功能 : 初始化SD卡
* 输    入 : 无
* 输    出 : 0:初始化失败
*   * 1:初始化成功
*******************************************************************************/

uchar SD_Init(void)
{
uchar i, r1;
uchar buf[4];

//--IO口初始化--//
SD_CS = 1;
TOUCH_CS = 1;        //因为触摸和SD共用SPI接口,所以先将触摸的关闭掉
SPI_LOWMODE = 1; //使用低速模式
SD_SPI_Start();
//--将SD卡通信模式转换为SPI模式,上电默认是用DAT0作数据线--//
//--接到CMD0时,CS信号有效,SPI模式启动--//
for(i=0; i<0x0F; i++)//初始时,先发送至少74个时钟,这个是必须的。
{
SD_SPI_WriteData(0xFF); //发送120个
}
//当读取到0x01的时候表示初始化成功
i = 0;
while(SD_WriteCmd(SD_CMD0, 0, 0x95) != 0x01)
{
i++;
if(i > 500)
{
return 0;        //初始化失败返回0
}
}
//--发送CMD8,检测是否SD V2.0--//
i = 0;
do
{
i++;
if(i > 500) //若是发送超过次数跳出循环管
{
break;
}
r1 = SD_WriteCmd(SD_CMD8, 0x01AA, 0x87);
}
while(r1 != 0x01); //发送CMD8
if(r1 == 0x01)     //如果CMD8有回应说明是SD V2.0协议
{
//--读取CMD8的返回值,检测是否支持电压--//
//--读取CMD8的返回值,检测是否支持电压--//
for(i=0; i<4; i++)
{
buf = SD_SPI_ReadData();
}
//--卡电压不支持电压,返回错误--//
if((buf[2] != 0x01) || (buf[3] != 0xAA))
{
return 0;
}
//--初始化SD卡--//
i = 0;
do
{
i++;
if(i > 100)
{
return 0;   //返回失败
}

SD_WriteCmd(SD_CMD55, 0, 0x01);
r1 = SD_WriteCmd(SD_CMD41, 0x40000000, 0x01);
}
while(r1 != 0);

//--检测是SDHC卡还是SD卡--//
i = 0;
while(SD_WriteCmd(SD_CMD58, 0, 0x01) != 0)
{
i++;
if(i > 100)
{
SD_TYPE = SD_TYPE_ERR;
break;
}
}

//--读取OCR--//
for(i=0; i<4; i++)
{
buf = SD_SPI_ReadData();
}

if(buf[0] & 0x40) 
{
SD_TYPE = SD_TYPE_V2HC;
}
else
{
SD_TYPE = SD_TYPE_V2;
}
}
else //否则就是SD V1.0或者MMC V3
{
SD_WriteCmd(SD_CMD55, 0x00, 0x01);
r1 = SD_WriteCmd(SD_CMD41, 0x00, 0x01);

if(r1 <= 1)   //对CMD41有回应说明是SD V1.0
{
SD_TYPE = SD_TYPE_V1; //是V1.0卡
i = 0;
do
{
if(i > 100)
{
return 0;
}

SD_WriteCmd(SD_CMD55, 0x00, 0x01);
r1 = SD_WriteCmd(SD_CMD41, 0x00, 0x01);
}
while(r1 != 0);
}

else  //没有回应说明是MMC V3
{
SD_TYPE = SD_TYPE_MMC; //卡类型是MMC卡
i = 0;
while(SD_WriteCmd(SD_CMD1, 0, 0x01) != 0)
{
i++;
if(i > 100)
{
return 0;
}
}
}
}

SD_CS = 1;   //取消片选
SD_SPI_WriteData(0xFF); 
SPI_LOWMODE = 0;   //使用高速模式

return 1;
}

回复 支持 反对

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2013-11-18 11:00:27 | 显示全部楼层
回复【5楼】思良月:
---------------------------------
只是一种思路,具体传输频率还是要调的
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复 支持 反对

使用道具 举报

4

主题

34

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
220
金钱
220
注册时间
2013-6-28
在线时间
0 小时
 楼主| 发表于 2013-11-19 21:06:07 | 显示全部楼层
回复【7楼】思良月:
---------------------------------
非常感谢
回复 支持 反对

使用道具 举报

4

主题

34

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
220
金钱
220
注册时间
2013-6-28
在线时间
0 小时
 楼主| 发表于 2013-11-19 21:07:46 | 显示全部楼层
回复【3楼】Badu_Space:
---------------------------------
恩恩 谢谢分享!
回复 支持 反对

使用道具 举报

4

主题

117

帖子

0

精华

初级会员

Rank: 2

积分
153
金钱
153
注册时间
2013-8-20
在线时间
0 小时
发表于 2013-11-19 21:35:08 | 显示全部楼层
SD卡的SPI建议还是不要模拟,如果对速度稍稍有要求的话(比如突发最高速度要大于100KB/S的情况)
回复 支持 反对

使用道具 举报

4

主题

34

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
220
金钱
220
注册时间
2013-6-28
在线时间
0 小时
 楼主| 发表于 2013-11-19 21:37:06 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
真是蛋碎,不知道是哪里的问题,打算换SD卡模式通信好了...
回复 支持 反对

使用道具 举报

4

主题

34

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
220
金钱
220
注册时间
2013-6-28
在线时间
0 小时
 楼主| 发表于 2013-11-19 21:38:04 | 显示全部楼层
回复【11楼】lanny_cn:
---------------------------------
恩 我也不想用模拟 但是开发板没有把引脚接到SPI上
回复 支持 反对

使用道具 举报

4

主题

117

帖子

0

精华

初级会员

Rank: 2

积分
153
金钱
153
注册时间
2013-8-20
在线时间
0 小时
发表于 2013-11-19 23:00:52 | 显示全部楼层
走飞线啊,再说很多不是共用SPI的嘛,用不同CS控制

模拟之类的,除了低速的外,对性能有要求的,一般不合适的。理论研究可以,拿到产品中用要慎重,不能纯技术而技术,要考虑到方方面面

再说你有这么多精力,可以改善改善原子的SD卡读写性能的,这种现实中更实用,理论上用SP1可以达到4MB/S的最高速度,SD卡应该能达到2MB/S吧
回复 支持 反对

使用道具 举报

4

主题

117

帖子

0

精华

初级会员

Rank: 2

积分
153
金钱
153
注册时间
2013-8-20
在线时间
0 小时
发表于 2013-11-19 23:01:27 | 显示全部楼层
另外,搞硬件来说,焊接也是很重要的基本功
回复 支持 反对

使用道具 举报

3

主题

222

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
355
金钱
355
注册时间
2012-8-13
在线时间
32 小时
发表于 2013-11-20 09:06:02 | 显示全部楼层
模拟SPI不如模拟SDBUS这样4位比一位要快不少吧
个人小店,弄了些大人玩具,希望各位老小玩童们喜欢。 http://autocute.taobao.com/
回复 支持 反对

使用道具 举报

4

主题

34

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
220
金钱
220
注册时间
2013-6-28
在线时间
0 小时
 楼主| 发表于 2013-11-27 11:33:23 | 显示全部楼层
回复【16楼】lura2:
---------------------------------
确实是这样,过段时间用SDBUS试试看
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-21 12:50

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表