SD卡系列之---SD卡读写

2 篇文章 0 订阅

上文已经介绍了关于SD的初始化流程,在完成初始化后就可以进行扇区读写了

注意事项:

SD卡只能进行整扇区读写,即512byte,每次读写必须为512byte整数倍

SD卡分2种寻址方式 1:字节寻址 2:扇区寻址

CMD读写命令说明:         0~7:cmd命令序号;

                                          8~39:扇区地址(注意寻址方式)

                                          40~47:crc校验字节

一、单块读、写流程

读单块:

1、拉低片选信号

2、发送cmd17,返回(r & 0x80)==0 表示指令被接收

3、持续读字节,直至读取到0xfe,则之后再读取512字节数据为所读目标内容

4、读取2个字节CRC(任意值均可)

5、拉高片选信号

6、补充8个时钟信号(SD卡协议说明)

写单块:

1、拉低片选信号

2、发送cmd24,返回(r & 0x80)==0 表示指令被接收

3、获取SD卡状态,等待SD好准备好

4、写入字节0xfe,该字节为数据开始标志,后续再512字节为写入字节

5、发送2个字节CRC(任意值均可)

6、读取返回值,返回值为0bxxx00101,则代表数据被正确写入

7、等待SD卡忙状态结束(SD卡将数据写入自身)

8、拉高片选信号

9、补充8个时钟信号

二、多块读、写流程

读多块:

1、拉低片选信号

2、发送cmd18,返回(r & 0x80)==0 表示指令被接收

3、持续读字节,直至读取到0xfe,则之后再读取512字节数据为所读目标内容

4、读取2个字节CRC(任意值均可)

5、如需继续读取下一扇区,跳转至步骤3,继续执行

6、发送cmd12,停止进行数据读取

7、拉高片选信号

8、补充8个时钟信号(SD卡协议说明)

写多块:

1、拉低片选信号

2、发送cmd25,返回(r & 0x80)==0 表示指令被接收

3、获取SD卡状态,等待SD好准备好

4、写入字节0xfc,该字节为数据开始标志,后续再512字节为写入字节

5、发送2个字节CRC(任意值均可)

6、读取返回值,返回值为0bxxx00101,则代表数据被正确写入

7、等待SD卡忙状态结束(SD卡将数据写入自身)

8、如需继续进行扇区写入,则跳转至步骤4继续执行

9、发送字节0XFD,完成写入

10、等待SD卡不忙

11、拉高片选信号

12、补充8个时钟信号

三、部分相关代码

(回家后补充相关代码。。。。)

写多块::

UINT8 sd_wr8_s(
        UINT8 *buff,     //pointer to the data dest address
        UINT32 sector,   //start sector number
        UINT8 count      //sector count
        )
{
    if (!(sd_inf.SD_TYPE & 4)) sector *= 512;    /* Convert to UINT8 address if needed */

    SELECT();            /* CS = L */

    if (count == 1)      /* Single block write */
    {
        if ((send_cmd(CMD24, sector) == 0)    /* WRITE_BLOCK */
                && xmit_datablock(buff, 0xFE))
            count = 0;
    }
    else                  /* Multiple block write */
    {
        if (sd_inf.SD_TYPE & 2)
        {
            send_cmd(CMD55, 0);
            send_cmd(CMD23, count);    /* ACMD23 */
        }
        if (send_cmd(CMD25, sector) == 0)      /* WRITE_MULTIPLE_BLOCK */
        {
            do{
                if (!xmit_datablock(buff, 0xFC)) break;
                buff += 512;
            }while (--count);
            if (!xmit_datablock(0, 0xFD))    /* STOP_TRAN token */
                count = 1;
        }
    }
    DESELECT();            /* CS = H */
    rcvr_spi();            /* Idle (Release DO) */
    return count ?  R_ERROR : R_OK;
}

读多块::

