?? sd.c
字號:
#include "..\inc\sd.h"
#include "..\inc\44b.h"
SD_INFO g_SDInfo;
volatile char endSioTR=0;
//啟用中斷傳輸模式
void __irq Sio_Int(void) //SPI中斷函數
{
rI_ISPC = BIT_SIO; //清零中斷標志位
endSioTR = 1;
}
/*************************************************************************
* 名稱: void SPI_MasterTransmit(INT8U u8Data)
* 功能: SPI主機模式傳送數據
* 參數: cData 要傳輸的字節數據
* 返回: SPI接收值
*************************************************************************/
INT8U SPI_MasterTransmit(INT8U u8Data)
{
rSIODAT = u8Data;
rSIOCON |= (1 << 3); //啟動數據傳輸
while (!endSioTR); //等待傳輸結束
endSioTR = 0;
return rSIODAT; //返回SPI接收的數據
}
/*************************************************************************
*名稱: SD_SendCMD
*功能: 向SD卡發送命令
*參數: u8Cmd 命令 u32Arg 參數
*返回: SD卡狀態值
*************************************************************************/
INT8U SD_SendCMD(INT8U u8Cmd, INT32U u32Arg)
{
INT8U r1;
INT16U Temp = 0;
SPI_CS_ASSERT;
SPI_MasterTransmit(u8Cmd | 0x40); //分別寫入命令
SPI_MasterTransmit(u32Arg >> 24);
SPI_MasterTransmit(u32Arg >> 16);
SPI_MasterTransmit(u32Arg >> 8);
SPI_MasterTransmit(u32Arg);
SPI_MasterTransmit(0x95);
do{
r1 = SPI_MasterTransmit(0xFF);
if(Temp++ > 100)
{
break; //超時退出
}
}while(r1 == 0xFF);
SPI_CS_DEASSERT;
SPI_MasterTransmit(0xFF); //發送8個填充時鐘
return r1; //返回狀態值
}
/*************************************************************************
*名稱: SD_GetOCR
*功能: 獲取OCR寄存器數據
*參數: *pu8Buff 數據緩存區指針
*返回: 0成功 非零失敗
*************************************************************************/
INT8U SD_GetOCR(INT8U *pu8Buff)
{
INT8U i;
INT8U r1=0;
r1 = SD_SendCMD(CMD_SD_SEND_OP_COND, 0);
if(r1 != 0) //響應錯誤
{
return 1;
}
SPI_CS_ASSERT;
for (i = 0; i < 4; i++)
{
pu8Buff[i] = SPI_MasterTransmit(0xFF);
}
SPI_CS_DEASSERT;
return 0;
}
/*************************************************************************
*名稱: SD_GetCID
*功能: 獲取CID寄存器數據
*參數: *pu8Buff 數據緩存區指針
*返回: 0成功 非零失敗
*************************************************************************/
INT8U SD_GetCID(INT8U *pu8Buff)
{
INT8U i;
INT8U Temp = 0;
INT8U r1=0;
r1 = SD_SendCMD(CMD_SEND_CID,0);//發送讀CSD寄存器命令
if(r1 != 0) //響應錯誤
{
return 1;
}
SPI_CS_ASSERT;
do{
r1 = SPI_MasterTransmit(0xFF);
if(Temp++ > 100)
{
return 1;
}
}while(r1 != 0xFE); //等待數據起始令牌
for (i = 0; i < 16; i++)
{
pu8Buff[i] = SPI_MasterTransmit(0xFF);
}
SPI_MasterTransmit(0xFF); //發送8個填充時鐘
SPI_CS_DEASSERT;
return 0;
}
/*************************************************************************
*名稱: SD_GetCSD
*功能: 獲取CSD寄存器數據
*參數: *pu8Buff 數據緩存區指針
*返回: 0成功 非零失敗
*************************************************************************/
INT8U SD_GetCSD(INT8U *pu8Buff)
{
INT8U i;
INT8U Temp = 0;
INT8U r1=0;
r1 = SD_SendCMD(CMD_SEND_CSD ,0);
r1 = SD_SendCMD(CMD_SEND_CSD ,0);//發送讀CSD寄存器命令
if(r1 != 0) //響應錯誤
{
return 1;
}
SPI_CS_ASSERT;
do{
r1 = SPI_MasterTransmit(0xFF);
if(Temp++ > 100)
{
return 1;
}
}while(r1 != 0xFE); //等待數據起始令牌
for (i = 0; i < 16; i++)
{
pu8Buff[i] = SPI_MasterTransmit(0xFF);
}
SPI_MasterTransmit(0xFF); //發送8個填充時鐘
SPI_CS_DEASSERT;
return 0;
}
/*************************************************************************
*名稱: SD_GetCardInfo
*功能: 獲取卡片信息
*參數:
*返回: 0成功 非零失敗
*************************************************************************/
INT8U SD_GetCardInfo(SD_INFO *pg_SDInfo)
{
INT8U Temp[16];
if(SD_GetCID(Temp) == 0) //獲取CID信息
{
INT8U i;
pg_SDInfo->mid = Temp[0];
pg_SDInfo->oid[0] = Temp[1];
pg_SDInfo->oid[1] = Temp[2];
for(i = 0; i < 5; i++)
{
pg_SDInfo->pnm[i] = Temp[i + 3];
}
pg_SDInfo->prv = Temp[1];
pg_SDInfo->psn = ((INT32U)Temp[9] << 24) + ((INT32U)Temp[10] << 16)
+ ((INT32U)Temp[11] << 8) + (INT32U)Temp[12];
//計算32位串號
pg_SDInfo->mdt = Temp[14];
}
else
{
return 3;
}
if(SD_GetCSD(Temp) == 0) //獲取CSD信息
{
INT32U j;
pg_SDInfo->bl = 1 << (Temp[5] & 0x0F); //計算塊長度
pg_SDInfo->bn = ((Temp[6] & 0x03) << 10) +
(Temp[7] << 2) + ((Temp[8] & 0xC0) >> 6);
//計算C_SIZE + 1
j = ((Temp[9] & 0x03) << 1) + ((Temp[10] & 0x80) >> 7);
//計算C_SIZE_MULT
pg_SDInfo->bn = (pg_SDInfo->bn + 1) * (1 << (j + 2));
//計算BLOCKNR = (C_SIZE + 1) * 2 ^ (C_SIZE_MULT + 2)
pg_SDInfo->cap = pg_SDInfo->bl * pg_SDInfo->bn; //計算容量大小
pg_SDInfo->cap >>= 20;
}
else
{
return 4;
}
return 0;
}
/*************************************************************************
*名稱: SD_Init
*功能: SD卡初始化
*參數: 無
*返回: 0成功 非零是失敗
*************************************************************************/
INT8U SD_Init(PSD_INFO psdi)
{
INT8U i;
INT8U Temp = 0;
INT8U r1=0;
pISR_SIO = (unsigned)Sio_Int; //中斷入口地址
rINTMSK = ~(BIT_GLOBAL | BIT_SIO);
//-- SPI(SIO) port initialize
rPCONF = (rPCONF & 0x3ff) + (3 << 19) + (3 << 16) + (3 << 13) + (3 << 10);
rPUPF |= 0x160; //Rx must pullup
//-- SPI(SIO) controller & card initialize
rSIOCON = (0x0 << 7) | (0x0 << 6) | (0x1 << 5) | (0x0 << 4) | (0x0 << 3) | (0x0 << 2) | 0x1;
//inter clk, MSB 1st, Tx/Rx, falling, no action, auto run, SIO int
rSBRDR = 99; //MCLK=60MHz,SIOCK=300KHz(in initialize time)
rIVTCNT = 0;
for (i = 0;i < 20;i++) //至少發送74個脈沖
{
SPI_MasterTransmit(0xFF);
}
do //復位存儲卡
{
r1 = SD_SendCMD(CMD_GO_IDLE_STATE , 0); //發IDLE命令
if(Temp++ > 20)
{
return 1; //超時退出
}
} while(r1 != 0x01);
Temp = 0;
do //激活存儲卡
{
r1 = SD_SendCMD(CMD_SEND_OP_COND , 0); //發CMD1命令激活卡
if(Temp++ > 20)
{
return 1; //超時退出
}
} while(r1 != 0x01);
do //判斷卡片類型
{
r1 = SD_SendCMD(CMD_APP, 0); //發CMD55命令
if(r1 == 0x01) //響應正確
{
r1 = SD_SendCMD(CMD_SD_SEND_OP_COND, 0);//發ACMD41命令
if(r1 == 0x00) //SD卡
{
psdi->ct = SD_TYPE_SD ;
}
}
else //響應錯誤
{
r1 = SD_SendCMD(CMD_SEND_OP_COND , 0); //發CMD1命令激活卡
if(r1 == 0x00) //MMC卡
{
psdi->ct = SD_TYPE_MMC;
}
}
// Uart_Printf("卡的類型\n",&psdi->ct);
/* if(Temp++ > 20)
{
return 1; //超時退出
} */
} while(r1 != 0x00);
Uart_Printf("SD卡的類型\n");
if(SD_GetCardInfo(psdi) != 0) // 獲取存儲卡信息失敗
{
return 1;
}
Uart_Printf("獲取存儲卡信息\n");
r1 = SD_SendCMD(CMD_CRC_ON_OFF, 0); // 關閉crc16
r1 = SD_SendCMD(CMD_CRC_ON_OFF, 0);
if(r1 != 0 )
{
return 1;
}
Uart_Printf("關閉crc16\n");
r1 = SD_SendCMD(CMD_SET_BLOCKLEN, 512); // 設扇區大小512
if(r1 != 0 )
{
return 1;
}
Uart_Printf("\nIn ready state\n");
rSIOCON = (0x0 << 7) | (0x0 << 6) | (0x1 << 5) | (0x0 << 4) | (0x0 << 3) | (0x0 << 2) | 0x1;
rSBRDR = 5; //MCLK=60MHz,SIOCK=5MHz
rIVTCNT = 0;
return 0;
}
/*************************************************************************
*名稱: SD_ReadBlockSingle
*功能: 讀取單塊數據
*參數: u32Sector扇區地址, *pBuff讀取數據存飯緩存指針
*返回: 0成功 非零失敗
*************************************************************************/
INT8U SD_ReadBlockSingle(INT32U u32Sector, INT8U *pu8Buff)
{
INT16U Temp = 0;
INT8U r1 = 0;
INT16U i = 0;
do{
r1 = SD_SendCMD(CMD_READ_SINGLE_BLOCK, u32Sector << 9);
//發送讀BLOCK命令
if(Temp++ > 10) //超時返回
{
return 1;
}
}while(r1 != 0x00);
Temp = 0;
SPI_CS_ASSERT;
while( SPI_MasterTransmit(0xFF) != 0xFE); //等待數據起始令牌
for (i = 0; i < 512; i++) //讀取一整塊數據
{
pu8Buff[i] = SPI_MasterTransmit(0xFF);
}
SPI_MasterTransmit(0xFF); //接收偽CRC16
SPI_MasterTransmit(0xFF);
SPI_CS_DEASSERT;
SPI_MasterTransmit(0xFF); //發送8個填充時鐘
return 0;
}
/*************************************************************************
*名稱: SD_WriteBlockSingle
*功能: 寫取單塊數據
*參數: u32Sector扇區地址, *pBuff指向寫入數據
*返回: 0成功 非零失敗
*************************************************************************/
INT8U SD_WriteBlockSingle(INT32U u32Sector, INT8U *pu8Buff)
{
INT16U i;
INT8U Temp = 0;
INT8U r1 = 0;
do{
r1 = SD_SendCMD(CMD_WRITE_SINGLE_BLOCK, u32Sector << 9);
//發送讀BLOCK命令
if(Temp++ > 10)
{
return 1;
}
}while(r1 != 0);
SPI_CS_ASSERT;
SPI_MasterTransmit(0xFF);
SPI_MasterTransmit(0xFE); //發送數據起始令牌
for (i = 0; i < 512; i++)
{
SPI_MasterTransmit(*pu8Buff++);
}
SPI_MasterTransmit(0xFF); //發送偽CRC16
SPI_MasterTransmit(0xFF);
r1 = SPI_MasterTransmit(0xFF);
if((r1 & 0x0F) != 0x05) //等待是否成功
{
SPI_MasterTransmit(0xFF);
SPI_CS_DEASSERT;
return 1;
}
while(SPI_MasterTransmit(0xFF) != 0xFF); //等待是否完成
SPI_MasterTransmit(0xFF);
SPI_CS_DEASSERT;
return 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -