SD卡系列之 |
您所在的位置:网站首页 › 51单片机sd卡读写速度 › SD卡系列之 |
上文已经介绍了关于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 |