SDIO协议简介
SDIO简介
SDIO接口设备
目前 SD 协议提供的 SD 卡规范版本最新是 4.01 版本,但 STM32F10x 系列控制器只支持 SD 卡规范版本 2.0,即只支持标准容量 SD 和高容量SDHC 标准卡,不支持超大容量 SDXC 标准卡,所以可以支持的最高卡容量是 32GB。
如下图所示(左边64GB为超大容量 SDXC,右边32GB为大容量 SDHC):
SD卡物理结构
一张SD卡包括有存储单元、存储单元接口、电源检测、卡及接口控制器和接口驱动器5个部分。
SD 卡总共有 8 个寄存器,用于设定或表示 SD 卡信息。这些寄存器只能通过对应的命令访问,对 SD 卡进行控制操作并不是像操作控制器 GPIO 相关寄存器那样一次读写一个寄存器的,它是通过命令来控制。 SDIO 定义了 64 个命令,每个命令都有特殊意义,可以实现某一特定功能, SD 卡接收到命令后,根据命令要求对 SD 卡内部寄存器进行修改,程序控制中只需要发送组合命令就可以实现 SD 卡的控制以及读写操作。
SD卡寄存器描述(很复杂,只需要关注常用的几个就可以):
SD卡总线结构:
引脚说明和操作时序:
SDIO和SPI的区别:
SDIO明显时钟频率更快,而且SDIO拥有4根数据线,同等频率下通信速度能提高4倍。
总线协议
SD 总线通信是基于命令和数据传输的。通讯由一个起始位(0),由一个停止位(1)终止。 SD 通信一般是主机发送一个命令,从设备在接收到命令后作出响应,如有需要会有数据传输参与。
stm32 多数据块写入
SD 数据传输支持单块和多块读写,它们分别对应不同的操作命令,多块写入还需要使用命令来停止整个写入操作。数据写入前需要检测 SD 卡忙状态,因为 SD 卡在接收到数据后编程到存储区过程需要一定操作时间, SD卡忙状态通过把 D0 线拉低表示。
SD卡操作时序:
先发送第1字节,然后发送第2字节,以此类推...
在发送每字节时,D0 ~ D3先发送高 4 位,再发送低 4 位。
宽位数据包格式(专用于SSR寄存器):
SDIO命令及响应
命令
SD 命令由主机发出,以广播命令和寻址命令为例,广播命令是针对与 SD 主机总线连接的所有从设备发送的,寻址命令是指定某个地址设备进行命令传输。
命令格式
命令参数意义:
命令类型:
常规命令(64条)和特定应用命令(厂商自定义的命令)
响应:
响应由 SD 卡向主机发出,部分命令要求 SD 卡作出响应,这些响应多用于反馈SD卡的状态。 SDIO 总共有7个响应类型(代号: R1~R7),其中 SD 卡没有 R4、 R5 类型响应。特定的命令对应有特定的响应类型,比如当主机发送 CMD3 命令时,可以得到响应 R6。与命令一样,SD卡的响应也是通过 CMD 线连续传输的。根据响应内容大小可以分为短响应和长响应。短响应是 48bit 长度,只有 R2 类型是长响应,其长度为 136bit。
命令描述:
如上所示,CMD0命令,类型为无响应广播命令,复位所有卡到空闲状态;
CMD2命令,位带响应广播命令,通知所有卡通过CMD线返回CID值,响应类型为R2;
可以看到,发送命令CMD2,返回R2类型,实际上就是返回CID或者CSD寄存器的值。
当发送CMD2命令后,会返回CID值(128位),这个128位标识符太长,可以通过CMD3命令,通知所有卡发布新RCA(16位)来区分系统上有几张卡(总线上的卡通信后会知道总线上有多少张卡,然后协调并自动分配每张卡的RCA标识符),返回类型为R6,如下所示:
R6类型会返回RCA寄存器值,并返回部分卡状态寄存器值(32位寄存器);
R1类型会返回卡状态寄存器的全部位。
CMD8命令,发送SD卡的接口条件,如果SD卡认为这是正常的电压,则返回R7类型;
数据读取操作(每次读取前,要先设置块的长度):
可以看到,SD卡的数据宽度为32位。注意,这里有区分SDSC(标准容量SD卡)和SDHC(大容量SD卡):
SDSC:地址以字节位单位,如 0 ~ 511地址位第1数据块,512 ~ 1023地址为第2数据块;
SDHC:地址以块为单位,1地址就是第1数据块,2地址就是第2数据块;
块写入操作类似:
块擦除操作(需要使用3个命令):
块擦除需要指定数据起始地址、结束地址、然后开始进行擦除操作;
当有多个SD卡存在时,SD卡如何得知是对哪一张SD卡进行操作?
实际上,要通过CMD7命令,选中一张SD卡。
SD卡操作模式
SD卡操作模式
模式状态如下:
卡识别模式状态机:
数据传输模式状态机:
stm32 SDIO接口
SDIO功能框图:
SDIO适配器:
控制单元:
命令路径:
下面是 stm32 中文参考手册中,相关的寄存器描述:
SDIO参数寄存器:
SDIO命令寄存器:
SDIO响应1...4寄存器(根据短响应or长响应不同来区分)
命令路径状态机:
数据路径:
数据路径状态机:
数据 FIFO
对应的寄存器描述:
SDIO状态寄存器 SDIO_STA
SDIO数据控制寄存器(设置数据块大小):
stm32 SDIO结构体
stm32标准库对 SDIO 外设建立了 3 个结构体,分别为 SDIO 初始化结构体 SDIO_InitTypeDef ,SDIO 命令初始化结构体 SDIO_CmdInitTypeDef 和 SDIO 数据初始化结构体 SDIO_DataInitTypeDef 。
1 SDIO 初始化结构体 SDIO_InitTypeDef
2 SDIO 命令初始化结构体 SDIO_CmdInitTypeDef
3 SDIO 数据初始化结构体 SDIO_DataInitTypeDef
SDIO 驱动分析
1 SD卡 原理图(使用到stm32的6个引脚)
标准库中,实际上给出了 SDIO 的示例,如下所示:
其中包含了 main.c stm32f10x_ic.h 等文件
在 Utilities 文件夹下,提供了评估板的驱动文件(提供了SD卡驱动函数):
以及评估板的BSP支持文件(外设GPIO初始化):
移植过程:
说白了,其实就是把 stm32_eval_sdio_sd.c 文件复制过来,但是,stm32_eval_sdio_sd.c 中会初始化一些外设,如 SDIO_GPIO 初始化,这些外设的初始化和评估板有关,在板级支持包 stm32f10e_eval.c 中实现,因此要把这些初始化程序也复制进来。
如下图所示(移植好的工程和原始工程对比):
移植过程,就是不断的编译,一开始肯定会各种报错(缺少初始化函数,位于stm32f10e_eval.c中),我们去stm32f10e_eval.c这个文件中找到对应的函数,移植添加进来。
注意,SDIO使用了中断,因此我们也需要将中断服务函数移植进来。
这就是移植的过程,测试代码一样在 example 中有提供,同样的可以移植。
驱动分析
下面是函数的执行过程:
if ((Status = SD_Init()) != SD_OK)
{
LED_RED;
printf("SD卡初始化失败,请确保SD卡已正确接入开发板,或换一张SD卡测试!n");
}
else
{
printf("SD卡初始化成功!n");
}
重点就是 SD_Init() 这个SD卡初始化函数:
/**
* 函数名:SD_Init
* 描述 :初始化SD卡,使卡处于就绪状态(准备传输数据)
* 输入 :无
* 输出 :-SD_Error SD卡错误代码
* 成功时则为 SD_OK
* 调用 :外部调用
*/
SD_Error SD_Init(void)
{
/*重置SD_Error状态*/
SD_Error errorstatus = SD_OK;
NVIC_Configuration();
/* SDIO 外设底层引脚初始化 */
GPIO_Configuration();
/*对SDIO的所有寄存器进行复位*/
SDIO_DeInit();
/*上电并进行卡识别流程,确认卡的操作电压 */
errorstatus = SD_PowerON();
/*如果上电,识别不成功,返回“响应超时”错误 */
if (errorstatus != SD_OK)
{
/*!< CMD Response TimeOut (wait for CMDSENT flag) */
return (errorstatus);
}
/*卡识别成功,进行卡初始化 */
errorstatus = SD_InitializeCards();
if (errorstatus != SD_OK) //失败返回
{
/*!< CMD Response TimeOut (wait for CMDSENT flag) */
return (errorstatus);
}
/* 配置SDIO外设
* 上电识别,卡初始化都完成后,进入数据传输模式,提高读写速度
*/
/* SDIOCLK = HCLK, SDIO_CK = HCLK/(2 + SDIO_TRANSFER_CLK_DIV) */
SDIO_InitStructure.SDIO_ClockDiv = SDIO_TRANSFER_CLK_DIV;
/*上升沿采集数据 */
SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising;
/* Bypass模式使能的话,SDIO_CK不经过SDIO_ClockDiv分频 */
SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable;
/* 若开启此功能,在总线空闲时关闭sd_clk时钟 */
SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable;
/* 暂时配置成1bit模式 */
SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_1b;
/* 硬件流,若开启,在FIFO不能进行发送和接收数据时,数据传输暂停 */
SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable;
SDIO_Init(&SDIO_InitStructure);
if (errorstatus == SD_OK)
{
/* 用来读取csd/cid寄存器 */
errorstatus = SD_GetCardInfo(&SDCardInfo);
}
if (errorstatus == SD_OK)
{
/* 通过cmd7 ,rca选择要操作的卡 */
errorstatus = SD_SelectDeselect((uint32_t)(SDCardInfo.RCA << 16));
}
if (errorstatus == SD_OK)
{
/* 最后为了提高读写,开启4bits模式 */
errorstatus = SD_EnableWideBusOperation(SDIO_BusWide_4b);
}
return (errorstatus);
}
1 基本的 NVIC配置(SDIO中断源,中断分组、中断优先级,使能NVIC);
2 SDIO引脚初始化(注意,这里还要使能SDIO AHB总线时钟 + DMA);
/*
* 函数名:GPIO_Configuration
* 描述 :初始化SDIO用到的引脚,开启时钟。
* 输入 :无
* 输出 :无
* 调用 :内部调用
*/
static void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*!< GPIOC and GPIOD Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE);
/*!< Configure PC.08, PC.09, PC.10, PC.11, PC.12 pin: D0, D1, D2, D3, CLK pin */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/*!< Configure PD.02 CMD line */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/*!< Enable the SDIO AHB Clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_SDIO, ENABLE);
/*!< Enable the DMA2 Clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);
}
3 复位 SDIO 寄存器,这个实际上应该放在最前面比较好,但这里因为没有配置寄存器,在这里执行也可以;
/*对SDIO的所有寄存器进行复位*/
SDIO_DeInit();
4 上电识别SD卡;
/* 上电并进行卡识别流程,确认卡的操作电压 */
errorstatus = SD_PowerON();
这里,主要就是 SD_PowerON() 这个函数,实现了SD卡整个的识别过程;
a 初始化时钟;
/******************************************************************************/
/* 上电初始化
* 配置SDIO的外设
* SDIOCLK = HCLK, SDIO_CK = HCLK/(2 + SDIO_INIT_CLK_DIV)
* 初始化时的时钟不能大于400KHz
*/
/* HCLK = 72MHz, SDIOCLK = 72MHz, SDIO_CK = HCLK/(178 + 2) = 400 KHz */
SDIO_InitStructure.SDIO_ClockDiv = SDIO_INIT_CLK_DIV;
SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising;
/* 不使用bypass模式,直接用HCLK进行分频得到SDIO_CK */
SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable;
/* 空闲时不关闭时钟电源 */
SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable;
/* 初始化的时候暂时先把数据线配置成1根 */
SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_1b;
/* 失能硬件流控制 */
SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable;
SDIO_Init(&SDIO_InitStructure);
/* 开启SDIO外设的电源 */
SDIO_SetPowerState(SDIO_PowerState_ON);
/* 使能 SDIO 时钟 */
SDIO_ClockCmd(ENABLE);
b 发送CMD0命令,使SD卡进入空闲状态;
/** 下面发送一系列命令,开始卡识别流程
* CMD0: GO_IDLE_STATE(复位所以SD卡进入空闲状态)
* 没有响应
*/
SDIO_CmdInitStructure.SDIO_Argument = 0x0;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_GO_IDLE_STATE;
/* 没有响应 */
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_No;
/* 关闭等待中断 */
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
/* 则CPSM在开始发送命令之前等待数据传输结束 */
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);
/* 检测是否正确接收到cmd0 */
errorstatus = CmdError();
/* 命令发送出错,返回 */
if (errorstatus != SD_OK)
{
/* CMD Response TimeOut (wait for CMDSENT flag) */
return (errorstatus);
}
/**
* 作用 :检查发送命令超时的函数
* 描述 :对CMD0命令的检查。
* 输出 :SD错误类型
*/
static SD_Error CmdError(void)
{
SD_Error errorstatus = SD_OK;
uint32_t timeout;
timeout = SDIO_CMD0TIMEOUT; /*!< 10000 */
/*检查命令是否已发送*/
while ((timeout > 0) && (SDIO_GetFlagStatus(SDIO_FLAG_CMDSENT) == RESET))
{
timeout--;
}
if (timeout == 0)
{
errorstatus = SD_CMD_RSP_TIMEOUT; // 返回超时
return (errorstatus);
}
/*!< Clear all the static flags */
SDIO_ClearFlag(SDIO_STATIC_FLAGS); //清除静态标志位
return (errorstatus); // 返回SD_OK
}
c 发送 CMD8 命令,判断SD卡是否为2.0协议版本;
d 循环发送 SDIO 支持的电压范围,发送一定次数。如果一直没有应答,说明供电电压不支持,如果没有超出循环次数,说明 SD 卡初始化正常,根据响应值判断SD卡表标准容量还是高容量类型;
5 初始化所有卡(实际上stm32只支持一个SDIO设备);
发送 CMD2 命令,获取CID号并存储;然后发送 CMD3 命令,获取 RCA 地址;
if (SDIO_SECURE_DIGITAL_IO_CARD != CardType)
{
/* Send CMD2 ALL_SEND_CID
* 响应:R2,对应CID寄存器
*/
SDIO_CmdInitStructure.SDIO_Argument = 0x0;
上一篇:stm32专题三十八:在SRAM中调试代码
下一篇:stm32实用篇2: 裸机系统实现多任务轮转
推荐阅读
史海拾趣
对不起,我无法提供关于Allen Avionics Inc 公司的相关故事。
爱特姆在国内市场取得一定成绩后,开始积极拓展国际市场。通过与欧洲、美国等国家的知名企业建立合作关系,爱特姆的产品逐渐打入国际市场,并赢得了良好的口碑。同时,公司还积极参加国际电子展会,与全球同行交流学习,不断提升自身的国际竞争力。
ANYSOLAR LTD.的创立源于一次技术突破。创始人李明,一位资深的电子工程师,在一次实验中意外发现了一种新型光伏材料的制备方法。这种材料具有高效的光电转换效率,且成本远低于市场上的同类产品。李明意识到这是一个巨大的商业机会,于是决定辞去工作,创立ANYSOLAR LTD.,专注于这种新型光伏材料的研发和生产。
初创期的ANYSOLAR面临着资金短缺、人才匮乏和市场认可度低等多重挑战。然而,李明凭借对技术的深厚理解和不懈追求,带领团队攻克了一个又一个技术难题,逐步将产品推向市场。通过参加行业展会、与潜在客户建立联系等方式,ANYSOLAR逐渐赢得了市场的认可。
COMPEX公司自成立以来,一直致力于电子技术的研发与创新。在光通讯领域,公司凭借先进的光通讯模块电路板小器件技术,逐渐在市场中占据了一席之地。COMPEX团队不断突破技术壁垒,推出了多款高性能、高可靠性的产品,赢得了客户的广泛认可。同时,公司还积极与国内外知名企业和研究机构合作,共同推动电子行业的技术进步。
为了降低成本、提高生产效率,AND Displays开始着手整合产业链。公司通过与上游原材料供应商建立长期合作关系,确保原材料的稳定供应和价格优势。同时,公司还加强了对下游客户的服务与支持,通过提供定制化解决方案和优质的售后服务,增强了客户黏性。此外,AND Displays还不断优化生产流程,提高生产效率,进一步降低了生产成本。
随着科技的不断进步,电子行业的发展日新月异。乾坤公司意识到,要想保持领先地位,就必须不断进行技术创新。于是,公司加大了对研发团队的投入,引进了一批高水平的科研人才,并与多所高校和研究机构建立了紧密的合作关系。在一次偶然的实验中,研发团队发现了一种新型材料,可以显著提升电子元器件的性能。经过一系列严格的测试和验证,这种新材料被成功应用于产品生产中,使得乾坤的电子元器件在性能上实现了质的飞跃。这一技术创新不仅为公司带来了丰厚的利润,更让乾坤在电子行业中声名鹊起。
有趣的香蕉手机外壳: 以后如果你看到有人把手机放在耳朵边自言自语,而不是放在嘴里,那你也不要大惊小怪,因为那个人是在打手机。这款有趣的香蕉手机外壳有别于其它手机外壳,适合把一些长条形的手机放在里面,如果你是一个爱搞笑的人,那这就是 ...… 查看全部问答∨ |
现在学校要求做毕业论文 题目是模拟电子万能调试板 题目很大 但内容并不多 就是用个板子可以多次利用做电路 但是我真的不知道如何下手啊 尤其是论文更是头疼 谁能帮帮我给个方向也好啊 谢谢了啊 [ 本帖最后由 nish ...… 查看全部问答∨ |
大家好,我第一次到这学习,呵呵,目前小弟在学习控制舵机,基础的准备都做好了,但是实在查找不到关于360度连续旋转舵机的相关资料,具体如何用51控制舵机360度连续旋转小弟一直很困惑,请各位大虾给予指导,非常感谢!… 查看全部问答∨ |
超低价专业PCB打样 双面板200元/款(含飞针测试) 一、单面板 工艺:喷锡/镀金 规格:10CMX10CM 单价 150元(10PCS) 交期:3-4天 加急1天 二、双面板 工艺:喷锡/镀金&n ...… 查看全部问答∨ |
各位大虾帮帮忙。怎么在Tornado下生成.syms文件啊?跟帖也给分。 .syms是内存映象文件。文档中只说可以使用 -mapped和-readnow用它。但是不知道怎么生成这个文件。 是在编译时在Makefile中加命令生成吗?还是通过代码或者一些选项?… 查看全部问答∨ |
|
本帖最后由 jameswangsynnex 于 2015-3-3 20:00 编辑 需求游戏3D眼镜投影仪3D眼镜影院3D眼镜方案,各种3D眼镜的解决方案,有意者请QQ联系:231628044 … 查看全部问答∨ |
|
导读:新款LED吸顶灯 品牌:鑫久盛 芯片:台湾进口芯片灯体尺寸:灯盘直径:300mmLED功率:18W LED颜色:白/暖白 输入电压:AC110V~AC240V 频率范围:50/60Hz 功率因数:>0.9 显色指数:Ra>90 控制方式:恒流驱动模块 环境温度:-45℃ ...… 查看全部问答∨ |
在项目设计中,因为我们都是直接负责采购器件,所以获得了一些宝贵的经验,现在和大家分享一些。 德州仪器的产品质量非常好,但是也存在一个缺点,那就是价格与其它厂家相比,就是贵一些,当你面对不同的需求时,就需要采取不同的策略。 1、需求 ...… 查看全部问答∨ |
设计资源 培训 开发板 精华推荐
- 解锁 TE 掌上信息智库,获取一站式资源!
- 下载、答题赢好礼:使用Mentor的Xpedition Layout高效设计PCB
- ST AMG SensorTile开发大赛驾到,重磅大奖与知识兼得,速来~
- 下载MPS汽车电机控制技术干货,赢【Keep体脂秤、自动洗手机套装、小米保温杯】,开启汽车技术进阶之旅!
- 有奖直播|TI 新一代Sitara™ AM62处理器革新人机交互——产品介绍和相关资源
- TMS320F28377S LaunchPad俱乐部已成立,让我们一起见证它高性能的魅力!
- Fluke有奖直播:示波器的基础知识及其校准
- 4月TI两场EP直播,都挺好:超声气体流量计量创新方案+SimpleLink平台小鲜肉CC13X2/CC26X2专场