-
- // set low speed
- SPI0CR1 = 0x5e; //CPOL=1,CPHA=1
- SPI0CR2 = 0x10;
- SPI0BR = 0x07; // 80M / 256 = 312.5k
-
- // > 74 clock cycle init
- for (i = 0; i < 10; i++)
- spi_write(0xff);
复制代码
3.发送cmd0,cmd55,acmd41,让卡初始化。这俺也不懂,网上搬过来的。
-
- retry = 0;
- do
- {
- //发送CMD0,让SD卡进入IDLE状态
- r1 = sd_send_cmd(0, 0, 0x95);
- retry++;
- } while ((r1 != 0x01) && (retry < 200));
-
- //发卡初始化指令CMD55+ACMD41
- do
- {
- r1 = sd_send_cmd(55, 0, 0);
- if (r1 != 0x01) {
- uart_printf("cmd55 failed %x\n\r", r1);
- return;
- }
- r1 = sd_send_cmd(41, 0x40000000, 0);
- if (retry > 200) {
- uart_printf("cmd41 failed %x\n\r", r1);
- return; //超时则返回r1状态
- }
- } while (r1 != 0);
复制代码4.现在就要把spi时钟调到最快了。初始化的时候spi时钟是很慢的,但是传输的时候,当然越快越好。这里spi的频率已经是最快了,40M。手册上说最多25m的,但是这里调40m也没事,不知道是nokia的sd卡质量好还是咋的。
-
- // set high speed
- SPI0BR = 0x00; // 80M / 2 = 40M
复制代码
作者: cfanfrank 时间: 2009-5-20 20:24
本帖最后由 cfanfrank 于 2009-5-20 20:30 编辑
5.读数据。Cmd17是读单块命令,一次读512字节(默认是512,如果你调了块大小,这里就可能不止512了)。
sd_send_cmd(17, 0x00, 0)就是说,命令sd卡读从地址0x00开始的512字节,第二个参数是地址,需要512字节对齐(如果你的是sdhc卡,传进去的是块的编号,编号1代表地址512,编号4代表地址2048。。。)。
接下来的sd_recv_data(buf, 512);就是说,接受字节流,把它们放到buf里。
还有一个命令是多块一起读的,有需要的话,查下手册自己写吧。
一块被格式化好的sd卡,上面一般是fat文件系统,所以buf[510],buf[511]里的值是0x55, 0xaa。这个是拿来测试的。
-
- byte sd_recv_data(byte *data, word len)
- {
- static word retry;
- static byte r1;
-
- // 启动一次传输
- SD_CS = 0;
- //等待SD卡发回数据起始令牌xFE
- retry = 0;
- do
- {
- spi_read(r1);
- retry++;
- if(retry>2000) //2000次等待后没有应答,退出报错
- {
- SD_CS = 1;
- return 1;
- }
- } while (r1 != 0xFE);
-
- //开始接收数据
- while (len--) {
- spi_read(*data);
- data++;
- }
- //下面是个伪CRC(dummy CRC)
- spi_read(r1);
- spi_read(r1);
-
- //传输结束
- SD_CS = 1;
- spi_write(0xFF);
-
- return 0;
- }
-
- // 测试读
- r1 = sd_send_cmd(17, 0x00, 0);//读命令
- if (r1 != 0x00) {
- uart_printf("cmd17 failed %x\n\r", r1);
- return;
- }
- r1 = sd_recv_data(buf, 512);
- if(r1 != 0) {
- uart_printf("recv data failed %x\n\r", r1);
- return;
- }
- uart_printf("%x %x\n\r", buf[510], buf[511]);
复制代码
作者: cfanfrank 时间: 2009-5-20 20:24
本帖最后由 cfanfrank 于 2009-5-20 20:31 编辑
6.写数据
写数据用的是批量写,也一定要用这个,不然你写完512字节又要发命令,很慢。那把块大小调大点行不行呢?我试过,我的sd卡是不行的,最大512,手册里也没说明最大多少。你可以自己试试,如果能调大,最好调大。
-
- //发多块写入指令
- r1 = sd_send_cmd(25, 0x00, 0x00);
- if (r1 != 0x00) {
- uart_printf("cmd25 failed %x\n\r", r1);
- return; //应答不正确,直接返回
- }
-
- //开始准备数据传输
- SD_CS = 0;
-
- //先放个空数据,等待SD卡准备好
- spi_write(0xff);
- spi_write(0xff);
复制代码
发送完命令以后,就可以写了。下面的代码是每次写512字节,你可以放到你的主循环里。
-
- spi_write(0xFC);
-
- //放一个sector的数据
- i = 512;
- while (i--)
- spi_write(*ptr++);
-
- //发个Byte的dummy CRC
- spi_write(0xff);
- spi_write(0xff);
-
- spi_read(r1);
- if ((r1 & 0x0F) != 0x05) {
- // 如果数据出错,死机..
- PORTB = 0xff;
- while (1);
- }
复制代码
作者: cfanfrank 时间: 2009-5-20 20:24
本帖最后由 cfanfrank 于 2009-5-20 20:50 编辑
经测试,40m的spi频率下,连续spi_write六次,大概是256个总线时钟,还是能接受的。
在执行算法的同时,写6*512B的数据,周期是40ms,摄像头周期是20ms。
光执行算法,周期是20ms,跟摄像头一样。
所以这跟上海大学那份技术报告里说得一样,如果加上sd调试,就只能是40ms周期了。
这也有些不爽。我也想过用一块arm同时读取摄像头数据,存在ram里,但是那样成本高,又麻烦。
北京科技大学的技术报告提到用无线影音模块的方法,可行是可行,不过估计数据处理又够麻烦,毕竟是模拟传输。如果用spi接口无线模块,估计速度也上不去。
如果有谁有好的方法,不用另外一块mcu,能在20ms内完成6*512B数据的读写,希望兄弟都能贴出来共享下!
补充几点:
sd卡的里的数据怎么组织,可以比较随便,可以没有文件系统,可以省很多事的。
VC里,CreateFile可以直接打开盘符。路径名为“\\.\X”,“X”就是你想要的盘符了。mfc里的CFile也行。
- CFile fp;
- if (!fp.Open("\\\\.\\H:", CFile::modeRead))
- return;
复制代码
s12跟x86平台存在“大端小端”的问题,8bit以上的字段,要转换。给个宏:
- #define be16_to_cpu(x) ((x) = (((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8))
复制代码
作者: 星空下的学生 时间: 2009-5-21 09:21
不错,虽然现在没有时间做。不过还是要谢谢楼主这么大方哦
作者: HCS12 时间: 2009-5-21 18:14
谢谢楼主奉献啊
作者: pengzhen_lin 时间: 2009-5-24 19:15
谢谢楼主奉献啊
作者: zdhly0401 时间: 2009-5-24 23:33
谢谢楼主奉献啊
作者: yjchen 时间: 2009-6-29 13:34
多谢LZ啊~~~~~~
作者: miaozaoyang 时间: 2009-6-29 20:16
不知道,楼主有没有 一些宏定义的 资料啊?
可否发一份能用的程序,谢谢!
作者: miaozaoyang 时间: 2009-8-5 17:27
谢谢楼主,很缺乏这东西。
作者: zhangq062336 时间: 2009-8-6 22:11
可谓是踏破铁靴无觅处,还是楼主比较大方,比上海大学有气度多了,谢了!!!!
作者: liuyiran 时间: 2009-8-7 22:52
首先电气连接上必须严格按照SD手册上说的去做,该3.3的3.3,该上拉的上拉,还必须解决信号完整性问题,SD卡选用高速卡,读写程序用汇编,并且可以忽略校验机制,我们车子5KB的图像数据是在4ms内存完的。还有就是程序中必须把SD卡存储的优先级设置最低,即使存储跳帧也不会影响正常程序的运行。
建议没有一定时间和精力的队伍不要盲目去开发,因为SD卡的作用并没有想象的那么大,看上去眩点罢了,还会导致很多额外的问题。要做这套系统,把硬件,单片机存储软件,FAT协议,上位机全部搞定,每项都是庞大工程,得花多长时间?值得么。。。
作者: October 时间: 2009-8-19 22:17
谢谢LZ~
作者: vallis 时间: 2009-8-24 21:15
楼主你好:我再使用你的程序,遇到如下问题:
我在做SD卡的时候,能够正确的初始化,和读取里面的数据,但是不能写数据,在执行写函数以后,再也不能初始化和读取数据了,只有把sd卡的引脚全部断开(包括电源)才能重新初始化和读取,但是还是不能写数据。我的写函数如下:
unsigned char SD_WriteData(byte *Write_Buff,dword length)
{
static byte r1;
dword i;
r1=SD_SendCMD(25,0x00,0x00); //发多块写入指令
if(r1!=0x00)
{
putstr("CMD25 faild\r\n");
return 0;
}
SD_CS=0;
//等待SD卡准备好
SPI_WriteByte(0xff);
SPI_WriteByte(0xff);
SPI_WriteByte(0xfc);
for(i=0;i<512;i++)
{
SPI_WriteByte(*Write_Buff);
Write_Buff++;
}
SPI_WriteByte(0xff);
SPI_WriteByte(0xff);
r1=SPI_ReadByte();
if((r1&0x0f)!=0x05)
{
putstr("write data error\r\n");
return 0 ; //数据如果数据出错,死机。。。。。。
}
SD_CS=1;
putstr("write data seccussful\r\n");
return 1;
}
作者: vallis 时间: 2009-8-26 17:13
楼主有个地方是错的吧~~~害的我好惨哦
应该是spi_write(0xfe) ////////////
# spi_write(0xFC);
#
# //放一个sector的数据
# i = 512;
# while (i--)
# spi_write(*ptr++);
#
# //发个Byte的dummy CRC
# spi_write(0xff);
# spi_write(0xff);
#
# spi_read(r1);
# if ((r1 & 0x0F) != 0x05) {
# // 如果数据出错,死机..
# PORTB = 0xff;
# while (1);
# }
作者: 新兴MCU 时间: 2009-9-13 20:48
好东西~~~~~~~~~~~谢谢~~正想学的东西~~~
作者: chiusir 时间: 2009-9-19 09:28
这代码风格很熟悉
作者: 786892880 时间: 2009-9-19 22:01
强大。。。
作者: zxzxy1988 时间: 2009-10-10 11:06
顶楼主,呵呵!
作者: chihua 时间: 2009-12-7 21:53
感谢楼主
作者: xab1987 时间: 2009-12-10 17:40
提示: 作者被禁止或删除 内容自动屏蔽
作者: DEMOK 时间: 2010-1-24 00:01
楼主分析得很详细啊 学习了 最近正在鼓捣SD卡
作者: louis 时间: 2010-1-24 12:39
不错哦 !!!!
作者: 807569039 时间: 2010-1-24 13:02
谢谢楼主奉献啊
作者: qicai 时间: 2010-2-7 18:33
多谢了 安逸可以对SD卡研究咯
作者: chengyongji 时间: 2010-2-26 18:15
感谢楼主的资料!
作者: abfgrab 时间: 2010-2-28 16:19
好
作者: abfgrab 时间: 2010-2-28 16:19
但是我不懂
作者: abfgrab 时间: 2010-2-28 16:19
这个论坛
作者: abfgrab 时间: 2010-2-28 16:20
什么都限制
作者: abfgrab 时间: 2010-2-28 16:20
搞定
作者: abfgrab 时间: 2010-2-28 16:20
简直是
作者: yourchen 时间: 2010-3-2 20:55
回复 1# cfanfrank
楼主有没有写FAT的程序呢?直接这样写SD,电脑无法识别的吧?还有对单片机有什么作用呢?
作者: lxh7792 时间: 2010-3-20 20:40
谢谢哈
作者: 时代还怪 时间: 2010-3-25 10:52
楼主,谢啦,我想做呢!
作者: lansedeyueliang 时间: 2010-3-26 09:16
谢谢楼主奉献啊
作者: zhuzhu0 时间: 2010-3-28 18:12
谢谢楼主奉献
作者: xixiangfeng0733 时间: 2010-4-4 15:20
谢谢你了!!
作者: 霜~哀伤 时间: 2010-4-4 17:00
还没到用SD的阶段,谢谢分享。
作者: pknew 时间: 2010-4-15 16:54
谢谢
作者: pknew 时间: 2010-4-15 16:54
谢谢
作者: huachou 时间: 2010-5-1 20:56
感谢楼主
作者: zyhqq 时间: 2010-5-30 16:52
谢谢楼主!
作者: 1160927 时间: 2010-6-13 19:15
对楼主表示无比的膜拜,
作者: qbh319 时间: 2010-7-4 17:26
很嫉妒你的40M~~
作者: yoyokeen 时间: 2010-8-13 22:56
多谢,多谢。
作者: wwei 时间: 2010-8-29 20:14
本帖最后由 wwei 于 2010-8-29 20:16 编辑
谢谢楼主分享,提个问题,为什么读卡器只要4个接口???菜鸟指教
作者: pika 时间: 2010-8-30 18:39
谢谢楼主奉献
很详细
作者: 梦的点滴 时间: 2010-10-10 20:52
好东西啊,谢谢楼主分享
作者: jiang1101 时间: 2010-11-2 15:24
顶!有时间一定要做做看!
作者: yijingjing 时间: 2010-11-5 20:06
xieixie,正研究呢,谢谢!!!!!!!!!!!!!!!!!!!!!
作者: sy373466062 时间: 2010-11-22 09:26
非常感谢
作者: wp1989 时间: 2010-12-4 14:55
谢谢
作者: JINLIANG 时间: 2010-12-8 19:52
xiexie
作者: GuySunYang 时间: 2010-12-13 10:38
很好的东西哦啊
作者: zhang54188 时间: 2011-1-3 04:58
作者: zhang54188 时间: 2011-1-3 04:58
作者: kakasky 时间: 2011-3-13 18:19
感谢楼主的分享!
作者: mengyaowuxiang 时间: 2011-4-2 16:39
好人啊
作者: wenziheni 时间: 2011-10-21 23:51
谢谢楼主奉献啊
作者: 清明 时间: 2011-11-12 20:58
kankan
作者: longhunlanxue 时间: 2011-11-20 15:53
作者: lihang29 时间: 2011-11-23 12:10
谢谢分享
作者: beandy 时间: 2011-12-4 20:47
楼主参考龙丘的吧?
作者: 逍遥锐锋 时间: 2012-1-2 13:52
厉害
作者: DOUBLE-L- 时间: 2012-5-5 10:21
正好需要,谢谢楼主了。
作者: DOUBLE-L- 时间: 2012-5-7 13:02
请问楼主,我们的pwm口都用作电机控制了,是买的s12上面自带的,没有多余的pwm可以控制怎么办?
作者: 我是谁2011 时间: 2012-9-3 21:56
楼主好人
作者: Move123456 时间: 2012-9-27 21:13
感谢楼主分享
作者: 二硫碘化钾 时间: 2013-4-2 17:57
谢谢 LZ
作者: 二硫碘化钾 时间: 2013-4-20 22:17
谢谢LZ
作者: 葱葱哥 时间: 2014-4-20 16:41
有没有电路啊
作者: ⊙Lin⊙ 时间: 2014-4-24 11:01
楼主能整理一下吗?
作者: 李祖勇 时间: 2014-10-28 16:57
作者: @@@#@! 时间: 2014-10-29 07:12
zan
作者: 车神帅杰 时间: 2014-11-3 18:46
就是自己还不懂 特郁闷
欢迎光临 智能车制作 (http://111.231.132.190/) |
Powered by Discuz! X3.2 |