- #ifndef SD_CARD_H_
- #define SD_CARD_H_
- #include "main.h"
- #define ENABLE_SD_CARD_DEBUG // 打开调试信息
- // debug switch
- #ifdef ENABLE_SD_CARD_DEBUG
- #define SD_CARD_DEBUG DEBUG
- #else
- #define SD_CARD_DEBUG(...)
- #endif
- uint8_t SD_CARD_SPI_Transfer(uint8_t byte);
- uint8_t SD_CARD_Init(void);
- //
- void SD_CARD_Open(void);
- void SD_CARD_Close(void);
- uint8_t SD_CARD_Write_Sector(uint32_t addr,uint8_t *buf);
- uint8_t SD_CARD_Read_Sector(uint8_t *CMD,uint8_t *buf,uint16_t n_bytes);
- uint8_t SD_CARD_Read_Sector_Start(uint32_t sector);
- static void SD_CARD_Read_Data(uint16_t n_bytes,uint8_t *buf);
- void SD_CARD_Read_Data_LBA(uint32_t LBA,uint16_t n_bytes,uint8_t *buf);
- void SD_CARD_Read_Sector_End(void);
- static uint8_t SD_CARD_Read_CSD(uint8_t *buf);
- static uint8_t SD_CARD_Read_CID(uint8_t *buf);
- void SD_CARD_Get_Info(void);
- void SD_CARD_DEMO(void);
- #endif /* SD_CARD_H_ */
sd_card.c
- #include "sd_card.h"
- // 错误宏定义
- #define INIT_CMD0_ERROR 0x01
- #define INIT_CMD1_ERROR 0x02
- #define WRITE_BLOCK_ERROR 0x03
- #define READ_BLOCK_ERROR 0x04
- #define Delay_Us DrvSYS_Delay // us级延时
- #define SD_CARD_Set_nCS DrvSPI_ClrSS(eDRVSPI_PORT1, eDRVSPI_SS0) // nCS = 1
- #define SD_CARD_Clr_nCS DrvSPI_SetSS(eDRVSPI_PORT1, eDRVSPI_SS0) // nCS = 0
- typedef union{
- uint8_t data[16];
- struct{
- uint8_t MID; // Manufacture ID; Binary
- uint8_t OLD[2]; // OEM/Application ID; ASCII
- uint8_t PNM[5]; // Product Name; ASCII
- uint8_t PRV; // Product Revision; BCD
- uint8_t PSN[4]; // Serial Number; Binary
- uint8_t MDT[2]; // Manufacture Data Code; BCD; upper 4 bits of first byte are reserved
- uint8_t CRC; // CRC7_checksum; Binary; LSB are reserved
- }CID;
- }CID_Info_STR;
- typedef struct{
- uint8_t data[16];
- uint32_t capacity_MB;
- uint8_t READ_BL_LEN;
- uint16_t C_SIZE;
- uint8_t C_SIZE_MULT;
- }CSD_Info_STR;
- uint16_t gByteOffset=0; // 某字节在扇区内的偏移地址
- uint16_t gSectorOffset=0; // 扇区在SD卡内的偏移地址
- uint8_t gSectorOpened = 0; // 0 关闭扇区;1 打开扇区
- // 打开SD卡
- void SD_CARD_Open(void)
- {
- DrvSYS_SetIPClock(E_SYS_SPI1_CLK,1);
- DrvGPIO_InitFunction(E_FUNC_SPI1); // enable SPI function and pin
-
- DrvSPI_Open(eDRVSPI_PORT1,eDRVSPI_MASTER,eDRVSPI_TYPE1,8, FALSE);
- DrvSPI_DisableAutoSS(eDRVSPI_PORT1);
- DrvSPI_SetSlaveSelectActiveLevel(eDRVSPI_PORT1, eDRVSPI_ACTIVE_LOW_FALLING);
- DrvSPI_SetEndian(eDRVSPI_PORT1, eDRVSPI_MSB_FIRST);
- DrvSPI_SetClockFreq(eDRVSPI_PORT1,300000,0);
-
- while(SD_CARD_Init() != 0x55);
- SD_CARD_DEBUG(("SD卡初始化完成\r"));
-
- DrvSPI_SetClockFreq(eDRVSPI_PORT1,10000000,0);
- }
- // 关闭SD卡
- void SD_CARD_Close(void)
- {
- DrvSPI_Close(eDRVSPI_PORT1);
- }
- // 收发一个字节
- static uint8_t SD_CARD_SPI_Transfer(uint8_t byte)
- {
- uint32_t SPIdata=(uint32_t)byte;
- DrvSPI_BurstTransfer(eDRVSPI_PORT1,1,2);
- DrvSPI_SingleWrite(eDRVSPI_PORT1,&SPIdata);
- while (DrvSPI_IsBusy(eDRVSPI_PORT1));
- DrvSPI_DumpRxRegister(eDRVSPI_PORT1,&SPIdata,1);
- return (uint8_t)SPIdata;
- }
- // SD卡写命令
- static uint8_t SD_CARD_Write_CMD(uint8_t *CMD)
- {
- uint8_t temp,retry;
- uint8_t i;
- SD_CARD_Set_nCS; // 失能SD卡
- SD_CARD_SPI_Transfer(0xFF); // 发8个脉冲
- SD_CARD_Clr_nCS; // 使能SD卡
- // 写6个字节到SD卡
- for(i=0;i<6;i++) SD_CARD_SPI_Transfer(*CMD++);
- // 读取16位响应
- SD_CARD_SPI_Transfer(0xFF); // 第一个字节无效
- retry=0;
- do{ // 只取最后一个字节
- temp=SD_CARD_SPI_Transfer(0xFF);
- retry++;
- }while((temp==0xFF) && (retry<100));
-
- return temp;
- }
- // 初始化SD卡;SPI模式
- static uint8_t SD_CARD_Init(void)
- {
- uint8_t retry,temp;
- uint8_t i;
- uint8_t CMD[]={0x40,0x00,0x00,0x00,0x00,0x95};
- SD_CARD_Set_nCS;
- Delay_Us(10*1000);
- for(i=0;i<10;i++) // 最少先发74个脉冲
- SD_CARD_SPI_Transfer(0xFF);
- SD_CARD_Clr_nCS;
- retry=0;
- do{
- temp=SD_CARD_Write_CMD(CMD);
- retry++;
- if(retry==200)
- return INIT_CMD0_ERROR;
- }while(temp!=1);
- CMD[0]=0x41;// CMD[1]
- CMD[5]=0xFF;
- retry=0;
- do{
- temp=SD_CARD_Write_CMD(CMD);
- retry++;
- if(retry==100)
- return INIT_CMD1_ERROR;
- }while(temp!=0);
- SD_CARD_Set_nCS; // 失能SD卡
-
- return 0x55; // 初始化完成
- }
- // 写入一个块(扇区)
- uint8_t SD_CARD_Write_Sector(uint32_t addr,uint8_t *buf)
- {
- uint8_t temp,retry;
- uint16_t i;
- uint8_t CMD[]={0x58,0x00,0x00,0x00,0x00,0xFF}; // CMD24
- // 地址转换:逻辑块(扇区)地址 --> 字节地址
- addr=addr << 9;
- CMD[1]=((addr & 0xFF000000) >>24 );
- CMD[2]=((addr & 0x00FF0000) >>16 );
- CMD[3]=((addr & 0x0000FF00) >>8 );
- retry=0;
- do{
- temp=SD_CARD_Write_CMD(CMD);
- retry++;
- if(retry==100)
- return temp;
- } while(temp!=0);
- // 写数据前,先发100个脉冲;100/8=13
- for(i=0;i<13;i++) SD_CARD_SPI_Transfer(0xFF);
- // 写入开始字节
- SD_CARD_SPI_Transfer(0xFE);
- // 写入512个字节
- for(i=0;i<512;i++) SD_CARD_SPI_Transfer(*buf++);
- SD_CARD_SPI_Transfer(0xFF); // 假读;读取CRC
- SD_CARD_SPI_Transfer(0xFF); // 假读;读取CRC
- // 读取响应
- temp=SD_CARD_SPI_Transfer(0xFF);
- if( (temp & 0x1F)!=0x05 ) {// 数据被接收否?
- SD_CARD_Set_nCS; // 失能SD卡
- return WRITE_BLOCK_ERROR;
- }
- // 等待,只到SD卡不忙
- while(SD_CARD_SPI_Transfer(0xFF)!=0xFF);
- SD_CARD_Set_nCS; // 失能SD卡
-
- return 0;
- }
- // 读取块(扇区)内的字节(一般情况下,1块对应512字节)
- uint8_t SD_CARD_Read_Sector(uint8_t *CMD,uint8_t *buf,uint16_t n_bytes)
- {
- uint16_t i;
- uint8_t retry,temp;
- retry=0;
- do{
- temp=SD_CARD_Write_CMD(CMD);
- retry++;
- if(retry==100)
- return READ_BLOCK_ERROR;
- }while(temp!=0);
- // 读开始字节(0xFEh)
- while(SD_CARD_SPI_Transfer(0xFF)!=0xFE);
-
- // 读取n个字节
- for(i=0;i<n_bytes;i++) *buf++=SD_CARD_SPI_Transfer(0xFF);
- SD_CARD_SPI_Transfer(0xFF); // 假读;读取CRC
- SD_CARD_SPI_Transfer(0xFF); // 假读;读取CRC
- SD_CARD_Set_nCS; // 失能SD卡
-
- return 0;
- }
- // 开始读取某个扇区
- uint8_t SD_CARD_Read_Sector_Start(uint32_t sector)
- {
- uint8_t retry;
- uint8_t CMD[]={0x51,0x00,0x00,0x00,0x00,0xFF}; // CMD16
- uint8_t temp;
- // 地址转换:逻辑块(扇区)地址 --> 字节地址
- sector=sector << 9;
- CMD[1]=((sector & 0xFF000000) >>24 );
- CMD[2]=((sector & 0x00FF0000) >>16 );
- CMD[3]=((sector & 0x0000FF00) >>8 );
- retry=0;
- do{
- temp=SD_CARD_Write_CMD(CMD);
- retry++;
- if(retry==100)
- return READ_BLOCK_ERROR;
- }while(temp!=0);
- // 读开始字节(0xFEh)
- while(SD_CARD_SPI_Transfer(0xFF) != 0xFE);
- gSectorOpened = 1; // 将扇区打开标志置一
-
- return 0;
- }
- static void SD_CARD_Read_Data(uint16_t n_bytes, uint8_t *buf)
- {
- uint16_t i;
- for(i=0; ((i<n_bytes) && (gByteOffset<512)); i++) {
- *buf++ = SD_CARD_SPI_Transfer(0xFF);
- gByteOffset++; // 读完一个字节;将扇区内的字节偏移地址加一
- }
- if(gByteOffset == 512) {
- gByteOffset=0; // 将扇区内的字节偏移地址清零
-
- SD_CARD_SPI_Transfer(0xFF); // 假读;读取CRC
- SD_CARD_SPI_Transfer(0xFF); // 假读;读取CRC
-
- gSectorOffset++; // 读完一个扇区;将SD卡内的扇区偏移地址加一
-
- gSectorOpened = 0; // 读完一个扇区后,扇区打开标志清零
- SD_CARD_Set_nCS; // 失能SD卡
- }
- }
- // 读取指定逻辑块地址(扇区偏移地址)内的数据;logic block address,LBA
- void SD_CARD_Read_Data_LBA(uint32_t LBA,uint16_t n_bytes,uint8_t *buf)
- { // 如果某扇区被读完,则打开下一个扇区
- if(gByteOffset == 0) while(SD_CARD_Read_Sector_Start(LBA));
- SD_CARD_Read_Data(n_bytes,buf);
- }
- // 假读;读完某扇区内剩余的字节
- void SD_CARD_Read_Sector_End(void)
- {
- uint8_t temp[1];
- while((gByteOffset!=0x00) | (gSectorOpened==1))
- SD_CARD_Read_Data(1,temp); // 假读
- }
- // 读SD卡的CSD寄存器
- static uint8_t SD_CARD_Read_CSD(uint8_t *buf)
- {
- uint8_t CMD[]={0x49,0x00,0x00,0x00,0x00,0xFF};
- return SD_CARD_Read_Sector(CMD,buf,16); // 读取16个字节
- }
- // 读SD卡的CID寄存器
- static uint8_t SD_CARD_Read_CID(uint8_t *buf)
- {
- uint8_t CMD[]={0x4A,0x00,0x00,0x00,0x00,0xFF};
- return SD_CARD_Read_Sector(CMD,buf,16); // 读取16个字节
- }
- void SD_CARD_Get_Info(void)
- {
- CID_Info_STR CID;
- CSD_Info_STR CSD;
- SD_CARD_Read_CID(CID.data);
- SD_CARD_DEBUG("SD-CARD CID:\r");
- SD_CARD_DEBUG(" Manufacturer ID(MID): 0x%.2X\r", CID.CID.MID);
- SD_CARD_DEBUG(" OEM/Application ID(OLD): %c%c\r", CID.CID.OLD[0], CID.CID.OLD[1]);
- SD_CARD_DEBUG(" Product Name(PNM): %c%c%c%c%c\r", CID.CID.PNM[0], CID.CID.PNM[1], CID.CID.PNM[2], CID.CID.PNM[3], CID.CID.PNM[4]);
- SD_CARD_DEBUG(" Product Revision: 0x%.2X\r", CID.CID.PRV);
- SD_CARD_DEBUG(" Serial Number(PSN): 0x%.2X%.2X%.2X%.2X\r", CID.CID.PSN[0], CID.CID.PSN[1], CID.CID.PSN[2], CID.CID.PSN[3]);
- SD_CARD_DEBUG(" Manufacture Date Code(MDT): 0x%.1X%.2X\r", CID.CID.MDT[0] & 0x0F, CID.CID.MDT[1]);
- SD_CARD_DEBUG(" CRC-7 Checksum(CRC7):0x%.2X\r", CID.CID.CRC >> 1);
- SD_CARD_Read_CSD(CSD.data);
- CSD.C_SIZE = ((CSD.data[6]&0x03) << 10) | (CSD.data[7] << 2) | ((CSD.data[8]&0xC0) >>6);
- CSD.C_SIZE_MULT = ((CSD.data[9]&0x03) << 1) | ((CSD.data[10]&0x80) >> 7);
- CSD.READ_BL_LEN = (CSD.data[5]&0x0F);
- CSD.capacity_MB = (((CSD.C_SIZE)+1) << (((CSD.C_SIZE_MULT) +2) + (CSD.READ_BL_LEN))) >> 20;
- SD_CARD_DEBUG("SD-CARD CSD:\r");
- SD_CARD_DEBUG(" max.read data block length: %d\r", 1<<CSD.READ_BL_LEN);
- SD_CARD_DEBUG(" device size: %d\r", CSD.C_SIZE);
- SD_CARD_DEBUG(" device size multiplier: %d\r", CSD.C_SIZE_MULT);
- SD_CARD_DEBUG(" device capacity: %d MB\r", CSD.capacity_MB);
- }
- void SD_CARD_DEMO(void)
- {
- uint16_t i;
- uint8_t buf[512];
-
- SD_CARD_DEBUG("\r");
- SD_CARD_DEBUG("开始读取SD卡信息\r");
- SD_CARD_Get_Info(); // 读取CID和CSD
- SD_CARD_DEBUG("SD卡信息读取完毕\r");
-
- SD_CARD_DEBUG("\r");
- SD_CARD_DEBUG("开始读取SD卡的第一个块(扇区)\r");
- SD_CARD_Read_Data_LBA(0,512,buf); // 读取SD卡的第一个块(扇区)
- for(i=0; i<512; i++) {
- if(i%16 == 0) SD_CARD_DEBUG("0x%.3X ", i);
- SD_CARD_DEBUG("%.2X ", buf[i]);
- if((i+1) % 8 == 0) SD_CARD_DEBUG(" ");
- if((i+1) % 16 == 0) SD_CARD_DEBUG("\r");
- }
- SD_CARD_DEBUG("读取SD卡的第一个块(扇区)完毕\r");
- }