0 概述
射频识别(RFID,Radio Frequency Identification)是一种非接触式的自动识别技术,通过射频信号在空间上的耦合实现非接触式数据传输,达到自动识别对象并获取相关信息的目的。 目前市场上有大量的、面向众多领域的RFID 应用系统。 在开发这些RFID 系统时, 若因不同的应用需求和应用环境,而将每个RFID 系统孤立看待,无疑会增加开发成本和延长开发周期。 因此,文中基于构件化的封装设计思想设计了一个RFID 系统通用的软硬件平台,对软硬件进行封装,提高软硬件的可重用性和可移植性,在保证系统性能的前提下,避免重复劳动,缩短开发周期。
1 总体设计方案
1.1 RFID 射频识别系统一般模型
RFID 射频识别系统因具体应用不同其组成会有所不同,但是通过分析它们的共性可以建立一个一般的模型, 如图1 所示。 该模型主要由电子标签、射频识别装置即读卡器、PC 主机组成。 电子标签与射频识别装置之间通过耦合元件实现射频信号的空间耦合。 在耦合通道内, 根据时序关系,实现能量的传递、数据的交换。
一个通用的RFID 系统开发平台是指:此平台以RFID 射频识别系统一般模型为基础,提供开发RFID 射频识别系统通用的硬件和软件构件。 在设计思路上须遵循构件化设计、可二次开发性和平台化设计原则。
1.2 RFID 通用开发平台硬件构件模型
在一般模型中,电子标签根据自身是否带电源可分为有源标签、无源标签,根据存储方式分为只读标签、读写标签,根据工作距离分为密耦合型标签识别距离1cm 内、近耦合型标签识别距离10 cm内、邻近型标签识别距离100 cm 内。 不同的电子标签识别技术不一样。
文中的通用开发平台主要面向无源的近耦合型RFID 应用, 参照ISO/IEC 14443 协议操作13.56MHz 读写标签(Type A 卡) 或者只读标签(Type B 卡), 并配备各种常用接口和外设如通用I/O口、网络、串口、SPI、USB、LCD、语音以适应不同的应用。 RFID 通用开发平台硬件构件模型如图2 所示。 在单芯片解决方案中, 通常MCU 内部包含有通用I/O 口和一些内置的功能模块如串口、网络等,因此相对于核心构件MCU 而言,通用I/O 口、SPI、串口、网络是MCU 内部构件,LCD、语音、USB、射频可以看成是其外设构件。
1.3 RFID 通用开发平台软件构件模型
RFID 通用开发平台软件设计分为两大部分:
底层软件构件层和高层构件层。 其中底层软件构件层针对硬件构件编程, 是硬件驱动程序的封装,高层构件层根据用户的实际应用需求调用底层软件构件层封装好的功能函数。 通用平台的软件构件层次模型如图3 所示。 将通用I/O 口的驱动封装为GPIO 构件,各内置功能模块的驱动程序封装为功能构件,合称为内部软件构件。 外设的驱动程序封装为外设软件构件。
原则上开发基于此平台的各种应用只需要设计PC 端的应用软件,其余软、硬件构件不需要进行改动,这就是RFID 通用开发平台的构件化封装设计的思想。 高层构件层提供了访问各个构件的网络命令,PC 端主机操作网络、射频、LCD、USB、语音等构件时,只需发送相应的网络命令即可。
2 RFID 通用开发平台设计
2.1 硬件设计
硬件构件模型中首先是主控制器MCU 的选型。 由于RFID 应用广泛, 很多场合要求控制器有较快的处理速度, 有多种控制模块如A/D 控制模块、CAN 总线模块、以太网控制模块等。 综合分析,文中选择了飞思卡尔单芯片解决方案MCF52235处理器。 该处理器采用Coldfire V2 内核和精简指令集(RISC),频率为60 MHz,通过设置锁相环( PLL ),MCF52235 能够稳定工作在80 MHz. 内部集成了10/100M 快速以太网控制器(FEC)、以太网物理收发器(EPHY)等模块,还有UART,I2C、QSPI、PWM 、快速ADC 等模块,实现了单芯片解决方案。
由于MCF52235 处理器中集成的以太网模块已经包括了以太网控制器和物理层收发器,因此网络硬件构件仅需添加少量的元件便可。 MCF52235处理器的PHY_RXP、PHY_RXN 引脚用于接收数据,PHY_TXP、PHY_TXN 引脚用于发送数据。 这两对收、发引脚分别接50 Ω 的上拉电阻。 SPDLED 引脚接网速LED 灯指示当前的连接速度是10 Mbps还是100 Mbps,LNKLED 引脚接的LED 灯则指示当前是否已经与另一个网络设备连接。 如果RFID射频系统中读卡器终端并不多,可以不采用网络而是通过USB 接口与PC 机进行通信。 USB 构件采用飞思卡尔的单芯片MC9S12UF32, 它提供了高速USB2.0接口, 即插即用。 此处使用USB 接口不是为了获得更高的速度而是为了使用方便,所以选择通过MCF52235 的一个串口与UF32 通信。
射频芯片选用的是飞利浦RC531芯片,工作频率为13.56 MHz, 在不外加功率放大器时读写距离可达10 cm,它通过SPI 接口与MCF52235 通信。
LCD 构件采用耀宇科技的YM12864图形点阵液晶。 该液晶显示器可以显示4 行、每行8 个汉字或者16 个字母。 它有两种常用的连接方式:并行和串行。 并行连接需要11 根引脚线, 串行连接仅用3 根引脚线,因此与MCU 的连接采用串行的连接方式。 另外还需一个引脚控制背光灯电源的正极LEDA开关。 语音模块和LCD 模块的功能一样,都是为了增强人机交互, 它采用上海奔流公司的BMP5008语音芯片。 状态指示灯用于观察系统的运行状态和用户的操作,通过GPIO 口连接,几乎所有的MCF52235 引脚都可以作为GPIO 引脚。 主控制器MCF52235 与各模块的引脚连接如图4 所示。
2.2 软件设计
根据平台的软件构件层次模型,先将各个模块的驱动程序封装成构件。 底层软件构件是与硬件直接打交道的,它由头文件和源程序文件两部分组成。 编程思想是分析构件的共性和个性,抽取出构件的属性和对外接口函,用户使用该构件时只需了解其接口函数, 而不必去了解内部具体如何实现。
头文件部分给出构件属性的宏定义和对外接口函数的原型说明,源程序部分是函数的实现。
以太网构件主要包括以太网物理收发器(EPHY)和快速以太网控制器(FEC) 的初始化、TCP/IP 协议栈实现。 它的接口函数原型说明如下:
//==================================
uint8 hw_ephy_init (uint16 sysclk,uint8 ratemode,
uint8 dupmode,uint8 autoneg); //EPHY 初始化
void hw_fec_init (uint8 mac_addr_fec [6];//FEC初始化
int8 hw_fec_sendframe (uint8 ch [], uint8destAdd[6], uint8 srcAdd[6], uint16 lenType, uint16len);//发送单个以太网帧
uint8 hw_fec_receiveframe(uint8 ch[], uint16 *len);//接收单个以太网帧
uint hw_icmp_handle(PACKET p);//处理接收到的ICMP 包,响应ping 请求
int hw_udp_send (unshort fport, unshort lport,
PACKET p);//发送UDP 包
//==================================
RC531 射频模块与MCF52235 通信严格按照串行通信时序要求。 RC531 与ISO/IEC 14443 TypeA 和Type B 卡通信,则按照A、B 卡调制和编码的方式设置相关的寄存器,并根据ISO/IEC 14443 协议来设计软件即可。 读卡器与A、B 卡之间的通信是按照应答方式来进行的,非接触式的卡有很多工作状态,各个状态的转化可通过读卡器向卡发送一系列命令完成。 射频构件的接口函数说明如下所示:
// ==操作Type A 卡的部分主要函数======
void pcdinit();//R 初始化
char pcdreset();//RC531 复位
char pcdrequest(uint8 req_code);//寻卡
char pcdanticoll(uint8 *snr);//防碰撞
char pcdselect(uint8 *snr);//选定一张卡
// =========操作Type B 卡的函数========
void pcdinitB();//B 卡初始化
char pcdrequestB(uint8 *pupi);//寻B 卡
char pcdattrib(uint8 *pupi);// 发送attrib 命令
char pcdhaltB(uint8 *pupi);// B 卡挂起
char pcdgetUID (uint8 *snr, uint8 *len); //获得B 卡的ID
//==================================
MCF52235 与LCD 构件的通信同样采用串行方式。 串行通信的一次数据分3 个字节传输。 第一个字节数据格式为11111AB0,表示串行控制,A 是选择数据方向,1 表示LCD 到MCF52235,0 表示MCF52235 到LCD. B 是选择数据类型,1 表示数据为显示数据,0 表示数据为控制命令。 第二个字节格式为DDDD0000, 表示8 位数据的高4 位。 第三个字节格式为0000DDDD 表示8 位数据的低4 位。
LCD 构件接口函数说明如下所示:
//==================================
void lcd_init();//初始化
void lcd_display (const char* buf, int line);//在第line 行显示buf,line>=0 && line<= 3
//==================================
USB 软件构件比较简单,只需对MC9S12UF32的USB 模块进行初始化,UF32 便可以和MCF52235 进行交互了。 由于MCF52235 与UF32采用串口连接, 因此只要在串口中断程序中调用USB 构件,UF32 便可从串口接收数据, 然后通过USB 传送给上位机。 上位机通过USB 接口发送数据给UF32 也产生一个中断,在中断程序把数据缓存起来再调用USB 构件, 通过串口发送给MCF52235. USB 构件接口函数说明如下所示:
//==================================
void uf32_uart_init(void);//uf32 模块初始化
void uf32_uart_send(uint8 ch[],uint32 n); //发送数据
uint32 uf32_uart_rev (uint8 ch [],uint32 n); //接收数据
//==================================
语音构件相对比较简单,接口函数说明如下所示:
//==================================
void audio_init();//语音模块初始化
void audio_play(int i);//语音播放
void audio_stop();//语音停止
//==================================
串口构件接口函数说明如下所示:
//==================================
uint8 hw_uart_init(uint8 uartNo, uint32 baud);//串口初始化
uint8 hw_uart_rev_one (uint8 uartNo, uint8 *fp); //串口接收一个字节到fp
uint8 hw_uart_send_one(uint8 uartNo, unit8 ch);
//串口发送一个字节
//==================================
SPI 构件接口函数说明如下所示:
//==================================
uint8 hw_spi_init (uint8 spiNo,uint8 master);//SPI 初始化
uint8 hw_spi_send (uint8 spiNo,uint8 data [],uint8 len);//SPI 发送数据
uint8 hw_spi_re(uint8 spiNo,uint8 data[]); //SPI接收数据
uint8 hw_spi_enable_re_int (uint8 spiNo); //开SPI 接收中断
uint8 hw_spi_disable_re_int (uint8 spiNo); //关SPI 接收中断
//==================================
GPIO 构件接口函数说明如下所示:
//==================================
uint8 hw_gpio_init (uint8 port,uint8 pin,uint8dir,uint8 state);//初始化端口为GPIO 引脚
uint8 hw_gpio_set (uint8 port,uint8 pin, uint8state); //设置指定引脚状态
uint8 hw_gpio_get(uint8 port,uint8 pin);//获取指定引脚状态
uint8 hw_gpio_reverse(uint8 port,uint8 pin);//反转指定引脚状态
//==================================
高层构件包括三个部分:FreeRTOS 操作系统在MCF52235 上的移植[13-14],Shell 的实现,网络命令和信息的封装。 将FreeRTOS 移植到MCF52235主要是实现3 个底层汇编级的支持函数,tk_frame(task *tk, int (*entry)(), int arg)函数为tk 进程创建堆栈帧保存进程的各种状态;tk_switch (task *tk)函数用于把当前进程切换到tk 进程;tk_getsp()函数返回当前堆栈指针。 另外,在FreeRTOS 中运行一个Shell 进程,进程函数为int keyboard (intparam),可调试或查看系统状态信息,比如各个进程的运行状态、ARP 表、IP 地址、MAC 地址、连接状态等。
Shell 实现的效果如图5 所示。
在实际应用中,通常一台PC 主机管理若干读卡器, 一个读卡器可以为若干PC 主机服务。 每个PC 主机和读卡器都具有不同的IP 地址, 一台PC主机可以控制读写器1 读写每个Type A 卡的某个块数据, 还可以同时控制读写器2 读写每个TypeA 卡的另一个块数据, 或者请求读取Type B 卡的UID, 整个网络关系比较复杂。 因此采用将主机发送的命令、网络信息、卡信息封装在如下所示的若干个数据结构中。
//==================================
struct invite_info //PC 主机发送的读卡请求
{ char del_or_add; //主机离开或加入
uint8 type; //卡的类型
uint8 block; //要访问的数据块
uint8 password[6]; //块的密码
};
struct ip_arrays_B //读Type B 卡信息
{ ip_addr ipaddress; //IP 地址
int port; //UDP 端口号
};
struct send_data_type //发送到主机的数据
{ uint8 sn[4]; //序列号
uint8 block; //块号
uint8 data[16]; //16 个字节块数据
uint8 ret; //返回值
};
struct IC_ope //用于消费用途的RFID 应用
{
uint8 block; //总的金额数
float fsub; //每次刷卡扣除的金额数量
uint8 *pass;
};
struct record_info //记录卡信息
{ //此块引用计数,0 表示没有请求读这块数据
uint8 ref; //引用计数
uint8 block; //块号
uint8 password[6]; //块的访问密码
};
struct ip_arrays_A //读Type A 卡信息
{ ip_addr ipaddress; //IP 地址
int port; // UDP 端口号
uint8 block [num_of_rf_structs]; //这个UDP连接要读取的所有块
};
struct net_cmd //发送到板子的命令
{ uint8 lenth; //请求数据长度
uint8 cmdope; //操作码
uint8 data[1]; //数据
};//=================================
3 RFID 通用开发平台应用
基于此平台文中开发了学生机房上机刷卡系统。 在每个机房安装一台读卡器,PC 主机的数据库中存储了每个机房的课表、任课教师和学生的信息。 学生持卡到各个机房的读卡器上刷卡,读卡器将读到的信息通过网络传输到PC 主机上,统计学生人数和上、下课时间等情况, 相关信息显示在LCD 上并进行语音提示。 PC 端软件实现了网络通信功能和学生机房上机刷卡管理系统。 网络通信通过CManagerDlg:: m_skInfo 和CManagerDlg::
m_skCmd 这2 个sokcet 接口完成。 学生机房上机刷卡管理系统开发软件采用VC++2012 和SQLServer 2012 关系型数据库管理系统。 学生机房上机刷卡管理系统界面如图6 所示。
4 结语
现有RFID 系统开发基本是根据具体应用需求进行单独设计的。 而这些不同的应用系统在软、硬件部分具有很大的重复性,为提高软、硬件的可重用性,文中通过分析RFID 射频识别系统一般模型,提出了一种基于MCF52235 的RFID 通用开发平台软、硬件构件化设计方案,设计了集成多种接口的具备通用功能的RFID 开发平台,并将该平台应用于学生机房上机管理系统中。 实践证明它为RFID 系统开发提供了一个快速、通用的软、硬件模型。