SD卡系列之

您所在的位置:网站首页 51单片机sd卡读写速度 SD卡系列之

SD卡系列之

2023-08-13 01:32| 来源: 网络整理| 查看: 265

上文已经介绍了关于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 */ }



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3