0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

SD卡是什么意思 SD卡普通模式操作實(shí)例

冬至子 ? 來(lái)源:舊巷聞書(shū) ? 作者:駱駝聽(tīng)海 ? 2023-07-28 14:41 ? 次閱讀

SD卡(Secure Digital Memory Card)即:安全數(shù)字內(nèi)存卡,它是在MMC的基礎(chǔ)上發(fā)展而來(lái),是一種基于半導(dǎo)體快閃記憶器的新一代記憶設(shè)備,它被廣泛地于便攜式裝置上使用,例如數(shù)碼相機(jī)、個(gè)人數(shù)碼助理(PDA)和多媒體播放器等。SD卡由日本松下、東芝及美國(guó)SanDisk公司于1999年8月共同開(kāi)發(fā)研制。

  • SD卡簡(jiǎn)介

SD非常小巧,可以嵌入到設(shè)備中,在嵌入式開(kāi)發(fā)中,產(chǎn)品需要存儲(chǔ)一些容量叫大的文件,就可能會(huì)運(yùn)用到SD卡。SD卡按容量分類(lèi),可以分為3類(lèi):SD卡、SDHC卡、SDXC卡,如下表所示。

圖片

容量大小不同的SD卡,其內(nèi)部的操作標(biāo)準(zhǔn)是不同的。很多外設(shè)會(huì)明確告訴用戶(hù)本設(shè)備最大能夠支持容量多大的外擴(kuò),不能無(wú)限制的擴(kuò)存,因?yàn)槿萘吭酱?,操作不同,?duì)控制器的要求比較高。當(dāng)前設(shè)備的控制器不足以支持大容量,所以有外擴(kuò)限制。

圖片

SD卡由9個(gè)引腳與外部通信,支持SPI和SDIO兩種模式,不同模式下,SD卡引腳功能描述如下表所示。

圖片

  • SD卡的物理結(jié)構(gòu)

一張SD卡包括有存儲(chǔ)單元、存儲(chǔ)單元接口、電源檢測(cè)、卡及接口控制器和接口驅(qū)動(dòng)器5個(gè)部分。

圖片

存儲(chǔ)單元:是存儲(chǔ)數(shù)據(jù)部件,存儲(chǔ)單元通過(guò)存儲(chǔ)單元接口與卡控制單元進(jìn)行數(shù)據(jù)傳輸;

電源檢測(cè)單元:保證SD卡工作在合適的電壓下,如出現(xiàn)掉電或上狀態(tài)時(shí),它會(huì)使控制單元和存儲(chǔ)單元接口復(fù)位;

卡及接口控制單元:控制SD卡的運(yùn)行狀態(tài),它包括有8個(gè)寄存器;

接口驅(qū)動(dòng)器:控制SD卡引腳的輸入輸出。

  • SD卡內(nèi)部寄存器

SD卡總共有8個(gè)寄存器,用于設(shè)定或表示SD卡信息。這些寄存器只能通過(guò)對(duì)應(yīng)的命令訪(fǎng)問(wèn),程序控制中只需要發(fā)送組合命令就可以實(shí)現(xiàn)SD卡的控制以及讀寫(xiě)操作。

圖片

  • SDIO接口

SDIO全稱(chēng)是安全數(shù)字輸入/輸出接口,多媒體卡(MMC)、SD卡、SD I/O卡都有SDIO接口。STM32F407系列控制器有一個(gè)SDIO主機(jī)接口,它可以與MMC卡、SD卡、SD I/O卡以及CE-ATA設(shè)備進(jìn)行數(shù)據(jù)傳輸。也就是說(shuō)SDIO接口不僅僅只會(huì)操作SD卡,凡是符合SDIO接口通信的設(shè)備都可以被操作。

圖片

SDIO 具有以下特性:

完全兼容 多媒體卡系統(tǒng)規(guī)范版本 4.2??ㄖС秩N不同數(shù)據(jù)總線(xiàn)模式:1 位(默認(rèn))、4 位和 8 位

完全兼容先前版本的多媒體卡(向前兼容性)

完全兼容 SD 存儲(chǔ)卡規(guī)范版本2.0

完全兼容 SD I/O 卡規(guī)范版本 2.0 : 卡支持兩種不同數(shù)據(jù)總線(xiàn)模式:1 位(默認(rèn))和 4 位

完全支持 CE-ATA 功能(完全符合 CE-ATA 數(shù)字協(xié)議版本 1.1)

對(duì)于 8 位模式,數(shù)據(jù)傳輸高達(dá) 48 MHz

