《电子技术应用》
您所在的位置:首页 > 嵌入式技术 > 设计应用 > 嵌入式系统中基于SPI协议的SD卡扩展实现
嵌入式系统中基于SPI协议的SD卡扩展实现
2014年微型机与应用第19期
蔡红专1, 刘 强1, 陈 琎2
1.西京学院 研究生部,陕西 西安 710123; 2.米脂县职业教育中心,陕西 榆林 718100
摘要: 介绍了在嵌入式系统中一种基于SPI协议实现对SD卡的扩展方法,结合FatFs文件系统,使小型嵌入式系统也能容易、方便地扩展大容量存储器。并在STM32上成功移植,打开SD卡中TXT文本,并通过串口输出文本中的内容。
Abstract:
Key words :

  摘 要: 介绍了在嵌入式系统中一种基于SPI协议实现对SD卡的扩展方法,结合FatFs文件系统,使小型嵌入式系统也能容易、方便地扩展大容量存储器。并在STM32上成功移植,打开SD卡中TXT文本,并通过串口输出文本中的内容。

  关键词: 嵌入式系统;SPI协议;SD卡;FatFs文件系统;移植

0 引言

  近年来,在各种嵌入式系统设计中,对大量数据的存储需求越来越高,例如音乐、图片以及经过A/D转换后得到的大量实时数据的存储。SD卡是一种基于 Flash 的新一代存储器,具有体积小、容量大、数据传输快、移动灵活、安全性能好等优点,是许多便携式电子仪器理想的外部存储介质选择。MCU可以通过SD模式或者SPI模式访问SD卡,具备串行通信和随机存取的能力,这很适合SD卡与单片机之间的互连和通信[1]。虽然只有少数高档的单片机才提供SD卡接口,但几乎所有单片机都支持SPI通信。本文着重介绍基于SPI协议扩展SD卡,并结合FatFs Module完成文件系统的设计。

  FatFs是针对小型嵌入式系统的一种通用的FAT文件系统模块,由标准C语言编写,并且完全与磁盘I/O层相独立。所以,对于8051、AVR、PIC、Z80、ARM等MCU,只需要修改文件系统中很少的一部分,FatFs就可以被应用到基于这些低成本MCU的控制系统中。

1 MCU与SD卡接口的设计


001.jpg

  SD卡只能兼容3.3 V的I/O电平,所以要求MCU能够支持3.3 V的I/O端口输出,或者提供电平转换电路,否则很容易损坏SD卡。本文提供一种5 V和3.3 V电平间的转换电路,如图1和图2分别是3.3 V转5 V电路和5 V转3.3 V的电路。在SPI模式下,CS/MOSI/MISO/CLK都需要加10 kΩ~100 kΩ左右的上拉电阻,如图3所示SD卡接口连接图[2]中R0,R1,R2,R3为4个上拉电阻。

002.jpg

2 SPI协议的介绍


003.jpg

  SD卡协议包含如图4[3]所示3个基本函数层次。其中SPI模式基础层主要包括产生片选信号函数、SD卡在SPI模式时的初始化函数、单字节读/写函数、双字节读/写函数等底层函数的封装。SPI模式中间层主要包括对SD卡命令的写函数、数据读取函数、响应的读写等函数。SD卡的API层主要包括对各种类型SD卡的初始化、SD卡扇区的读/写函数、SD卡的信息(容量、厂家等)读取等具有具体功能的应用函数。

3 SD卡的初始化


004.jpg

  SD卡在上电后默认工作在SD模式状态,所以要连续发送大于74个最大频率不超过400 kHz的CLK时钟来完成与SD卡时钟的同步,之后开始CMD0的操作,直到CS为有效电平(低电平)SPI模式就被启用了。接下来按照图5所示初始化流程来完成SD卡的初始化工作。通过SD卡的初始化,可以识别出插入卡槽中SD卡的类型(MMC、V1、V2或者V2HC),然后就可以开始对SD卡进行数据读写操作。

4 FatFs介绍


005.jpg

  FatFs模块的层次如图6所示,其中应用层主要是由FatFs模块提供给MCU的一系列具有独立操作功能的接口函数,而用户无需了解FatFs模块的内部结构和FAT文件系统协议,MCU只需要调用其中的API接口函数就可以完成在PC机上读/写文件操作。

  FatFs模块主要实现FAT协议。使用时,直接将FatFs模块提供的ff.c和ff.h文件包含到程序中,除非有必要,一般不用修改就可使用。

  最底层包括用户移植代码,需要根据不同MCU,编写存储媒介的读/写接口函数和供给文件创建修改时的实时时钟函数。

