拥有响应式网站,网站绑定多个域名,网站加友情链接的好处,如何将aaa云主机做网站七个响应类型#xff1a;
R1 Response (Normal Response): R1响应是最基本的响应#xff0c;包含一个字节的状态位#xff0c;用于指示命令是否成功执行。常用。最高位为0。最低位为1表示是空闲状态。其他位是各种错误提示。
R1b Response (Normal with Busy): 类似于R1
R1 Response (Normal Response): R1响应是最基本的响应包含一个字节的状态位用于指示命令是否成功执行。常用。最高位为0。最低位为1表示是空闲状态。其他位是各种错误提示。
R1b Response (Normal with Busy): 类似于R1但在命令执行完成后卡会持续将忙位busy发送给主机直到卡准备好执行下一个命令。
R2 Response (CID or CSD Register Response): 包含两个字节的数据用于读取CIDCard ID或CSDCard Specific Data寄存器内容。
R3 Response (OCR Register Response): 包含四个字节的数据用于读取OCROperating Conditions Register寄存器内容。第一个字节就是R1响应然后是OCR寄存器。OCR中主要看CCS位标志v2.0高容量和标准容量和电压支持范围
R6 Response (Published RCA Response): 包含一个字节的状态位和一个字节的相对卡地址RCA用于获取卡的相对地址。
R7 Response (Card Interface Condition Response): 包含一个字节的状态位和一个字节的回应信息用于卡初始化阶段。常用返回状态。命令8专属响应
Data Response (for Data Transfer Commands): 在读/写数据时卡会响应数据响应用于指示数据是否成功接收。
数据传输控制
数据块传输时存在Token控制传输。
1.数据响应Token
一个字节格式如下
XXX Status 1
其中Status三个bit010数据正常接收101 CRC校验失败。110写入错误
2.数据块开始和停止Token
单块读写和多块读中数据块开头的Token是固定0xFE表示数据块开始
多块写使用0xFC开始0xFD结束。
命令表 初始化流程图
这个流程图实际上是SDIO模式的SPI在识别V1卡上有区别然后并没有进入识别状态和请求RCA的过程。 1.上电后将SPI模式设置为低速模式要求小于400Kb/s。然后片选
2.等待至少47个CLK时间一般发送8个无效字节即可
3.发送CMD0直至卡进入空闲状态r10x01
4.检查卡类型发送CMD8,若有回应则是V2.0卡需进行后续判别V1卡的识别是发送CMD8失败后继续发送CMD55ACMD41然后根据r1返回值小于等于1则是V1.0卡不响应就要判断MMC和其他不受支持的卡。判断MMC卡是继续发送CMD1如果响应是MMC卡否则不受支持均结束初始化。SPI模式中没有获取RCA步骤。
5.如果确定是V2.0卡为获得R3回复需再发送4个字节第3第4字节分别为0x01和0xAA则支持2.7-3.6V。
6.再循环发送CMD55ACMD41直到返回0x00进入Ready状态
7.发送CMD58获得R1回复后再发送4字节获得OCR值R3回复。buff[0]0x40就是V2HC否则就是V2标准容量。
结束初始化。
数据传输
SD卡单块读取流程
发送CMD17开始读取数据块并等待R1响应后继续等待数据起始令牌0xFE,然后接收数据禁止片选即可完成读取。
对于标准容量卡数据块大小由CMD16设置SDHC卡就是512字节
多块读取
发送CMD18等待R1响应等待起始数据令牌0XFE读第一块等待数据令牌0xFE读第二块
...
发送CMD12后等待R1
禁止片选
SD单块写入
发CMD24,等待响应发送数据起始令牌0xFE,写入第一数据块检测MISO是否为低低表示SD卡忙MISO为高后发送两字节伪CRC 0xFF禁止片选
多块写
发ACMD23预擦除发ACMD25开始写发送起始令牌0xFC写入第一个数据块等待不忙了再写2字节伪CRC 0xFF继续发起始令牌第二块数据.....,发送结束令牌0xFD,禁止片选。
驱动代码
//mmc_sd.h
/*
GPIO初始化要求 片选线需要推挽输出默认输出高电平高速。片选线低电平有效
SPI选用CPOL1CPHA1,全双工256分频Motorola模式软件NSS不使用CRC禁用TI模式
*/
#ifndef __SD_H
#define __SD_H#include main.h
#include spi.h
#include stdio.h
//片选线宏定义CubeMX初始化后还需要在这里设置一下宏定义
#define SD_CS_GPIO_Port GPIOA
#define SD_CS_Pin GPIO_PIN_3#define SD_SPI hspi1extern uint8_t SD_TYPE;//SD卡类型
#define ERR 0x00
#define MMC 0x01
#define V1 0x02
#define V2 0x04
#define V2HC 0x06#define DUMMY_BYTE 0xFF
#define MSD_BLOCKSIZE 512//CMD定义
#define CMD0 0 //卡复位
#define CMD1 1
#define CMD8 8 //命令8 SEND_IF_COND
#define CMD9 9 //命令9 读CSD数据
#define CMD10 10 //命令10读CID数据
#define CMD12 12 //命令12停止数据传输
#define CMD16 16 //命令16设置SectorSize 应返回0x00
#define CMD17 17 //命令17读sector
#define CMD18 18 //命令18读Multi sector
#define CMD23 23 //命令23设置多sector写入前预先擦除N个block
#define CMD24 24 //命令24写sector
#define CMD25 25 //命令25写Multi sector
#define CMD41 41 //命令41应返回0x00
#define CMD55 55 //命令55应返回0x01
#define CMD58 58 //命令58读OCR信息
#define CMD59 59 //命令59使能/禁止CRC应返回0x00//数据写入回应字意义
#define MSD_DATA_OK 0x05
#define MSD_DATA_CRC_ERROR 0x0B
#define MSD_DATA_WRITE_ERROR 0x0D
#define MSD_DATA_OTHER_ERROR 0xFF
//SD卡回应标记字
#define MSD_RESPONSE_NO_ERROR 0x00
#define MSD_IN_IDLE_STATE 0x01
#define MSD_ERASE_RESET 0x02
#define MSD_ILLEGAL_COMMAND 0x04
#define MSD_COM_CRC_ERROR 0x08
#define MSD_ERASE_SEQUENCE_ERROR 0x10
#define MSD_ADDRESS_ERROR 0x20
#define MSD_PARAMETER_ERROR 0x40
#define MSD_RESPONSE_FAILURE 0xFFenum _CD_HOLD
{HOLD 0,RELEASE 1,
};typedef struct /* Card Specific Data */
{uint8_t CSDStruct; /* CSD structure */uint8_t SysSpecVersion; /* System specification version */uint8_t Reserved1; /* Reserved */uint8_t TAAC; /* Data read access-time 1 */uint8_t NSAC; /* Data read access-time 2 in CLK cycles */uint8_t MaxBusClkFrec; /* Max. bus clock frequency */uint16_t CardComdClasses; /* Card command classes */uint8_t RdBlockLen; /* Max. read data block length */uint8_t PartBlockRead; /* Partial blocks for read allowed */uint8_t WrBlockMisalign; /* Write block misalignment */uint8_t RdBlockMisalign; /* Read block misalignment */uint8_t DSRImpl; /* DSR implemented */uint8_t Reserved2; /* Reserved */uint32_t DeviceSize; /* Device Size */uint8_t MaxRdCurrentVDDMin; /* Max. read current VDD min */uint8_t MaxRdCurrentVDDMax; /* Max. read current VDD max */uint8_t MaxWrCurrentVDDMin; /* Max. write current VDD min */uint8_t MaxWrCurrentVDDMax; /* Max. write current VDD max */uint8_t DeviceSizeMul; /* Device size multiplier */uint8_t EraseGrSize; /* Erase group size */uint8_t EraseGrMul; /* Erase group size multiplier */uint8_t WrProtectGrSize; /* Write protect group size */uint8_t WrProtectGrEnable; /* Write protect group enable */uint8_t ManDeflECC; /* Manufacturer default ECC */uint8_t WrSpeedFact; /* Write speed factor */uint8_t MaxWrBlockLen; /* Max. write data block length */uint8_t WriteBlockPaPartial; /* Partial blocks for write allowed */uint8_t Reserved3; /* Reserded */uint8_t ContentProtectAppli; /* Content protection application */uint8_t FileFormatGrouop; /* File format group */uint8_t CopyFlag; /* Copy flag (OTP) */uint8_t PermWrProtect; /* Permanent write protection */uint8_t TempWrProtect; /* Temporary write protection */uint8_t FileFormat; /* File Format */uint8_t ECC; /* ECC code */uint8_t CSD_CRC; /* CSD CRC */uint8_t Reserved4; /* always 1*/
}
MSD_CSD;typedef struct /*Card Identification Data*/
{uint8_t ManufacturerID; /* ManufacturerID */uint16_t OEM_AppliID; /* OEM/Application ID */uint32_t ProdName1; /* Product Name part1 */uint8_t ProdName2; /* Product Name part2*/uint8_t ProdRev; /* Product Revision */uint32_t ProdSN; /* Product Serial Number */uint8_t Reserved1; /* Reserved1 */uint16_t ManufactDate; /* Manufacturing Date */uint8_t CID_CRC; /* CID CRC */uint8_t Reserved2; /* always 1 */
}
MSD_CID;typedef struct
{MSD_CSD CSD;MSD_CID CID;uint32_t Capacity; /* Card Capacity */uint32_t BlockSize; /* Card Block Size */uint16_t RCA;uint8_t CardType;uint32_t SpaceTotal; /* Total space size in file system */uint32_t SpaceFree; /* Free space size in file system */
}
MSD_CARDINFO, *PMSD_CARDINFO;extern MSD_CARDINFO SD0_CardInfo;//SD_Init需要在CubeMX提前配置好SPI和CS线GPIO High Level,High Speed,Push Up,PushPull
uint8_t SD_init(void);
void SD_CS(uint8_t p);
//得到的值右移11位即为MB
uint32_t SD_GetSectorCount(void);
uint8_t SD_GETCID (uint8_t *cid_data);
uint8_t SD_GETCSD(uint8_t *csd_data);
int MSD0_GetCardInfo(PMSD_CARDINFO SD0_CardInfo);
uint8_t SD_ReceiveData(uint8_t *data, uint16_t len);
uint8_t SD_SendBlock(uint8_t*buf,uint8_t cmd);
//主要导出函数
uint8_t SD_ReadDisk(uint8_t*buf,uint32_t sector,uint8_t cnt);
uint8_t SD_WriteDisk(uint8_t*buf,uint32_t sector,uint8_t cnt);void SPI_setspeed(uint8_t speed);
uint8_t spi_readwrite(uint8_t Txdata);
void Get_SDCard_Capacity(void);
//void WritetoSD(char filename[], uint8_t write_buff[], uint8_t bufSize);#endif //mmc_sd.c
#include mmc_sd.huint8_t DFF0xFF;
uint8_t test;
uint8_t SD_TYPE0x00;MSD_CARDINFO SD0_CardInfo;//
//片选
//
void SD_CS(uint8_t p){if(p0){ HAL_GPIO_WritePin(SD_CS_GPIO_Port,SD_CS_Pin,GPIO_PIN_SET);}else{HAL_GPIO_WritePin(SD_CS_GPIO_Port,SD_CS_Pin,GPIO_PIN_RESET);}
}
///
//发送命令发完释放
//
int SD_sendcmd(uint8_t cmd,uint32_t arg,uint8_t crc){uint8_t r1;uint8_t retry;printf(\r\nCMD:0x%2X\r\n,cmd);SD_CS(0);HAL_Delay(20);SD_CS(1);do{retryspi_readwrite(DFF);}while(retry!0xFF);uint8_t Txdata[6]{cmd|0x40,arg24,arg16,arg8,arg,crc};HAL_SPI_Transmit(SD_SPI,Txdata,6,100); if(cmdCMD12){spi_readwrite(DFF);}do{HAL_SPI_Receive(SD_SPI,r1,1,0xFF);}while(r10X80);return r1;
}//SD卡初始化uint8_t SD_init(void)
{uint8_t r1; uint8_t buff[6] {0};uint16_t retry; uint8_t i;uint8_t data0xff;SPI_setspeed(SPI_BAUDRATEPRESCALER_256);SD_CS(0);//等待至少74个低速时钟周期for(retry0;retry10;retry){HAL_SPI_Transmit(SD_SPI,data,1,0xFF);}//SD卡进入IDLE状态do{r1 SD_sendcmd(CMD0 ,0, 0x95); }while(r1!0x01);//查看SD卡的类型SD_TYPE0;r1 SD_sendcmd(CMD8, 0x1AA, 0x87);if(r10x01)//SD V2.0{for(i0;i4;i){buff[i]spi_readwrite(DFF); //Get trailing return value of R7 resp}if(buff[2]0X01 buff[3]0XAA)//卡是否支持2.7~3.6V{retry0XFFFE;//等待卡进入Ready状态do{SD_sendcmd(CMD55,0,0X01); //发送CMD55r1SD_sendcmd(CMD41,0x40000000,0X01);//发送CMD41}while(r1retry--);if(retrySD_sendcmd(CMD58,0,0X01)0)//鉴别SD2.0卡版本开始{for(i0;i4;i)buff[i]spi_readwrite(0XFF);//得到OCR值//检查CCS位是否为1if(buff[0]0x40){SD_TYPEV2HC;}else {SD_TYPEV2;} }}}else//SD V1.x/ MMC V3{SD_sendcmd(CMD55,0,0X01); //发送CMD55r1SD_sendcmd(CMD41,0,0X01); //发送CMD41if(r11){ SD_TYPEV1;retry0XFFFE;do //等待退出IDLE模式{SD_sendcmd(CMD55,0,0X01); //发送CMD55r1SD_sendcmd(CMD41,0,0X01);//发送CMD41}while(r1retry--);}else//MMC卡不支持CMD55CMD41识别{SD_TYPEMMC;//MMC V3retry0XFFFE;do //等待退出IDLE模式{ r1SD_sendcmd(CMD1,0,0X01);//发送CMD1}while(r1retry--); }if(retry0||SD_sendcmd(CMD16,512,0X01)!0)SD_TYPEERR;//错误的卡}SD_CS(0);SPI_setspeed(SPI_BAUDRATEPRESCALER_2);if(SD_TYPE)return 0;else return r1;
}//读取指定长度数据
uint8_t SD_ReceiveData(uint8_t *data, uint16_t len)
{uint8_t r1;SD_CS(1); do{ r1 spi_readwrite(0xFF); HAL_Delay(100);}while(r1 ! 0xFE); while(len--){*data spi_readwrite(0xFF);data;}//接收两个无效的CRC和停止位spi_readwrite(0xFF);spi_readwrite(0xFF); return 0;
}
//向sd卡写入一个数据包的内容 512字节
uint8_t SD_SendBlock(uint8_t*buf,uint8_t cmd)
{ uint16_t t;
uint8_t r1; do{r1spi_readwrite(0xFF);}while(r1!0xFF);spi_readwrite(cmd);if(cmd!0XFD)//不是结束指令{for(t0;t512;t)spi_readwrite(buf[t]);//提高速度,减少函数传参时间spi_readwrite(0xFF);//忽略crcspi_readwrite(0xFF);tspi_readwrite(0xFF);//接收响应if((t0x1F)!0x05)return 2;//响应错误 } return 0;//写入成功
}//获取CID信息
uint8_t SD_GETCID (uint8_t *cid_data)
{uint8_t r1;r1SD_sendcmd(CMD10,0,0x01); //读取CID寄存器if(r10x00){r1SD_ReceiveData(cid_data,16);}SD_CS(0);if(r1)return 1;else return 0;
}
//获取CSD信息
uint8_t SD_GETCSD(uint8_t *csd_data){uint8_t r1; r1SD_sendcmd(CMD9,0,0x01);//发CMD9命令读CSD寄存器if(r10){r1SD_ReceiveData(csd_data, 16);//接收16个字节的数据 }SD_CS(0);//取消片选if(r1)return 1;else return 0;
}
//获取SD卡的总扇区数,右移11位就是MB单位
uint32_t SD_GetSectorCount(void)
{uint8_t csd[16];uint32_t Capacity; uint8_t n;uint16_t csize; //取CSD信息如果期间出错返回0if(SD_GETCSD(csd)!0) return 0; //如果为SDHC卡按照下面方式计算if((csd[0]0xC0)0x40) //V2.00的卡{ csize csd[9] ((uint16_t)csd[8] 8) 1;Capacity (uint32_t)csize 10;//得到扇区数 }else//V1.XX的卡{ n (csd[5] 15) ((csd[10] 128) 7) ((csd[9] 3) 1) 2;csize (csd[8] 6) ((uint16_t)csd[7] 2) ((uint16_t)(csd[6] 3) 10) 1;Capacity (uint32_t)csize (n - 9);//得到扇区数 }return Capacity;
}
int MSD0_GetCardInfo(PMSD_CARDINFO SD0_CardInfo)
{uint8_t r1;uint8_t CSD_Tab[16];uint8_t CID_Tab[16];/* Send CMD9, Read CSD */r1 SD_sendcmd(CMD9, 0, 0xFF);if(r1 ! 0x00){return r1;}if(SD_ReceiveData(CSD_Tab, 16)){return 1;}/* Send CMD10, Read CID */r1 SD_sendcmd(CMD10, 0, 0xFF);if(r1 ! 0x00){return r1;}if(SD_ReceiveData(CID_Tab, 16)){return 2;} /* Byte 0 */SD0_CardInfo-CSD.CSDStruct (CSD_Tab[0] 0xC0) 6;SD0_CardInfo-CSD.SysSpecVersion (CSD_Tab[0] 0x3C) 2;SD0_CardInfo-CSD.Reserved1 CSD_Tab[0] 0x03;/* Byte 1 */SD0_CardInfo-CSD.TAAC CSD_Tab[1] ;/* Byte 2 */SD0_CardInfo-CSD.NSAC CSD_Tab[2];/* Byte 3 */SD0_CardInfo-CSD.MaxBusClkFrec CSD_Tab[3];/* Byte 4 */SD0_CardInfo-CSD.CardComdClasses CSD_Tab[4] 4;/* Byte 5 */SD0_CardInfo-CSD.CardComdClasses | (CSD_Tab[5] 0xF0) 4;SD0_CardInfo-CSD.RdBlockLen CSD_Tab[5] 0x0F;/* Byte 6 */SD0_CardInfo-CSD.PartBlockRead (CSD_Tab[6] 0x80) 7;SD0_CardInfo-CSD.WrBlockMisalign (CSD_Tab[6] 0x40) 6;SD0_CardInfo-CSD.RdBlockMisalign (CSD_Tab[6] 0x20) 5;SD0_CardInfo-CSD.DSRImpl (CSD_Tab[6] 0x10) 4;SD0_CardInfo-CSD.Reserved2 0; /* Reserved */SD0_CardInfo-CSD.DeviceSize (CSD_Tab[6] 0x03) 10;/* Byte 7 */SD0_CardInfo-CSD.DeviceSize | (CSD_Tab[7]) 2;/* Byte 8 */SD0_CardInfo-CSD.DeviceSize | (CSD_Tab[8] 0xC0) 6;SD0_CardInfo-CSD.MaxRdCurrentVDDMin (CSD_Tab[8] 0x38) 3;SD0_CardInfo-CSD.MaxRdCurrentVDDMax (CSD_Tab[8] 0x07);/* Byte 9 */SD0_CardInfo-CSD.MaxWrCurrentVDDMin (CSD_Tab[9] 0xE0) 5;SD0_CardInfo-CSD.MaxWrCurrentVDDMax (CSD_Tab[9] 0x1C) 2;SD0_CardInfo-CSD.DeviceSizeMul (CSD_Tab[9] 0x03) 1;/* Byte 10 */SD0_CardInfo-CSD.DeviceSizeMul | (CSD_Tab[10] 0x80) 7;SD0_CardInfo-CSD.EraseGrSize (CSD_Tab[10] 0x7C) 2;SD0_CardInfo-CSD.EraseGrMul (CSD_Tab[10] 0x03) 3;/* Byte 11 */SD0_CardInfo-CSD.EraseGrMul | (CSD_Tab[11] 0xE0) 5;SD0_CardInfo-CSD.WrProtectGrSize (CSD_Tab[11] 0x1F);/* Byte 12 */SD0_CardInfo-CSD.WrProtectGrEnable (CSD_Tab[12] 0x80) 7;SD0_CardInfo-CSD.ManDeflECC (CSD_Tab[12] 0x60) 5;SD0_CardInfo-CSD.WrSpeedFact (CSD_Tab[12] 0x1C) 2;SD0_CardInfo-CSD.MaxWrBlockLen (CSD_Tab[12] 0x03) 2;/* Byte 13 */SD0_CardInfo-CSD.MaxWrBlockLen | (CSD_Tab[13] 0xc0) 6;SD0_CardInfo-CSD.WriteBlockPaPartial (CSD_Tab[13] 0x20) 5;SD0_CardInfo-CSD.Reserved3 0;SD0_CardInfo-CSD.ContentProtectAppli (CSD_Tab[13] 0x01);/* Byte 14 */SD0_CardInfo-CSD.FileFormatGrouop (CSD_Tab[14] 0x80) 7;SD0_CardInfo-CSD.CopyFlag (CSD_Tab[14] 0x40) 6;SD0_CardInfo-CSD.PermWrProtect (CSD_Tab[14] 0x20) 5;SD0_CardInfo-CSD.TempWrProtect (CSD_Tab[14] 0x10) 4;SD0_CardInfo-CSD.FileFormat (CSD_Tab[14] 0x0C) 2;SD0_CardInfo-CSD.ECC (CSD_Tab[14] 0x03);/* Byte 15 */SD0_CardInfo-CSD.CSD_CRC (CSD_Tab[15] 0xFE) 1;SD0_CardInfo-CSD.Reserved4 1;if(SD0_CardInfo-CardType V2HC){/* Byte 7 */SD0_CardInfo-CSD.DeviceSize (uint16_t)(CSD_Tab[8]) *256;/* Byte 8 */SD0_CardInfo-CSD.DeviceSize CSD_Tab[9] ;}SD0_CardInfo-Capacity SD0_CardInfo-CSD.DeviceSize * MSD_BLOCKSIZE * 1024;SD0_CardInfo-BlockSize MSD_BLOCKSIZE;/* Byte 0 */SD0_CardInfo-CID.ManufacturerID CID_Tab[0];/* Byte 1 */SD0_CardInfo-CID.OEM_AppliID CID_Tab[1] 8;/* Byte 2 */SD0_CardInfo-CID.OEM_AppliID | CID_Tab[2];/* Byte 3 */SD0_CardInfo-CID.ProdName1 CID_Tab[3] 24;/* Byte 4 */SD0_CardInfo-CID.ProdName1 | CID_Tab[4] 16;/* Byte 5 */SD0_CardInfo-CID.ProdName1 | CID_Tab[5] 8;/* Byte 6 */SD0_CardInfo-CID.ProdName1 | CID_Tab[6];/* Byte 7 */SD0_CardInfo-CID.ProdName2 CID_Tab[7];/* Byte 8 */SD0_CardInfo-CID.ProdRev CID_Tab[8];/* Byte 9 */SD0_CardInfo-CID.ProdSN CID_Tab[9] 24;/* Byte 10 */SD0_CardInfo-CID.ProdSN | CID_Tab[10] 16;/* Byte 11 */SD0_CardInfo-CID.ProdSN | CID_Tab[11] 8;/* Byte 12 */SD0_CardInfo-CID.ProdSN | CID_Tab[12];/* Byte 13 */SD0_CardInfo-CID.Reserved1 | (CID_Tab[13] 0xF0) 4;/* Byte 14 */SD0_CardInfo-CID.ManufactDate (CID_Tab[13] 0x0F) 8;/* Byte 15 */SD0_CardInfo-CID.ManufactDate | CID_Tab[14];/* Byte 16 */SD0_CardInfo-CID.CID_CRC (CID_Tab[15] 0xFE) 1;SD0_CardInfo-CID.Reserved2 1;return 0;
}//可跨block写SD卡写的数量是sector*cnt,如果buf不够长则继续向下写入乱码
//buf:数据缓存区
//sector:起始扇区
//cnt:扇区数
//返回值:0,ok;其他,失败.
uint8_t SD_WriteDisk(uint8_t*buf,uint32_t sector,uint8_t cnt)
{uint8_t r1;if(SD_TYPE!V2HC)sector * 512;//转换为字节地址if(cnt1){r1SD_sendcmd(CMD24,sector,0X01);//标准卡是写SEL_BLOCK_LEN字节,SDHC写入512字节块命令if(r10)//指令发送成功{r1SD_SendBlock(buf,0xFE);//写512个字节 }}else{if(SD_TYPE!MMC){SD_sendcmd(CMD55,0,0X01); SD_sendcmd(CMD23,cnt,0X01);//发送指令 }r1SD_sendcmd(CMD25,sector,0X01);//连续写SD卡命令if(r10){do{r1SD_SendBlock(buf,0xFC);//接收512个字节 buf512; }while(--cnt r10);r1SD_SendBlock(0,0xFD);//接收512个字节 }} SD_CS(0);//取消片选return r1;//
}
//读SD卡
//buf:数据缓存区
//sector:扇区
//cnt:扇区数
//返回值:0,ok;其他,失败. 2是缓冲区溢出告警
uint8_t SD_ReadDisk(uint8_t *buf,uint32_t sector,uint8_t cnt)
{if(sector*cnt sizeof(buf))return 2;uint8_t r1;if(SD_TYPE!V2HC)sector 9;//转换为字节地址if(cnt1){r1SD_sendcmd(CMD17,sector,0X01);//读命令if(r10)//指令发送成功{r1SD_ReceiveData(buf,512);//接收512个字节 }}else{r1SD_sendcmd(CMD18,sector,0X01);//连续读命令do{r1SD_ReceiveData(buf,512);//接收512个字节 buf512; }while(--cnt r10); SD_sendcmd(CMD12,0,0X01); //发送停止命令} SD_CS(0);//取消片选return r1;//
}uint8_t spi_readwrite(uint8_t Txdata){uint8_t Rxdata; HAL_SPI_TransmitReceive(hspi1,Txdata,Rxdata,1,100);return Rxdata;
}
//SPI1波特率设置
void SPI_setspeed(uint8_t speed){assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));//判断有效性__HAL_SPI_DISABLE(SD_SPI); //关闭SPISD_SPI.Instance-CR10XFFC7; //位3-5清零用来设置波特率SD_SPI.Instance-CR1|speed;//设置SPI速度__HAL_SPI_ENABLE(SD_SPI); //使能SPI
}void Get_SDCard_Capacity(void)
{uint8_t res;res SD_init(); //SD卡初始化if(res 1){printf(SD卡初始化失败! \r\n); }else{printf(SD卡初始化成功 \r\n); }} ///END//参考文献
36. SD卡—读写测试SPI模式 — [野火]STM32库开发实战指南——基于野火MINI开发板 文档
stm32中的SDIO_stm32 sdio-CSDN博客
stm32读写SD卡(SPI模式)_spi sd卡-CSDN博客
还有正点原子的讲解视频