大家看看德国鬼子对SD卡操作(全套上传含文件系统)
本帖最后由 jazsmile 于 2012-8-16 20:32 编辑这个是全套程序。看懂了的,说说 扇区的读写是怎么回事??
怎么调用它的函数。
=================、
老德全套程序下载地址
=======================
自己写的sdhc操作总存在问题,就找他人的来调试。
但看到其他人的总觉得有点不对,请大家看看。
#if SD_RAW_SDHC
if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? block_address / 512 : block_address)))
如上面红色部分,按理sdhc卡 在操作时就是扇区地址不需要左移9位,可是老德不对。请分析。/**
* \ingroup sd_raw
* Reads raw data from the card.
*
* \param offset The offset from which to read.
* \param buffer The buffer into which to write the data.
* \param length The number of bytes to read.
* \returns 0 on failure, 1 on success.
* \see sd_raw_read_interval, sd_raw_write, sd_raw_write_interval
*/
uint8_t sd_raw_read(offset_t offset, uint8_t* buffer, uintptr_t length)
{
offset_t block_address;
uint16_t block_offset;
uint16_t read_length;
while(length > 0)
{
/* determine byte count to read at once */
block_offset = offset & 0x01ff; //512内的偏移量
block_address = offset - block_offset; //这个不懂
read_length = 512 - block_offset; /* read up to block border */
if(read_length > length)
read_length = length;
#if !SD_RAW_SAVE_RAM
/* check if the requested data is cached */
if(block_address != raw_block_address)
#endif
{
#if SD_RAW_WRITE_BUFFERING
if(!sd_raw_sync())
return 0;
#endif
/* address card */
select_card();
/* send single block request */
#if SD_RAW_SDHC
if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? block_address / 512 : block_address)))
#else
if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, block_address))
#endif
{
unselect_card();
return 0;
}
/* wait for data block (start byte 0xfe) */
while(sd_raw_rec_byte() != 0xfe);
#if SD_RAW_SAVE_RAM
/* read byte block */
uint16_t read_to = block_offset + read_length;
for(uint16_t i = 0; i < 512; ++i)
{
uint8_t b = sd_raw_rec_byte();
if(i >= block_offset && i < read_to)
*buffer++ = b;
}
#else
/* read byte block */
uint8_t* cache = raw_block;
for(uint16_t i = 0; i < 512; ++i)
*cache++ = sd_raw_rec_byte();
raw_block_address = block_address;
memcpy(buffer, raw_block + block_offset, read_length);
buffer += read_length;
#endif
/* read crc16 */
sd_raw_rec_byte();
sd_raw_rec_byte();
/* deaddress card */
unselect_card();
/* let card some time to finish */
sd_raw_rec_byte();
}
#if !SD_RAW_SAVE_RAM
else
{
/* use cached data */
memcpy(buffer, raw_block + block_offset, read_length);
buffer += read_length;
}
#endif
length -= read_length;
offset += read_length;
}
return 1;
}代码如下
表达式为:表达式1?表达式2:表达式3
先求解表达式1,
若其值为真(非0)则将表达式2的值作为整个表达式的取值,
否则(表达式1的值为0)将表达式3的值作为整个表达式的取值
在init中 sd_raw_card_type =4; SD_RAW_SPEC_SDHC=2; 对扇区的操作与 sdver2.0的规定不一致。
你想说什么呢?按你所给出的代码中,sd_raw_card_type =4; SD_RAW_SPEC_SDHC=2
那么sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC)的值就是1了,你看到没有1 << SD_RAW_SPEC_SDHC左移一位,即值由2变为4.那么
sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? block_address / 512 : block_address)
将执行block_address / 512 这一表达式。 /* determine byte count to read at once */
block_offset = offset & 0x01ff;
block_address = offset - block_offset;
read_length = 512 - block_offset; /* read up to block border */
if(read_length > length)
read_length = length;
这部分不知道啥意思?? 难道给的offset不是扇区? john_patson 发表于 2012-8-16 16:44 static/image/common/back.gif
你想说什么呢?按你所给出的代码中,sd_raw_card_type =4; SD_RAW_SPEC_SDHC=2
那么sd_raw_card_type & (1 ...
所以这样才更不懂了。
sdhc卡 不需要对扇区地址左移9位,sdhc卡操作的地址就是扇区号。其它卡才会左移。 当然,谁有兴趣,我将老德的程序发过去。 jazsmile 发表于 2012-8-16 16:50 static/image/common/back.gif
当然,谁有兴趣,我将老德的程序发过去。
{:titter:} 我想学习学习,可以的话,发一下我的邮箱,jeenter@163.com jazsmile 发表于 2012-8-16 16:47 static/image/common/back.gif
/* determine byte count to read at once */
block_offset = offset & 0x01ff;
b ...
block_offset = offset & 0x01ff;
block_address = offset - block_offset;
read_length = 512 - block_offset; /* read up to block border */
if(read_length > length)
read_length = length;
offset不是扇区是向量(偏移量),这段代码的意思是把offset的向量固定在0x01ff这个范围内后赋给block_offset,而0x01ff则是一个扇区(位块)大小的容量。然后
block_address = offset - block_offset;
这一句求出它的具体的扇区(位块)地址是多少。
read_length = 512 - block_offset
这一句是读写某个扇区(位块)的地址的长度。 jazsmile 发表于 2012-8-16 16:49 static/image/common/back.gif
所以这样才更不懂了。
sdhc卡 不需要对扇区地址左移9位,sdhc卡操作的地址就是扇区号。其它卡才会左移。 ...
不需要,SD都是按扇区(位块)来进行存储的,扇区号不一样,但是它每一位块的的存储容量大小相同且偏移量都相等。 john_patson 发表于 2012-8-16 17:12 static/image/common/back.gif
block_offset = offset & 0x01ff;
block_address = offset - block_offset;
read_length ...
非常感谢您的解答!!
那调用这个函数 uint8_t sd_raw_read(offset_t offset, uint8_t* buffer, uintptr_t length)
需要将参数 offset 处理一下。 1.给出扇区地址 sector.2.给出偏移量地址 OFFSET 3. 组成地址 ( sector<<9|OFFSET )
请问是这样理解吗?
若这样: 在 sdinit中 也有问题,源代码请看 最上面 上传的附件,仅上传了sd处理部分。
#endif
if(!sd_raw_read(0, raw_block, sizeof(raw_block)))
// 这里的 offset 是0 ,与我上面理解不一样。
return 0;
#endif
return 1;
} 本帖最后由 jazsmile 于 2012-8-16 17:34 编辑
小策策 发表于 2012-8-16 17:04 static/image/common/back.gif
我想学习学习,可以的话,发一下我的邮箱,
请在最上面下载。
老德SD代码下载地址
已上传。 这个好像没上系统吧,就当很普通的FLASH来用。新手来的,说错别见笑{:titter:} 小策策 发表于 2012-8-16 17:59 static/image/common/back.gif
这个好像没上系统吧,就当很普通的FLASH来用。新手来的,说错别见笑 ...
有的。 我没i有上传。
看这个。。因为 上了系统文件太大了,编译后atmage16不能用的。
===============================================
老德的 sd卡操作以及系统,供大家参考。
看清楚了,请给大家分享 一下 怎么调用。 请明白的同志们:
说说他的 uint8_t sd_raw_read(offset_t offset, uint8_t* buffer, uintptr_t length)
这个函数应该如何调用啊??
john_patson 发表于 2012-8-16 17:12 static/image/common/back.gif
block_offset = offset & 0x01ff;
block_address = offset - block_offset;
read_length ...
能否具体介绍一下offset的使用呢?
例如要对扇区2 读、 烦下载的同志们:说说 它的扇区读写 函数如何调用,特别是offset 这个参数如何设置。 不懂 jazsmile 发表于 2012-8-16 17:32 static/image/common/back.gif
非常感谢您的解答!!
那调用这个函数 uint8_t sd_raw_read(offset_t offset, uint8_t* buffer, uintptr ...
if(!sd_raw_read(0, raw_block, sizeof(raw_block)))
这一句的意思是指数据从读SD卡的0地址。所读的值放在raw_block数组,sizeof(raw_block)算出数组的大小是多少,也即是长度。同样也可以人为的设定你自己想要的长度。
而你说“需要将参数 offset 处理一下。 1.给出扇区地址 sector.2.给出偏移量地址 OFFSET 3. 组成地址 ( sector<<9|OFFSET )”这个在处理SD操作时确时需要这样做。
具体的我还是建议你去看看SD方面的协议比较好,因为我看了一下你给的代码后发现这个函数已经在代码里把扇区(位块),向量(偏移量)等计算好了,所以你只需要直接给你虚拟线性地址即可以了。如你的SD卡是2G的,那么你给出你想读1G处的内容,即需直接给1G的向量(偏移量)即可。内部会自动的查找哪个扇区(位块)。当然前提是你要设置好那些初始值。
标记一下,有空看看 john_patson 发表于 2012-8-16 21:43 static/image/common/back.gif
if(!sd_raw_read(0, raw_block, sizeof(raw_block)))
这一句的意思是指数据从读SD卡的0地址。所读的值放 ...
非常感谢!!
尝试了,结果还是没有实现。
能初始化
加入读写,程序就不执行了。看来是与软件无关。难道是硬件。 好东西 好好学习下! mark一下 将老德的程序改了一下,如main.cint main()
{
//we will just use ordinary idle mode
// set_sleep_mode(SLEEP_MODE_IDLE);
//setup uart
uart_init(); //程序在这里死循环了
uart_putc(0xaa);//test char
if(!sd_raw_init())
{
uart_puts_p(PSTR("MMC/SD initialization failed\n"));
}
else uart_puts_p(PSTR("MMC/SD initialization ok\n"));
uint8_t data,read;
uint16_t i;
for(i=0;i<512;i++) {data='a'+i%26;}//赋值
sd_raw_write((0),data,sizeof(data)); //写数据
_delay_ms(1000);
sd_raw_read((0),read,512);//读数据
for(i=0;i<512;i++) uart_putc(read);
while(1){};
} 程序在这里来回跑。
运行几次后又跑到串口初始化了,导致串口初始化 成死循环了。 估计老德的程序没有问题。我试过, sd_int没有问题。
我自己编写的sdhc的底层也存在这个问题,加上 sd的读写程序就 会执行到串口初始化,然后就回到main.c的头部。再执行串口初始化,因为该函数是main.c第一个函数。
用老德的程序也存在这个问题。
原因不知道啊。
程序就在main.c的开始到 串口初始化函数来回执行。
int main()
{
//we will just use ordinary idle mode
// set_sleep_mode(SLEEP_MODE_IDLE);
//setup uart
uart_init(); //程序在这里死循环了 去掉扇区的写操作。
读 sdhc卡的状态,正确。
8G正确识别 识别到我的卡 12年5月出厂
OEM:54 4D (16#)。 {:smile:}{:smile:}{:smile:} {:lol:}{:lol:}{:lol:}{:lol:}{:lol:} 参考学习 记号,有空过来取 SHDC啊……我买的个AtXmega32A4的例程中就用的这个,但我怎么移植都不成功。 有新版本了:
http://www.roland-riegel.de/sd-reader/index.html mark ..... 德國鬼子?不是叫德國佬嗎? 记号一下............. {:smile:}{:smile:}{:smile:}{:smile:} 学习!!!{:smile:}{:smile:}{:smile:} 这东西也太牛了,学习了 {:smile:}mark 顶一下。。。。。 {:loveliness:}{:loveliness:}{:loveliness:} 不错,他的Makefile很有特点。 看起来不错~学习学习 本帖最后由 sunliezhi 于 2013-9-5 12:27 编辑
我修改了他的Makefile,将目标文件和输出文件放到某个独立的文件夹,以免和源文件混在一起:
1.在顶部添加2行: OBJDIR=Objs
OUTDIR=Output
2.HEX := $(NAME).hex
OUT := $(NAME).out
MAP := $(NAME).map
改为: HEX := $(OUTDIR)/$(NAME).hex
OUT := $(OUTDIR)/$(NAME).out
MAP := $(OUTDIR)/$(NAME).map
3.OBJECTS := $(patsubst %.c, %.o, $(SOURCES))
改为: OBJECTS := $(patsubst %.c, $(OBJDIR)/%.o, $(SOURCES))
4.rm -f xxxxxxx
改为: rm -f $(OBJDIR)/*$(OUTDIR)/*
5.%.o : %.c $(HEADERS)
改为: $(OBJDIR)/%.o : %.c $(HEADERS)
6.在最底部添加:
$(shell mkdir $(OBJDIR)2>/dev/null)
$(shell mkdir $(OUTDIR)2>/dev/null)
----------------------------------
标记 D_FAT 需要来取~~~ 不错,学习了。 马克一下 德国佬的东西还是可以的 收藏一个,谢谢楼主分享 收藏,记号 不错,收藏一下。 学习一下mark 学习一下 谢谢分享!
不错,收藏一下。
页:
[1]