基于API函数库实现串口数据通信的分析与设计
2020-04-30屈武江
屈武江
(大连海洋大学 应用技术学院,辽宁 大连 116300)
0 引 言
数据通信也称为数据获取和数据交换,是将从系统外部采集的数据通过一种通信设备传送到系统内部的一个接口[1]。数据通信不仅包括计算机与计算机之间的数据传输,也包括计算机与其他外部设备之间的数据传输。目前数据通信技术在实时监控系统和工业自动化系统中得到了广泛应用。
1 串口数据通信
1.1 串口数据通信
串口数据通信是指通过计算机上的串行接口使计算机与计算机之间或者计算机与外部设备之间进行数据传输的一种数据获取方式[2]。串行接口通常是指计算机上的COM接口,是一种通用的设备通信接口[3]。一般来说串口主要用于连接鼠标等外部设备,同时串口也是用于外部设备与计算机系统之间传输数据的通道。如果计算机上没有串行接口,用户可以使用USB转接器将USB接口转换为串行接口。串口数据通信由于使用设备简单,同时通过实现超远距离数据传送,因此在工业和自动化系统中经常使用串行接口进行数据通信[4]。
1.2 串口数据通信的过程
应用串行接口实现数据通信的过程:首先通过命令设置串口名称、波特率、数据位、停止位和奇偶位检验等串口参数,然后打开串口等待接口数据[5]。接着进行数据通信,也就是读取串口数据或者向串口传递数据[3-6]。最后数据通信完毕关闭串口,释放资源。
2 串口数据通信实现方法
2.1 使用VB6.0中的MSComm控件
VB6.0提供了MSComm串口通讯控件,MSComm控件隐藏了串口通信的运行过程,用户只需要编写少量的程序代码就可以实现数据通信[7]。MSComm串口通讯控件提供了事件驱动通信和查询检测通信两种数据通信的方法,事件驱动通信指当CD线或RTS线上有字符到达或发生改变时,OnComm事件捕获或处理这些通讯事件和处理通讯中的错误。查询检测通信指可以在每个重要的程序功能之后检查CommEvent属性的值来检测事件和通信错误。对于数据通讯量不大和对通信要求不高的数据通信环境下建议采取这种方式进行数据通信[8]。但是应用MSComm控件进行数据通信时,每一个MSComm控件对应一个串口,如果在程序中需要提供多个串口,则必须要添加多个MSComm控件。
2.2 使用SerialPort串口通讯类
VS2012是Microsoft Visual Studio 2012的简称,是微软公司开发的目前最流行的Windows平台应用程序的集成开发环境,提供了软件开发过程中所需要的各种工具[3,9]。其集成架构Framework2.0以上类库提供了SerialPort类可以取代MSComm控件实现串口通信。其执行过程如下:
(1)创建数据通信类对象,设置通信串口的主要参数:BaudRate(波特率)、PortName(串口名称)、ReceivedBytesThreshold(触发数据接收事件DataReceived)、WriteBufferSize/ReadBufferSize(写缓冲区和读缓冲区大小),并执行数据通信类对象的Open方法打开新的串行口。
(2)执行Read或者ReadLine方法从新打开的串行口中读取数据,通过执行Write或者WriteLine方法将数据写入新建的串行口,但要注意读方法与写方法必须要配对,即用Write方法写数据,则必须用Read方法读取数据。
(3)通信完毕,调用Close方法关闭串口。
2.3 调用API库中的通信函数
Windows操作系统提供了低层的API函数库,API函数库提供了多种函数可以实现串口数据通信。这种方法实现的数据通信效率高,主要适用于大型通信程序及通信质量要求较高的场合[10]。
调用API函数来实现串口通信基本过程包括:
(1)执行API函数库的CreateFile()函数创建一个新的串口,通过执行SetupComm()函数为新创建的串口分配输入和输出缓冲区大小,调用BuildCommDCB()或者SetCommState()函数设置串口通信的控制参数[11]。
(2)执行API库的WriteFile()库函数将数据发送到新创建的串行口,同时将发送到串行口的数据写入相应的文件,也可以执行ReadFile()库函数从写入的文件中读取数据[12]。
(3)通信完毕,调用API库函数CloseHandle()函数关闭串口。
3 基于API函数库实现串口通信的设计与实现
文中以设计农业生产中蔬菜大棚自动杀虫灯为例,介绍基于API函数库实现串口通信的设计与实现。
3.1 基于API函数库实现串口数据通信的设计
在农业生产中农户经常在蔬菜大棚安装自动杀虫灯并进行实时监控和统计显示在计算机系统中。该系统的设计思路是当昆虫被杀死时,昆虫落下触发传输设备触点并自动计数,通过网络4G在指定的时间间隔内将计数数据传输到接收端数据传输设备,数据传输设备将接收的数据通过串行接口传输数据通信软件,而数据通信软件通过串行接口接收数据并存储到数据库,同时软件以图表或其他方式显示自动杀虫灯的各月杀虫情况。基于API函数库串口数据通信软件设计流程如图1所示。
3.2 编写串口通信通用类
基于API函数库的串口数据通信软件采用VS2012集成开发环境,存储数据库采用Access 2013。在程序设计时首先设计串口数据通信通用类,旨在充分发挥面向对象程序设计的优势,提高程序的通用性和可移植性,以便实现串口通信接收文件的建立、打开串口和数据接收转换。重要通用类方法的关键代码如下:
(1)引入DLLImport属性类。
[DllImport("kernel32.dll")]
Private atatic extern int CreaFile(
string sfnd //定义串口名称
uint dwDesiredAccess //将串口的访问方式设置为可读可写
int dwShareMode,lpSecurityAttributes,dwcd,dwFlagsAnd Attributes,hTemplateFile);
其中DllImport是System.Runtime.InteropServices名称空间下的属性类,用来提供从非托管DLL导出函数的必要调用信息。上述代码导出函数CreateFile创建文件的调用信息,其中sfnd表示串口的名称,dwDesiredAccess设置串口的访问方式,DwShareMode指定串口的共享模式(0表示不共享),lpSecurityAttributes设置串口的安全属性,dwcd设置串口的创建方式,dwFlagsAndAttributes设置串口属性和标志,hTemplateFile表示文件模板(串口通讯只能设置为0)。
图1 基于API函数库串口数据通信软件设计流程
(2)打开串口方法。
打开串口方法名为open,实现过程是首先建立串口参数属性及标志设置结构体变量dcbCommPort和超时结构体变量ctoCommPort,然后调用外部方法CreateFile建立串口文件打开串口,如果返回的句柄无效,则提示错误信息,否则设置通信超时时间,调用外部方法GetCommState方法取得串口状态参数,最后调用SetCommState方法设置串口参数,如果出现错误,则抛出异常,否则设置串口状态为打开[13]。关键代码如下:
…………
DCB dcbcp=new DCB();
COMMTIMEOUTS ctocp=new COMMTIMEOUTS();
hc=CreateFile(PortNum, GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,0,0);
if(hc==INVALID_HANDLE_VALUE)
{throw (new ApplicationException("系统提示,无法打开串行端口!"));}
GetCommTimeouts(hComm, ref ctoCommPort);
SetCommTimeouts(hComm, ref ctoCommPort);
GetCommState(hComm, ref dcbCommPort);
…………
if(!SetCommState(hc, ref dcp)) //设置串口参数
{throw (new ApplicationException("系统提示,无法打开串行端口!")); }
Opened = true;
(3)数据接收方法。
数据接收方法主要实现从串行口中接收数据。实现过程是首先定义缓冲区字节变量数组,判断句柄是否有效,如果返回句柄有效则调用ReadFile外部方法从串口的缓冲区中读取数据,然后使用数组复制的Copy方法将读取的缓冲区数据复制到OutBytes数组并返回,如果返回句柄无效则抛出异常错误。
(4)关闭串口方法。
处理代码判断hComm是否为无效的句柄,如果是有效的句柄,执行CloseHandle方法关闭串行口。
if (hc!=INVALID_HANDLE_VALUE) {CloseHandle(hComm);}
3.3 基于API函数库串口数据通信分析软件功能的实现
串口数据通信分析软件的功能主要有串口参数设置、打开串口、接收数据并存储文件,具体实现如下:
3.3.1 打开和关闭串口功能的实现
串口数据通信在接收数据前首先要打开串口,在程序设计的主窗体上添加“打开/关闭”按钮,用于打开或关闭串口。“打开/关闭”按钮的代码事件主要包括按钮的Click单击事件和打开串口的方法OpenComPort,在窗体级声明串口通信通用类对象_myserialPort,进行串口的打开、关闭、接收数据。“打开/关闭”串口的Click单击事件的处理代码根据按钮标题判断是打开还是关闭串口,根据标题的不同分别调用不同的代码进行串口打开或关闭。关键代码如下:
private static Com_IO serialPort1=new Com_IO();
private void btcom1_Click(object sender, EventArgs e)
{if (btcom1.Text== "关闭")
{serialPort1.Close();
btcom1.Text="打开";
return;}
serialPort1.PortNum=com_port.Text;
serialPort1.BaudRate=int.Parse(BaudRate.Text);
serialPort1.ByteSize=Convert.ToByte(ByteSize.Text);
…………
}
3.3.2 接收数据并存储功能的实现
程序执行时单击主窗体上的“接收数据”按钮,系统自动将Tick1定时器控件设置为工作状态,并根据控制设置的时间间隔自动调用Tick事件,Tick事件判断串口的状态,如果串口处于打开状态,则调用通用类的读取数据方法接收数据,如果串口处于关闭状态,则给出提示信息。如果接收数据成功,则进行数据转换并存储到数据库中。关键代码如下:
…………
byte[] text1=serialPort1.Read(40);//调用Read方法从串口读取数据
tbcon1.Text=BitConverter.ToString(context);//数据类型转换
string string1=tbcon1.Text;
string[] Arr1=string1.Split('-');
string string1="";
foreach (string i in Arr1)//将接收的数据转换为字符串
string1=string1+i.ToString();
if (string1=="")
{MessageBox.Show("接收数据为空!", "分析系统提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
int lenage=string1.Length;
inta1=0;
string string2="";
for (a1=0;a1 {string2=string2+string1.Substring(a1,4)+",";} string2=string2.Substring(0, 19); string[] Arr2=Regex.Split(string2, ",", RegexOptions.IgnoreCase); string[] da=new string[4]; int l=0; foreach (string str_array in sArray1) { int b=Convert.ToInt32(Convert.ToInt32(str_array, 16)); da[l]=b.ToString(); l=l+1; } …………//向数据库中添加获取的数据,代码略 应用VS2012集成开发工具通过调用API函数库中的串口数据通信函数设计了农业生产蔬菜大棚杀虫灯数据采集应用系统。通过系统的设计得出,调用API库通信函数实现串口数据通信,由于涉及的硬件较少,传输速度较快,适用于要求通信质量和远距离的数据通信需求,具有较强的实用性。4 结束语