//------------------------------------------------------------------------ //获取SD卡的容量(字节) //返回值:0: 取容量出错 // 其他:SD卡的容量(字节) u32 SD_GetCapacity(void) {
u8 csd[16]; u32 Capacity; u8 r1; u16 i;
u16 temp;
//取CSD信息,如果期间出错,返回0 if(SD_GetCSD(csd)!=0) return 0;
//如果为SDHC卡,按照下面方式计算 if((csd[0]&0xC0)==0x40) {
Capacity=((u32)csd[8])<<8;
Capacity+=(u32)csd[9]+1;
Capacity = (Capacity)*1024;//得到扇区数 Capacity*=512;//得到字节数 } else {
i = csd[6]&0x03; i<<=8;
i += csd[7]; i<<=2;
i += ((csd[8]&0xc0)>>6); //C_SIZE_MULT r1 = csd[9]&0x03; r1<<=1;
r1 += ((csd[10]&0x80)>>7); r1+=2;//BLOCKNR temp = 1; while(r1) {
temp*=2; r1--; }
Capacity = ((u32)(i+1))*((u32)temp); // READ_BL_LEN i = csd[5]&0x0f;
//BLOCK_LEN temp = 1; while(i) {
temp*=2; i--; }
//The final result
Capacity *= (u32)temp;//字节为单位 }
return (u32)Capacity; }
//-------------------------------------------------------------------- //读SD卡的一个block
//输入:u32 sector 取地址(sector值,非物理地址) // u8 *buffer 数据存储地址(大小至少512byte) //返回值:0: 成功
// other:失败
u8 SD_ReadSingleBlock(u32 sector, u8 *buffer) {
u8 r1;
//设置为高速模式
//SPIx_SetSpeed(SPI_SPEED_4);
//spi_high_speed();
//如果不是SDHC,给定的是sector地址,将其转换成byte地址 if(SD_Type!=SD_TYPE_V2HC) {
sector = sector<<9;
}
r1 = SD_SendCommand(CMD17, sector, 0);//读命令 if(r1 != 0x00)return r1;
r1 = SD_ReceiveData(buffer, 512, RELEASE); if(r1 != 0)return r1; //读数据出错! else return 0; }
/*u8 SD_ReadSingleBlock(u32 sector, u8 *buffer) {
u8 r1;
//设置为高速模式
//SPIx_SetSpeed(SPI_SPEED_4);
spi_high_speed();
//如果不是SDHC,给定的是sector地址,将其转换成byte地址 if(SD_Type!=SD_TYPE_V2HC) {
sector = sector<<9;
}
r1 = SD_SendCommand(CMD17, sector, 0);//读命令 if(r1 != 0x00)return r1;
r1 = SD_ReceiveData(buffer, 512, RELEASE); if(r1 != 0)return r1; //读数据出错! else return 0; }*/
//---------------------------------------------------------------------- //写入SD卡的一个block(未实际测试过)
//输入:u32 sector 扇区地址(sector值,非物理地址) // u8 *buffer 数据存储地址(大小至少512byte) //返回值:0: 成功
// other:失败
u8 SD_WriteSingleBlock(u32 sector, const u8 *data) {
u8 r1; u16 i; u16 retry;
//设置为高速模式
//SPIx_SetSpeed(SPI_SPEED_4);
//如果不是SDHC,给定的是sector地址,将其转换成byte地址 if(SD_Type!=SD_TYPE_V2HC) {
sector = sector<<9; }
r1 = SD_SendCommand(CMD24, sector, 0x00); if(r1 != 0x00)
{
return r1; //应答不正确,直接返回 }
//开始准备数据传输 sd_cs_0;
//先放3个空数据,等待SD卡准备好 SPIx_ReadWriteByte(0xff); SPIx_ReadWriteByte(0xff); SPIx_ReadWriteByte(0xff); //放起始令牌0xFE
SPIx_ReadWriteByte(0xFE); //放一个sector的数据 for(i=0;i<512;i++) {
SPIx_ReadWriteByte(*data++); }
//发2个Byte的dummy CRC SPIx_ReadWriteByte(0xff); SPIx_ReadWriteByte(0xff); //等待SD卡应答
r1 = SPIx_ReadWriteByte(0xff); if((r1&0x1F)!=0x05) {
sd_cs_1; return r1; }
//等待操作完成 retry = 0;
while(!SPIx_ReadWriteByte(0xff)) {
retry++;
if(retry>0xfffe) //如果长时间写入没有完成,报错退出 {
sd_cs_1;
return 1; //写入超时返回1 } }
//写入完成,片选置1 sd_cs_1;
SPIx_ReadWriteByte(0xff); return 0; }
//------------------------------------------------------------------- //读SD卡的多个block(实际测试过)
//输入:u32 sector 扇区地址(sector值,非物理地址) // u8 *buffer 数据存储地址(大小至少512byte) // u8 count 连续读count个block //返回值:0: 成功
// other:失败
u8 SD_ReadMultiBlock(u32 sector, u8 *buffer, u8 count) {
u8 r1;
//SPIx_SetSpeed(SPI_SPEED_4);//设置为高速模式 //如果不是SDHC,将sector地址转成byte地址 if(SD_Type!=SD_TYPE_V2HC)sector = sector<<9; //SD_WaitDataReady();
//发读多块命令
r1 = SD_SendCommand(CMD18, sector, 0);//读命令 if(r1 != 0x00)return r1; do//开始接收数据 {
if(SD_ReceiveData(buffer, 512, NO_RELEASE) != 0x00)break; buffer += 512;
} while(--count);
//全部传输完毕,发送停止命令 SD_SendCommand(CMD12, 0, 0); //释放总线
sd_cs_1;
SPIx_ReadWriteByte(0xFF);
if(count != 0)return count; //如果没有传完,返回剩余个数 else return 0; }
//------------------------------------------------------------------------ //写入SD卡的N个block(未实际测试过)
//输入:u32 sector 扇区地址(sector值,非物理地址) // u8 *buffer 数据存储地址(大小至少512byte) // u8 count 写入的block数目 //返回值:0: 成功 // other:失败
u8 SD_WriteMultiBlock(u32 sector, const u8 *data, u8 count) { u8 r1; u16 i;
//SPIx_SetSpeed(SPI_SPEED_4);//设置为高速模式
if(SD_Type != SD_TYPE_V2HC)sector = sector<<9;//如果不是SDHC,给定的是sector地址,将其转换成byte地址
if(SD_Type != SD_TYPE_MMC) r1 = SD_SendCommand(ACMD23, count, 0x00);//如果目标卡不是MMC卡,启用ACMD23指令使能预擦除
r1 = SD_SendCommand(CMD25, sector, 0x00);//发多块写入指令 if(r1 != 0x00)return r1; //应答不正确,直接返回
sd_cs_0;//开始准备数据传输
SPIx_ReadWriteByte(0xff);//先放3个空数据,等待SD卡准备好 SPIx_ReadWriteByte(0xff);