jazsmile 发表于 2012-8-16 16:09:43

大家看看德国鬼子对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;
}代码如下

jazsmile 发表于 2012-8-16 16:22:32

  表达式为:表达式1?表达式2:表达式3
  先求解表达式1,
  若其值为真(非0)则将表达式2的值作为整个表达式的取值,
  否则(表达式1的值为0)将表达式3的值作为整个表达式的取值

在init中 sd_raw_card_type =4; SD_RAW_SPEC_SDHC=2; 对扇区的操作与 sdver2.0的规定不一致。

john_patson 发表于 2012-8-16 16:44:53

你想说什么呢?按你所给出的代码中,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 这一表达式。

jazsmile 发表于 2012-8-16 16:47:49

      /* 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不是扇区?

jazsmile 发表于 2012-8-16 16:49:24

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:11

当然,谁有兴趣,我将老德的程序发过去。

小策策 发表于 2012-8-16 17:04:06

jazsmile 发表于 2012-8-16 16:50 static/image/common/back.gif
当然,谁有兴趣,我将老德的程序发过去。

{:titter:} 我想学习学习,可以的话,发一下我的邮箱,jeenter@163.com

john_patson 发表于 2012-8-16 17:12:31

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
这一句是读写某个扇区(位块)的地址的长度。

john_patson 发表于 2012-8-16 17:15:58

jazsmile 发表于 2012-8-16 16:49 static/image/common/back.gif
所以这样才更不懂了。

sdhc卡 不需要对扇区地址左移9位,sdhc卡操作的地址就是扇区号。其它卡才会左移。 ...

不需要,SD都是按扇区(位块)来进行存储的,扇区号不一样,但是它每一位块的的存储容量大小相同且偏移量都相等。

jazsmile 发表于 2012-8-16 17:32:18

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:32:39

本帖最后由 jazsmile 于 2012-8-16 17:34 编辑

小策策 发表于 2012-8-16 17:04 static/image/common/back.gif
我想学习学习,可以的话,发一下我的邮箱,

请在最上面下载。

老德SD代码下载地址
已上传。

小策策 发表于 2012-8-16 17:59:04

这个好像没上系统吧,就当很普通的FLASH来用。新手来的,说错别见笑{:titter:}

jazsmile 发表于 2012-8-16 20:30:41

小策策 发表于 2012-8-16 17:59 static/image/common/back.gif
这个好像没上系统吧,就当很普通的FLASH来用。新手来的,说错别见笑 ...

有的。 我没i有上传。

看这个。。因为 上了系统文件太大了,编译后atmage16不能用的。

===============================================
老德的 sd卡操作以及系统,供大家参考。

看清楚了,请给大家分享 一下 怎么调用。

jazsmile 发表于 2012-8-16 20:35:17

请明白的同志们:

说说他的 uint8_t sd_raw_read(offset_t offset, uint8_t* buffer, uintptr_t length)
这个函数应该如何调用啊??

jazsmile 发表于 2012-8-16 20:45:10

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 读、

jazsmile 发表于 2012-8-16 20:54:02

烦下载的同志们:说说 它的扇区读写 函数如何调用,特别是offset 这个参数如何设置。

eryueniao 发表于 2012-8-16 20:58:10

不懂                                                                                                   

john_patson 发表于 2012-8-16 21:43:25

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的向量(偏移量)即可。内部会自动的查找哪个扇区(位块)。当然前提是你要设置好那些初始值。

wzd5230 发表于 2012-8-17 00:13:11

标记一下,有空看看

jazsmile 发表于 2012-8-17 08:29:19

john_patson 发表于 2012-8-16 21:43 static/image/common/back.gif
if(!sd_raw_read(0, raw_block, sizeof(raw_block)))
这一句的意思是指数据从读SD卡的0地址。所读的值放 ...

非常感谢!!

jazsmile 发表于 2012-8-17 11:58:17

尝试了,结果还是没有实现。
能初始化
加入读写,程序就不执行了。看来是与软件无关。难道是硬件。

wangku001wei 发表于 2012-8-17 18:37:21

好东西 好好学习下!

tgnui 发表于 2012-8-17 19:20:39

mark一下

jazsmile 发表于 2012-8-18 16:53:40

将老德的程序改了一下,如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){};
}

jazsmile 发表于 2012-8-18 16:54:55

程序在这里来回跑。

运行几次后又跑到串口初始化了,导致串口初始化 成死循环了。

jazsmile 发表于 2012-8-18 16:57:12

估计老德的程序没有问题。我试过, sd_int没有问题。

我自己编写的sdhc的底层也存在这个问题,加上 sd的读写程序就 会执行到串口初始化,然后就回到main.c的头部。再执行串口初始化,因为该函数是main.c第一个函数。

用老德的程序也存在这个问题。

原因不知道啊。

jazsmile 发表于 2012-8-18 16:58:29

程序就在main.c的开始到 串口初始化函数来回执行。

int main()
{
    //we will just use ordinary idle mode
   // set_sleep_mode(SLEEP_MODE_IDLE);

    //setup uart
    uart_init(); //程序在这里死循环了

jazsmile 发表于 2012-8-18 18:27:37

去掉扇区的写操作。

读 sdhc卡的状态,正确。

8G正确识别

jazsmile 发表于 2012-8-18 19:47:04

识别到我的卡 12年5月出厂
OEM:54 4D (16#)。

yfgww 发表于 2012-9-5 10:46:34

{:smile:}{:smile:}{:smile:}

hamipeter 发表于 2012-9-10 22:41:20

{:lol:}{:lol:}{:lol:}{:lol:}{:lol:}

wcm_e 发表于 2012-9-10 23:48:07

参考学习

Feco 发表于 2012-9-11 08:14:34

记号,有空过来取

XA144F 发表于 2012-9-11 08:31:53

SHDC啊……我买的个AtXmega32A4的例程中就用的这个,但我怎么移植都不成功。

luvemcu 发表于 2012-9-11 23:31:33

有新版本了:
http://www.roland-riegel.de/sd-reader/index.html

cai_mouse 发表于 2012-9-12 00:02:51

mark   .....   

jjj206 发表于 2012-9-12 01:12:36

德國鬼子?不是叫德國佬嗎?

jz701209李 发表于 2012-9-13 19:51:45

记号一下.............

yfgww 发表于 2012-9-14 15:21:05

{:smile:}{:smile:}{:smile:}{:smile:}

dory_m 发表于 2012-9-14 15:26:25

学习!!!{:smile:}{:smile:}{:smile:}

fanbinhua 发表于 2012-9-14 18:15:26

这东西也太牛了,学习了

jinchenaquarius 发表于 2013-7-25 19:28:35

{:smile:}mark

tlong_1919 发表于 2013-9-4 20:45:26

顶一下。。。。。

ds663 发表于 2013-9-4 22:41:45

{:loveliness:}{:loveliness:}{:loveliness:}

sunliezhi 发表于 2013-9-4 23:39:45

不错,他的Makefile很有特点。

zgxcom123 发表于 2013-9-4 23:51:16

看起来不错~学习学习

sunliezhi 发表于 2013-9-5 12:22:16

本帖最后由 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)
----------------------------------

sunplus 发表于 2014-1-6 14:01:01

标记 D_FAT 需要来取~~~

智慧星 发表于 2014-2-28 18:44:43

不错,学习了。

cxhy 发表于 2014-2-28 19:15:35

马克一下      

Ryan 发表于 2014-2-28 20:20:20

德国佬的东西还是可以的

wyw08 发表于 2014-3-2 10:16:42

收藏一个,谢谢楼主分享

zzz123456 发表于 2014-7-11 23:33:41

收藏,记号

天行者 发表于 2014-7-11 23:45:17

不错,收藏一下。

机器人天空 发表于 2014-7-11 23:50:19

学习一下mark

longfeixue 发表于 2014-9-1 12:00:59

学习一下

liushenyoko 发表于 2014-9-9 08:34:53

谢谢分享!

moen 发表于 2014-9-9 08:39:53


不错,收藏一下。
页: [1]
查看完整版本: 大家看看德国鬼子对SD卡操作(全套上传含文件系统)