引言
近年来,数据采集及其应用得到了人们越来越广泛的关注,数据采集系统也有了迅速的发展,特别是以单片机为核心的数据采集系统,由于其超高的性价比,已经广泛应用于很多领域。但是传统的以51单片机为核心的数据采集系统受限于有限的存储空间和通信方式,存在实时性差、采集容量小等缺点,已无法满足数据量越来越大的现代社会的需求,大容量数据存储已成为微控制器应用的瓶颈。为突破容量的限制,一般采用外扩存储器,比如U盘、SD卡等,并移植文件系统便于对数据进行后续管理和处理。
1采集系统方案设计
本系统由模拟量输入模块、USB传输模块、大容量存储模块和人机交互模块组成,系统框图如图1所示。模拟信号经信号调理输入模块处理后,通过模数转换器ADC转换为数字信号,再由STM32微控制器进行滤波等数据处理后,存储在SD卡里,并通过串口传输到上位机进行数据分析。

图1 采集系统方案图
1.1STM32F107微控制器[1]
系统采用了ST公司基于ARM CortexM3内核的32位增强型闪存微控制器STM32F107作为控制核心。CortexM3内核专门用于满足集高性能、低功耗、实时应用、具有竞争性价格于一体的嵌入式领域的要求,采用哈佛结构,能够达到1.25 DMIPS/MHz和0.19 mW/MHz,有单周期乘法指令和硬件除法指令。该芯片最高工作频率可达到72 MHz,具有256 KB的闪存以及64 KB的SRAM,以及性能出众的片上外设(如USB、USART、SPI、I2C、GPIO、PWM、10/100M Ethernet MAC等),最大限度地实现集成,丰富的片上资源大大简化了系统硬件,同时降低了系统功耗,待机电流仅为2 μA 。
1.224位A/D转换器控制原理[2]
ADS1252采用简单的三线串口接口进行控制和数据读取,其仅有一个数字输出引脚,该引脚为DOUT和DRDY之间的多路复用引脚。一次完整的转换需要耗费 384 个 CLK 周期,可将转换周期分为两个模式或阶段,即DOUT及DRDY(如图2所示)。该周期的第一阶段为DRDY模式。DOUT时隙结束后,DRDY信号的上升沿表示,在 36 个CLK 期内将可以使用新数据,在此时间内,可更新数据输出寄存器[3],将该信号与STM32F107的外部中断使能引脚相连。 该周期的第二阶段为DOUT模式, 在此时间内,用户能够以串行移位时钟 (SCLK) 确定的数据速率安全地读取已转换数据。

图2 A/D转换器读取时序图
1.3SD卡简介[4]
SD卡是一种为满足安全性、容量、性能和使用环境等各方面的需求而设计的一种新型Flash存储器件。SD卡允许在两种模式下工作,即SD模式和SPI模式,本系统采用SPI模式。SD卡使用卡内智能控制模块进行Flash操作控制,包括协议、安全算法、数据存取、ECC算法、 缺陷处理和分析、电源管理、时钟管理。SD卡被广泛使用在便携装置,如数码相机、个人数码设备和多媒体播放器等,目前SD卡容量已经进入以G为单位的时代。
1.4FatFS文件系统[5]
FatFS是一种开源的FAT 文件系统模块,专门为小型的嵌入式系统而设计。它完全采用标准C格式语法编写,完全独立于I/O 层,只需做简单的修改即可移植到8051、PIC、AVR、SH、Z80、H8 和ARM 等系列单片机上。FatFS的特点是分离缓冲FAT结构的每个文件,可以快速访问多个文件,支持多个驱动器和分区,支持FAT12、FAT16和FAT32,支持8.3格式的文件名,优化了8/16位微控制器。FatFS的设计思想是小块的数据可以通过Buffer存储,大块的数据直接存取,提高了存取速度和效率。FatFS模块层次结构如图3所示。

图3 FatFs 模块层次结构图
2SD卡操作
SD卡协议采用命令的方式进行数据操作[6],因此SD卡和STM32F107的通信采用发送应答机制,每发送一个命令,SD卡都会给出一个应答,以告知主机该命令的执行情况,或者返回主机请求的数据。SPI模式下常用的命令如表1所列。

