2.2 LwIP协议栈移植
① 完成LwIP协议内部使用的数据类型的定义,如u8_t、s8_t、u16_t、u32_t等。这样使得协议栈内部使用的数据类型不再受移植平台处理器和编译器的影响,增强了协议栈的可移植性。移植时,根据编译器和移植平台事先定义好这些数据类型,定义如下:
typedef unsignedcharu8_t;//定义8位无符号整数
typedef signedchars8_t;//定义8位带符号整数
typedef unsignedshortu16_t;//定义16位无符号整数
typedef signedshorts16_t;//定义16位带符号整数
typedef unsignedintu32_t;//定义32位无符号整数
typedef signedints32_t;//定义32位带符号整数
② 定义临界区保护函数用于开关中断,定义结构体封装宏以避免编译器地址自动对齐。LwIP的实现基于这样一种机制,即上层协议已经明确知道了下层所传上来的数据的结构特点,上层直接使用地址计算得到想要的数据,而避免了数据递交时的复制与缓冲。所以需定义结构体封装宏,禁止编译器的地址自动对齐以防止数据结构被打乱。
③ 实现与信号量和邮箱操作相关的函数[5],比如建立、删除、等待、释放等。LwIP使用邮箱和信号量来实现上层应用程序与协议栈间、下层硬件驱动与协议栈间的信息交互。这些函数可以通过调用μC/OSII提供的信号量、邮箱函数来实现。
④ 实现一个与等待超时相关的函数sys_arch_timeouts.该函数能够返回当前协议栈超时事件链表的首地址。在初始化LwIP进程时,会同时初始化一些超时事件,如ARP超时、TCP超时等,当某些事件等待超时后,协议栈会自动调用一些超时处理函数作相关处理,以满足TCP/IP协议栈的需求。
⑤ 实现创建一个进程的函数,可以通过操作系统提供的OSTaskCreate函数完成。
2.3 网卡驱动程序编写
网卡芯片生产厂商一般都提供了丰富的驱动函数,对这些接口函数进行相应的封装,将接收到的数据包封装为LwIP协议栈熟悉的数据结构,将发送的数据包封装为芯片熟悉的数据结构。发送数据包和接收数据包的函数需要被实现。芯片与控制器LPC2138接口定义如下:
#defineSPI_SCK(0x01﹤﹤4) //P0.4
#defineSPI_MISO(0x01﹤﹤5) //P0.5
#defineSPI_MOSI(0x01﹤﹤6) //P0.6
#defineENC28J60_CS(0x01﹤﹤8) //P0.8
#defineENC28J60_INT(0x01﹤﹤9) //P0.9
2.4 应用程序编写
基于多任务环境,在读写器上创建两个任务:一个为HTTP服务器任务,此时读写器可看作是一个网络服务器,它可以响应远程的浏览器连接请求,并返回Html数据至浏览器上,这样就可以远程获取读写器状态;另一个为读写器的读写任务,此时读写器作为一个客户端使用,它需要连接到远程的控制服务器,接收服务器的配置或控制命令,以响应并进行相关操作,最后返回操作结果或数据给服务器端。应用程序流程如图5所示。
图5 应用程序流程
结语
诸如电子商务、智能物流等需要大量使用电子标签的领域的兴起,使得超高频读写器在物联网及RFID领域发挥出日趋重要的作用。目前国内市场上出现了部分UHF读写器,这些读写器大都采用USB接口或串口实现与上位机的通信。由于上位机与读写器的距离有限,这就限制了UHF读写器的自由安装,在某些远程控制读写场合不再适用。另外,由于上位机硬件资源的限制,不可能实现对大量读写器的同时实时控制。本文基于射频芯片AS3990和网卡芯片ENJ28C60提出的网络UHF读写器能够很好地解决上述问题,满足目前RFID市场的需求。