數(shù)據(jù)和命令輸出使能信號(hào),控制外部雙向驅(qū)動(dòng)程序。

SDIO 不具備兼容 SPI 的通信模式。

  • SDIO組成

SDIO 適配器塊提供特定于 MMC/SD/SD I/O 卡的所有功能,如時(shí)鐘生成單元、命令和數(shù)據(jù)傳輸。

APB2 接口訪(fǎng)問(wèn) SDIO 適配器寄存器,并且生成中斷和 DMA 請(qǐng)求信號(hào)。

圖片

注:

1、默認(rèn)情況下,SDIO_D0用于數(shù)據(jù)傳輸。初始化后,主機(jī)可以更改數(shù)據(jù)總線(xiàn)寬度。

2、SD 卡連接到總線(xiàn),主機(jī)可以將數(shù)據(jù)傳輸配置為SDIO_D[3:0]

3、SDIO使用兩個(gè)時(shí)鐘信號(hào):SDIO適配器時(shí)鐘(SDIOCLK= 48 MHz)和APB2總線(xiàn)時(shí)鐘(PCLK2)。

4、卡時(shí)鐘(SDIO_CK):每個(gè)時(shí)鐘周期在命令和數(shù)據(jù)線(xiàn)上傳輸1位命令或數(shù)據(jù)。對(duì)于SD或SDI/O卡,時(shí)鐘頻率可以在0MHz至25MHz間變化,當(dāng)數(shù)據(jù)正式穩(wěn)定傳輸?shù)臅r(shí)候配置為24MHz。SDIO_CK計(jì)算公式:SDIO_CK=SDIOCLK/(2+CLKDIV)

5、SDIO適配器時(shí)鐘(SDIOCLK):該時(shí)鐘用于驅(qū)動(dòng)SDIO適配器,可用于產(chǎn)生SDIO_CK時(shí)鐘。對(duì)F4來(lái)說(shuō),SDIOCLK來(lái)自PLL48CK(48Mhz)。

6、F4:APB2總線(xiàn)接口時(shí)鐘(PCLK2):該時(shí)鐘用于驅(qū)動(dòng)SDIO的APB2總線(xiàn)接口,其頻率為PCLK2=84Mhz。

注意:在SD卡初始化時(shí),SDIO_CK不可以超過(guò)400Khz,初始化完成后,可以設(shè)置為最大頻率(但不可以超過(guò)SD卡最大操作頻率)。

圖片

該適配器由五個(gè)子單元組成:

1.適配器寄存器塊 :適配器寄存器模塊包含所有系統(tǒng)寄存器。

2.控制單元 : 控制單元包含電源管理功能和存儲(chǔ)卡時(shí)鐘的時(shí)鐘分頻器。

3.命令路徑 :命令路徑單元向卡發(fā)送命令并從卡接收響應(yīng)。

4.數(shù)據(jù)路徑 :數(shù)據(jù)路徑子單元負(fù)責(zé)與卡相互傳輸數(shù)據(jù)。

5.數(shù)據(jù) FIFO :數(shù)據(jù) FIFO(先進(jìn)先出)子單元是一個(gè)數(shù)據(jù)緩沖器,帶發(fā)送和接收單元。FIFO 包含一個(gè)寬度為 32 位且深度為 32 字的數(shù)據(jù)緩沖器和發(fā)送/接收邏輯。(一共32 個(gè)單元,一個(gè)單元一個(gè)字)。所有的數(shù)據(jù)傳輸都要經(jīng)過(guò)FIFO,便于管理。

  • SDIO 命令簡(jiǎn)介

SD命令由主機(jī)發(fā)出,以廣播命令和尋址命令為例,廣播命令是針對(duì)與SD主機(jī)總線(xiàn)連接的所有從設(shè)備發(fā)送的,尋址命令是指定某個(gè)地址設(shè)備進(jìn)行命令傳輸。

SD命令格式固定為48bit,都是通過(guò)CMD線(xiàn)連續(xù)傳輸?shù)模瑪?shù)據(jù)線(xiàn)不參與。

圖片

SD命令的組成如下:

起始位和終止位:命令的主體包含在起始位與終止位之間,它們都只包含一個(gè)數(shù)據(jù)位,起始位為 0,終止位為 1。

傳輸標(biāo)志:用于區(qū)分傳輸方向,該位為 1 時(shí)表示命令,方向?yàn)橹鳈C(jī)傳輸?shù)?SD 卡,該位為 0時(shí)表示響應(yīng),方向?yàn)?SD卡傳輸?shù)街鳈C(jī)。

