当前位置:首页 > 嵌入式 > 嵌入式硬件
[导读]SD的驱动和应用困扰了我很久,寒假的时候看到SD简化版物理层协议的时候就傻掉了,看到SD的驱动快3000行的代码也动摇了。这几天几种地看了一下SD卡的相关内容,总结了一些体

SD的驱动和应用困扰了我很久,寒假的时候看到SD简化版物理层协议的时候就傻掉了,看到SD的驱动快3000行的代码也动摇了。这几天几种地看了一下SD卡的相关内容,总结了一些体会,感觉也没有那么恐怖了。我决定从分层上来讨论SD的驱动和应用,因为这样可以构建一个清晰的逻辑,且不知哪位计算机大师曾说过:一切计算机问题都可以用分层的方法来解决。
我自己把SD卡从驱动到应用共分为4层,从下至上依次为:驱动层、物理层、文件系统层、应用层。下面一一来介绍各层的一些重要的操作。
1)驱动层
驱动层,对应到ST的库,就是stm32f10x_sdio.c/.h这个两文件。其实使用任何一个STM32的外设,只要用库函数都离不开这一对互相对应的.c/.h文件。对于SDIO外设来说,它就是用来操作寄存器的,由于涉及ST库函数的编写,没能力参透,在此不赘述它的实现过程。
2)物理层
这一层可以说是承上启下的一层,下接驱动层,用于操作寄存器,上接文件系统层,用于统一管理文件,可谓整个SD驱动的核心代码。其实,如果对于SD的要求不高,可以直接在这一层上面进行文件操作,只是没有文件系统操作起来实在不便。之所以叫物理层是因为这一部分的代码主要参考了“SD卡物理层简化协议”这样一个东西。这个协议规定了控制器对SD卡操作的各种指令的格式和操作时序。这一层对应了源代码中的sdio_sdcard.c/.h这两个文件,那么它主要实现了什么功能呢?这一层最重要的一个函数就是SD_Init()——SD卡的初始化函数。这函数包括了SD卡的上电、识别、卡初始这三个重要步骤,分别对应两个子函数——SD_PowerOn、SD_InitializeCards(),而SD_InitializeCards()的返回值包含了卡的类型信息。这两个子函数的实现则是通过STM32内置的SDIO控制器发送CMD命令完成,这个命令的发送要严格遵守SD协议的流程图,而且要及时进行标志位判断,否则很容易程序跑飞了。发送CMD命令是通过填写SDIO_CmdInitStructure这个结构体完成的。举个例子:
SDIO_CmdInitStructure.SDIO_Argument = 0x00;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
这个结构体包含了五个参数,从上至下分别控制的是:参数、命令索引、响应格式、是否等待、硬件流控制。填写了五个结构体也就也就配置好了一个CMD命令格式,使用SDIO_SendCommand()函数发送命令即可。当然,这一层还包含了一些其他外设的初始化——NVIC(配置中断向量优先级)、GPIO(配置了SD插槽的IO口)、DMA(使用DMA模式传输)。总结一下这部分就是主机(STM32)用CMD命令控制了SD卡,所以说在这一层上就已经可以直接调用函数来进行初始化、读写操作了。那么为什么又会有文件系统层呢?
3)文件系统层
它的存在就是用来管理文件的。一个SD卡,现在普通的8个G,要是直接使用物理层来操作,就要操作人来记住好多文件的地址、长度等等,这些事情本来就是计算机可以完成的,所以人们就发明了文件系统这么个东西,用来管理大容量储存设备,在文件系统之上来进行操作,整个格局就显得很大了,也更高端大气上档次,否则调用个文件就要写个地址,什么0x20000f54之类的,用的人不得疯了。说了这么多,文件系统的作用就是一个管理层,下接SD的物理层,用来发送各种CMD操作SDIO控制器的寄存器,上承应用函数,封装好了由开发人员自由调用,可以说也是承上启下的关键代码。而且很幸运的是已经有人替你写好了这个代码的绝大部分,你只需要进行适量的修改就能为你所用,搭建起一个文件系统来。FATFS就是在一个很遥远的地方的好心人已经替你写好的东西,这东西通用性很强,与驱动层完全脱离,留下了一些接口函数,往哪个平台上移植,就填写相应的接口函数即可。这个接口连接了SD卡的物理层和文件系统的操作函数。这一层对应的ff.c/.h文件由于也是很遥远的大神编写的,参透不能。故在此不讲怎么实现。
4)应用层
这一层应该是硬件开发人员发挥的一层,因为对应的平台不同,这一层的接口函数填写就完全不同。应用层就是由上一层(文件系统层)留下的各种接口构成,我们填写了接口函数,就可以直接跑文件系统了。怎么写接口函数呢?FATFS在留接口时除了留下了函数名,还留下了参数以及参数对应的功能和格式。帮助文件中有对应接口函数要实现的功能,其实不用查帮助文件通过接口函数的名字也能猜到,比如disk_read就是读盘。这个接口函数要实现读盘功能,就得调用在物理层写下的各种函数,如SD_ReadBlock(),只要注意子函数与母函数调用参数要一致就行,这个一致性就需要开发人员充分理解函数参数功能了。这部分代码很少,编写起来也不是很难,就是要注意记得判断标志位。
至此,SD的操作函数就已经被封装好了,只需要查询FATFS中各种操作函数的功能既可以调用它。
SD驱动还有很多问题没有搞清楚,之前只是对着源码单步调试,看了看功能实现过程,接下来就准备动手移植文件系统试试了,希望能成功。SD驱动做起来还是很有意思的,通过它与其他外设,比如MP3模块或液晶屏模块连接可以实现歌曲播放和图片显示,还是颇有成就感。以前在用电子产品的时候没想到想听首歌看张图这么复杂,从0101的最原始编码到我们看到听到的模拟信号经过了这么多道的工序,想起来也只得感叹人类智慧的无穷尽也。0次

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