SDIO模式
SDIO簡介
SD/SDIO/MMC 主機接口可以支援 MMC 卡系統規範 4.2 版中的 3 個不同的資料。總線模式:1 位(預設)、4 位和 8 位。在 8 位模式下,該接口可以使資料傳輸速率達到 48MHz,該接口相容 SD 存儲卡規範 2.0 版。SDIO 存儲卡規範 2.0 版支援兩種資料總線模式:1 位(預設)和 4 位。
目前的晶片版本隻能一次支援一個 SD/SDIO/MMC 4.2 版的卡,但可以同
時支援多個 MMC 4.1 版或之前版本的卡。除了 SD/SDIO/MMC,這個接口完全
與 CE-ATA 數字協定版本 1.1 相容。
SD協定

SDIO的時鐘
SDIO_CK 時鐘是通過 PC12 引腳連接配接到 SD 卡的,是 SDIO 接口與 SD 卡用于同步的時鐘。
SDIO 選配器挂載到 AHB 總線上,通過 HCLK 二分頻輸入到擴充卡得到SDIO_CK 的時鐘,這時 SDIO_CK = HCLK/(2+CLKDIV)。其中 CLKDIV 是SDIO_CLK(寄存器)中的 CLKDIV 位。
另外,SDIO_CK 也可以由 SDIOCLK 通過設定 bypass 模式直接得到,這時SDIO_CK = SDIOCLK=HCLK。
通過下面的庫函數來配置時鐘:
SDIO_Init(&SDIO_InitStructure);
對 SD 卡的操作一般是大吞吐量的資料傳輸,是以采用 DMA 來提高效率,SDIO 采用的是 DMA2 中的通道 4。在資料傳輸的時候 SDIO 可向 DMA 送出請求。
SDIO 的指令、資料傳輸方式
SDIO 的所有指令及指令響應,都是通過 SDIO-CMD 引腳來傳輸的。
指令隻能由 host 即 STM32 的 SDIO 控制器發出。SDIO 協定把指令分成了11 種,包括基本指令,讀寫指令還有 ACMD 系列指令等。其中,在發送 ACMD指令前,要先向卡發送編号為 CMD55 的指令。
下面的指令格式圖,其中的 start bit,transmission bit ,crc7,endbit,都是由 STM32 中的 SDIO 硬體完成,我們在軟體上配置的時候隻需要設定 command index 和指令參數 argument。Command index 就是指令索引(編号),如 CMD0,CMD1…被編号成 0,1...。有的指令會包含參數,讀指令的位址參數等,這個參數被存放在 argument 段。
SD 卡指令格式
通過下面的函數來配置、發送指令:
SDIO_SendCommand(&SDIO_CmdInitStructure);
SD 卡對 host 的各種指令的回複稱為響應,除了 CMD0 指令外,SD 卡在接收到指令都會傳回一個響應。對于不同的指令,會有不同的響應格式,共 7種,分為長響應型(136bit)和短響應型(48bit)。以下圖,響應 6(R6)為例:
SD 卡指令響應格式(R6)
SDIO 通過 CMD 接收到響應後,硬體去除頭尾的資訊,把 command index儲存到 SDIO_RESPCMD 寄存器,把 argument field 内容儲存存儲到SDIO_RESPx 寄存器中。這兩個值可以分别通過下面的庫函數得到。
SDIO_GetCommandResponse(); //卡傳回接收到的指令
SDIO_GetResponse(SDIO_RESP1); //卡傳回的 argument field 内容
資料寫入,讀取。請看下面的寫資料時序圖,在軟體上,我們要處理的隻是讀忙。另外,我們的實驗中用的是 Micro SD 卡,有 4 條資料線,預設的時候 SDIO 采用 1 條資料線的傳輸方式,更改為 4 條資料線模式要通過向卡發送指令來更改。
卡的種類
STM32 的 SDIO 支援 SD 存儲卡,SD I/O 卡 ,MMC 卡。
其中 SDI/O 卡與 SD 存儲卡是有差別的,SDI/O 卡實際上就是利用 SDIO 接口的一些子產品,插入 SD 的插槽中,擴充裝置的功能,如:SDI/O wifi, SDI/Ocmos 相機等。而 SD 存儲卡就是我們平時常見的單純用于存儲資料的卡。
下面以SD卡讀寫測試為例:
Main函數入口
int main(void)
{
NVIC_Configuration();
RS232_Init(9600);
printf( " 開始初始化\r\n " );
if( SD_OK == ( Status = SD_Init() ) )
printf( "初始化成功 \r\n " );
else
printf("初始化失敗 \r\n" );
printf( " \r\n CardType is :%d ", SDCardInfo.CardType );
printf( " \r\n CardCapacity is :%d ", SDCardInfo.CardCapacity );
printf( " \r\n CardBlockSize is :%d ", SDCardInfo.CardBlockSize );
printf( " \r\n RCA is :%d ", SDCardInfo.RCA);
printf( " \r\n ManufacturerID is :%d \r\n", SDCardInfo.SD_cid.ManufacturerID );
SD_EraseTest();
SD_SingleBlockTest();
SD_MultiBlockTest();
while (1)
{}
}
用 NVIC_Configuration() 初始化好 SDIO 的中斷;用 RS232_Init(9600); 配置好用于傳回調試資訊的序列槽, SD_Init() 開始
進行 SDIO 的初始化;最後分别用 SD_EraseTest()、SD_SingleBlockTest()、SD_MultiBlockTest()
進行擦除,單資料塊讀寫,多資料塊讀寫測試。
SD_Init() SD初始化 卡處于傳輸資料狀态
SD_Error SD_Init(void)
{
SD_Error errorstatus = SD_OK;
GPIO_Configuration();
SDIO_DeInit();
errorstatus = SD_PowerON();
if (errorstatus != SD_OK)
{
return(errorstatus);
}
errorstatus = SD_InitializeCards();
if (errorstatus != SD_OK)
{
return(errorstatus);
}
SDIO_InitStructure.SDIO_ClockDiv = SDIO_TRANSFER_CLK_DIV;
SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising;
SDIO_InitStructure.SDIO_ClockBypass=SDIO_ClockBypass_Disable;
SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable;
SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_1b;
SDIO_InitStructure.SDIO_HardwareFlowControl=SDIO_HardwareFlowControl_Disable;
SDIO_Init(&SDIO_InitStructure);
if (errorstatus == SD_OK)
{
errorstatus = SD_GetCardInfo(&SDCardInfo);
}
if (errorstatus == SD_OK)
{
errorstatus = SD_SelectDeselect((uint32_t) (SDCardInfo.RCA << 16));
}
if (errorstatus == SD_OK)
{
errorstatus = SD_EnableWideBusOperation(SDIO_BusWide_4b);
}
return(errorstatus);
}
用 GPIO_Configuration() 進行 SDIO 的端口底層配置
分别調用了 SD_PowerON()和 SD_InitializeCards()函數,這兩個函數共同實作了上面提到的卡檢測、識别流程。
調用 SDIO_Init(&SDIO_InitStructure) 庫函數配置 SDIO 的時鐘,資料線寬度,硬體流(在讀寫資料的時候,開啟硬體流是和很必要的,可以減少出錯)。
調用 SD_GetCardInfo(&SDCardInfo) 擷取 sd 卡的 CSD 寄存器中的内容,在main 函數裡輸出到序列槽的資料就是這個時候從卡讀取得到的。
調用 SD_SelectDeselect() 標明後面即将要操作的卡。
調用 SD_EnableWideBusOperation(SDIO_BusWide_4b) 開啟 4bit 資料線模式。
如果 SD_Init() 函數能夠執行完整個流程,并且傳回值是 SD_OK 的話則說明初始
化成功,就可以開始進行擦除、讀寫的操作了。
分析SD_PowerON()的工作過程,大緻能了解SDIO的接收和發送指令的過程。下面将會上傳完整的工程到我的網盤,工程裡附帶詳細的注釋和完整的代碼,有需要的自行下載下傳。連結:https://pan.baidu.com/s/1ancN8BAqB_NkHuvwnKGWJg 提取碼:9pjm
有興趣的可以加一下我建立的STM32技術交流群:956967059,一起交流STM32技術,有疑問大家可以一起幫忙解決。