命令主體內(nèi)容包括命令、地址信息/參數(shù)和 CRC 校驗(yàn)三個(gè)部分。

命令號(hào):它固定占用 6bit,所以總共有 64個(gè)命令(代號(hào):CMD0~CMD63),每個(gè)命令都有特定的用途,部分命令不適用于 SD 卡操作,只是專(zhuān)門(mén)用于 MMC卡或者SD I/O卡。

地址/參數(shù):每個(gè)命令有 32bit地址信息/參數(shù)用于命令附加內(nèi)容,例如,廣播命令沒(méi)有地址信息,這 32bit用于指定參數(shù),而尋址命令這 32bit用于指定目標(biāo) SD卡的地址。

CRC7 校驗(yàn):長(zhǎng)度為 7bit的校驗(yàn)位用于驗(yàn)證命令傳輸內(nèi)容正確性,如果發(fā)生外部干擾導(dǎo)致傳輸數(shù)據(jù)個(gè)別位狀態(tài)改變將導(dǎo)致校準(zhǔn)失敗,也意味著命令傳輸失敗,SD卡不執(zhí)行命令。

SD命令有4種類(lèi)型:

1.無(wú)響應(yīng)廣播命令(bc),發(fā)送到所有卡,不返回任務(wù)響應(yīng);

2.帶響應(yīng)廣播命令(bcr),發(fā)送到所有卡,同時(shí)接收來(lái)自所有卡響應(yīng);

3.尋址命令(ac),發(fā)送到選定卡,DAT線(xiàn)無(wú)數(shù)據(jù)傳輸;

5.尋址數(shù)據(jù)傳輸命令(adtc),發(fā)送到選定卡,DAT線(xiàn)有數(shù)據(jù)傳輸。

在標(biāo)準(zhǔn)中定義了兩種類(lèi)型的通用命令:特定應(yīng)用命令(ACMD)和常規(guī)命令(GEN_CMD),也就是說(shuō)在64個(gè)命令作為常規(guī)命令的基礎(chǔ)上加了特定的命令

要使用SD卡制造商特定的ACMD命令如ACMD6,需要在發(fā)送該命令之前無(wú)發(fā)送CMD55命令,告知SD卡接下來(lái)的命令為特定應(yīng)用命令。CMD55命令只對(duì)緊接的第一個(gè)命令有效,SD卡如果檢測(cè)到CMD55之后的第一條命令為ACMD則執(zhí)行其特定應(yīng)用功能,如果檢測(cè)發(fā)現(xiàn)不是ACMD命令,則執(zhí)行標(biāo)準(zhǔn)命令。

SD命令響應(yīng)由SD卡向主機(jī)發(fā)出,部分命令要求SD卡作出響應(yīng),這些響應(yīng)多用于反饋SD卡的狀態(tài)。基本特性如下:

lSDIO總共有7個(gè)響應(yīng)類(lèi)型(代號(hào):R1~R7),其中SD卡沒(méi)有R4、R5類(lèi)型響應(yīng)。特定的命令對(duì)應(yīng)有特定的響應(yīng)類(lèi)型,比如當(dāng)主機(jī)發(fā)送CMD3命令時(shí),可以得到響應(yīng)R6。與命令一樣,SD卡的響應(yīng)也是通過(guò)CMD線(xiàn)連續(xù)傳輸?shù)摹8鶕?jù)響應(yīng)內(nèi)容大小可以分為短響應(yīng)和長(zhǎng)響應(yīng)。短響應(yīng)是48bit長(zhǎng)度,只有R2類(lèi)型是長(zhǎng)響應(yīng),其長(zhǎng)度為136bit。

SDIO讀數(shù)據(jù)

圖片

單個(gè)塊讀操作與多個(gè)塊的讀操作除命令不同外,還體現(xiàn)在讀操作結(jié)束時(shí),單個(gè)塊讀取一個(gè)塊自動(dòng)結(jié)束,而多個(gè)塊還需要主機(jī)發(fā)送停止命令。寫(xiě)操作類(lèi)似,也要多發(fā)一個(gè)結(jié)束命令,只不過(guò)寫(xiě)操作寫(xiě)數(shù)據(jù)前需要檢查卡的狀態(tài)是否為忙狀態(tài)。

SDIO寫(xiě)數(shù)據(jù)

圖片

  • SD卡操作模式

