SDIO,全稱:Secure Digital Input and Output,即安全數字輸入輸出接口。它是在SD卡接口的基礎上發展而來,它能夠兼容以前的SD卡,並能夠鏈接SDIO接口設備,好比:藍牙、WIFI、照相機等。git
SDIO和SD卡規範間的一個重要區別是增長了低速標準。低速卡的目標應用是以最小的硬件開支支持低速I/O能力。低速卡支持相似調制解調器、條碼掃描儀和GPS接收器等應用。github
STM32的SDIO控制器支持多媒體卡(MMC卡)、SD存儲卡、SDI/O卡和CE-ATA設備。安全
SDIO框圖app
復位後SDIO_D0用於數據傳輸。初始化後主機能夠改變數據總線的寬度(經過ACMD6命令設置)函數
若是一個多媒體卡接到了總線上,則SDIO_D0、SDIO_D[3:0]或SDIO_D[7:0]能夠用於數據傳輸。 ui
MMC版本V3.31和以前版本的協議只支持1位數據線,因此只能用SDIO_D0(爲了通用性考慮,在程序裏面咱們只要檢測到是MMC卡就設置爲1位總線數據)spa
①與多媒體卡系統規格書版本4.2全兼容。支持三種不一樣的數據總線模式:1位(默認)、4位和8位。命令行
②與較早的多媒體卡系統規格版本全兼容(向前兼容)。code
③與SD存儲卡規格版本2.0全兼容。blog
④與SDI/O卡規格版本2.0全兼容:支持兩種不一樣的數據總線模式:1位(默認)和4位。
⑤徹底支持CE-ATA功能(與CE-ATA數字協議版本1.1全兼容)。8位總線模式下數據傳輸速率可達48MHz。
⑥數據和命令輸出使能信號,用於控制外部雙向驅動器。
卡時鐘(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卡最大操做頻率)
命令
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類響應(R一、R1b、R二、R三、R六、R7),咱們這裏以R1爲例簡單介紹一下。R1(普通響應命令)響應屬於短響應,其長度爲48位,以下表所示:
在收到R1響應後,咱們能夠從SDIO_RESPCMD寄存器和SDIO_RESP1寄存器分別讀出命令索引和卡狀態信息。關於其餘響應的介紹,請你們參考光盤:《SD卡2.0協議.pdf》
多數據塊讀操做
SDIO與SD卡通訊通常以數據塊的形式進行傳輸,SDIO(多)數據塊讀操做,以下圖所示
從機在收到主機相關命令後,開始發送數據塊給主機,全部數據塊都帶CRC校驗(由硬件自動處理),單個數據塊讀的時候,在收到1個數據塊之後便可以中止了,不須要發送中止命令(CMD12).可是多塊數據讀的時候,SD卡將一直髮送數據給主機,直到接到主機發送的STOP命令(CMD12)
多數據塊寫操做
SDIO(多)數據塊寫操做,以下圖所示
數據塊寫操做同數據塊讀操做基本相似,只是數據塊寫的時候,多了一個繁忙判斷,新的數據塊必須在SD卡非繁忙的時候發送。這裏的繁忙信號由SD卡拉低SDIO_D0,以表示繁忙,SDIO硬件自動控制,不須要咱們軟件處理。
注意:當SDIO_CK頻率過快時,可能致使SD卡通訊失敗,此時,建議下降SDIO_CK試試。
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教程