新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > STM32之SD卡驅動

        STM32之SD卡驅動

        作者: 時間:2016-11-26 來源:網絡 收藏
        44.3軟件設計
        打開上一章的工程,首先在HARDWARE文件夾下新建一個SD的文件夾。然后新建一個MMC_SD.C和MMC_SD.H的文件保存在SD文件夾下,并將這個文件夾加入頭文件包含路徑。
        打開MMC_SD.C文件,在該文件里面,我們輸入與SD卡相關的操作代碼,這里由于篇幅限制,我們不貼出所有代碼,僅介紹兩個最重要的函數,第一個是SD_Initialize函數,該函數源碼如下:
        //初始化SD卡
        u8 SD_Initialize(void)
        {
        u8 r1;//存放SD卡的返回值
        u16 retry;//用來進行超時計數
        u8 buf[4];
        u16 i;
        SD_SPI_Init();//初始化IO
        SD_SPI_SpeedLow();//設置到低速模式
        for(i=0;i<10;i++)SD_SPI_ReadWriteByte(0XFF);//發送最少74個脈沖
        retry=20;
        do
        {
        r1=SD_SendCmd(CMD0,0,0x95);//進入IDLE狀態
        }while((r1!=0X01) && retry--);
        SD_Type=0;//默認無卡
        if(r1==0X01)
        {
        if(SD_SendCmd(CMD8,0x1AA,0x87)==1)//SD V2.0
        {
        for(i=0;i<4;i++)buf[i]=SD_SPI_ReadWriteByte(0XFF);//得到R7相應值
        if(buf[2]==0X01&&buf[3]==0XAA)//卡是否支持2.7~3.6V
        {
        retry=0XFFFE;
        do
        {
        SD_SendCmd(CMD55,0,0X01);//發送CMD55
        r1=SD_SendCmd(CMD41,0x40000000,0X01);//發送CMD41
        }while(r1&&retry--);
        if(retry&&SD_SendCmd(CMD58,0,0X01)==0)//鑒別SD2.0卡版本開始
        {
        for(i=0;i<4;i++)buf[i]=SD_SPI_ReadWriteByte(0XFF);//得到OCR值
        if(buf[0]&0x40)SD_Type=SD_TYPE_V2HC;//檢查CCS
        else SD_Type=SD_TYPE_V2;
        }
        }
        }else//SD V1.x/ MMCV3
        {
        SD_SendCmd(CMD55,0,0X01);//發送CMD55
        r1=SD_SendCmd(CMD41,0,0X01);//發送CMD41
        if(r1<=1)
        {
        SD_Type=SD_TYPE_V1;
        retry=0XFFFE;
        do //等待退出IDLE模式
        {
        SD_SendCmd(CMD55,0,0X01);//發送CMD55
        r1=SD_SendCmd(CMD41,0,0X01);//發送CMD41
        }while(r1&&retry--);
        }else//MMC卡不支持CMD55+CMD41識別
        {
        SD_Type=SD_TYPE_MMC;//MMC V3
        retry=0XFFFE;
        do //等待退出IDLE模式
        {
        r1=SD_SendCmd(CMD1,0,0X01);//發送CMD1
        }while(r1&&retry--);
        }
        if(retry==0||SD_SendCmd(CMD16,512,0X01)!=0)SD_Type=SD_TYPE_ERR;
        //錯誤的卡
        }
        }
        SD_DisSelect();//取消片選
        SD_SPI_SpeedHigh();//高速
        if(SD_Type)return 0;
        else if(r1)return r1;
        return 0xaa;//其他錯誤
        }
        該函數先設置與SD相關的IO口及SPI初始化,然后發送CMD0,進入IDLE狀態,并設置SD卡為SPI模式通信,然后判斷SD卡類型,完成SD卡的初始化,注意該函數調用的SD_SPI_Init等函數,實際是對SPI2的相關函數進行了一層封裝,方便移植。另外一個要介紹的函數是SD_ReadDisk,該函數用于從SD卡讀取一個扇區的數據(這里一般為512字節),該函數代碼如下:
        //讀SD卡
        //buf:數據緩存區
        //sector:扇區
        //cnt:扇區數
        //返回值:0,ok;其他,失敗.
        u8 SD_ReadDisk(u8*buf,u32 sector,u8 cnt)
        {
        u8 r1;
        if(SD_Type!=SD_TYPE_V2HC)sector <<= 9;//轉換為字節地址
        if(cnt==1)
        {
        r1=SD_SendCmd(CMD17,sector,0X01);//讀命令
        if(r1==0) r1=SD_RecvData(buf,512);//命令發送成功,接收512個字節
        }else
        {
        r1=SD_SendCmd(CMD18,sector,0X01);//連續讀命令
        do
        {
        r1=SD_RecvData(buf,512);//接收512個字節
        buf+=512;
        }while(--cnt && r1==0);
        SD_SendCmd(CMD12,0,0X01);//發送停止命令
        }
        SD_DisSelect();//取消片選
        return r1;//
        }
        此函數先發送CMD17命令,然后讀取一個扇區的數據,詳細見代碼,這里我們就不多介紹了。保存MMC_SD.C文件,并加入到HARDWARE組下,然后打開MMC_SD.H,在該文件里面輸入如下代碼:
        #ifndef _MMC_SD_H_
        #define _MMC_SD_H_
        #include "sys.h"
        #include
        // SD卡類型定義
        #define SD_TYPE_ERR0X00
        #define SD_TYPE_MMC0X01
        #define SD_TYPE_V10X02
        #define SD_TYPE_V20X04
        #define SD_TYPE_V2HC0X06
        // SD卡指令表
        #define CMD00//卡復位
        #define CMD11
        #define CMD88//命令8,SEND_IF_COND
        #define CMD99//命令9,讀CSD數據
        #define CMD1010//命令10,讀CID數據
        #define CMD1212//命令12,停止數據傳輸
        #define CMD1616//命令16,設置SectorSize應返回0x00
        #define CMD1717//命令17,讀sector
        #define CMD1818//命令18,讀Multi sector
        #define CMD2323//命令23,設置多sector寫入前預先擦除N個block
        #define CMD2424//命令24,寫sector
        #define CMD2525//命令25,寫Multi sector
        #define CMD4141//命令41,應返回0x00
        #define CMD5555//命令55,應返回0x01
        #define CMD5858//命令58,讀OCR信息
        #define CMD5959//命令59,使能/禁止CRC,應返回0x00
        //數據寫入回應字意義
        #define MSD_DATA_OK0x05
        #define MSD_DATA_CRC_ERROR0x0B
        #define MSD_DATA_WRITE_ERROR0x0D
        #define MSD_DATA_OTHER_ERROR0xFF
        //SD卡回應標記字
        #define MSD_RESPONSE_NO_ERROR0x00
        #define MSD_IN_IDLE_STATE0x01
        #define MSD_ERASE_RESET0x02
        #define MSD_ILLEGAL_COMMAND0x04
        #define MSD_COM_CRC_ERROR0x08
        #define MSD_ERASE_SEQUENCE_ERROR0x10
        #define MSD_ADDRESS_ERROR0x20
        #define MSD_PARAMETER_ERROR0x40
        #define MSD_RESPONSE_FAILURE0xFF
        //這部分應根據具體的連線來修改!
        //戰艦STM32開發板使用的是PD2作為SD卡的CS腳.
        #defineSD_CSPDout(2) //SD卡片選引腳extern u8SD_Type;//SD卡的類型
        //函數申明區
        u8 SD_SPI_ReadWriteByte(u8 data);
        void SD_SPI_SpeedLow(void);
        void SD_SPI_SpeedHigh(void);
        u8 SD_WaitReady(void);//等待SD卡準備
        u8 SD_GetResponse(u8 Response);//獲得相應
        u8 SD_Initialize(void);//初始化
        u8 SD_ReadDisk(u8*buf,u32 sector,u8 cnt);//讀塊
        u8 SD_WriteDisk(u8*buf,u32 sector,u8 cnt);//寫塊
        u32 SD_GetSectorCount(void);//讀扇區數
        u8 SD_GetCID(u8 *cid_data);//讀SD卡CID
        u8 SD_GetCSD(u8 *csd_data);//讀SD卡CSD
        #endif
        該部分代碼主要是一些命令的宏定義以及函數聲明,在這里我們設定了SD卡的CS管腳為PD2。保存MMC_SD.H,就可以在主函數里面編寫我們的應用代碼了,打開test.c文件,在該文件中修改main函數如下:
        int main(void)
        {
        u8 key; u8 t=0; u8 *buf;
        u32 sd_size;
        Stm32_Clock_Init(9);//系統時鐘設置
        uart_init(72,9600); //串口初始化為9600
        delay_init(72);//延時初始化
        LED_Init();//初始化與LED連接的硬件接口
        LCD_Init();//初始化LCD
        usmart_dev.init(72);//初始化USMART
        KEY_Init();//按鍵初始化
        FSMC_SRAM_Init();//初始化外部SRAM
        mem_init(SRAMIN);//初始化內部內存池
        POINT_COLOR=RED;//設置字體為紅色
        LCD_ShowString(60,50,200,16,16,"WarShip STM32");
        LCD_ShowString(60,70,200,16,16,"SD CARD TEST");
        LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");
        LCD_ShowString(60,110,200,16,16,"2012/9/17");
        LCD_ShowString(60,130,200,16,16,"KEY0:Read Sector 0");
        while(SD_Initialize())//檢測不到SD卡
        {
        LCD_ShowString(60,150,200,16,16,"SD Card Error!");
        delay_ms(500);
        LCD_ShowString(60,150,200,16,16,"Please Check! ");
        delay_ms(500);
        LED0=!LED0;//DS0閃爍
        }
        POINT_COLOR=BLUE;//設置字體為藍色
        //檢測SD卡成功
        LCD_ShowString(60,150,200,16,16,"SD Card OK");
        LCD_ShowString(60,170,200,16,16,"SD Card Size:MB");
        sd_size=SD_GetSectorCount();//得到扇區數
        LCD_ShowNum(164,170,sd_size>>11,5,16);//顯示SD卡容量(MB)
        while(1)
        {
        key=KEY_Scan(0);
        if(key==KEY_RIGHT)//KEY0按下了
        {
        buf=mymalloc(0,512);//在內部內存池,申請512字節內存
        if(SD_ReadDisk(buf,0,1)==0)//讀取0扇區的內容
        {
        LCD_ShowString(60,190,200,16,16,"USART1 Sending Data...");
        printf("SECTOR 0 DATA:");
        for(sd_size=0;sd_size<512;sd_size++)printf("%x ",buf[sd_size]);
        //打印0扇區數據
        printf("DATA ENDED");
        LCD_ShowString(60,190,200,16,16,"USART1 Send Data Over!");
        }
        myfree(0,buf);//釋放內存
        }
        t++;
        delay_ms(10);
        if(t==20)
        {
        LED0=!LED0;
        t=0;
        }
        }
        }

        上一頁 1 2 下一頁

        關鍵詞: STM32SD卡驅

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 德昌县| 泗洪县| 稻城县| 马公市| 饶河县| 上栗县| 邮箱| 郯城县| 班戈县| 元江| 高邑县| 龙口市| 建宁县| 东明县| 广昌县| 乐清市| 临清市| 清流县| 佛教| 民乐县| 准格尔旗| 鲜城| 务川| 南涧| 兴安县| 稷山县| 曲麻莱县| 长沙市| 和林格尔县| 海宁市| 上思县| 凉山| 宁国市| 中江县| 盖州市| 普陀区| 宁远县| 象州县| 靖西县| 从江县| 伽师县|