浅谈多线程串口DLL在 称重软件中的应用

类别:公司新闻 时间:2018-01-22 点击:160 次

介绍了在C++builder环境中编写DLL,封装称重仪表通讯协议。
在汽车衡称重管理软件中,经常要读写串口。 由于不同厂家的仪表,通讯协议往往不同,因此在具 体应用时有诸多不便。本文介绍了使用C++builder 编写DLL,封装称重仪表的通讯协议并给出主要代 码。这种方法符合OIMLD- SW中,将软件部件之间 隔离的标准。
在 Win16 中,可以利用 OpenCcmm、CloseComm 和WriteComm等函数打开、关闭和读写串口。但在 Win32中,串口和其他通信设备均被作为文件处理, 串口的打开、关闭和读写等操作所用的API函数与 操作文件的函数相同。可通过CreateFile函数打开 串口,通过CloseFile函数关闭串口,通过Comm- Prop、DCB 结构、GetCommProperties、SetCommProp- erties、GetCommState 及 SetCommState 等函数设置串 口状态,通过函数ReadFile和WritFile读写串口。
采用C++builder进行串口编程,可以很方便的 编译DLL。而且可以利用它提供的线程类,使DLL 使用多线程,减少资源的占用。本文将以柯力公司
的D2002C/E和上海耀华的XK3190A9表为例,介 绍编写多线程串口 DLL的过程。
//用C++builder工程向导,创建一个DLL工程
//定义相关变量如下
char InBuff[100]; //数据接收缓冲区
HANDLEhComm = NULL; // 串 口句柄
AnsiStringtemp="0M; //仪表重量临时值
COMMTIMEOUTS ctmoNew = {0}, ctmoOld; //超时设置
AnsiString ybtype=""; //仪表类型
// 声明外部调用接口函数
//打开串口
//参数1:串口号,如Com1, Com2 //参数2:串口设置字符串:如"9600, n, 8, 1" extern "C" —declspec ( dllexport) long —stdcall OpenPort char *ComNo, char *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 )
if hComm)
{
PurgeCommi hComm, PURGE_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 String, ByVal 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 Combo1 .Text) // 取重量,参数 为仪表类型:如"D2002E", "XK3190A9" Label1.Caption = zhong End Sub
运行后情况如下:
 
 
在易语言中调用如下:
 
上述程序修改后,也可工作在指令模式下,如上 海耀华XK3190A9系列仪表,有两种数据传送方式: 一种是连续传送tF=0), 一种是指令传送tF=1)。此 时需要在DLL程序中处理串口写函数WriteFile (hCom, &order, lenght, &k, NULL),第 二个参数为仪 表指令,第三个参数为指令长度。发送完指令后,立 即读取结果。
而且,当使用RS485-232转换器,将电脑和数 字传感器连接起来时,可以通过扩充上述程序,将标 定、调角差等过程封装成DLL给客户调用。其目的 是方便用户进行软件功能的二次开发。

中国领先的称重软件技术提供商

The Leading Provider of Geomatic Solutions in China

展开收起网站地图