内容 |
0 引言
USB(通用串行总线),是近年来逐步在PC领域广为应用的新型接口技术,广泛地应用于PC机以及嵌入式系统上。目前市场上的USB设备, 除计算机是主机接口外,其他多数为从机接口, 如打印机、U 盘等,然而USB 的拓扑结构中居于核心地位的是Host (也称为主机) , 任何一次USB的数据传输都必须由主机来发起和控制,DEVICE (从机或设备) 只能响应主机的请求,任何2个外设之间或是2个主机之间无法直接通信。随着USB应用领域的逐渐扩大,人们对于USB的期望也越来越高,希望USB能应用在没有PC的领域中,基于USB HOST的开发应用也越来越广泛。笔者考虑到传统的环境监测仪多利用RS485实现与PC主机的有线远程数据传输,使得监测仪的工作场合和便携性受到相当大的限制,在本文中提出一种新型环境参数监测仪,它配置两路音频和温度传感器,以USB HOST系统为核心,以U盘为数据存储媒介,不受场合限制随时随地实现环境参数(环境噪音响度,温度)的采集、处理、存储和通信等功能;更有助于准确地建立环境参数的演变数据库,为环境的监控和整改提供客观依据;便于携带,成本低廉,有较强的市场前景。
1 环境监测仪的设计
1.1 系统概述
环境监测仪对环境参数的处理可分为信号采集和数据处理两部分,与此相对应,环境监测仪主要由环境参数采集电路和USB主机两个部分组成。整体结构框图见图1:

图 1 整体结构框图
1.2 环境参数采集电路设计
以DS18B20单线数字温度传感器,MCA-BTA声音传感器加上高速A/D构成了系统的环境参数采集电路。
DS18B20数字温度计是DALLAS公司生产的1-Wire,即单总线器件,线路简单(三个引脚GND,DQ:数字信号输入输出端,VDD),体积小;只要求一个端口即可实现通信;不需要外部任何元器件即可实现测温,范围在-55℃到+125℃之间;可以通过寄生电源或者外部电源两种供电方式工作。因此完全符合便利地对现场温度测量的要求。需要注意的是,在寄生电源接线模式下,必须确保电源电压汲取能量充足,否则会导致测量温度偏高,误差量较大。
MCA-MTA声音传感器由美国Vernier公司生产,使用的是与人类耳朵相似具有频率反应的电麦克风。它的工作原理为:声压讯号→传感器→电压讯号→放大器→计权网络dB值。
为增加检测信息的实用性,USB主机系统设计中加了一个日历时钟模块:DS 12C887。DS 12C887 能够自动产生世纪、年、月、日、时、分、秒等时间信息; 具有标准的并行总线口, 可以方便与单片机连接。
1.3 嵌入式USB主机硬件结构设计
1.3.1 硬件要求
USB主机是本监测仪开发中的重点和核心。设计嵌入式USB主机电路要遵循USB主机的协议规范,具体在硬件设计上要选择USB主机的接口芯片,并且要选用合适的MCU(单片机或微控制器)或MPU(微处理器)来控制。因为整个USB协议框架非常复杂,所以就需要MCU具有较大的内部RAM,用以处理大量的数据缓冲区,变量,数据存储等等;其次系统要有大量的程序存储区,一般FLASH的需求大概是在10K至60K。
1.3.2 CH375简介
CH375是一个USB总线的通用接口芯片,支持HOST主机方式和SLAVE 设备方式。CH375的USB主机方式支持各种常用的USB全速设备,外部单片机/DSP/MCU可以通过CH375按照相应的USB 协议与USB 设备通讯。CH375还内置了处理Mass Storage海量存储设备的专用通讯协议的固件,外部单片机/DSP/MCU可以直接以扇区为基本单位读写常用的USB 存储设备(包括USB硬盘/USB闪存盘/U盘)。 CH375芯片内部集成了PLL倍频器、主从USB接口SIE、数据缓冲区、被动并行接口、异步串行接口、命令解释器、控制传输的协议处理器、通用的固件程序等。对于USB存储设备的应用,CH375直接提供了数据块的读写接口,以512b的物理扇区为基本读写单位,从而将USB存储设备简化为一种外部数据存储器,单片机可以自由读写USB存储设备中的数据,也可以自由定义其数据结构。
1.3.3 CPU的选择
CH375的文件级子程序库(实现FAT文件系统层,详细请见软件设计)需要大约600字节的随机存储器RAM作为缓冲区。鉴于采用MCS51内核, 且与AT89C52兼容的SM 5964单片机内部嵌有64KB的flash和1KB的SRAM,为USB主机协议的实现提供了足够的代码空间和数据存储区,无须扩展外部RAM,简化了硬件层面的设计,而且抗干扰能力较强,温度范围宽,在目前市场上性价比较高,嵌入式USB主机CPU采用SM 5964。
1.3.4 连接电路
CH375工作于主机模式时,分为串行方式与并行方式两种。我们这里采用串行方式,这种的连线相对比较简单。如果CH375芯片的TXD引脚悬空(待接单片机)或者没有通过下拉电阻接地,那么CH375工作于串口方式。在串口方式下,CH375只需要与单片机/DSP/MCU连接3个信号线,TXD引脚、RXD引脚以及INT#引脚,其它引脚都可以悬空,就可以进行较远距离的点对点连接。CH375芯片的RXD 和TXD分别连接到单片机的串行数据输出引脚和串行数据输入引脚。INT#输出的中断请求是低电平有效,用于通知单片机(见图2)。
CH375 的串行数据格式是1个起始位、9个数据位、1个停止位,其中前8个数据位是一个字节数据,最后1个数据位是命令标志位。第9位为0时,前8位的数据被写入CH375芯片中,第9位为1时,前8位被作为命令码写入CH375芯片中。CH375的串行通讯波特率默认是 9600 bps,单片机可以随时通过SET_BAUDRATE 命令选择合适的通讯波特率。