SD卡有多個(gè)版本,STM32控制器目前最高支持《Physical Layer SimplifiedSpecification V2.0》定義的SD卡,STM32控制器對(duì)SD卡進(jìn)行數(shù)據(jù)讀寫(xiě)之前需要識(shí)別卡的種類(lèi):V1.0標(biāo)準(zhǔn)卡、V2.0標(biāo)準(zhǔn)卡、V2.0高容量卡或者不被識(shí)別卡。

SD卡系統(tǒng)定義了兩種操作模式:卡識(shí)別模式和數(shù)據(jù)傳輸模式。

在系統(tǒng)復(fù)位后,主機(jī)處于卡識(shí)別模式,尋找總線(xiàn)上可用的SDIO設(shè)備;同時(shí),SD卡也處于卡識(shí)別模式,直到被主機(jī)識(shí)別到,即當(dāng)SD卡接收到SEND_RCA(CMD3)命令后,SD卡就會(huì)進(jìn)入數(shù)據(jù)傳輸模式,而主機(jī)在總線(xiàn)上所有卡被識(shí)別后也進(jìn)入數(shù)據(jù)傳輸模式。

每個(gè)不同的操作模式下,SD卡都有不同狀態(tài),通過(guò)命令控制實(shí)現(xiàn)卡狀態(tài)的切換,在不同的狀態(tài)下做不同的事,比如在發(fā)送數(shù)據(jù)前需要SD卡處于傳輸狀態(tài),發(fā)送數(shù)據(jù)時(shí),SD卡處于接收狀態(tài)。

圖片

  • 卡識(shí)別模式

圖片

①上電后,主機(jī)發(fā)送CMD0讓所有卡軟復(fù)位從而進(jìn)入空閑狀態(tài)。

②主機(jī)發(fā)送CMD8確定卡的電壓范圍,并識(shí)別是否為2.0的卡

③主機(jī)發(fā)送ACMD41識(shí)別或拒絕不匹配它的電壓范圍的卡,SD卡需要工作在特定的電壓范圍之內(nèi)

④主機(jī)發(fā)送CMD2來(lái)控制所有卡返回它們的卡識(shí)別號(hào)CID(128位)

⑤主機(jī)發(fā)送CMD3命令,讓卡推薦一個(gè)RCA(16)地址作為以后通信的標(biāo)識(shí),之后都以RCA值作為身份標(biāo)識(shí)進(jìn)行信息交互。

注:在卡識(shí)別過(guò)程中,要求SD卡工作在識(shí)別時(shí)鐘頻率FOD的狀態(tài)下,在SD卡初始化時(shí),SDIO_CK不可以超過(guò)400Khz

  • 數(shù)據(jù)傳輸模式

圖片

只有SD卡系統(tǒng)處于數(shù)據(jù)傳輸模式下才可以進(jìn)行數(shù)據(jù)讀寫(xiě)操作。數(shù)據(jù)傳輸模式下可以將主機(jī)SD時(shí)鐘頻率設(shè)置為FPP,默認(rèn)最高為25MHz,頻率切換可以通過(guò)CMD4命令來(lái)實(shí)現(xiàn)。通過(guò)CMD7命令加上RCA值來(lái)選定指定的卡,選中后SD卡進(jìn)入數(shù)據(jù)傳輸狀態(tài),就可以發(fā)送CMD17讀單個(gè)塊,CMD18讀多個(gè)塊,讀多個(gè)塊時(shí)只有發(fā)送CMD12命令才會(huì)停止。SD卡再次進(jìn)入傳輸狀態(tài),若不想對(duì)卡有任何操作可以再次發(fā)送CMD7命令加上RCA值來(lái)取消指定的卡,寫(xiě)操作與上述原理相同。

  • SD卡普通模式操作實(shí)例

實(shí)驗(yàn)內(nèi)容:向SD卡寫(xiě)入數(shù)據(jù)后讀出

實(shí)驗(yàn)步驟:

1.配置RCC,與以往不同的是SDIO適配器的時(shí)鐘是單獨(dú)配置的,需要專(zhuān)用的SDIOCLK,標(biāo)準(zhǔn)工作在48MHz

圖片

2.配置SDIO

圖片

圖片

3.編寫(xiě)代碼

