#include "DrvSdSpi.h" #include "BSPSpi.h" #include static uint8_t sd_type = 0; // SD卡的类型 static unsigned char gSDCsd[16] = {0}; // SD片选 static uint8_t Drv_SdSelect(void); static void Drv_SdDisselect(void); void Drv_SdSpiCs(uint8_t value); uint8_t Drv_SdSpiRWByte(uint8_t data); void Drv_SdSpiSetSpeed(uint8_t mode); // 数据指令收发函数 static uint8_t Drv_SdSendCmd(uint8_t cmd, uint32_t arg, uint8_t crc); static unsigned char Drv_SDGetResponse(unsigned char response); static unsigned char Drv_SDRecvData(unsigned char *buf, unsigned short len); static unsigned char Drv_SDSendBlock(unsigned char *buf, unsigned char cmd); static unsigned char Drv_SDGetCsd(unsigned char *csd_data); // sd等待卡片准备好 uint8_t Drv_SdWaitReady(void); // SD卡初始化 uint8_t Drv_SdInit(void); // 读取和写入SD卡 unsigned char Drv_SdReadDisk(unsigned char *buf, unsigned int sector, unsigned char cnt); unsigned char Drv_SdWriteDisk(unsigned char *buf, unsigned int sector, unsigned char cnt); // 获取SD卡总扇区数 unsigned int Drv_SdGetSectorCount(void); // 向SD卡发送指令 static uint8_t Drv_SdSendCmd(uint8_t cmd, uint32_t arg, uint8_t crc) { uint8_t response; uint8_t retry_limit = 0x1f; Drv_SdDisselect(); if (Drv_SdSelect() != 0) { return 0xff; } Drv_SdSpiRWByte(cmd | 0x40); for (int shift = 24; shift >= 0; shift -= 8) { Drv_SdSpiRWByte((uint8_t)((arg >> shift) & 0xff)); } Drv_SdSpiRWByte(crc); if (cmd == CMD12) { Drv_SdSpiRWByte(0xff); } do { response = Drv_SdSpiRWByte(0xff); } while ((response & 0x80) && retry_limit--); return response; } // sd等待卡片准备好 uint8_t Drv_SdWaitReady(void) { uint8_t rec; uint32_t retry_time = 0; do { rec = Drv_SdSpiRWByte(0xff); if (0xff == rec) { return 0; } retry_time++; if (retry_time % 0xffffff == 0) { /* 长时间没有成功,进行重新初始化 */ Bsp_SpiInit(BSP_SPI3); Drv_SdSpiCs(1); } } while (retry_time < 0xfffffff); return 1; } // SD片选 static uint8_t Drv_SdSelect(void) { Drv_SdSpiCs(0); if (Drv_SdWaitReady() == 0) { return 0; } Drv_SdDisselect(); return 1; } // SD取消片选 static void Drv_SdDisselect(void) { Drv_SdSpiCs(1); Drv_SdSpiRWByte(0xff); } void Drv_SdSpiCs(unsigned char value) { Bsp_SpiCS(BSP_SPI3, value); } // 设置SD通信速度 void Drv_SdSpiSetSpeed(uint8_t mode) { uint32_t speed; if (mode == USR_DRV_SD_LOW_SPEED_MODE) { speed = USR_DRV_SD_LOW_SPEED; } else if (mode == USR_DRV_SD_HIGH_SPEED_MODE) { speed = USR_DRV_SD_HIGH_SPEED; } Bsp_SpiSetSpeed(BSP_SPI3, speed); } // 设置SD读写函数 uint8_t Drv_SdSpiRWByte(uint8_t data) { return Bsp_RWByte(BSP_SPI3, data); } // 从SD卡读取一个数据包的内容 static unsigned char Drv_SDRecvData(unsigned char *buf, unsigned short len) { if (Drv_SDGetResponse(0xfe)) { return 1; } while (len--) { *buf = Drv_SdSpiRWByte(0xff); buf++; } Drv_SdSpiRWByte(0xff); Drv_SdSpiRWByte(0xff); return 0; } // 向SD卡写入一个数据包的内容512字节 static unsigned char Drv_SDSendBlock(unsigned char *buf, unsigned char cmd) { unsigned char rt; unsigned short i; rt = Drv_SdWaitReady(); if (0 != rt) { return 1; } Drv_SdSpiRWByte(cmd); if (cmd != 0xfd) { for (i = 0; i < 512; i++) { Drv_SdSpiRWByte(buf[i]); } Drv_SdSpiRWByte(0xff); Drv_SdSpiRWByte(0xff); rt = Drv_SdSpiRWByte(0xff); if ((rt & 0x1F) != 0x05) { return 2; } } return 0; } // 等待SD回应 static unsigned char Drv_SDGetResponse(unsigned char response) { unsigned short count = 0xffff; while ((Drv_SdSpiRWByte(0xff) != response) && count) { count--; } if (count == 0) { return MSD_RESPONSE_FAILURE; } else { return 0; } } // 获取SD卡的CSD信息包括容量和速度信息 static unsigned char Drv_SDGetCsd(unsigned char *csd_data) { unsigned char rt; rt = Drv_SdSendCmd(CMD9, 0, 0x01); if (rt == 0x00) { rt = Drv_SDRecvData(csd_data, 16); } Drv_SdDisselect(); if (rt != 0x00) { return 1; } return 0; } // 获取SD卡总扇区数 unsigned int Drv_SdGetSectorCount(void) { unsigned int capacity; // 记录扇区数量 unsigned char n; unsigned short csize; memset(gSDCsd, 0, sizeof(gSDCsd)); /* 获取CSD信息 */ if (Drv_SDGetCsd(gSDCsd) != 0x00) { return 0; } if ((gSDCsd[0] & 0xc0) == 0x40) { csize = gSDCsd[9] + ((unsigned short)gSDCsd[8] << 8) + 1; capacity = (unsigned int)csize << 10; } else { n = (gSDCsd[5] & 15) + ((gSDCsd[10] & 128) >> 7) + ((gSDCsd[9] & 3) << 1) + 2; csize = (gSDCsd[8] >> 6) + ((unsigned short)gSDCsd[7] << 2) + ((unsigned short)(gSDCsd[6] & 3) << 10) + 1; capacity = (unsigned int)csize << (n - 9); } return capacity; } // SD卡初始化 uint8_t Drv_SdInit(void) { unsigned char RxData; // 返回值 unsigned short RetryTime; // 用来进行超时计数 unsigned char buf[4]; unsigned short i; Bsp_SpiInit(BSP_SPI3); Drv_SdSpiCs(0); Drv_SdSpiSetSpeed(USR_DRV_SD_LOW_SPEED_MODE); // 初始化的时候要是低速模式 for(i = 0; i < 100; i++) { RxData = Drv_SdSpiRWByte(0xff); // 发送最少74个脉冲,保守起见多发送一点 } /* 格式化命令 */ Drv_SdSpiRWByte(CMD0 | 0x40); Drv_SdSpiRWByte((unsigned char)((0 >> 24) & 0xff)); Drv_SdSpiRWByte((unsigned char)((0 >> 16) & 0xff)); Drv_SdSpiRWByte((unsigned char)((0 >> 8) & 0xff)); Drv_SdSpiRWByte((unsigned char)(0 & 0xff)); Drv_SdSpiRWByte(0x95); RetryTime = 20; do { RxData = Drv_SdSendCmd(CMD0, 0, 0x95);// } while((RxData != 0x01) && RetryTime--); sd_type = 0; // 设置默认没有卡 if(RxData == 0x01) { if(Drv_SdSendCmd(CMD8, 0x1AA, 0x87) == 1) // SD 协议版本V2.0 { for(i = 0; i < 4; i++) { buf[i] = Drv_SdSpiRWByte(0xff); } if(buf[2] == 0x01 && buf[3] == 0xaa) // 判断卡是否支持2.7V~3.6V { RetryTime = 0xfffe; do { Drv_SdSendCmd(CMD55, 0, 0x01); RxData = Drv_SdSendCmd(ACMD41, 0x40000000, 0x01); } while(RxData && RetryTime--); if(RetryTime && (Drv_SdSendCmd(CMD58, 0, 0x01)) == 0) // 鉴别SD2.0卡版本 { for(i = 0; i < 4; i++) { buf[i] = Drv_SdSpiRWByte(0xff); // 得到OCR值 } // 检查CSS if (buf[0] & 0x40) { sd_type = SD_TYPE_V2HC; } else { sd_type = SD_TYPE_V2; } } } } else { // SD V1.x/ MMC V3 Drv_SdSendCmd(CMD55, 0, 0X01); RxData = Drv_SdSendCmd(ACMD41, 0, 0X01); if(RxData <= 1) { sd_type = SD_TYPE_V1; RetryTime = 0xfffe; do { // 等待退出IDLE模式 Drv_SdSendCmd(CMD55, 0, 0X01); RxData = Drv_SdSendCmd(ACMD41, 0, 0X01); } while(RxData && RetryTime--); } else { // MMC卡不支持CMD55余CMD41识别 sd_type = SD_TYPE_MMC; // MMC V3 RetryTime = 0xfffe; do { // 等待退出IDLE模式 RxData = Drv_SdSendCmd(CMD1, 0, 0X01); } while(RxData && RetryTime--); } if((RetryTime == 0) || (Drv_SdSendCmd(CMD16, 512, 0X01) != 0)) { sd_type = SD_TYPE_ERR; // 错误的卡,未能识别 } } } Drv_SdDisselect(); Drv_SdSpiSetSpeed(USR_DRV_SD_HIGH_SPEED_MODE); if(sd_type != 0) { return 0; } else if(RxData != 0) { return RxData; } return 0xaa; // 其他错误 } // 读取SD卡 unsigned char Drv_SdReadDisk(unsigned char *buf, unsigned int sector, unsigned char cnt) { unsigned char rt; if(sd_type != SD_TYPE_V2HC) { sector <<= 9; // 转换为字节地址 } if(cnt == 1) { rt = Drv_SdSendCmd(CMD17, sector, 0x01); // 读命令 if (rt == 0) // 指令发送成功 { rt = Drv_SDRecvData(buf, 512); // 接收512个字节 } } else { rt = Drv_SdSendCmd(CMD18, sector, 0X01); // 连续读命令 do { rt = Drv_SDRecvData(buf, 512); // 接收512个字节 buf += 512; } while(--cnt && rt == 0); Drv_SdSendCmd(CMD12, 0, 0X01); // 发送停止命令 } Drv_SdDisselect(); // 取消片选 return rt; } // 写入SD卡 unsigned char Drv_SdWriteDisk(unsigned char *buf, unsigned int sector, unsigned char cnt) { unsigned char rt; if(sd_type != SD_TYPE_V2HC) { sector *= 512; // 转换为字节地址 } if (cnt == 1) { rt = Drv_SdSendCmd(CMD24, sector, 0x01); if(rt == 0) { rt = Drv_SDSendBlock(buf, 0xfe); } } else { if(sd_type != SD_TYPE_MMC) { Drv_SdSendCmd(CMD55, 0, 0X01); Drv_SdSendCmd(CMD23, cnt, 0X01); } rt = Drv_SdSendCmd(CMD25, sector, 0X01); // 连续读取 if(rt == 0) { do { rt = Drv_SDSendBlock(buf, 0xfc); // 接收512个字节 buf += 512; } while(--cnt && rt == 0); rt = Drv_SDSendBlock(0, 0xfd); // 接收512个字节 } } Drv_SdDisselect(); return rt; }