5 程序移植

  移植 FatFs 主要分为三步:

  (1) 数据类型:在 integer.h 中定义好数据的类型。这里需要了解所使用的编译器和MCU的数据类型,并定义好数据类型,基本上不需要修改。

  (2) 配置:打开 ffconf.h文件,根据对文件操作功能的需求,分别对宏定义设置文件系统的定义配置,以裁剪不必要的API操作函数。如表1配置API函数表所示,其中标有“X”的选项函数即被裁剪掉。例如,_FS_READONLY设为0时,FatFs为读/写文件系统;设为1时,系统为只读,在宏汇编中裁剪掉与写操作相关的函数。_FS_MINIMIZE,选择性裁剪API函数。_USE_STRFUNC,选择性裁剪与字符操作相关的API函数。_USE_MKFS设为1时,结合_FS_READONLY为1来使能API函数f_mkfs(),在驱动器上创建文件系统。_USE_FASTSEEK,设为1,使能快速搜索特性。_USE_LABEL设为1,启用磁盘卷标功能。_USE_FORWARD设为1时,结合_FS_TINY为1,使能f_forward()函数,读取文件数据转移到数据流设备。_CODE_PAGE指定在目标系统上使用的OEM代码页,例如,设936为简体中文。_FS_RPATH用于配置相对路径的功能。

008.jpg

006.jpg

  (3) 函数编写:打开diskio.c进行底层驱动编写,实际上需要编写6个接口函数,如图7中diskio结构图所示[4]。其中前5个接口函数与MCU底层I/O接口相关,而get_fattime()与系统的RTC时钟相关。

  ①DSTATUS disk_initialize(BYZE Drive):函数初始化逻辑驱动器,为对SD卡读/写做准备,函数成功时,其返回值的STA_NOINIT标志位被清零,Drive是指定逻辑驱动器号。应用程序在操作时不应直接调用此函数,而是调用FatFs模块中提供的API函数,如f_mount。

  ②DSTATUS disk_status(BYTE Drive):返回磁盘驱动器的当前状态。Drive是指定逻辑驱动器号,不调用此函数的情况下,函数体内可以直接返回0。

  ③DRESULT disk_read(BYTE Drive,BYTE* Buffer,DWORD SectorNumber,BYTE SectorCount):从磁盘驱动器的扇区上读取数据。Drive是指定逻辑驱动器号,Buffer为指向存储读取数据的数组的指针,SectorNumber为开始读取的扇区号,SectorCount为需要读取的扇区数,函数成功后返回0。

  ④DRESULT disk_write(BYTE Drive,const BYTE* Buffer,DWORD SectorNumber,BYTE SectorCount):向磁盘驱动器的扇区写入数据。Drive是指定逻辑驱动器号,Buffer为指向写入操作的数据字节数组的指针,SectorNumber为开始写入的扇区号,SectorCount为需要写入的扇区数,函数成功后返回0。

  ⑤DRESULT disk_ioctl(BYTE Drive,BYTE Command,void* Buffer):存储媒介控制函数。Drive是指定逻辑驱动器号,Command是指定的命令代码,Buffer是指向参数缓冲区的指针,函数成功后返回0。

  ⑥DWORD get_fattime(void):获取当前时间。返回一个32位无符号整数,代表的时钟信息如表2所示[5]。在简单使用时,可以令该函数直接返回一个固定的常数。

009.jpg

6 结束语

  本文简述了一种免费开源的FatFs文件系统基于SPI模式下,使各种小型嵌入式系统能够扩展、管理SD卡这种大容量存储器,并在STM32上成功移植,效果演示图如图8所示,读出SD卡中TEXT文件夹下的“liuqiang.txt”文件里的内容等信息,并通过串口打印出来。

007.jpg

参考文献

  [1] 段琪炜,周洪利. 基于MMC卡的嵌入式文件系统的设计与实现[J].现代计算机,2006(7):94-96,109.

  [2] 李宁. ARM开发工具RealViewMDK使用入门[M].北京:北京航空航天大学出版社,2008: 266-280.

  [3] 王永虹,徐炜,郝立平. STM32系列为ARM Cortex-M3微控制器原理与实践[M].北京:北京航空航天大学出版社,2008: 305-313.

  [4] 张洪涛,莫文承,李兵兵. 基于SPI协议的 SD卡读写机制与实现方法[J]. 电子元器件应用,2008( 3):42-43,47.

  [5] 谭浩强. C程序设计(第三版)[M].北京:清华大学出版社,2006.


此内容为AET网站原创,未经授权禁止转载。