//mian.c
#include "main.h"
#include "stm32f4xx_hal.h"
#include "sdio.h"
#include "usart.h"
#include "gpio.h"
#define SDBUF_SIZE   1024
uint8_t SDBUF_TX[SDBUF_SIZE],SDBUF_RX[SDBUF_SIZE];//數(shù)據(jù)傳輸?shù)腷uf,一個(gè)用于傳輸,一個(gè)用于接收
//定義全局變量,最好不定義局部變量,防止因過(guò)大造成棧溢出
int main(void)
{
      uint32_t i;
      HAL_SD_CardInfoTypeDef pCardInfo;//定義結(jié)構(gòu)體用來(lái)接收卡信息
      HAL_Init();
      SystemClock_Config();
      MX_GPIO_Init();
      MX_SDIO_SD_Init();
      MX_USART1_UART_Init();
      printf("this is sd testn");
      //卡識(shí)別結(jié)束后就可以調(diào)用HAL_SD_GetCardInfo()函數(shù)獲取卡信息并打印
      HAL_SD_GetCardInfo(&hsd, &pCardInfo);
      printf("pCardInfo.CardType = %un",pCardInfo.CardType);
      printf("pCardInfo.CardVersion = %un",pCardInfo.CardVersion);//版本
      printf("pCardInfo.BlockNbr = %un",pCardInfo.BlockNbr);//SD卡塊數(shù)
      printf("pCardInfo.BlockSize = %un",pCardInfo.BlockSize);//每一塊大小
      /*--------------------SD卡寫(xiě)測(cè)試----------------------------------*/
      memset(SDBUF_TX, 0x8, SDBUF_SIZE);  /、填充TXbuf為0x8
      /**
         //函數(shù)功能及參數(shù)描述                             
        *HAL_StatusTypeDef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, 
                      *uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
        * @param  hsd Pointer to SD handle
        * @param  pData pointer to the buffer that will contain the data to transmit
        * @param  BlockAdd Block Address where data will be written,從哪一個(gè)塊開(kāi)始寫(xiě)  
        * @param  NumberOfBlocks Number of SD blocks to write   寫(xiě)幾個(gè)塊
        * @param  Timeout Specify timeout value 超時(shí)時(shí)間
        * @retval HAL status
        if( HAL_SD_WriteBlocks(&hsd, SDBUF_TX, 0 , 2, 1000) == HAL_OK)
        {
            while(HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER);//處于傳輸狀態(tài)退出
            printf("WriteBlocks Successfullyn");
            for(i=0; i< SDBUF_SIZE; i++)
            {
                printf("%d ",SDBUF_TX[i]);
            }
            printf("rn");
        }
        else
        {
            printf("WriteBlocks Failedn");
        }
        /*--------------------SD 卡讀測(cè)試----------------------------------*/
        //與HAL_SD_WriteBlocks函數(shù)的參數(shù)功能相同
        if( HAL_SD_ReadBlocks(&hsd, SDBUF_RX , 0, 2, 1000) == HAL_OK)
        {
            while(HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER);//返回到傳輸狀態(tài)退出
            printf("ReadBlocks Successfullyn");
            for(i=0; i< SDBUF_SIZE; i++)
            {
                printf("%d ",SDBUF_RX[i]);
            }
            printf("rn");
        }
        else
        {
            printf("ReadBlocks Failedn");
        }
        /*--------------------SD 擦除測(cè)試----------------------------------*/
        if (HAL_SD_Erase(&hsd, 0, 1) == HAL_OK )
        {
            while(HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER);
            printf("SD_Erase Successfullyn");
        }
        else
        {
            printf("SD_Erase Failedn");
        }
        /*--------------------SD 卡讀測(cè)試----------------------------------*/
        if( HAL_SD_ReadBlocks(&hsd, SDBUF_RX , 0, 2, 1000) == HAL_OK)
        {
            while(HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER);
            printf("ReadBlocks Successfullyn");
            for(i=0; i< SDBUF_SIZE; i++)
            {
                printf("%d ",SDBUF_RX[i]);
            }
            printf("rn");
            }
        else
        {
            printf("ReadBlocks Failedn");
        }
        while (1)
        {
        }  
}
//sdio.c
//此代碼為工程自動(dòng)生成,非用戶(hù)編寫(xiě),這里只做分析
#include "sdio.h"
#include "gpio.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
SD_HandleTypeDef hsd;
/* SDIO init function */
void MX_SDIO_SD_Init(void)   //初始化配置
{
  hsd.Instance = SDIO;    //SDIO句柄,整個(gè)系統(tǒng)中只有這一個(gè)
  hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
  hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
  hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
  hsd.Init.BusWide = SDIO_BUS_WIDE_1B;   //初始化時(shí)設(shè)置數(shù)據(jù)寬度為1位
  hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
  hsd.Init.ClockDiv = 0;
//HAL_SD_Init()函數(shù)內(nèi)部做了很多事去識(shí)別SD卡,具體的卡識(shí)別代碼分析在下方
if (HAL_SD_Init(&hsd) != HAL_OK) 
  {
    _Error_Handler(__FILE__, __LINE__);
  }
//初始化結(jié)束后重新配置數(shù)據(jù)寬度為4位
if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK) 
  {
    _Error_Handler(__FILE__, __LINE__);
  }
}
//卡識(shí)別代碼如下
HAL_StatusTypeDef HAL_SD_InitCard(SD_HandleTypeDef *hsd)
{
  uint32_t errorstate = HAL_SD_ERROR_NONE;
  SD_InitTypeDef Init;
/* Default SDIO peripheral configuration for SD card initialization */
//完成卡識(shí)別
  Init.ClockEdge           = SDIO_CLOCK_EDGE_RISING;
  Init.ClockBypass         = SDIO_CLOCK_BYPASS_DISABLE;
  Init.ClockPowerSave      = SDIO_CLOCK_POWER_SAVE_DISABLE;
  Init.BusWide             = SDIO_BUS_WIDE_1B;
  Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
  Init.ClockDiv            = SDIO_INIT_CLK_DIV;
//SDIO_CK卡識(shí)別階段要求時(shí)鐘小于400KHz,宏定義
//SDIO_CK計(jì)算公式:SDIO_CK=SDIOCLK/(2+CLKDIV)
/* SDIO Initialization Frequency (400KHz max) */
/*#define SDIO_INIT_CLK_DIV     ((uint8_t)0x76)*/
/* Initialize SDIO peripheral interface with default configuration */
  SDIO_Init(hsd- >Instance, Init);
/* Disable SDIO Clock */
  __HAL_SD_DISABLE(hsd); 
/* Set Power State to ON 對(duì)SD卡進(jìn)行上電 */
  SDIO_PowerState_ON(hsd- >Instance);
/* Enable SDIO Clock */
  __HAL_SD_ENABLE(hsd);
/* Required power up waiting time before starting the SD initialization 
  sequence */
  HAL_Delay(2U);
/* Identify card operating voltage */
  errorstate = SD_PowerON(hsd);
if(errorstate != HAL_SD_ERROR_NONE)
  {
    hsd- >State = HAL_SD_STATE_READY;
    hsd- >ErrorCode |= errorstate;
return HAL_ERROR;
  }
/* Card initialization */
  errorstate = SD_InitCard(hsd);
if(errorstate != HAL_SD_ERROR_NONE)
  {
    hsd- >State = HAL_SD_STATE_READY;
    hsd- >ErrorCode |= errorstate;
    return HAL_ERROR;
  }
 return HAL_OK;
}
  • SD卡DMA模式操作實(shí)例