图 2 串口方式下CH375与单片机连接示意图
1.4 嵌入式USB主机的软件设计
嵌入式USB主机主要实现USB设备的热插拔检测、设备重启、读取设备的各种描述符等USB1.1协议规范, 并实现USB Mass Storage 类。Mass Storage 类主要用于为软磁盘接口、ATA接口、硬盘接口及FLASH存储器等设备建立的USB接口。 在USB主机方式下,CH375支持各种常用的USB全速设备,以中断方式通知外部单片机(SM5964)进行处理,中断逻辑图如图3。单片机需要编写固件程序按照相应的USB协议与USB设备通讯。

图 3 主机方式下CH375中断逻辑图
单片机处理USB存储设备的文件系统需要实现图3左边的4个层次,右边是USB存储设备的内部结构层次。CH375不仅是一个通用的USB-HOST硬件接口芯片,还内置了相关的固件程序,包含了图4左边的3个层次(深色),所以实际的单片机程序主要处理FAT文件系统层。

图 4 处理USB存储设备文件系统示意图
在上图中的SCSI,UFI,RBC都是Mass Storage类的子类,都有自己的协议,应用于不尽相同的设备。他们通过命令的形式实现各种功能,而这些命令都是各子类所特有的。在USB进行数据传输的时候,这些命令都被打包成一系列的命令包进行传输。真正与Mass Storage的传输方式相关的是其传输协议,在这里为BULK-ONLY传输协议。有关Mass Storage类的标准描述符在传输协议中实现。
FAT文件系统层可以由CH375的U盘文件级子程序库实现。该子程序库提供了USB存储设备的文件级接口,这些应用层接口API包含了常用的文件级操作,可以移植并嵌入到SM5964单片机程序中。CH375的U盘文件级子程序库具有以下特性:支持常用的FAT16和FAT32文件系统,磁盘容量可达100GB以上,支持多级子目录,支持8.3格式的大写字母文件名,支持文件打开、新建、删除、读写以及搜索等。
综上所述,分层次程序段示例如下:
#define UINT8 unsigned char #define UINT16 unsigned short #define UINT32 unsigned long #define UINT8X unsigned char xdata #define UINT8VX unsigned char volatile xdata UINT8VX CH375_CMD_PORT _at_ 0xBDF1; /* CH375命令端口的I/O地址 */ UINT8VX CH375_DAT_PORT _at_ 0xBCF0; /* CH375数据端口的I/O地址 */ #define CH375_INT_WIRE INT0 /* P3.2, 连接CH375的INT#引脚,用于查询中断状态 */ UINT8X DISK_BUFFER[512*32] _at_ 0x0000; /* 外部RAM数据缓冲区的起始地址 */ UINT32 DiskStart; /* 逻辑盘的起始绝对扇区号LBA */ UINT8 SecPerClus; /* 逻辑盘的每簇扇区数 */ UINT8 RsvdSecCnt; /* 逻辑盘的保留扇区数 */ UINT16 FATSz16; /* FAT16逻辑盘的FAT表占用的扇区数 */ /* ********** 硬件USB接口层*/ void mDelaymS( UINT8 delay ) { UINT8 i, j, c; for ( i = delay; i != 0; i -- ) { for ( j = 200; j != 0; j -- ) c + = 3; for ( j = 200; j != 0; j -- ) c + = 3; } } void CH375_WR_CMD_PORT( UINT8 cmd ) { /* 向CH375的命令端口写入命令 */ CH375_CMD_PORT=cmd; for ( cmd = 2; cmd != 0; cmd -- ); /* 发出命令码前后应该各延时2uS */ } void CH375_WR_DAT_PORT( UINT8 dat ) { /* 向CH375的数据端口写入数据 */ CH375_DAT_PORT=dat; /* 因为单片机较慢所以实际上无需延时 */ } UINT8 CH375_RD_DAT_PORT( void ) { /* 从CH375的数据端口读出数据 */ return( CH375_DAT_PORT ); /* 因为单片机较慢所以实际上无需延时 */ } UINT8 mWaitInterrupt( void ) { /* 等待CH375中断并获取状态,返回操作状态 */ while( CH375_INT_WIRE ); /* 查询等待CH375操作完成中断(INT#低电平) */ CH375_WR_CMD_PORT( CMD_GET_STATUS ); /* 产生操作完成中断,获取中断状态 */ return( CH375_RD_DAT_PORT( ) ); } /* ********** BulkOnly传输协议层,被CH375内置了,无需编写单片机程序 */ /* ********** RBC/SCSI命令层,虽然被CH375内置了,但是要写程序发出命令及收发数据 */ UINT8 mInitDisk( void ) { /* 初始化 */ UINT8 Status; CH375_WR_CMD_PORT( CMD_GET_STATUS ); /* 产生操作完成中断, 获取中断状态 */ Status = CH375_RD_DAT_PORT( ); if ( Status == USB_INT_DISCONNECT ) return( Status ); /* USB设备断开 */ CH375_WR_CMD_PORT( CMD_DISK_INIT ); /* 初始化USB存储器 */ Status = mWaitInterrupt( ); /* 等待中断并获取状态 */ if ( Status != USB_INT_SUCCESS ) return( Status ); /* 出现错误 */ CH375_WR_CMD_PORT( CMD_DISK_SIZE ); /* 获取USB存储器的容量 */ Status = mWaitInterrupt( ); /* 等待中断并获取状态 */ if ( Status != USB_INT_SUCCESS ) { /* 出错重试 */ mDelaymS( 250 ); CH375_WR_CMD_PORT( CMD_DISK_SIZE ); /* 获取USB存储器的容量 */ Status = mWaitInterrupt( ); /* 等待中断并获取状态 */ } if ( Status != USB_INT_SUCCESS ) return( Status ); /* 出现错误 */ return( 0 ); /* U盘已经成功初始化 */ } UINT8 mReadSector( UINT32 iLbaStart, UINT8 iSectorCount, UINT8X *oDataBuffer ) { UINT16 mBlockCount; UINT8 c; CH375_WR_CMD_PORT( CMD_DISK_READ ); /* 从USB存储器读数据块 */ CH375_WR_DAT_PORT( (UINT8)iLbaStart ); /* LBA的最低8位 */ CH375_WR_DAT_PORT( (UINT8)( iLbaStart >> 8 ) ); CH375_WR_DAT_PORT( (UINT8)( iLbaStart >> 16 ) ); CH375_WR_DAT_PORT( (UINT8)( iLbaStart >> 24 ) ); /* LBA的最高8位 */ CH375_WR_DAT_PORT( iSectorCount ); /* 扇区数 */ for ( mBlockCount = iSectorCount * 8; mBlockCount != 0; mBlockCount -- ) { c = mWaitInterrupt( ); /* 等待中断并获取状态 */ if ( c == USB_INT_DISK_READ ) { /* 等待中断并获取状态,请求数据读出 */ CH375_WR_CMD_PORT( CMD_RD_USB_DATA ); /* 从CH375缓冲区读取数据块 */ c = CH375_RD_DAT_PORT( ); /* 后续数据的长度 */ while ( c -- ) *oDataBuffer++ = CH375_RD_DAT_PORT( ); CH375_WR_CMD_PORT( CMD_DISK_RD_GO ); /* 继续执行USB存储器的读操作 */ } else break; /* 返回错误状态 */ } if ( mBlockCount == 0 ) { c = mWaitInterrupt( ); /* 等待中断并获取状态 */ if ( c== USB_INT_SUCCESS ) return( 0 ); /* 操作成功 */ } return( c ); /* 操作失败 */ } FAT文件系统层的程序量较大,主要包括下列函数: mIdenDisk,识别分析当前逻辑盘;mLinkCluster,获得指定簇号的链接簇,输入:当前簇号, 返回:原链接簇号, 如果为0则说明错误;mStopIfError,若错误则停止运行并显示错误状态,等等,在此不予详述。
2 工作流程
基于嵌入式USB主机的交通监测仪的工作流程见图5:

图 5 工作流程图
在实际测试中,将采集到的环境参数以“.txt”方式存储,目标盘为64M和128M的U盘,成功存入自定的文件“Data.txt”,支持文件续写和重定义文件名,并可在PC中打开该文件,也可以直接用上层测控软件进行进一步的处理。
3 结束语
本系统设计充分体现了便携,可靠,实用的优点,可为城市环境规划提供充分的数据参考。随着进一步的实际应用,仍然有改进的余地,如可以扩展多路传感器,测量如包括气压、二氧化碳浓度等其他环境参数;相应地,提高存储容量;还可以考虑构建区域服务器以增加效率等等。
参考文献:
[1] 马伟 计算机USB系统原理及其主从机设计 北京:北京航空航天大学出版社,2004,94~98
[2] 张慧 USB ON-THE-GO技术及应用 工业控制计算机学报,2005,18,10
[3] 嵌入式USB-HOST解决方案[DB/OL] http://www.broadmaking.com,2002,6
|