UINT8 sd_rd8_s(
        UINT8 *buff,
        UINT32 sector,
        UINT8 count
        )
{
    if (!(sd_inf.SD_TYPE & 4)) sector *= 512;    /* Convert to UINT8 address if needed */

        SELECT();            /* CS = L */

        if (count == 1)      /* Single block read */
        {
            if ((send_cmd(CMD17, sector) == 0)    /* READ_SINGLE_BLOCK */
                    && rcvr_datablock(buff, 512))
                count = 0;
        }
        else                  /* Multiple block read */
        {
            if (send_cmd(CMD18, sector) == 0)      /* READ_MULTIPLE_BLOCK */
            {
                do{
                    if (!rcvr_datablock(buff, 512)) break;
                    buff += 512;
                }while (--count);
                send_cmd12();                /* STOP_TRANSMISSION */
            }
        }

        DESELECT();            /* CS = H */
        rcvr_spi();            /* Idle (Release DO) */
        return count ?  R_ERROR : R_OK;
}

发送数据块

BOOL xmit_datablock (
    const UINT8 *buff,    /* 512 UINT8 data block to be transmitted */
    UINT8 token            /* Data/Stop token */
)
{
    UINT8 resp, wc;

    if (wait_ready() != 0xFF) return FALSE;

    xmit_spi(token);                    /* Xmit data token */
    if (token != 0xFD)      /* Is data token */
    {
        wc = 32;    //  512/16
        do{                              /* Xmit the 512 UINT8 data block to MMC */
//            xmit_spi(*buff++);
//            xmit_spi(*buff++);
            xmit8_spi(buff);
            buff+=16;
        }while (--wc);
        xmit_spi(0xFF);                    /* CRC (Dummy) */
        xmit_spi(0xFF);
        resp = rcvr_spi();                /* Reveive data response */
        if ((resp & 0x1F) != 0x05)        /* If not accepted, return with error */
            return FALSE;
    }
    return TRUE;
}

接受数据块:

BOOL rcvr_datablock (
    UINT8 *buff,            /* Data buffer to store received data */
    UINT16 btr            /* UINT8 count (must be even number) */
)
{
    UINT8 token;

    timer_rt(100000);
    do{                              /* Wait for data packet in timeout of 100ms */
        token = rcvr_spi();
    }while ((token == 0xFF) && (work_mode.timer));
    if(token != 0xFE) return FALSE;    /* If not valid data token, retutn with error */

    do{                              /* Receive the data block into buffer */
//        rcvr_spi_m(buff++);
//        rcvr_spi_m(buff++);
        rcvr8_spi(buff);
        buff+=16;
    }while (btr -= 16);
    rcvr_spi();                        /* Discard CRC */
    rcvr_spi();

    return TRUE;                    /* Return with success */
}

  • 21
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
MicroBlaze是一种可重构的32位RISC处理器架构,它可以用于FPGA (Field-Programmable Gate Array)或SoC (System-on-Chip)中。SD卡是一种小型存储设备,可用于储存数据、音频、视频等各种信息。 MicroBlaze可以通过外部接口与SD卡进行读写操作。要实现MicroBlaze与SD卡的通信,需要使用SD卡控制器模块和相应的软件设计。 首先,需要在MicroBlaze处理器的硬件设计中包含一个SD卡控制器模块。该模块可以与SD卡进行通信,控制其读写操作。控制器模块通常会使用SPI (Serial Peripheral Interface)或SDIO (Secure Digital Input Output)等接口与SD卡进行数据传输。 其次,需要编写软件设计来实现与SD卡的交互。在软件设计中,需要使用SD卡控制器模块提供的接口函数来发送命令、读取数据以及写入数据。可以使用C语言或者汇编语言编写相应的软件驱动程序。 通过这些硬件设计和软件设计,MicroBlaze处理器就能够控制SD卡进行读写操作了。例如,可以使用软件设计读取SD卡中的文件,将其加载到内存中进行进一步处理;或者可以使用软件设计将数据写入SD卡,实现数据的存储和传输。 需要注意的是,在进行SD卡读写操作之前,需要正确初始化SD卡控制器模块并检测SD卡的状态。此外,读写操作时还要注意数据的正确传输和校验,以保证数据的完整性和准确性。 总之,MicroBlaze可以通过适当的硬件设计和软件设计与SD卡进行读写操作。这种通信可以让MicroBlaze处理器实现更丰富的功能,如数据存储、文件操作等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值