當(dāng)SD卡中有大量的音視頻需要讀取時(shí),整個(gè)過(guò)程需要CPU干預(yù),這樣CPU的利用率就會(huì)降低,因此大量數(shù)據(jù)的傳輸最好啟用DMA。

實(shí)驗(yàn)內(nèi)容:向SD卡寫(xiě)入數(shù)據(jù)后讀出。

實(shí)驗(yàn)步驟:工程的時(shí)鐘配置和SDIO配置與普通模式相同,只有一點(diǎn)不同需要打開(kāi)SDIO的全局中斷,因?yàn)镾DIO發(fā)送與接收完成后都需要中斷去生成DMA請(qǐng)求。設(shè)置SDIO全局中斷優(yōu)先級(jí)更高一些,因?yàn)樗鼉?nèi)部還有很多其他中斷,發(fā)生錯(cuò)誤時(shí)更需要處理。

圖片

配置DMA

圖片

編寫(xiě)代碼:

//mian.c


#include "main.h"
#include "stm32f4xx_hal.h"
#include "dma.h"
#include "sdio.h"
#include "usart.h"
#include "gpio.h"


#define SDBUF_SIZE   1024
uint8_t SDBUF_TX[SDBUF_SIZE],SDBUF_RX[SDBUF_SIZE];//數(shù)據(jù)傳輸?shù)腷uf,一個(gè)用于傳輸,一個(gè)用于接收
//定義全局變量,最好不定義局部變量,防止因過(guò)大造成棧溢出
uint8_t DMA_SEND_OK, DMA_RCV_OK;


