document.write (''); document.write ('');

行业动态

浅谈多线程串口DLL在钱柜娱乐汽车衡称重软件中的应用

时间:2017-09-21 15:09 来源: 点击数:

介绍了在C++builder环境中编写DLL,封装称重仪表通讯协议。

钱柜娱乐汽车衡称重管理软件中经常要读写串口。 由于不同厂家的仪表通讯协议往往不同,因此在具 体应用时有诸多不便。本文介绍了使用C++builder 编写DLL封装称重仪表的通讯协议并给出主要代 码。这种方法符合OIMLD- SW中,将软件部件之间 隔离的标准。

 Win16 中,可以利用 OpenCcmmCloseComm WriteComm等函数打开、关闭和读写串口。但在 Win32中,串口和其他通信设备均被作为文件处理, 串口的打开、关闭和读写等操作所用的API函数与 操作文件的函数相同。可通过CreateFile函数打开 串口,通过CloseFile函数关闭串口,通过Comm- PropDCB 结构、GetCommPropertiesSetCommProp- ertiesGetCommState  SetCommState 等函数设置串 口状态,通过函数ReadFileWritFile读写串口。

采用C++builder进行串口编程,可以很方便的 编译DLL而且可以利用它提供的线程类,使DLL 使用多线程,减少资源的占用。本文将以D2002C/EXK3190A9表为例,介 绍编写多线程串口 DLL的过程。

//C++builder工程向导,创建一个DLL工程

//定义相关变量如下

char InBuff[100]; //数据接收缓冲区

HANDLEhComm = NULL; //  口句柄

AnsiStringtemp="0M; //仪表重量临时值

COMMTIMEOUTS ctmoNew = {0}ctmoOld; //超时

设置

AnsiString ybtype=""; //仪表类型

// 声明外部调用接口函数

//打开串口

//参数1:串口号,如ComlCom2 //参数2:串口设置字符串:"9600n81" extern "C" —declspec ( dllexport) long —stdcall OpenPort char *ComNochar *comset);

//ReadPort函数取重量,参数是仪表类型字符串 "D2002E""XK3190A9"

extern "C" —declspec ( dllexport) char* —stdcall ReadPort char * yibiao);

//关闭串口

extern "C" __declspec ( dllexport) long __stdcall ClosePor(t ) ;

//

为了减少读串口函数占用系统资源问题采用 多线程来解决,TformThread为自定义线程类它继 承父类TThread

class TFormThread: public TThread{ public: / User declarations __fastcall TFormThread( bool CreateSuspended) ; void __fastcall Execute( void);

};

__fastcall TFormThread: TFormThread ( bool Cre- ateSuspended) :TThread( CreateSuspended) { CreateSuspended=true;

};

在读串口线程中分别处理仪表的通讯协议,仪 表类型由ReadPort函数的参数送入。 void __fastcall TFormThread::Execute( void) {/读线程 DWORD dwBytesRead; while( !Terminated)

{

ReadFile ( hComm, InBuff, 50, &dw- BytesRead, NULL);

if ybtype=="D2002E") // ——仪表 1 {

//此处处理D2002E仪表协议 PurgeCommi hComm, PURGE_RXCLr

EAR);

}

else

InBuff[dwBytesRead]=0; if ybtype=="XK3190A9") //…仪表 2 {

//此处处理XK3190仪表协议 PurgeComm( hComm, PURGE_RX-

CLEAR) ;

}

else//…没有找到相应的仪表类型 InBuff[dwBytesRead]=0;

Purg eComm ( hComm, PURGE_RX-

CLEAR) ;

}

}

TFormThread*readport; //声明线程对象指针

// 外部接口函数的定义

打开串口,并设置串口相关参数。

long —stdcall OpenPor( char *ComNo, char *comset)

//打开串口 {

DCB dcbCommPort;

本文采用同步方式打开串口,通过修改参数也可以 用异步方式打开串口。

hComm=CreateFile ComNo, GENERIC_READ|GENER-

IC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);

i(f hComm==INVALID_HANDLE_VALUE) return 0;

设置超时

GetCommTimeout( hComm, &ctmoOld); ctmoNew. ReadTotalTimeoutConstant = 100; ctmoNew. ReadTotalTimeoutMultiplier = 0; ctmoNew.WriteTotalTimeoutMultiplier = 0; ctmoNew.WriteTotalTimeoutConstant = 0; SetCommTimeout( hComm, &ctmoNew); dcbCommPort. DCBlength = sizeof DCB);

GetCommState hComm, &dcbCommPort); BuildCommDCB( comset, &dcbCommPort) ; SetCommState hComm, &dcbCommPort); readport=newTFormThread true) ; // 创建线程实例 readport- >Priority=tpNormal; //线程优先级 readport- >Resume( ) ; //唤醒线程 return 1;

}

读取重量函数

char * —stdcall ReadPort char * yibiao)

{

ybtype=yibiao; //仪表类型

returntemp.c_str ) ; //将重量作为字符串返回

}

当应用程序中不再使用时,应将串口设备关闭 时关闭线程停止取数。

long __stdcall ClosePor(t )

i(f hComm)

{

PurgeComn( hCommPURGE_RXABORT); //清空节收缓冲区

SetCommTimeout( hComm&ctmoOld); CloseHandle hComm) ; // 关闭串口 readport- >Terminate( ) ; //结束线程 hComm=0;

}

return 0;

}

将工程名称命名为D2002E编译后将在当前 目录下生成存D2002E.dll文件。我们在编写称重软 件时,可以调用这个函数库。

VB中调用如下:

Private Declare Function OpenPort Lib "D2002E.dll" (ByVal a As StringByVal setstr As String) As Long Private Declare Function ReadPort Lib "D2002E.dll" ( ByVal b As String) As String Private Declare Function ClosePort Lib "D2002E.dll" ( ) As Long

在打开串口后,用时钟循环读取仪表的当前重量。 Private Sub Timer1_Timer )

DoEvents

zhong = ReadPort Combol .Text) // 取重量,参数 为仪表类型:如"D2002E""XK3190A9" Labell.Caption = zhong

End Sub

运行后情况如下:

云网客1.jpg

云网客2.jpg

在易语言中调用如下:

 上述程序修改后,也可工作在指令模式下,如XK3190A9系列仪表,有两种数据传送方式:

种是连续传送tF=0),一种是指令传送tF=1)。此 时需要在DLL程序中处理串口写函数WriteFile (hCom&orderlenght&kNULL),第 二个参数为仪

表指令,第三个参数为指令长度。发送完指令后,立 即读取结果。

而且,当使用RS485-232转换器,将电脑和数 字传感器连接起来时,可以通过扩充上述程序,将标 定、调角差等过程封装成DLL给客户调用。其目的 是方便用户进行软件功能的二次开发。

 

 


Baidu
搜狗