-第2页-0、友情提示《零死角玩转STM32》系列教程由初级篇、中级篇、高级篇、系统篇、四个部分组成,根据野火STM32开发板旧版教程升级而来,且经过重新深入编写,重新排版,更适合初学者,步步为营,从入门到精通,从裸奔到系统,让您零死角玩转STM32。M3的世界,与野火同行,乐意惬无边。另外,野火团队历时一年精心打造的《STM32库开发实战指南》将于今年10月份由机械工业出版社出版,该书的排版更适于纸质书本阅读以及更有利于查阅资料。内容上会给你带来更多的惊喜。是一本学习STM32必备的工具书。敬请期待!-第3页-1、SDIO(4bit+DMA、支持SDHC)1.1实验描述及工程文件清单实验描述MicroSD卡(SDIO模式)测试实验,采用4bit数据线模式。没有跑文件系统,只是单纯地读block并将测试信息通过串口1在电脑的超级终端上打印出来。硬件连接PC12-SDIO-CLK:CLKPC10-SDIO-D2:DATA2PC11-SDIO-D3:CD/DATA3PD2-SDIO-CMD:CMDPC8-SDIO-D0:DATA0PC9-SDIO-D1:DATA1用到的库文件startup/start_stm32f10x_hd.cCMSIS/core_cm3.cCMSIS/system_stm32f10x.cFWlib/stm32f10x_gpio.cFWlib/stm32f10x_rcc.cFWlib/stm32f10x_usart.cFWlib/stm32f10x_sdio.cFWlib/stm32f10x_dma.cFWlib/misc.c用户编写的文件USER/main.cUSER/stm32f10x_it.cUSER/usart1.cUSER/sdio_sdcard.c-第4页-野火STM32开发板MicroSD卡硬件原理图:1.2SDIO简介野火STM32开发板的CPU(STM32F103VET6)具有一个SDIO接口。SD/SDIO/MMC主机接口可以支持MMC卡系统规范4.2版中的3个不同的数据总线模式:1位(默认)、4位和8位。在8位模式下,该接口可以使数据传输速率达到48MHz,该接口兼容SD存储卡规范2.0版。SDIO存储卡规范2.0版支持两种数据总线模式:1位(默认)和4位。目前的芯片版本只能一次支持一个SD/SDIO/MMC4.2版的卡,但可以同时支持多个MMC4.1版或之前版本的卡。除了SD/SDIO/MMC,这个接口完全与CE-ATA数字协议版本1.1兼容。1.3SD协议大多数人原来没有了解过SD协议,又看到SDIO的驱动有2000多行,感觉无从下手。所以野火重新写了这个文档进行详细的解释,帮助大家更快地跨过这道槛。附资料:《Simplified_Physical_Layer_Spec.pdf》,这个资料包含了SDIO协议中SD存储卡的部分。-第5页-下面野火结合STM32的SDIO,分析SD协议,让大家对它先有个大概了解,更具体的说明在代码中展开。SDIO接口图一.从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。通过下面的库函数来配置时钟:1.SDIO_Init(&SDIO_InitStructure);对SD卡的操作一般是大吞吐量的数据传输,所以采用DMA来提高效率,SDIO采用的是DMA2中的通道4。在数据传输的时候SDIO可向DMA发出请求。二.讲解SDIO的命令、数据传输方式。SDIO的所有命令及命令响应,都是通过SDIO-CMD引脚来传输的。-第6页-命令只能由host即STM32的SDIO控制器发出。SDIO协议把命令分成了11种,包括基本命令,读写命令还有ACMD系列命令等。其中,在发送ACMD命令前,要先向卡发送编号为CMD55的命令。参照下面的命令格式图,其中的startbit,transmissionbit,crc7,endbit,都是由STM32中的SDIO硬件完成,我们在软件上配置的时候只需要设置commandindex和命令参数argument。Commandindex就是命令索引(编号),如CMD0,CMD1…被编号成0,1...。有的命令会包含参数,读命令的地址参数等,这个参数被存放在argument段。SD卡命令格式可以通过下面的函数来配置、发送命令:1.SDIO_SendCommand(&SDIO_CmdInitStructure);//发送命令SD卡对host的各种命令的回复称为响应,除了CMD0命令外,SD卡在接收到命令都会返回一个响应。对于不同的命令,会有不同的响应格式,共7种,分为长响应型(136bit)和短响应型(48bit)。以下图,响应6(R6)为例:SD卡命令响应格式(R6)-第7页-SDIO通过CMD接收到响应后,硬件去除头尾的信息,把commandindex保存到SDIO_RESPCMD寄存器,把argumentfield内容保存存储到SDIO_RESPx寄存器中。这两个值可以分别通过下面的库函数得到。1.SDIO_GetCommandResponse();//卡返回接收到的命令2.SDIO_GetResponse(SDIO_RESP1);//卡返回的argumentfield内容数据写入,读取。请看下面的写数据时序图,在软件上,我们要处理的只是读忙。另外,我们的实验中用的是MicroSD卡,有4条数据线,默认的时候SDIO采用1条数据线的传输方式,更改为4条数据线模式要通过向卡发送命令来更改。SD卡的多块写入时序图三.卡的种类。STM32的SDIO支持SD存储卡,SDI/O卡,MMC卡。其中SDI/O卡与SD存储卡是有区别的,SDI/O卡实际上就是利用SDIO接口的一些模块,插入SD的插槽中,扩展设备的功能,如:SDI/Owifi,SDI/Ocmos相机等。而SD存储卡就是我们平时常见的单纯用于存储数据的卡。-第8页-可使用SDIO接口类型的卡本实验中使用的MicroSD卡属于SDSC(标准容量,最大两G)卡。介绍卡的种类是因为SD协议中的命令也支持这三种类型的卡,因此对STM32中的SDIO接口进行初始化后,上电后就要对接入的卡进行检测、分类,这个过程是通过向卡发送一系列不同的命令,根据卡不同的响应来进行分类。下面进入代码展开具体讲解。1.4代码分析首先要添加用的库文件,在工程文件夹下Fwlib下我们需添加以下库文件:FWlib/stm32f10x_gpio.cFWlib/stm32f10x_rcc.cFWlib/stm32f10x_usart.cFWlib/stm32f10x_sdio.cFWlib/stm32f10x_dma.cFWlib/misc.c还要在stm32f10x_conf.h中把相应的头文件添加进来:-第9页-1.#includestm32f10x_dma.h2.#includestm32f10x_gpio.h3.#includestm32f10x_rcc.h4.#includestm32f10x_sdio.h5.#includestm32f10x_usart.h6.#includemisc.h保持良好的习惯,从main函数开始分析:1.intmain(void)2.{3.4./*进入到main函数前,启动文件startup(startup_stm32f10x_xx.s)已经调用了在5.system_stm32f10x.c中的SystemInit(),配置好了系统时钟,在外部晶振8M的条件下,6.设置HCLK=72M*/7.8./*InterruptConfig*/9.NVIC_Configuration();10.11./*USART1config*/12.USART1_Config();13.14./*------------------------------SDInit----------------------------------*/15.Status=SD_Init();16.17.printf(\r\n这是一个MicroSD卡实验(没有跑文件系统).........\r\n);18.19.20.if(Status==SD_OK)//检测初始化是否成功21.{22.printf(\r\nSD_Init初始化成功\r\n);23.}24.else25.{26.printf(\r\nSD_Init初始化失败\r\n);27.printf(\r\n返回的Status的值为:%d\r\n,Status);28.}29.30.printf(\r\nCardTypeis:%d,SDCardInfo.CardType);31.printf(\r\nCardCapacityis:%d,SDCardInfo.CardCapacity);32.printf(\r\nCardBlockSizeis:%d,SDCardInfo.CardBlockSize);33.printf(\r\nRCAis:%d,SDCardInfo.RCA);34.printf(\r\nManufacturerIDis:%d\r\n,SDCardInfo.SD_cid.ManufacturerID);35.36.SD_EraseTest();//擦除测试37.38.SD_SingleBlockTest();//单块读写测试39.40.SD_MultiBlockTest();//多块读写测试41.42.while(1)43.{}44.}-第10页-main函数的流程简单明了:1.用NVIC_Configuration()初始化好SDIO的中断;2.用USART1_Config()配置好用于返回调试信息的串口,SD_Init()开始进行SDIO的初始化;3.最后分别用SD_EraseTest()、SD_SingleBlockTest()、SD_MultiBlockTest()进行擦除,单数据块读写,多数据块读写测试。下面我们先进入SDIO驱动函数的大头——SD_Init()进行分析:1./*2.*函数名:SD_Init3.*描述:初始化SD卡,使卡处于就绪状态(准备传输数据)4.*输入:无5.*输出:-SD_ErrorSD卡错误代码6.*成功时则为SD_OK7.*调用:外部调用8.*/9.SD_ErrorSD_Init(void)10.{11./*重置SD_Error状态*/12.SD_Errorerrorstatus=SD_OK;13.14./*SDIO外设底层引脚初始化*/15.GPIO_Configuration();16.17./*对SDIO的所有寄存器进行复位*/18.SDIO_DeInit();19.20./*上电并进行卡识别流程,确认卡的操作电压*/21.errorstatus=SD_PowerON();22.23./*如果上电,识别不成功,返回“响应超时”错误*/24.if(errorstatus!=SD_OK)25.{26./*!CMDResponseTimeOut(waitforCMDSENTflag)*/27.return(errorstatus);28.}29.30./*卡识别成功,进行卡初始化*/31.errorstatus=SD_InitializeCards();32.33.if(errorstatus!=SD_OK)//失败返回34.{35./*!CMDResponseTimeOut(waitforCMDSENTflag)*/36.return(errorstatus);37.}38.39./*!ConfiguretheS