int main(void)
{
      uint32_t i;
      HAL_SD_CardInfoTypeDef pCardInfo;//定義結(jié)構(gòu)體用來(lái)接收卡信息
      HAL_Init();
      SystemClock_Config();
      MX_GPIO_Init();
      MX_DMA_Init();
      MX_SDIO_SD_Init();
      MX_USART1_UART_Init();


      printf("this is sd testn");
      //卡識(shí)別結(jié)束后就可以調(diào)用HAL_SD_GetCardInfo()函數(shù)獲取卡信息并打印
      HAL_SD_GetCardInfo(&hsd, &pCardInfo);
      printf("pCardInfo.CardType = %un",pCardInfo.CardType);
      printf("pCardInfo.CardVersion = %un",pCardInfo.CardVersion);//版本
      printf("pCardInfo.BlockNbr = %un",pCardInfo.BlockNbr);//SD卡塊數(shù)
      printf("pCardInfo.BlockSize = %un",pCardInfo.BlockSize);//每一塊大小
      /*------------------- SD DMA 寫(xiě)測(cè)試-------------------------------------*/
      memset(SDBUF_TX, 0x2, SDBUF_SIZE );
      DMA_SEND_OK = 0;//設(shè)置發(fā)送完成標(biāo)志位為0,完成時(shí)為1
       /**
       //函數(shù)原型
       *HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, 
                                             uint32_t BlockAdd, uint32_t NumberOfBlocks)

        * @param  hsd Pointer to SD handle
        * @param  pData Pointer to the buffer that will contain the data to transmit
        * @param  BlockAdd Block Address where data will be written  從哪個(gè)塊開(kāi)始寫(xiě)
        * @param  NumberOfBlocks Number of blocks to write寫(xiě)幾個(gè)塊
        * @retval HAL status
        */

      if( HAL_SD_WriteBlocks_DMA(&hsd, SDBUF_TX, 0, 1) == HAL_OK )
      {
          //等待DMA傳輸完成,并且SD卡狀態(tài)為傳輸狀態(tài)
          while( (DMA_SEND_OK ==0 ) || (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER));  
          printf("WriteBlocks Successfullyn");

          for(i=0; i< SDBUF_SIZE; i++)
          {
            printf("%d ",SDBUF_TX[i]);
          }
          printf("rn"); 
          }
          else
          {
             printf("WriteBlocks Failedn");
          }

          /*------------------- SD DMA 讀測(cè)試-------------------------------------*/
          DMA_RCV_OK = 0;//設(shè)置讀取完成標(biāo)志位為0,完成時(shí)為1
          if(HAL_SD_ReadBlocks_DMA(&hsd, SDBUF_RX, 0, 1) == HAL_OK)
          {
              while( (DMA_RCV_OK ==0) || (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER));          
              printf("ReadBlocks Successfullyn");          
              for(i=0; i< SDBUF_SIZE; i++)
              {
                printf("%d ",SDBUF_RX[i]);
              }
              printf("rn");
           }
            else
            {
              printf("ReadBlocks Failedn");
            }
            while (1){}
}
//sdio.c


