李丽宏 王淑娟
(太原理工大学信息工程学院,太原 030024)
在高速公路计重收费系统中,车辆称重数据是收费软件计算通行费的主要依据。通常收费计算机通过串口获取称重仪表数据,但不同厂商、不同型号的称重仪表采用不同的协议,导致计重收费软件的通用性差和管理复杂[1]。因此本文设计了串口通信动态链接库,它作为称重仪表与收费软件接口,使收费软件可以通过访问动态链接库中的函数来获取车辆称重数据;同时,方便了收费软件的管理,并实现不同协议的仪表共用统一收费软件的目的。计重收费系统中称重数据流图如图1所示。
图1 计重收费系统中称重数据流图
动态链接库的三个关键文件:*.cpp、*.h和*.def,其中“*.cpp”文件用来编写函数主体[2];“*.h”文件用来定义动态链接库的导出函数,在导出函数前使用_declspec (dllexport)关键字和extern "C"连接指示符来实现动态链接库函数的导出[3];“*.def”文件用来设置导出函数名,当使用“_stdcall”调用约定时,若不通过此文件来设置导出函数名称,则会发生函数命名改变的情况[4]。
本文设计的串口通信动态链接库是在Microsoft Visual C++6.0环境下开发完成的,VC++6.0中对串口操作的流程为:打开串口、设置串口、读串口、写串口及关闭串口[5]。在实现串行通信的动态链接库时,首先以重叠I/O方式打开串口并初始化,然后创建读串口线程[6],此时读串口线程函数开始在后台实时读取串口数据。当收到符合要求的数据后,该线程回应相应数据帧给称重仪表,同时将数据保存在Temprecord.dat文件中,确保串口数据的掉电不丢失,从而达到数据完整的效果。
串口设置函数WimDev_SetCom实现对串口通信的配置,函数中首先判断串口是否已打开,然后再对串口号、波特率、输入输出缓冲区以及字符间隔时间进行配置,最后创建串口读线程,设置串口函数流程图如图2所示。
图2 串口设置流程图
函数中主要采用串口API函数CreateFile、SetCommState来打开、设置串口,并用CreateThread函数创建串口读线程。
由于高速公路计重收费系统要求在接收称重数据的同时完成对已接收到的数据进行实时保存,若处理不好,将导致称重数据的丢失甚至程序的崩溃,这就需要应用程序能够同时处理多个不同任务。因此在动态链接库中创建读串口数据线程,它在动态链接库的运行中一直处于后台运行的状态,为其它数据处理函数提供数据来源。读串口线程的创建不但提高了收费软件的响应速度,同时增强了对称重数据处理的实时性。
在读线程函数中,线程打开后先对已保存在Temprecord.dat文件中的车辆数据进行读取并存入数据链表中。当串口缓存区中有新数据时,首先对收到的数据进行CRC校验,然后根据数据的功能位对串口做出相应的回应并发送相应的消息,即:若读取的是设备自检信息,则将数据存入state.dat文件中,并发送自检消息;若读取的是过车信息,待数据校验成功后,通过WriteFile函数实现对串口的过车信息回应,并将车辆数据信息保存在数据链表中和Temprecord.dat文件中,最后发送过车消息;若读取的是倒车信息且数据校验成功后,通过WriteFile函数实现对串口的倒车信息回应,并删除数据链表中最后一辆车的数据和Temprecord.dat文件中最后一辆车数据,最后发送倒车消息。读取串口线程流程如图3所示。
线程挂起就是使线程暂停运行,此时CPU不再给线程分配时间片,从而降低了计算机的CPU使用率。本文设计的串口通信动态链接库中通过sleep方法实现线程挂起,具体实现如下:
while(1)//线程主体
{
……//读串口数据并保存
sleep(50);//线程挂起
}
关闭串口程序主要用来关闭已打开的串口,退出应用程序并释放资源。
void _stdcall CloseCom()
{
CloseHandle(hCom); //关闭串口
………
}
图3 读串口线程流程图
为增强计重收费软件对称重数据读取的主动性,在动态链接库收到称重数据并校验成功后,向Windows发送相应的消息告知其某事件发生了,收费软件再根据捕捉到的消息内容执行相应的动作。
本文设计的串口通信动态链接库使用的是Windows自定义消息[7],通过自定义消息来告知收费软件称重仪表发生的动作类型,包括:设备故障信息、过车信息、倒车信息三种,设备故障消息号为0464H、过车消息号为0465H、倒车消息号为0466H。动态库中消息发送的具体实现如下:
if(lpInBuffer[i]==255&&lpInBuffer[i+1]==0&&lpInBuffer[i+2]==5)
SendMessage(hhWnd,0x0464,0,0);//发送设备故障消息
if(lpInBuffer[i]==255&&lpInBuffer[i+1]==0&&lpInBuffer[i+2]==1)
SendMessage(hhWnd,0x0465,0,0);//发送过车消息
if(lpInBuffer[i]==255&&lpInBuffer[i+1]==0&&lpInBuffer[i+2]==6)
SendMessage(hhWnd,0x0466,0,0);//发送倒车消息
计重收费系统中动态链接库的使用,提高了收费软件的通用性,并方便了收费软件的管理。在动态链接库实现串口通信时,数据链表和Temprecord.dat文件的使用,保证了称重表数据的完整性;同时,采用线程技术和Windows消息机制,提高了计算机对称重仪表数据采集的实时性和主动性。本文设计的动态链接库在某收费站进行了测试,测试表明:动态链接库运行稳定、可靠。
[1] 张会铭,雷志华.基于Windows服务的网口与串口通信软件设计[J].微计算机信息,2009,25(4):114-116
[2] 陆云龙,雷志华.基于Windows服务的网口与串口通信设计及应用[J].科学技术与工程,2008,8(17):76-79
[3] 吴先亮,刘春生.基于多线程的串口通信软件的设计与实现[J].控制工程,2004,11(2):171-174
[4] 兰波,曾潇,周建瑜.利用VC++6.0动态链接库实现三坐标测量机的CNC化[J].中国测试技术,2008,34(5):75-78
[5] 文欣秀,米西峰,等.基于动态链接库实现软件界面组件化方法研究[J].计算机应用与软件,2007,24(7):18-20
[6] 刘浩,万昆.基于动态链接库DLL的实时数据库系统研究与开发[J].东北电力学院学报,2005,25(1):36-39
[7] 龚力柱,蒋泽军,王丽芳.基于Windows消息机制的软件本地化[J].计算机工程,2008,31(21):87-89