bsp_SD.cpp D:/gitt/MicrochipFor32/bsp_Device/bsp_SPI/bsp_SD.cpp 浏览该文件的文档.00001 /*---------------------------------------------------------------------------------------------------- 00002 # 00003 # Copyright (c) 2022 Yuankang Liang(XerolySkinner) 00004 # 00005 # 本软件按原样提供,无任何明示或暗示 00006 # 在任何情况下,作者都不承担任何损害赔偿责任 00007 # 00008 # 使用的许可声明: 00009 # 1. 不得歪曲本软件的来源,你不能声称你编写了原始软件. 00010 # 2. 免费授予以任何目的,前提是版权声明出现在所有副本中. 00011 # 并且版权声明和许可声明同时出现. 00012 # 3. 你有使用,复制,修改,分发,和销售本软件的许可. 00013 # 4. 如果你在产品中使用,产品文档中的声明是赞赏的但不是必须的. 00014 # 5. 本通知不得从任何来源删除或更改. 00015 # 00016 # Yuankang Liang(XerolySkinner) 00017 # E-mail:zabbcccbbaz@163.com 00018 # QQ:2715099320 00019 # Mobile Phone:13005636215 00020 # 00021 # All rights reserved. 00022 */ 00023 00034 #include "bsp_SD.h" 00036 //---------------------------------------------------------------------------------------------------- 00037 // 程序 00038 // 00043 void bsp_SD::SD_CS(u8 p){ 00044 HAL_GPIO_WritePin(GPIOx_CS, GPIO_Pin_CS, p == 0 ? GPIO_PIN_SET: GPIO_PIN_RESET);} 00045 //---------------------------------------------------------------------------------------------------- 00053 u32 bsp_SD::SD_sendcmd(u8 cmd, u32 arg, u8 crc){ 00054 u8 r1; 00055 u8 retry; 00056 SD_CS(0); 00057 __nop(); 00058 SD_CS(1); 00059 do retry = spi_readwrite(DFF);while(retry != 0xFF); 00060 spi_readwrite(cmd | 0x40); 00061 spi_readwrite(arg >> 24); 00062 spi_readwrite(arg >> 16); 00063 spi_readwrite(arg >> 8); 00064 spi_readwrite(arg); 00065 spi_readwrite(crc); 00066 if (cmd == CMD12) spi_readwrite(DFF); 00067 do r1 = spi_readwrite(0xFF);while(r1 & 0X80); 00068 return r1;} 00069 //---------------------------------------------------------------------------------------------------- 00074 u8 bsp_SD::SD_init(void){ 00075 u8 r1; 00076 u8 buff[6] = {0}; 00077 u16 retry; 00078 u8 i; 00079 // MX_SPI3_Init(); 00080 SPI_setspeed(SPI_BAUDRATEPRESCALER_256); 00081 SD_CS(0); 00082 for (retry = 0; retry < 10; retry++) spi_readwrite(DFF); 00083 // SD卡进入IDLE状态 00084 do r1 = SD_sendcmd(CMD0, 0, 0x95);while(r1 != 0x01); 00085 // 查看SD卡的类型 00086 SD_TYPE = 0; 00087 r1 = SD_sendcmd(CMD8, 0x1AA, 0x87); 00088 if (r1 == 0x01) { 00089 for (i = 0; i < 4; i++) buff[i] = spi_readwrite(DFF); //Get trailing return value of R7 resp 00090 if (buff[2] == 0X01 && buff[3] == 0XAA) { //卡是否支持2.7~3.6V 00091 retry = 0XFFFE; 00092 do { 00093 SD_sendcmd(CMD55, 0, 0X01); //发送CMD55 00094 r1 = SD_sendcmd(CMD41, 0x40000000, 0X01); //发送CMD41 00095 }while(r1 && retry--); 00096 if (retry && SD_sendcmd(CMD58, 0, 0X01) == 0) { //鉴别SD2.0卡版本开始 00097 for (i = 0; i < 4; i++) buff[i] = spi_readwrite(0XFF); //得到OCR值 00098 if (buff[0] &0x40) SD_TYPE = V2HC; 00099 else SD_TYPE = V2;}} 00100 else { 00101 SD_sendcmd(CMD55, 0, 0X01); //发送CMD55 00102 r1 = SD_sendcmd(CMD41, 0, 0X01); //发送CMD41 00103 if (r1 <= 1) { 00104 SD_TYPE = V1; 00105 retry = 0XFFFE; 00106 do { //等待退出IDLE模式 00107 SD_sendcmd(CMD55, 0, 0X01); //发送CMD55 00108 r1 = SD_sendcmd(CMD41, 0, 0X01); //发送CMD41 00109 }while(r1 && retry--);} 00110 else { //MMC卡不支持CMD55+CMD41识别 00111 SD_TYPE = MMC; //MMC V3 00112 retry = 0XFFFE; 00113 do r1 = SD_sendcmd(CMD1, 0, 0X01);while(r1 && retry--);} //等待退出IDLE模式 00114 if (retry == 0 || SD_sendcmd(CMD16, 512, 0X01) != 0) SD_TYPE = ERR;} //错误的卡 00115 } 00116 SD_CS(0); 00117 SPI_setspeed(SPI_BAUDRATEPRESCALER_2); 00118 if (SD_TYPE) return 0; 00119 else return 1;} 00120 //---------------------------------------------------------------------------------------------------- 00127 u8 bsp_SD::SD_ReceiveData(u8 * data, u16 len){ 00128 u8 r1; 00129 SD_CS(1); 00130 do { 00131 r1 = spi_readwrite(0xFF); 00132 __nop(); 00133 }while(r1 != 0xFE); 00134 while (len--) { 00135 *data = spi_readwrite(0xFF); 00136 data++;} 00137 spi_readwrite(0xFF); 00138 spi_readwrite(0xFF); 00139 return 0;} 00140 //---------------------------------------------------------------------------------------------------- 00147 u8 bsp_SD::SD_SendBlock(u8 * buf, u8 cmd){ 00148 u16 t; 00149 u8 r1; 00150 do r1 = spi_readwrite(0xFF);while(r1 != 0xFF); 00151 spi_readwrite(cmd); 00152 if (cmd != 0XFD) { //不是结束指令 00153 for (t = 0; t < 512; t++) spi_readwrite(buf[t]); //提高速度,减少函数传参时间 00154 spi_readwrite(0xFF); //忽略crc 00155 spi_readwrite(0xFF); 00156 t = spi_readwrite(0xFF); //接收响应 00157 if ((t & 0x1F) != 0x05) return 2;} //响应错误 00158 return 0;} //写入成功 00159 //---------------------------------------------------------------------------------------------------- 00164 u8 bsp_SD::SD_GETCID(u8 * cid_data){ 00165 u8 r1; 00166 r1 = SD_sendcmd(CMD10, 0, 0x01); //读取CID寄存器 00167 if (r1 == 0x00) r1 = SD_ReceiveData(cid_data, 16); 00168 SD_CS(0); 00169 if (r1) return 1; 00170 else return 0;} 00171 //---------------------------------------------------------------------------------------------------- 00176 u8 bsp_SD::SD_GETCSD(u8 * csd_data){ 00177 u8 r1; 00178 r1 = SD_sendcmd(CMD9, 0, 0x01); //发CMD9命令,读CSD寄存器 00179 if (r1 == 0) r1 = SD_ReceiveData(csd_data, 16); //接收16个字节的数据 00180 SD_CS(0); //取消片选 00181 if (r1) return 1; 00182 else return 0;} 00183 //---------------------------------------------------------------------------------------------------- 00188 u32 bsp_SD::SD_GetSectorCount(void){ 00189 u8 csd[16]; 00190 u32 Capacity; 00191 u8 n; 00192 u16 csize; 00193 //取CSD信息,如果期间出错,返回0 00194 if (SD_GETCSD(csd) != 0) return 0; 00195 //如果为SDHC卡,按照下面方式计算 00196 if ((csd[0] &0xC0) == 0x40) { //V2.00的卡 00197 csize = csd[9] + ((u16) csd[8] << 8) + 1; 00198 Capacity = (u32) 00199 csize << 10;} //得到扇区数 00200 else { //V1.XX的卡 00201 n = (csd[5] &15) + ((csd[10] &128) >> 7) + ((csd[9] &3) << 1) + 2; 00202 csize = (csd[8] >> 6) + ((u16) csd[7] << 2) + ((u16) (csd[6] &3) << 10) + 1; 00203 Capacity = (u32) 00204 csize << (n - 9);} //得到扇区数 00205 return Capacity;} 00206 //---------------------------------------------------------------------------------------------------- 00207 int bsp_SD::MSD0_GetCardInfo(PMSD_CARDINFO SD0_CardInfo){ 00208 u8 r1; 00209 u8 CSD_Tab[16]; 00210 u8 CID_Tab[16]; 00211 /* Send CMD9, Read CSD */ 00212 r1 = SD_sendcmd(CMD9, 0, 0xFF); 00213 if (r1 != 0x00) return r1; 00214 if (SD_ReceiveData(CSD_Tab, 16)) return 1; 00215 /* Send CMD10, Read CID */ 00216 r1 = SD_sendcmd(CMD10, 0, 0xFF); 00217 if (r1 != 0x00) return r1; 00218 if (SD_ReceiveData(CID_Tab, 16)) return 2; 00219 /* Byte 0 */ 00220 SD0_CardInfo->CSD.CSDStruct = (CSD_Tab[0] &0xC0) >> 6; 00221 SD0_CardInfo->CSD.SysSpecVersion = (CSD_Tab[0] &0x3C) >> 2; 00222 SD0_CardInfo->CSD.Reserved1 = CSD_Tab[0] &0x03; 00223 /* Byte 1 */ 00224 SD0_CardInfo->CSD.TAAC = CSD_Tab[1]; 00225 /* Byte 2 */ 00226 SD0_CardInfo->CSD.NSAC = CSD_Tab[2]; 00227 /* Byte 3 */ 00228 SD0_CardInfo->CSD.MaxBusClkFrec = CSD_Tab[3]; 00229 /* Byte 4 */ 00230 SD0_CardInfo->CSD.CardComdClasses = CSD_Tab[4] << 4; 00231 /* Byte 5 */ 00232 SD0_CardInfo->CSD.CardComdClasses |= (CSD_Tab[5] &0xF0) >> 4; 00233 SD0_CardInfo->CSD.RdBlockLen = CSD_Tab[5] &0x0F; 00234 /* Byte 6 */ 00235 SD0_CardInfo->CSD.PartBlockRead = (CSD_Tab[6] &0x80) >> 7; 00236 SD0_CardInfo->CSD.WrBlockMisalign = (CSD_Tab[6] &0x40) >> 6; 00237 SD0_CardInfo->CSD.RdBlockMisalign = (CSD_Tab[6] &0x20) >> 5; 00238 SD0_CardInfo->CSD.DSRImpl = (CSD_Tab[6] &0x10) >> 4; 00239 SD0_CardInfo->CSD.Reserved2 = 0; /* Reserved */ 00240 SD0_CardInfo->CSD.DeviceSize = (CSD_Tab[6] &0x03) << 10; 00241 /* Byte 7 */ 00242 SD0_CardInfo->CSD.DeviceSize |= (CSD_Tab[7]) << 2; 00243 /* Byte 8 */ 00244 SD0_CardInfo->CSD.DeviceSize |= (CSD_Tab[8] &0xC0) >> 6; 00245 SD0_CardInfo->CSD.MaxRdCurrentVDDMin = (CSD_Tab[8] &0x38) >> 3; 00246 SD0_CardInfo->CSD.MaxRdCurrentVDDMax = (CSD_Tab[8] &0x07); 00247 /* Byte 9 */ 00248 SD0_CardInfo->CSD.MaxWrCurrentVDDMin = (CSD_Tab[9] &0xE0) >> 5; 00249 SD0_CardInfo->CSD.MaxWrCurrentVDDMax = (CSD_Tab[9] &0x1C) >> 2; 00250 SD0_CardInfo->CSD.DeviceSizeMul = (CSD_Tab[9] &0x03) << 1; 00251 /* Byte 10 */ 00252 SD0_CardInfo->CSD.DeviceSizeMul |= (CSD_Tab[10] &0x80) >> 7; 00253 SD0_CardInfo->CSD.EraseGrSize = (CSD_Tab[10] &0x7C) >> 2; 00254 SD0_CardInfo->CSD.EraseGrMul = (CSD_Tab[10] &0x03) << 3; 00255 /* Byte 11 */ 00256 SD0_CardInfo->CSD.EraseGrMul |= (CSD_Tab[11] &0xE0) >> 5; 00257 SD0_CardInfo->CSD.WrProtectGrSize = (CSD_Tab[11] &0x1F); 00258 /* Byte 12 */ 00259 SD0_CardInfo->CSD.WrProtectGrEnable = (CSD_Tab[12] &0x80) >> 7; 00260 SD0_CardInfo->CSD.ManDeflECC = (CSD_Tab[12] &0x60) >> 5; 00261 SD0_CardInfo->CSD.WrSpeedFact = (CSD_Tab[12] &0x1C) >> 2; 00262 SD0_CardInfo->CSD.MaxWrBlockLen = (CSD_Tab[12] &0x03) << 2; 00263 /* Byte 13 */ 00264 SD0_CardInfo->CSD.MaxWrBlockLen |= (CSD_Tab[13] &0xc0) >> 6; 00265 SD0_CardInfo->CSD.WriteBlockPaPartial = (CSD_Tab[13] &0x20) >> 5; 00266 SD0_CardInfo->CSD.Reserved3 = 0; 00267 SD0_CardInfo->CSD.ContentProtectAppli = (CSD_Tab[13] &0x01); 00268 /* Byte 14 */ 00269 SD0_CardInfo->CSD.FileFormatGrouop = (CSD_Tab[14] &0x80) >> 7; 00270 SD0_CardInfo->CSD.CopyFlag = (CSD_Tab[14] &0x40) >> 6; 00271 SD0_CardInfo->CSD.PermWrProtect = (CSD_Tab[14] &0x20) >> 5; 00272 SD0_CardInfo->CSD.TempWrProtect = (CSD_Tab[14] &0x10) >> 4; 00273 SD0_CardInfo->CSD.FileFormat = (CSD_Tab[14] &0x0C) >> 2; 00274 SD0_CardInfo->CSD.ECC = (CSD_Tab[14] &0x03); 00275 /* Byte 15 */ 00276 SD0_CardInfo->CSD.CSD_CRC = (CSD_Tab[15] &0xFE) >> 1; 00277 SD0_CardInfo->CSD.Reserved4 = 1; 00278 if (SD0_CardInfo->CardType == V2HC) { 00279 /* Byte 7 */ 00280 SD0_CardInfo->CSD.DeviceSize = (u16) (CSD_Tab[8]) * 256; 00281 /* Byte 8 */ 00282 SD0_CardInfo->CSD.DeviceSize += CSD_Tab[9];} 00283 SD0_CardInfo->Capacity = SD0_CardInfo->CSD.DeviceSize * MSD_BLOCKSIZE * 1024; 00284 SD0_CardInfo->BlockSize = MSD_BLOCKSIZE; 00285 /* Byte 0 */ 00286 SD0_CardInfo->CID.ManufacturerID = CID_Tab[0]; 00287 /* Byte 1 */ 00288 SD0_CardInfo->CID.OEM_AppliID = CID_Tab[1] << 8; 00289 /* Byte 2 */ 00290 SD0_CardInfo->CID.OEM_AppliID |= CID_Tab[2]; 00291 /* Byte 3 */ 00292 SD0_CardInfo->CID.ProdName1 = CID_Tab[3] << 24; 00293 /* Byte 4 */ 00294 SD0_CardInfo->CID.ProdName1 |= CID_Tab[4] << 16; 00295 /* Byte 5 */ 00296 SD0_CardInfo->CID.ProdName1 |= CID_Tab[5] << 8; 00297 /* Byte 6 */ 00298 SD0_CardInfo->CID.ProdName1 |= CID_Tab[6]; 00299 /* Byte 7 */ 00300 SD0_CardInfo->CID.ProdName2 = CID_Tab[7]; 00301 /* Byte 8 */ 00302 SD0_CardInfo->CID.ProdRev = CID_Tab[8]; 00303 /* Byte 9 */ 00304 SD0_CardInfo->CID.ProdSN = CID_Tab[9] << 24; 00305 /* Byte 10 */ 00306 SD0_CardInfo->CID.ProdSN |= CID_Tab[10] << 16; 00307 /* Byte 11 */ 00308 SD0_CardInfo->CID.ProdSN |= CID_Tab[11] << 8; 00309 /* Byte 12 */ 00310 SD0_CardInfo->CID.ProdSN |= CID_Tab[12]; 00311 /* Byte 13 */ 00312 SD0_CardInfo->CID.Reserved1 |= (CID_Tab[13] &0xF0) >> 4; 00313 /* Byte 14 */ 00314 SD0_CardInfo->CID.ManufactDate = (CID_Tab[13] &0x0F) << 8; 00315 /* Byte 15 */ 00316 SD0_CardInfo->CID.ManufactDate |= CID_Tab[14]; 00317 /* Byte 16 */ 00318 SD0_CardInfo->CID.CID_CRC = (CID_Tab[15] &0xFE) >> 1; 00319 SD0_CardInfo->CID.Reserved2 = 1; 00320 return 0;} 00321 //---------------------------------------------------------------------------------------------------- 00329 u8 bsp_SD::SD_WriteDisk(u8 * buf, u32 sector, u8 cnt){ 00330 u8 r1; 00331 if (SD_TYPE != V2HC) sector *= 512; //转换为字节地址 00332 if (cnt == 1){ 00333 r1 = SD_sendcmd(CMD24, sector, 0X01); //读命令 00334 if (r1 == 0) //指令发送成功 00335 r1 = SD_SendBlock(buf, 0xFE);} //写512个字节 00336 else { 00337 if (SD_TYPE != MMC) { 00338 SD_sendcmd(CMD55, 0, 0X01); 00339 SD_sendcmd(CMD23, cnt, 0X01);} //发送指令 00340 r1 = SD_sendcmd(CMD25, sector, 0X01); //连续读命令 00341 if (r1 == 0) { 00342 do { 00343 r1 = SD_SendBlock(buf, 0xFC); //接收512个字节 00344 buf += 512;}while(--cnt && r1 == 0); 00345 r1 = SD_SendBlock(0, 0xFD);}} //接收512个字节 00346 SD_CS(0); //取消片选 00347 return r1;} 00348 //---------------------------------------------------------------------------------------------------- 00356 u8 bsp_SD::SD_ReadDisk(u8 * buf, u32 sector, u8 cnt){ 00357 u8 r1; 00358 if (SD_TYPE != V2HC) sector <<= 9; //转换为字节地址 00359 if (cnt == 1) { 00360 r1 = SD_sendcmd(CMD17, sector, 0X01); //读命令 00361 if (r1 == 0) //指令发送成功 00362 r1 = SD_ReceiveData(buf, 512);} //接收512个字节 00363 else { 00364 r1 = SD_sendcmd(CMD18, sector, 0X01); //连续读命令 00365 do { 00366 r1 = SD_ReceiveData(buf, 512); //接收512个字节 00367 buf += 512;} 00368 while(--cnt && r1 == 0); 00369 SD_sendcmd(CMD12, 0, 0X01);} //发送停止命令 00370 SD_CS(0); //取消片选 00371 return r1;} 00372 //---------------------------------------------------------------------------------------------------- 00373 u8 bsp_SD::spi_readwrite(u8 Txdata){ 00374 u8 Rxdata; 00375 HAL_SPI_TransmitReceive(hspi, &Txdata, &Rxdata, 1, 0xFF); 00376 return Rxdata;} 00377 //---------------------------------------------------------------------------------------------------- 00383 void bsp_SD::SPI_setspeed(u8 speed){ 00384 hspi->Init.BaudRatePrescaler = speed;} 00385 //---------------------------------------------------------------------------------------------------- 00393 u8 bsp_SD::offsetWrite(u64 offset,u8* dat,u64 datlen) { 00394 u8 sectorBuff[512] = { 0 }; 00395 u64 sectorBuffptr = 0; 00396 00397 u64 sectorSour = offset / 512; // 起始扇 00398 u64 sectorSourlen = offset % 512; // 起始扇内位 00399 00400 // 填入数据 00401 SD_ReadDisk(sectorBuff,sectorSour,1); 00402 sectorBuffptr = sectorSourlen; 00403 for (u64 i = 0; i < datlen; i++) { 00404 // 写入数据 00405 sectorBuff[sectorBuffptr] = dat[i]; 00406 sectorBuffptr++; 00407 // 扇区回写 00408 if (sectorBuffptr == 512 || i == datlen - 1) { 00409 SD_WriteDisk(sectorBuff,sectorSour,1); 00410 sectorBuffptr = 0; 00411 sectorSour++; 00412 if (i != datlen - 1)SD_ReadDisk(sectorBuff,sectorSour,1);}} 00413 return 0; 00414 } 00415 //---------------------------------------------------------------------------------------------------- 00423 u8 bsp_SD::offsetRead(u64 offset,u8* dat,u64 datlen) { 00424 u8 sectorBuff[512] = { 0 }; 00425 u64 sectorBuffptr = 0; 00426 00427 u64 sectorSour = offset / 512; // 起始扇 00428 u64 sectorSourlen = offset % 512; // 起始扇内位 00429 00430 // 填入数据 00431 SD_ReadDisk(sectorBuff,sectorSour,1); 00432 sectorBuffptr = sectorSourlen; 00433 for (u64 i = 0; i < datlen; i++) { 00434 // 写入数据 00435 dat[i]=sectorBuff[sectorBuffptr]; 00436 sectorBuffptr++; 00437 // 扇区回写 00438 if (sectorBuffptr == 512 || i == datlen - 1) { 00439 sectorBuffptr = 0; 00440 sectorSour++; 00441 if (i != datlen - 1)SD_ReadDisk(sectorBuff,sectorSour,1);}} 00442 return 0;} 00444 //---------------------------------------------------------------------------------------------------- 00445 // 构造函数 00446 // 00447 bsp_SD::bsp_SD( 00448 SPI_HandleTypeDef *hspi, 00449 GPIO_TypeDef *GPIOx_CS, 00450 uint16_t GPIO_Pin_CS){ 00451 bsp_SD::hspi=hspi; 00452 bsp_SD::GPIOx_CS=GPIOx_CS; 00453 bsp_SD::GPIO_Pin_CS=GPIO_Pin_CS; 00454 bsp_SD::DFF=0xFF; 00455 bsp_SD::SD_TYPE=0x00;}