extern uint8_t DMA_SEND_OK, DMA_RCV_OK;
//發(fā)送完成中斷處理
void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
{
  DMA_SEND_OK = 1;
}
//接收完成中斷處理
 void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)
{
  DMA_RCV_OK = 1;
}
聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 控制器
    +關(guān)注

    關(guān)注

    112

    文章

    16039

    瀏覽量

    176746
  • 嵌入式系統(tǒng)
    +關(guān)注

    關(guān)注

    41

    文章

    3534

    瀏覽量

    128995
  • 適配器
    +關(guān)注

    關(guān)注

    8

    文章

    1901

    瀏覽量

    67786
  • SD卡
    +關(guān)注

    關(guān)注

    2

    文章

    555

    瀏覽量

    63685
  • FIFO存儲(chǔ)
    +關(guān)注

    關(guān)注

    0

    文章

    103

    瀏覽量

    5953
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    SD的原理/操作模式/引腳功能/寄存器介紹

    SDXC ,同這兩者區(qū)別就比較大了,本文我們討論的主要是 SD/SDHC (簡(jiǎn)稱(chēng) SD )。SD
    發(fā)表于 01-14 17:13

    sd接口電路

    sd接口電路是由LPC2000與SD的線(xiàn)路連接圖.
    發(fā)表于 08-24 15:49 ?202次下載
    <b class='flag-5'>sd</b><b class='flag-5'>卡</b>接口電路

    sd-mmc-CPU說(shuō)明資料

    sd-mmc-CPU說(shuō)明資料:sd-mmc-CPU說(shuō)明資料
    發(fā)表于 08-22 17:55 ?25次下載

    SPI模式SD驅(qū)動(dòng)的設(shè)計(jì)與實(shí)現(xiàn)

    SPI模式SD驅(qū)動(dòng)的設(shè)計(jì)與實(shí)現(xiàn) SD以其優(yōu)越的性能在嵌入式設(shè)備上得到廣泛的應(yīng)用。介紹在 S1C33L05 處理器上利用 SPI總線(xiàn)進(jìn)
    發(fā)表于 02-11 08:50 ?240次下載

    SD詳細(xì)介紹

    SD詳細(xì)介紹 SD(Secure Digital Memory Card)是一種基于半導(dǎo)體快閃記憶器的新一代記憶設(shè)備。SD
    發(fā)表于 04-12 12:30 ?1612次閱讀

    SD-IDE是什么?

    SD-IDE是什么?  問(wèn):最近在逛電子市場(chǎng)時(shí),發(fā)現(xiàn)一種SD-IDE,商家說(shuō)這種設(shè)備可以將
    發(fā)表于 02-05 09:29 ?1368次閱讀

    SD要點(diǎn)說(shuō)明

    SD有兩個(gè)可選的通信協(xié)議:SD模式和SPI模式。為了電路的簡(jiǎn)化,選用SPI模式
    發(fā)表于 07-11 18:00 ?266次下載
    <b class='flag-5'>SD</b><b class='flag-5'>卡</b>要點(diǎn)說(shuō)明

    SD的SPI模式(中文)

    SD的SPI模式(中文),學(xué)習(xí)手機(jī)、GPS定位的好資料。
    發(fā)表于 01-06 14:25 ?0次下載

    spi讀取sd數(shù)據(jù)例程

    SD 有兩個(gè)可選的通訊協(xié)議:SD 模式和 SPI模式 SD
    發(fā)表于 02-02 13:55 ?8916次閱讀
    spi讀取<b class='flag-5'>sd</b><b class='flag-5'>卡</b>數(shù)據(jù)例程

    SD端子定義,sd card pin description

    SD端子定義,sd card pin description 關(guān)鍵字:SD端子定義
    的頭像 發(fā)表于 09-20 18:53 ?2444次閱讀

    SD的簡(jiǎn)介和操作資料概述

    SD使用內(nèi)智能控制模塊進(jìn)行FLASH操作控制,包括協(xié)議、安全算法、數(shù)據(jù)存取、ECC算法、缺陷處理和分析、電源管理、時(shí)鐘管理。
    發(fā)表于 06-04 08:00 ?0次下載
    <b class='flag-5'>SD</b><b class='flag-5'>卡</b>的簡(jiǎn)介和<b class='flag-5'>操作</b>資料概述

    SD nand 與 SD的SPI模式驅(qū)動(dòng)

    文章目錄SDnand與SD的SPI模式驅(qū)動(dòng)1.概述2.SPI接口模式SD接口模式區(qū)別2.1接
    的頭像 發(fā)表于 05-10 17:45 ?1263次閱讀
    <b class='flag-5'>SD</b> nand 與 <b class='flag-5'>SD</b><b class='flag-5'>卡</b>的SPI<b class='flag-5'>模式</b>驅(qū)動(dòng)

    怎么通過(guò)FPGA采取SD模式實(shí)現(xiàn)Micro SD的驅(qū)動(dòng)

    在這篇文章,進(jìn)入正題,說(shuō)一說(shuō)怎么通過(guò)FPGA采取SD模式來(lái)實(shí)現(xiàn)Micro SD 的驅(qū)動(dòng),也就是怎么去讀寫(xiě) Micro SD
    的頭像 發(fā)表于 09-19 11:48 ?2016次閱讀
    怎么通過(guò)FPGA采取<b class='flag-5'>SD</b><b class='flag-5'>模式</b>實(shí)現(xiàn)Micro <b class='flag-5'>SD</b><b class='flag-5'>卡</b>的驅(qū)動(dòng)

    MicroSD如何轉(zhuǎn)接成SD?

    SD套主要用于將TF(MicroSD)轉(zhuǎn)接成SD的形狀,以實(shí)現(xiàn)TF卡在
    的頭像 發(fā)表于 01-11 14:00 ?1225次閱讀
    MicroSD<b class='flag-5'>卡</b>如何轉(zhuǎn)接成<b class='flag-5'>SD</b><b class='flag-5'>卡</b>?

    貼片式SD功能介紹【MK SD NAND】

    SDNAND,通常稱(chēng)為嵌入式SD、貼片式TF、SD Flash、直接貼裝SD、貼裝
    的頭像 發(fā)表于 07-05 17:03 ?549次閱讀
    貼片式<b class='flag-5'>SD</b><b class='flag-5'>卡</b>功能介紹【MK <b class='flag-5'>SD</b> NAND】