2.1SD卡初始化操作[7]
因为系统使用的是SPI模式,所以先得让卡进入SPI模式,方法如下:在SD卡收到复位(CMD0)时,CS引脚为低电平,则SPI模式被启用。不过在发送复位命令之前,要发送至少74个时钟周期,以保证SD卡内部供电电压的上升。在卡初始化的时候,时钟周期最大不能超过400 kHz,初始化完成后,才能切换到SPI高速模式。初始化流程如图4所示。

图4 SD卡初始化流程图
2.2SD卡读写操作
通过SD卡初始化,可以得知卡的类型(V1、V2、V2HC或MMC),完成初始化后,可以开始通过命令读写数据。SD卡读取数据通过命令CMD17来实现,流程如图5所示。

图5 SD卡读取数据流程图
SD卡写数据和读取数据差不多,只不过是通过命令CMD24来实现。
3FatFS文件系统移植[8]
FatFS文件系统,最顶层是应用层,使用时无需理会FatFS内部结构和复杂的Fat协议,只需要调用FatFS模块提供的API接口函数即可,比如f_open、f_read、f_write和f_close等,就像在PC机上读写文件那样简单。中间层是FatFS模块,实现了Fat文件读写协议,使用时不作修改,包含头文件即可。
需要编写移植代码的是FatFS模块提供的底层接口,它包括存储介质读写接口(disk I/O)和供给文件创建修改时间的实时时钟(RTC)。
从网站上下载FatFS的R0.09a版本源代码,解压后有两个文件夹:doc和src。前者是FatFS的说明文档,后者是源代码文件夹,移植时,只需要修改两个文件:ffconf.h和diskio.c。
首先,修改数据类型,修改integer.h,使其中定义的数据类型与keil mdk4.74编译器相对应。
其次,修改文件ffconf.h,按照需求配置相关功能。例如,_VOLUMES用于设置FatFS支持的逻辑设备数目,本系统只有一个存储设备(SD卡),所以_VOLUMES设置为1,其他设置可参考注释进行修改。
最后,编写底层函数,因为FatFS模块完全与磁盘I/O层分开,因此需要下面的函数来实现底层物理磁盘的读写与获取当前时间。打开diskio.c,进行底层驱动编写,编写6个接口函数,如图6所示。

图6 底层接口函数
DSTATUS disk_initialize()函数初始化磁盘驱动器,本系统采用SD卡作为存储介质,因此该函数主要就是对SD卡进行初始化操作,初始化成功后返回状态0。需要注意的是应用程序不能调用此函数,否则文件卷上的FAT结构可能会损坏。
DSTATUS disk_status()函数返回当前驱动器的状态,例如磁盘驱动初始化是否成功,驱动器中有无设备,设备是否写保护等。
DRESULT disk_read()函数从磁盘驱动器上读取扇区内容,调用SPI读取单个或多个块的内容。
DRESULT disk_write()函数调用SPI向磁盘写入一个或多个扇区。
DRESULT disk_ioctl()函数通过底层SPI驱动可以读取存储设备中的一些特殊寄存器(SD卡中的OCR、CID、RCA等),获得相关信息后,后续操作才能执行成功,比如格式化操作等。
DWORD get_fattime()函数获取当前时间。
通过以上3个步骤,完成了对FatFS文件系统的移植,在应用程序中可以调用该文件系统的API函数。
4硬件电路设计
4.1SD卡电路连接
图7为SD卡的硬件连接电路图。使用了STM32F107的SPI3,引脚PC3为SD卡片选,配置为推挽输出;PC12为MOSI,配置为推挽复用;PC11为MISO,配置为推挽复用,PC2引脚用来检测SD是否插入,配置为输入模式,硬件上拉;PC10引脚为SPI时钟信号,配置为推挽输出。

图7 SD卡硬件连接图
4.2采集电路设计
采集电路包括输入信号滤波、限幅、单端转差分等预处理电路,ADC和STM32F107之间通过SPI1接口连接,电路图如图8所示。A/D转换完成后,会在DOUT引脚产生一个下降沿,触发STM32F107的外部中断,在中断程序里,通过SPI1读取数据。读取多个数据完成后,再写入到SD卡。

图8 采集电路原理图
结语
本文完成了开源软件FatFS文件系统在STM32F107微控制器上的移植,设计了基于24位高精度A/D转换器。ADS1252的数据采集电路,将SD卡作为存储介质,对基于单片机的大容量数据采集系统具有借鉴意义。