1、SDIO簡介
SDIO,全稱:Secure Digital Input and Output,即安全數字輸入輸出介面,它是在SD卡介面的基礎上發展而來,它可以兼容之前的SD卡,并可以連接SDIO介面設備,比如:藍牙、WIFI、照相機等,
SDIO和SD卡規范間的一個重要區別是增加了低速標準,低速卡的目標應用是以最小的硬體開支支持低速I/O能力,低速卡支持類似調制解調器、條碼掃描儀和GPS接收器等應用,
STM32的SDIO控制器支持多媒體卡(MMC卡)、SD存盤卡、SDI/O卡和CE-ATA設備,
SDIO框圖

復位后SDIO_D0用于資料傳輸,初始化后主機可以改變資料總線的寬度(通過ACMD6命令設定)
如果一個多媒體卡接到了總線上,則SDIO_D0、SDIO_D[3:0]或SDIO_D[7:0]可以用于資料傳輸,
MMC版本V3.31和之前版本的協議只支持1位資料線,所以只能用SDIO_D0(為了通用性考慮,在程式里面我們只要檢測到是MMC卡就設定為1位總線資料)
02、SDIO特點
①與多媒體卡系統規格書版本4.2全兼容,支持三種不同的資料總線模式:1位(默認)、4位和8位,
②與較早的多媒體卡系統規格版本全兼容(向前兼容),
③與SD存盤卡規格版本2.0全兼容,
④與SDI/O卡規格版本2.0全兼容:支持兩種不同的資料總線模式:1位(默認)和4位,
⑤完全支持CE-ATA功能(與CE-ATA數字協議版本1.1全兼容),8位總線模式下資料傳輸速率可達48MHz,
⑥資料和命令輸出使能信號,用于控制外部雙向驅動器,
03、SDIO時鐘
卡時鐘(SDIO_CK):每個時鐘周期在命令和資料線上傳輸1位命令或資料,對于SD或SD I/O卡,時鐘頻率可以在0MHz至25MHz間變化,
SDIO配接器時鐘(SDIOCLK):該時鐘用于驅動SDIO配接器,可用于產生SDIO_CK時鐘,SDIOCLK來自PLL48CK(48Mhz),
APB2總線介面時鐘(PCLK2):該時鐘用于驅動SDIO的APB2總線介面,其頻率為PCLK2=84Mhz,
SDIO_CK計算公式:SDIO_CK=SDIOCLK/(2+CLKDIV)
注意:在SD卡初始化時,SDIO_CK不可以超過400Khz,初始化完成后,可以設定為最大頻率(但不可以超過SD卡最大操作頻率)
04、SDIO的命令與回應
命令
SDIO的命令分為:應用相關命令(ACMD)和通用命令(CMD)兩部分,發送ACMD時,需先發送CMD55,
SDIO所有的命令和回應都是在SDIO_CMD引腳上面傳輸的,命令長度固定為48位,SDIO命令格式如下表所示:

其中:除了命令索引和引數需要我們設定,其他都是由SDIO硬體自動控制,命令索引(如CMD0,CMD1之類)由SDIO_CMD暫存器設定,命令引數則由SDIO_ARG暫存器設定
回應
一般SD卡在接收到命令列,都會有一個應答(CMD0例外),這個應答我們也稱之為回應,STM32的SDIO介面,支持2種回應型別:短回應(48位)和長回應(136位)
STM32 SDIO短回應(48位)格式如下表所示:

STM32 SDIO長回應(136位)格式如下表所示

不論是短回應還是長回應,硬體都會自動濾除了起始位、傳輸位、CRC7以及結束位等資訊,對于短回應,命令索引存放在SDIO_RESPCMD暫存器,引數則存放在SDIO_RESP1暫存器里面,對于長回應,則僅留CID/CSD位域,存放在SDIO_RESP1~SDIO_RESP4等4個暫存器,
SD卡的回應
SD卡總共有6類回應(R1、R1b、R2、R3、R6、R7),我們這里以R1為例簡單介紹一下,R1(普通回應命令)回應屬于短回應,其長度為48位,如下表所示:

在收到R1回應后,我們可以從SDIO_RESPCMD暫存器和SDIO_RESP1暫存器分別讀出命令索引和卡狀態資訊,關于其他回應的介紹,請大家參考光碟:《SD卡2.0協議.pdf》
05、SDIO塊資料傳輸
多資料塊讀操作
SDIO與SD卡通信一般以資料塊的形式進行傳輸,SDIO(多)資料塊讀操作,如下圖所示

從機在收到主機相關命令后,開始發送資料塊給主機,所有資料塊都帶CRC校驗(由硬體自動處理),單個資料塊讀的時候,在收到1個資料塊以后即可以停止了,不需要發送停止命令(CMD12).但是多塊資料讀的時候,SD卡將一直發送資料給主機,直到接到主機發送的STOP命令(CMD12)
多資料塊寫操作
SDIO(多)資料塊寫操作,如下圖所示

資料塊寫操作同資料塊讀操作基本類似,只是資料塊寫的時候,多了一個繁忙判斷,新的資料塊必須在SD卡非繁忙的時候發送,這里的繁忙信號由SD卡拉低SDIO_D0,以表示繁忙,SDIO硬體自動控制,不需要我們軟體處理,
注意:當SDIO_CK頻率過快時,可能導致SD卡通信失敗,此時,建議降低SDIO_CK試試,
06、代碼
STM32的SDIO控制器驅動還是很復雜的,ST提供了stm32f2x_sdio_sd.c驅動檔案,我們組要修改對應的GPIO驅動即可,
/** * @brief Initializes the SD Card and put it into StandBy State (Ready for * data transfer). * @param None * @retval None */ void SD_LowLevel_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; /* GPIOC and GPIOD Periph clock enable */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | SD_DETECT_GPIO_CLK, ENABLE); GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_SDIO); GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_SDIO); GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_SDIO); GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_SDIO); GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_SDIO); GPIO_PinAFConfig(GPIOD, GPIO_PinSource2, GPIO_AF_SDIO); /* Configure PC.08, PC.09, PC.10, PC.11 pins: D0, D1, D2, D3 pins */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOC, &GPIO_InitStructure); /* Configure PD.02 CMD line */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_Init(GPIOD, &GPIO_InitStructure); /* Configure PC.12 pin: CLK pin */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOC, &GPIO_InitStructure); /*!< Configure SD_SPI_DETECT_PIN pin: SD Card detect pin */ /*GPIO_InitStructure.GPIO_Pin = SD_DETECT_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(SD_DETECT_GPIO_PORT, &GPIO_InitStructure);*/ /* Enable the SDIO APB2 Clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_SDIO, ENABLE); /* Enable the DMA2 Clock */ RCC_AHB1PeriphClockCmd(SD_SDIO_DMA_CLK, ENABLE); }
DMA等配置使用默認的即可,
我們需要使用的函式介面有
SD_Error SD_Init(void); SD_Error SD_Erase(uint32_t startaddr, uint32_t endaddr); SD_Error SD_WriteBlock(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize); SD_Error SD_ReadBlock(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize);
下載驗證

SDIO驅動和硬體PCB開源地址:
https://github.com/strongercjd/STM32F207VCT6
點擊查看本文所在的專輯,STM32F207教程
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/265795.html
標籤:其他
上一篇:STM32 SDIO詳解
下一篇:Linux 守護行程
