多线程串口通信

2025-01-22

多线程串口通信(共8篇)

多线程串口通信 篇1

0引言

闭气塞是火工品中的关键零部件,为保证火工品的可靠性,必须对闭气塞质量进行全面控制。火工品闭气塞自动检测装置的研制,可替代目前落后的手工检测方法,实现闭气塞的自动检测,并能够更准确地得到测量结果,方便地完成多个测量项目[1]。

在设计的自动检测装置中,PLC和上位机组成了分布式/分级型控制系统,上位机完成被测件的检测,PLC控制系统完成被测件的传送及测量过程的控制。针对以往设计中串口通信占用CPU过多资源、通信开销大、影响系统整体性能等问题,提出了采用多线程串口通信技术[2,3],实现上位机和PLC之间的通信。本文主要讨论基于多线程串口通信,闭气塞检测系统通信程序的设计。

1上位机通信机制

由于Windows API串口通信函数提供了超时设置及事件响应等功能,使数据传输更为可靠、程序更加灵活、可控性大大加强[4]。因此,采用API函数进行闭气塞检测系统串口通信程序设计。

多线程使得多个线程并行工作以完成多项任务,可以提高系统的效率。为此,PLC和上位机通信系统在闭气塞自动检测系统中,数据的采集采用多线程工作方式。

1.1API函数通信

Windows API函数以文件的形式对串口进行操作,通过对文件打开、读写、关闭来实现串行通信。设计中,通过创建TCommunication类,封装对串口底层进行操作的一系列API函数,方便了串行通信程序的编制,通信类为外部调用提供了若干接口关系简单的成员函数。通信类图如图1所示。

类中接收缓冲区Buffer和接收缓冲区计数器BufferOffset,用于保存一次接收的连续的若干个字符。osRead和osWrite分别用于重叠方式接收和发送的数据结构。文件句柄hCom为API函数以文件创建的方式建立使用串行通信设备的句柄。

通信类中串口初始化函数ComInitialization功能:1)建立串行设备句柄;2)设置接收和发送缓冲区的大小;3)设置端口、波特率和流量控制等控制参数;4)设置超时参数;5)初始化接收和发送重叠类型数据结构osRead和osWrite;6)为接收和发送操作的重叠建立信号事件;7)接收缓冲区Buffer计数器清0。

串行通信设备初始化完成后,接收工作在操作系统内部自动进行,接收的字符自动放在内部输入缓冲区中。通信类中ReadCommBlock用于完成数据块的接收。

通信类中接收处理函数ReceiveProcess,调用ReadCommBlock函数接收的字符,将接收到一个或多个字符变成0结尾的ASCII码串,为后续的操作做准备。该函数由多线程程序调用。

通信类中发送接收处理函数WriteCommBlock,完成指定长度数据块的发送。

1.2通信线程

在C++ Builder中VCL类库提供了用于线程编程的TThread类。在TThread类中封装了Windows中关于线程机制的WindowsAPI函数。线程通过封装所需的内容,简化了多线程应用程序的编写[5]。在闭气塞自动检测系统中,负责通信的线程对象主要用于监视串行通信设备的通信事件,即收到有效字符事件和发送缓冲区空事件,这两个事件分别驱动接收或发送操作。

2PLC和上位机通信协议

2.1通信端口

西门子S7-200CPU的通信口使用的为RS-485通信端口,而上位机通信使用的是RS-232端口,可通过PC/PPI电缆实现S7-200CPU和上位机端口连接。

2.2通信方式

PLC和上位机通信采用自由口通信方式。自由口通信采用的是主从方式,计算机作为主机发起通信,从站PLC始终处于被动状态,随时准备响应来自计算机的通信请求。

上位机和PLC通信是以帧进行的。根据上位机数据流动的方向,可定义二种帧格式:一种是命令帧,数据流向由PC机发向PLC;另一种是状态帧,数据流向由PLC到PC。帧格式如图2和图3所示。

命令帧中起始字符占1个字节,可设置为“g”;指令类型占1个字节,设置“05H”为写指令,“06H”为读指令;寄存器地址占4个字节,其中前两个字节表示寄存器类型,后两个字节表示寄存器号;命令帧采用异或校验(BCC);结束字符占1个字节,可设置为“G”。

状态帧中的信息状态占1个字节。设置“01H”为读入正确,“02H”为写入正确,“03H”为BCC校验码错误,“04H”指令格式错误。

3检测系统通信程序的实现

3.1通信要求

(1) PLC完成火工品闭气塞的排序、转向与定位后,向上位机发送到位信号;

(2) 上位机接收到信号后,进行尺寸、粗糙度和缺陷检测的检测;

(3) PLC接收上位机数据处理结果,根据检测结果自动剔除不合格产品,并按合格与不合格自动收集检测过的产品;

(4) 上位机对检测的零件自动计数;

(5) 上位机进行运行参数设置、参数在线修改、控制系统运行、报警及故障显示。

3.2上位机程序的设计

在设计的通信类基础上,创建线程对象ThreadComm,定义相关属性和方法。根据通信要求,程序设计关键在于重载线程的Execute方法,监视“收到有效字符”和“发送缓冲区空”通信事件,适当时机启动字符接收或者发送操作。设置相关事件掩码后,在线程中使用等待通信事件函数WaitCommEvent监视指定的通信事件,这个函数在线程Execute方法中被反复调用。依据通信事件,程序产生了两个分支:“收到有效字符”事件触发字符接收、处理和显示操作;“发送缓冲区空”事件触发字符。收到数据后将其送到主窗体有关VCL控件,并做相关处理,线程和主窗体控件交互需借助同步函数Synchronize(),线程的Execute方法的主要代码如下:

根据同步函数Synchronize()的要求,DataProcess()为无参数和无返回值的函数,数据传递可用公有变量来传递。

线程中SendOneByte()函数用来发送缓冲区当前位置的数据。缓冲区的内容由主线程组合,结合发送缓冲区计数器可计算发送位置。

3.3PLC程序的设计

由于PLC内部端口为485端口,是半双工方式,所以PLC的XMT命令和RCV命令不能同时执行。因此,编制自由口通信协议须保证发送、接收的分时性。在实际工程中,采用中断方式实现了半双工通信,即接收完成后启动发送程序,或发送完成后启动接受程序。

4结论

在闭气塞自动检测装置中,采用自由口通信方式的PLC+上位机控制系统,具有线路简单、应用灵活、高可靠性的优点。此系统中,上位机完成了图像的采集、处理和显示,PLC控制系统完成了被测件的传送、分离和测量过程的控制,实现闭气塞的自动检测。运行证明,该系统引入多线程后,检测效率由原来12件/分钟,达到15件/分钟,效果明显,且性能稳定,可靠性高。

摘要:针对单线程进程机制通信开销大,系统工作效率低的问题,利用多线程技术和W indows API函数,开发设计了上位机的串行通信程序;根据PLC自由端口模式,设计了PLC的串口通信程序,从而实现了闭气塞自动检测装置中PLC和PC之间的通信。系统运行表明:基于自由口通信方式的上位机+PLC的自动检测控制系统,引入多线程后,检测效率明显提高,且性能稳定,可靠性高。

关键词:PLC,自动检测,串口通信,多线程

参考文献

[1]陈智利,高明,杜玉军,等.PLC在闭气塞自动检测装置中的应用[J].自动化仪表,2006,27(9).

[2]李志俊,程涛.基于多线程的多串行通信任务的实现[J].武汉理工大学学报,2002,26(5):15-17.

[3]王伟,王敏.多线程技术在串口通信中的应用及实现[J].计算机应用与软件,2004,21(2):47-49.

[4]杨颂,邱云超,费敏锐.Windows环境下实现串行通信的3种常用方法及比较[J].自动化与仪表,2000,15(4):1-4.

[5]张万里,陈占林.C++Builder 5.0高级开发技巧与范例[M].北京:电子工业出版社,2001:359-384.

多线程串口通信 篇2

摘要:通过多串口通信技术在金刚石合成控制系统中的应用,讨论了32位Windows操作系统下,VC多串口通信技术的设计与实现方法,并运用面向对象方法和多线程技术设计了一个比较完善的串口通信类。阐述了用VC开发上位机与PLC之间的串口通信程序设计方法和实现技术。

关键词:串口通信;面向对象方法;多线程;PLC

1引言

传统的金刚石合成机控制系统是由一个PLC和一个可显示终端构成。这种传统的控制系统一般具有如下缺点:

(1)系统所有的工作都由PLC完成,其控制精度较差,致使合成的金刚石质量较差;

(2)显示终端的平面尺寸过小,这一方面使得操作人员观察系统的状态很不方便,另一方面?也常常会引起误操作;

(3)金刚石合成工艺复杂,需控制的参数很多,但原控制系统不能对参数进行保存,这样在根据不同产品和工艺要求对部分参数进行调整时,每次都必须重新设置所有的参数,操作非常麻烦;

(4)界面不友好;

(5)不能通过控制系统自动考核操作人员的工作质量。

为了提高控制精度、方便操作,开发新的控制系统迫在眉睫。笔者针对以上问题,将IPC与PLC有机结合在一起,开发了一套新的控制系统。通过该系统可在上位机(IPC)和PLC之间通过RS-232与RS-485进行大量串口通信。

2VC串口通信分析

在32位Windows系统下使用VC开发串口通信程序通常有如下4种方法:

(1)使用Microsoft公司提供的名为MSCOMM的通信控件;

(2)直接使用Windows应用程序接口(API);

(3)自行设计一个串口通信类;

(4)通过开发一个ActiveX控件来实现串口通信功能。

在上述几种方法中,实际上还是使用WindowsAPI函数,然后把串口通信的细节给封装起来,同时提供给用户几个简单的接口函数。上述几种方法各有优缺点,但在实际情况下,大多数编程人员喜欢使用API函数自行设计串口通信类。

用WindowsAPI函数进行串口通信的编程流程如图1所示。其中打开串口是确定串口号与串口的打开方式;初始化串口用于配置通讯的波特率、每字节位数、校验位、停止位和读写超时等;读写串口用于向串口进行发送数据和从串口接收数据;关闭串口用于将串口关闭并释放串口资源(Windows系统下串口是系统资源)。

由于绝大多数控制系统中串口通信是比较费时的,而且监控系统还要进行数据处理和显示等,所以一般采用多线程技术,并用AfxBeginThread函数创建辅助线程来管理串口通信,这样,主进程就能在进行串口读写的同时,处理数据并完成用户指令的响应,但是设计时一定要处理好数据的共享问题。

串口读写既可以选择同步、异步方式,也可以选择查询、定时读写和事件驱动方式。由于同步方式容易造成线程阻塞,所以一般采用异步方式;而查询方式要占用大量的CPU时间,所以一般采用定时读写或者事件驱动方式,事件驱动方式相关文献较多,故此重点讨论定时读写方式。定时读写方式就是上位机向下位机发送固定格式的数据,在下位机收到后向上位机返回状态信息数据。由于数据的传输需要时间,所有上位机发送数据后就调用_sleep()函数进行休眠,休眠的时间可根据需要进行不同的设置。这样,可以节省CPU时间,以使系统能够很好地进行监控工作和处理其它事务。

3VC串口通信的设计与实现

笔者在Windows系统下,采用面向对象的方法和多线程技术,并使用VisualC6.0作为编程工具开发了一个通用串口通信类CSerialPort,该CSerialPort类封装了串口通信的基本数据和方法,下面给出CSerialPort类的简单介绍。

CSerialPort类头文件中的主要成员变量和成员函数如下:

ClassCSerialPort

{

private:

HANDELm_hPort;

DCBm_Dcb;

COMMTIMEOUTSm_TimeOuts;

DWORDm_Error;

Public:

CSerialPort;??//构造函数

virtual~CSerialPort();??//析构函数

//InitPort()函数实现初始化串口

BOOLInitPort(

char*str=“com1”,

UINTBaudRate=9600,

UINTParity=0,

UINTByteSize=8,

UINTStopBits=1,

UINTReadMultiplier=0,

UINTReadConstant=0,

UINTWriteMultiplier=10,

UINTWriteConstant=1000);

DCBGetDCB();?//获得DCB参数

//SetDCB()函数实现设置DCB参数

BOOLSetDCB(

UINTBaudRate=9600,

UINTParity=0,

UNITByteSize=8,

UINTStopBits=1);

//GetTimeOuts()函数获得超时参数

COMMTIMEOUTSGetTimeOuts();

//SetTimeOuts()函数设置超时参数

BOOLSetTimeOuts(

UINTReadMultiplier=0,

UINTReadConstant=0,

UINTWriteMultiplier=10,

UINTWriteConstant=1000);

//WritePort()函数实现写串口操作

voidWritePort(HANDLEport,CString);

CStringReadPort(HANDLEport);//读串口操作

BOOLClosePort();?//关闭串口

};

下面对该类的重要函数作以说明:

(1)在构造函数CSerialPort()中已对该类的数据成员进行了初始化操作。

(2)初始化串口函数InitPort()函数用于完成串口的初始化工作,包括打开串口、设置DCB参数、设置通信的超时时间等。

打开串口使用CreateFile()函数,其中InitPort()函数中的第一个参数为要打开的串口,通常将该参数赋给CreateFile()函数中的第一个参数;设置DCB参数应调用该类中的SetDCB()函数,并将InitPort()函数中的第2至第5参数赋给SetDCB()函数;设置通信的超时时间应调用该类中的SetTimeOuts()函数,并将InitPort()函数中的第6至第9参数赋给SetTimeOuts()函数。另外,该串口是系统资源,应该根据不同要求对其安全属性进行设置。

(3)SetDCB()函数用于设置DCB参数,包括传输的波特率、是否进行奇偶校验、每字节长度以及停止位等。

(4)SetTimeOuts()函数用于设定访问的超时值,根据设置的值可以计算出总的超时间隔。前面两个参数用来设置读操作总的超时值,后面两个参数用来设置写操作总的超时值。

(5)WritePort()函数用来完成向串口写数据。由于该系统需要对多个串口进行通信,所以首先应把串口号作为参数传递给该函数;接着该函数把按参数传递过来的、要发送的数据进行编码(也就是加入校验,这样能减少误码率),然后再调用WindowsAPI函数WriteFile()并把数据发送到串口。

(6)ReadPort()函数用来完成从串口读数据,由于有多个串口,所以应把串口作为参数传递进来,然后调用API函数ReadFile(),并把下位机发送到串口,数据读出来放到缓存里面,接着对数据进行处理以将其变换成字符串

(CString)类型并返回。

(7)GetDCB()函数主要用于获得串口的当前配置,可通过调用API函数GetCommState()来实现,然后再进行相应的处理。

(8)GetTimeOuts()函数用于获得访问超时值。

(9)ClosePort()函数可用来关闭串口。因为在Windows系统中串口是系统资源,因而在不用时,应将其释放掉,以便于其它进程对该资源的使用。

4基于串口通信的金刚石合成控制

金刚石合成控制系统采用主从式控制方式,上位机为微机、下位机为PLC。上位机的主要功能是对系统进行实时监控,下位机的主要功能是对系统进行实时控制。上位机采用Windows98操作系统,其监控程序可用VC开发,上、下位机之间通过RS-232与RS-485串口进行通信,它们之间采用的通信波特率为9600bps,无奇偶校验,每字节8位,并有1位停止位。上、下位机之间传送的数据格式可自己定义。由于传输数据时可能会引起错误,所以加入了校验算法。该系统通过上位机向下位机发送数据,下位机收到后就把当前系统的状态参数返回给上位机。由于该系统中所控制的参数具有迟滞性,所以应采用定时发送数据的方法来采集现场状态信息。

上位机编程时,可用VC6.0生成一个对话框类型的`程序框架,然后将自己编写的CSerialPort类加入到该工程中,并在主界面类?CCrystal?中添加一个CSerialPort类的成员变量serial。当监控系统开始工作时,可用AfxBeginThread??函数创建辅助线程来管理串口通信,当调用CSerialPort类中的WritePort??函数向串口发送数据后,可调用_sleep??函数使辅助线程休眠一段时间,以便使PLC有充分的时间返回数据;接着再调用CSerialPort类中的ReadPort()函数并从串口读数据,然后再调用_sleep()函数使辅助线程再休眠一定的时间。这样设计后,当进行串口通信时,主线程就能继续完成监控功能和处理其他事务。辅助线程函数的主要代码如下:

UINTSerialPro(void*param)

{

Ccrystal*mdlg=(Ccrystal*)param?

CStringstr;

intflag=1;

//如果初始化串口失败返回

if(!InitPort(“com2”))

{AfxMessageBox(“打开串口2失败”);

return0;

}

//循环读写串口,直到结束

while(flag)

{

//这里把要发送的数据传送给变量str

……

//向串口写数据

mdlg->serial.WritePort(hport,str);

//让辅助线程休眠100ms

_sleep(100);

//从串口读数据并赋给变量str

str=mdlg->serial.ReadPort(hport);

//这里把从串口得到的数据进行处理

……

5结束语

多线程串口通信 篇3

1.多线程技术简介

进程是程序的一个执行实例,属于在计算机的基础上执行程序的一个分支,多线进程就是能在同一时间内执行多个任务。工作状态下多线程的进程中至少需要有一个主执行线程,这个线程是程序自带的,不需要用户去创建,但是其他的线程如果需要应用,得靠用户自己去建立,然后多个线程可以并行得运行在一个程序当中,共同的使用这个进程中的空间和资源。多线程技术得运用要靠VC++环境的支持,MFC类库为多线程的编程提供了很大的方便,MFC类库中一般存在着两种类型的线程,划分的标准是用户群体的不同,一种是工作者线程,另一种是用户界面的线程,一个完整的线程的完成要在MFC中经过创建、挂起、恢复和终止等步骤。线程之间的同步问题也是多线程技术必选要研究的,这是因为,在实际的工作中,由于多个线程都要使用一个进程中的资源,所以不可避免的会出现摩擦等状况,为了解决这个问题,一般使用的是Win32 API[1]。

2.串口通信的原理和编程

串口通信是近几年兴起的技术,由于便捷性和精确性,很受通信事业的重视。互联网是一个很庞大且复杂的环境,在这样一个大环境下,串口通信技术依然是不可获取的,属于系统资源的一部分。串行端口的本质功能主要是作为一个转换器,在CPU中起到转换编码的作用,在整个系统中起着不可替代的作用,当有数据通过CPU并经由串行的端口发送出去的时候,原本属于字节的数据经过串口的转变就变为了串行数据。所有的应用程序使用串口进行通信的时候,都必须要向操作系统申请资源,如果没有资源申请,通信就不会有开始的机会,同样在通信结束的时候也必须进行资源的释放环节。

在互联网的大环境下,编程工作中串口通信技术的使用主要有三种,分别是MSComm控件、Windows API、第三方串口通信类,三者都各有特点,为不同环境下的使用提供了不同的选择。MSComm控件能够简化编程,使工作变得简单明了,但是由于MSComm控件做了比较大的封装,所以会对编程的灵活性和可控性有不小的影响,因此在进行多线程多串口的编程时,为了工作的效率,还需要做很多复杂的处理。Windows API也有自己的特点,使用Windows API编写串口程序时,对编程人员的能力要求比较高,不仅操作技术需要娴熟,还需要掌握多种编程技术,但是Windows API在应用的过程比较稳定。第三方串口通信类相较于前两种处于居中的转台,既可以使得编程的效率高,也可以加强程序的控制性,所以第三方串口通信类的应用要比前两种广泛。

3.多线程串口通信技术在GPS导航中的应用

■3.1分析GPS导航系统

GPS导航的工作要借用卫星来实现定位技术,对用户提供帮助,为了实现定位需要将用户申请的实时数据使用接口机串口来接收,并且在接收的过程中,还需要对数据进行监控、存储和显示等,这些都可以通过多线程串口通信技术来实现,为此,我们首先对GPS导航系统进行分析。GPS导航程序主要分为以下几个部分,首先是主线程,主要是负责用户消息的处理,然后再通过已经预定好的义流程来调度其他的支线程来处理数据。其次是串口坚实的线程,属于数据处理的一个缓冲期,入库线程是将缓冲期的数据进行处理之后再对数据进行储存。最后是显示线程,顾名思义,是将处理好的数据显示给用户的一个程序,呈现出的状态一般都已经和地图相匹配,是用户能够看懂的各种数据[2]。具体的图如1所示。

■3.2具体的实现

GPS系统中对串口的操作大多采用的是CSerial Port类,一般的应用流程是:首先需要做的是设置好串口的参数,之后才开启串口的监测工作。监测到的数据要通知主线程,由主线程进行控制,根据事先预定的情绪和实际的情况,分发给支线程处理,这是针对数据的接收而言的,对于数据的发送,则可以直接向串口进行发送。对此首先应该建立一个CSerial-Port Test,其他的程序先保持不变的状态,之后需要添加各种类文件,还需要在视觉类的文件上添加定义串对象。接下来是增加消息响应函数,对串口进行初始化并且开启监控程序,最后是对函数中的数据进行处理,比如将收到的数据对照实际位置的经度和纬度,将处理后的数据收集到数据库,再通过特定的程序展现给用户。

4.结束语

GPS导航已经在人们的生活中扮演了重要的地位,不管是普通的日常出行还是专业的开发,GPS导航都有重要的作用,所以及时更新GPS导航有着很大的社会现实意义。多线程串口通信技术的出现,解决了GPS系统中存在的各种问题,提高了导航的精准度,增强了系统的工作效率。但是多线程串口通信技术也不是发展的非常完善,并且现实中在GPS系统中的应用也没有达到完美的程度,依然需要社会各界人士的共同努力。

参考文献

[1]冯正,韩焱,王黎明.多线程串口通信技术在GPS导航中的应用[J].现代电子技术,2009,05(8):28-30+33.

多线程串口通信 篇4

1 TCP的工作原理

在TCP/IP的参考模型中,应用程序处在应用层,应用层下面分别是传输层、网络层、网络接口层。传输层通过两种核心协议,为应用层提供会话和数据报通信服务。即TCP(Transmission Control Protocol,传输控制协议)和UDP(User Datagram Protocol,用户数据报协议)。TCP协议是一种面向连接的可靠传输协议,其工作原理是两个进程在利用TCP协议通信前必须先建立TCP协议连接;UDP是面向非连接的,即传送数据前不需要建立连接。该文讨论的是基于TCP的Socket通信。

2 Socket通信机制

为了能够方便的开发网络应用软件,由美国伯克利大学在Unix上推出了一种应用程序访问通信协议的操作系统调用Socket。Socket的出现,使程序员可以很方便地访问Tcp/Ip,从而开发各种网络应用的程序。在网络通信中Socket可以理解为客户端或服务器端的一个特殊对象,Socket通常也称为“套接字”,用于描述IP地址和端口,是一个通信链的句柄。Socket和Server Socket类中封装了实现Socket通信的主要方法,通信过程中有两个关键的方法:get Input Stream()和get Output Stream()。前者得到的是一个输入流,后者得到是一个输出流。客户与服务器可调用各自的get Input Stream()和get Output Stream()方法,实现服务器与客户端一对一的流式传输。一个完整的Socket通信程序一般包括以下几个步骤:

1)创建Socket。

2)打开连接到Socket的输入输出流。

3)按照一定的协议对Socket进行读/写操作。

4)关闭Socket。

3 服务器端程序编写:

Java使用专门建立Socket服务器的类Server Socket来创建服务器对象,Server Socket server=new Server Socket(int port),这里提供了一个端口作为参数,要注意的是端口的分配必须是唯一的。因为端口是为了唯一标识每台计算机唯一服务的,另外端口号是从0~65535之间的,前1024个端口已经被Tcp/Ip作为保留端口,例如:Http使用80端口。因此我们所分配的端口只能是1024之后的。

建立服务器端的Socket对象步骤如下:

1)创建一个服务器端套接字,并绑定到指定端口上;

Server Socket ss=new Server Socket(int port),

2)调用accept(),监听连接请求,如果客户端请求连接,则接受连接,返回通信套接字。

Socket s=ss.accept();

3)调用Socket类的get Output Stream()和get Input Stream获取输出流和输入流,开始网络数据的发送和接收。

4)最后关闭通信套接字。os.close();is.close();s.close();

4 客户端程序编写

客户端应用程序和服务器端很相似,

1)调用Socket()创建一个流套接字,并连接到服务器端;

Socket s=new Socket(Inet Address.get By Name(“服务器的主机名”),port);

2)调用Socket类的get Output Stream()和get Input Stream获取输出流和输入流,开始网络数据的发送和接收。

3)最后关闭通信套接字。os.close();is.close();s.close();

5 实现多线程通信

通常服务器程序必须同时为多个客户端提供服务,为达到这个目的,我们要使用多线程的机制,每当客户端提出请求后,服务器程序就会产生一个线程来用来和这个客户端建立一个套接字连接。多线程是Java提供的一个重要机制,支持多个程序并发执行。

1)多线程Socket通信的服务器端程序:

2)为了证实服务器代码能为多个客户端提供服务,下面的程序将创建多个线程,并同相同的服务建立连接。

多线程Socket通信的客户端程序:

6 测试

此程序在MyEclipse6.5和jdk1.5环境下运行,图1是服务器启动后的状态。图2是服务器运行中的状态。图3是客户端运行中的状态。

7 结束语

Java是一种优秀的编程语言,具有可移植性、面向对象、多线程、简单性、解释性、安全性等优点,广泛应用于网络开发环境中。基于TCP的Socket通信,保证了网络通信的准确性、及时性。本文就其如何进行多线程通信作了介绍,并通过一个实例,介绍了多线程通信的具体实现。

摘要:在基于TCP的网络应用开发中,Socket是一种流的机制,线程通过Socket进行数据流的读取和发送,该文阐述了Socket编程的方法和步骤,并实现了基于TCP的Socket多线程通信。

关键词:TCP/IP,socket,多线程

参考文献

[1]李芝兴.Java程序设计之网络编程[M].北京:清华大学出版社,2006.

[2]李新良,罗戈夕.用Socket的编程机制实现网上交谈[J].电脑知识与技术,2006(29).

[3]王静,曲凤娟.基于Socket的多用户并发通信的设计[J].福建电脑,2007(3):164.

[4]陈小艳.用Java实现多线程Socket通信[J].湖北广播电视大学学报,2008(1).

多线程串口通信 篇5

1 Socket基本原理

在C#中, MS为我们提供了System.Net.Sockets命名空间, 程序员可以通过socket来发送和接收网络上的数据。我们可以把它理解成是一个API, 有了它就可以通过这个接口访问网络从而省去了很多复杂的操作。

要通过互联网进行通信, 至少需要一对套接字, 它是通信主机之间的端点, 由它构成了单个主机内及整个网络间的编程界面。我们把运行于客户机端的称之Client Socket, 运行于服务器端的称之为Server Socket。它的连接过程可以分为三个步骤:服务器监听, 客户端请求, 连接确认。

2 Socket通信过程的实现

2.1 服务器端

申请一个Socket, 定义到一个IP地址和一个端口上开启侦听。每成功接受一个客户端的链接便在服务端产生一个对应的Socket, 在接收客户端连接时创建责和对应的客户端通信。

int recv;//用于表示客户端发送的信息长度

byte[]data=new byte[1024];//用于缓存客户端所发送的信息

IPEnd Point ipep=new IPEnd Point (IPAddress.Any, 9050) ;//定义一网络端点Socket newsock=newSocket (Address Family.Inter Network, Socket Type.Dgram, Protocol Type.Udp) ;//定义一个Socket

newsock.Bind (ipep) ;//Socket与本地的一个终结点相关联

IPEnd Point sender=new IPEnd Point (IPAddress.Any, 0) ;//定义要发送的计算机的地址

recv=newsock.Receive From (data, ref Remote) ;//接受数据

newsock.Send To (data, data.Length, Socket Flags.None, Remote) ;//发送信息

2.2 客户端

申请一个Socket, 连接服务器 (必须指明IP地址和端口号) , 通过创建一个Socket对象来初始化一个服务器端的TCP链接:

byte[]data=new byte[1024];//定义一个数组用来做数据的缓冲区

string input, string Data;

IPEnd Point ipep=new IPEnd Point (IPAddress.Parse ("1 2 7.0.0.1") , 9050) ;

//本机预使用的IP和端口

server.Send To (data, data.Length, Socket Flags.None, ipep) ;//将数据发送到指定的终结点

data=new byte[1024];

int recv=server.Receive From (data, ref Remote) ;//接受来自服务器的数据

2.3 服务器

服务器接到连接请求后, 产生一个新的Socket (端口大于1024) 与客户端建立连接并进行通讯, 原侦听Socket继续侦听。每个服务打开一个socket, 并绑定到一个端口上, 不同的端口对应不同的服务 (应用程序) 。

3 结语

许多Internet服务都可以见到Socket的踪影, 如Telnet、Http、Email、Echo等, 这些服务尽管通讯协议Protocol的定义不同, 但是其基础的传输都是采用的Socket。针对Socket编程, .NET框架的Socket类是Winsock32 API提供的套接字服务的托管代码版本。其中为实现网络编程提供了大量的方法, 大多数情况下, Socket类方法只是将数据封送到它们的本机Win32副本中并处理, 如果你熟悉Winsock API函数, 那么用Socket类编写网络程序会非常容易。

摘要:本文简要介绍了c#中Socket的通信流程, 探讨了基于多线程和Scoket在不同的程序之间进行数据通信的方法, 并通过实例讲解了多线程Socket通信的实现过程。

关键词:多线程,Scoket,通信

参考文献

[1]郑阿奇.Visual C#网络编程[M].电子工业出版社, 2011 (10) .

[2]马骏.C#网络应用编程[M].人民邮电出版社, 2010 (2) .

多线程串口通信 篇6

FPGA (Field-Programmable Gate Array) , 即现场可编程门阵列, 它是作为专用集成电路领域中一种半定制电路出现的, 既解决了定制电路的不足, 又克服了原有可编程器件门电路数有限的缺点。FPGA中具有丰富的触发器和I/O口, 采用描述语言 (VHDL和Verilog HDL) 进行设计, 用户可以根据需要, 描述出具有各种功能的电路。[2]

基于以上原因, 我们可以利用FPGA实现多串口通信中的数据转换和中断控制功能, 从而简化电路、缩小PCB面积, 也可以很方便的进行升级改动和模块移植。

1 设计要求

整个设计的硬件电路以DSP和FPGA为主构架, DSP和FPGA之间通过DSP的EMIF接口连接。其中, DSP是主处理器, 用于实现串口数据的处理, FPGA作为DSP的外围电路, 实现UART模块的串行数据的接收和发送、数据的串并/并串转换及接收中断的产生, 同时, 实现多串口的中断控制功能。当有接收数据时, FPGA通过中断方式通知DSP。

UART模块的数据格式:波特率可以按标准波特率设置;按字节接收, 每个字节前包含一个起始位 (低电平, 逻辑值0) , 无校验位, 最后是一位停止位和不定长度的空闲位 (高电平, 逻辑值1) ;接收到一个完整字节后产生一个中断 (高电平, 逻辑值1) , 当数据被读取后, 中断信号复位 (低电平, 逻辑值0) 。

中断控制器应能实现8路UART模块的中断接收和处理, 最后给DSP输出一个中断信号, 输入的各中断信号之间无优先级设定。

2 设计方案

完整的设计由时钟管理模块、接口模块、UART模块和中断控制器组成。时钟管理模块产生设计中所需各种时钟, 包括主处理时钟和接收与发送的波特率时钟;接口模块实现DSP和FPGA之间的中断、读写功能;UART模块由接收和发送子模块组成, 实现数据的串行接收和串行发送功能;中断控制器由中断采样子模块和中断处理子模块组成, 实现8路UART中断接收和处理功能。下面分别对这些模块的设计给予描述。[1]

2.1 时钟管理模块[3]

设输入FPGA的时钟为50MHz, 则主处理时钟设计为50MHz。U A R T的接收和发送采用相同的波特率进行, 本设计中采用115200b/s进行收发, 这就需要对50MHz时钟进行分频以产生所需的波特率。

2.2 接口模块

接口模块连接时钟管理模块、UART模块和中断处理器, 并与DSP采用EMIF总线相连接。与DSP相关的信号有:wr_n、rd_n、cs_n、addrs、data_bus和dsp_int, 在cs_n和wr_n有效时, DSP通过addrs选通不同的UART模块, 将需要发送的并行数据发送给发送寄存器, 执行发送功能。DSP响应外部中断时, 在cs_n和rd_n有效时, 通过addrs读取中断控制器的中断矢量和UART模块接收的数据。[4]

2.3 UART模块

2.3.1 发送模块

根据UART模块的数据格式, 发送状态机如图1所示。[5]

当复位信号rst_n=‘0’时, 状态机初始化为空闲状态, 当有需要发送的数据时, 即tx_flag=‘1’时, 状态机转入发送起始位状态;在发送起始位状态中, 串行输出数据线被置为0, 并保持一个波特率时钟周期, 即在baud_rate=‘1’时, 转入数据移位状态;在数据移位状态中, 利用baud_rate=‘1’的驱动, 将8位并行数据依次移位, 转成串行数据输出, 每移一位, 相应的计数器加1, 当cnt_bit_tx=“1000”时, 转入发送停止位状态;在发送停止位状态中, 串行输出数据线被置为1, 并保持一个波特率时钟周期, 即在baud_rate=‘1’时, 转入发送结束状态;在发送结束状态, 一个字节的发送过程完成, 清除发送标志, 即tx_flag=‘0’, 转入空闲状态。

2.3.2 接收模块

根据UART模块的数据格式, 接收状态机如图2所示。

当复位信号rst_n=‘0’时, 状态机初始化为空闲状态, 当检测到数据线上出现由1到0的跳变沿时, 即data_coming_flag=‘1’时, 状态机转入接收起始位状态;在接收起始位状态中, 在baud_rate=‘1’时, 判断数据是否为0, 如果是0, 则转入数据移位状态, 如果是1, 则回到空闲状态;在数据移位状态中, 利用baud_rate=‘1’的驱动, 将串行数据依次移位, 转成并行数据, 每移一位, 相应的计数器加1, 当cnt_bit_rx=“1000”时, 转入接收停止位状态;在接收停止位状态中, 在baud_rate=‘1’时, 判断数据是否为1, 如果是1, 则转入接收结束状态, 如果是0, 则回到空闲状态;在接收结束状态, 产生一个中断信号。

2.4 中断控制器[6]

2.4.1 中断采样子模块

在中断采样子模块中, 利用主处理时钟作触发, 检测各UART模块是否有中断输入, 如果中断输入端口出现由0到1的跳变沿, 则置该UART模块的中断采样值为1, 该值只有在复位信号rst_n=‘0’或清除信号clr=‘1’时, 恢复为0。程序逻辑如图3所示。

2.4.2 中断处理子模块

在该模块中, 主要完成中断矢量的生成、DSP中断信号的产生和中断清除信号的生成3个功能。

中断矢量由8个UART模块的中断输出信号合成, 特别注意的是因为各个UART模块中断清除信号和该矢量相关, 因此, 当该矢量不为0时, 要暂时锁定中断矢量, 即在DSP响应中断之前, 即使有新的中断信号产生, 也不允许更新中断矢量, 判断逻辑如图4所示。

在主时钟的触发下, 当中断矢量不为0时, 产生一个中断信号, 且只有当DSP读取了该中断矢量时, 才清除该DSP中断信号, 判断逻辑如图5所示。

当DSP中断清除信号有效时, 根据中断矢量, 生成中断清除矢量, 用于清除各个UART模块的中断采样信号, 该模块采用组合逻辑完成。

3 结语

在本设计中, 基于FPGA平台实现了通用UART芯片的核心功能和中断控制器逻辑, 能够满足多串口通信的需要。该电路已运用于实际工程中, 实践证明该电路结构简单、工作稳定, 可运用于低速率的异步通信。

参考文献

[1]杨英强.一种基于FPGA的UART电路实现[J].现代电子技术, 2005.YANG Ying-qiang.Realization of a Sort of UART Based on FPGA[J].Modern Electronics Technique.

[4]卞红雨, 纪祥春, 等.TMS320C6000系列DSP的CPU与外设[M].清华大学出版社, 2007.BIAN Hong-yu, JI Xiang-chun, et al.TMS320C6000DSP CPU and peripherals[M].TSINGHUA UNIVERSITY PRESS.

[5]李仁发, 凌纯清, 徐成.VHDL数字系统设计[M].电子工业出版社, 2004.LI Ren-fa, LING Chun-qing, XU Chengdu.Digital System Design with VHDL[M].Publishing House of Electronics Industry.2004.

多线程串口通信 篇7

首先,需要分析8142Pro传输的数据格式,以及各数据位的具体含义,并找出需要的数据位。

1 托利多8142Pro的数据采集端口及发送的数据格式

在8142Pro的实际使用中,最后一位校验和没有使用,所以每个数据包共有17个字节。8142Pro背面板如图1所示。

由图1可知,程序采集的数据来自COM2端口。

8142Pro发送的数据格式如表1

其中各数据位意义如下:

1:ASCII起始符为(02H)。

2:状态字A:小数点位置和分度值因子。B:毛重或净重等信息。C:是否有打印命令。

3:显示重量,毛重或净重(可设置),6位不带符号和小数点的数字。

4:皮重,6位不带符号和小数点的数字。

5:ASCII回车符(0DH)。

6:可选的校验和。

2 设计思路及实现方法

2.1 Java串口通信简介及开发环境设置

Java读写串口要用到的是javax扩展类库comm,其核心是抽象的CommPort类及其两个子类:SerialPort类和ParallePort类。其中,SerialPort类是用于串口通信的类,ParallePort类是用于并行口通信的类。本文只关心SerialPort类,SerialPort类具有以下重要属性和方法:

setSerialPortParams:描述一个RS-232串行通信端口的底层接口,它定义了串口通信所需的最小功能集。通过它,用户可以直接对串口进行读、写及设置工作。

open:打开端口。

close:关闭端口。

getInputStream:获取端口上的输入流对象。

available:是否有数据通过。

read:读取一个字节并将其放到指定字节变量中。

java.comm类库在sun的官网上只提供Linux版本。由于开发的平台是Win32。所以下载的java.comm包解压后必须进行相应配置,配置方法如下:

(1)把javax.comm.properties文件拷贝到Java运行时环境的lib目录中。

(2)把win32com.dll拷贝到C:windowssystem32和C:Program FilesJavajdk1.5.0_12jrebin下。

(3)把comm.jar放到Java运行时环境的lib目录中。

(4)在“环境变量”的CLASSPATH中添加comm.jar,如:%JAVA_HOME%libcomm.jar。

2.2 重量数据的提取

要在缓存中得到有效数据,首先将数据按字节存到一个字节数组变量中,在此字节数组查找需要的有效数据。按照8142Pro字节定义,开始字节为02H,结束字节为0DH,按照ASCII换算为十进制为2和13。

在字节数组中查找readBuffer[i]等于2且readBuffer[i+16]等于13的数据,如果有则存储为一个有效数据。否则,继续返回查找。

2.3 重量数据的转换显示

接收的重量数据是6个字节。每个字节为8位,根据ASCII表,所以应该是0~127。实际接收的数据应该为ASCII表中的48~57,减去48之后即为显示的结果0~9。如果接收的数据大于127,则应再减去128之后按照前述进行处理。

3 主要程序源代码

4 实际应用

多线程串口通信 篇8

在Windows应用程序开发时, 有两种主要方法:基于Windows API的开发方法和基于Windows MFC的开发方法。后者借助于其应用程序向导及类向导的帮助, 简化了程序开发的过程并减少了开发的工作量和难度, 故获得广泛的应用。本文研究的重点就是基于VC++的MFC多线程通信程序。

1 线程的优先级状态

高的优先级可以使一个线程获得更多的CPU时间片, 更快地完成它的任务, 或更及时地响应用户的输入。但是设置线程的优先级时要非常注意, 如果一组线程具有相同的优先级, 则不论这组线程具有的优先级是高还是低, 调度程序都会给它们分配相同的处理器时间。线程的优先级是和这个线程所在的进程的优先级密切相关的。进程的优先级一共有4个等级, 如表1所示。

2 多线程通信程序的设计技术

2.1 使用全局变量通信

要使主线程具有停止某线程的能力, 则需要一种通知该线程停止的方法。可以在程序中建立一个全局变量, 接着让线程监视这个全局变量。当这个变量变为某值时, 表示线程应该停止了, 这种方法比较简单和机械。其用法示例如下:

在一个多线程的程序中添加一个菜单项“Stop Thread”, 并且为它创建一个消息响应函数On Stop Thread () 。然后声明一个全局变量:Volatile int timer;关键字Volatile表明这个变量可以在使用它的线程之外改变它的值。接着在主线程的函数OnStop Thread () 中添加一行代码:

同时在开始创建线程代码中添加这样的代码:

在新线程的执行代码中这样写:

现在, 在程序中单击菜单项“Stop Thread”时, 会弹出一个对话框告诉我们线程已经结束了。这个例子说明了全局变量相当于一个控制键, 当时间用完时新线程从主线程中得到这个值, 发现符合结束的条件于是就自动中止了。使用全局变量实现线程之间的通信适用于不复杂的线程之间通信。若是对VC++处理变量的过程不太了解的话, 这个方法比较危险, 容易引起一些错误。

2.2 使用用户自定义的消息

子线程与主线程的通信可以采用用户自定义Windows消息的方法来实现。首先要定义用户消息, 定义的位置在相应的头文件中, 可以是这样:

WM_USER常数是由Windows定义的, 它保留第一个可用的用户消息号。在应用程序中的其它部分出于各自的目的, 需要使用一些用户消息, 所以在上面的代码中把用户消息号定义为WM_USER+10。然后在头文件把下面的代码加入消息映射中, 位置是在AFX_MSG注释的后面, 在DECLARE_MESSAGE_MAP的前面:

接着在相应的.cpp文件中将消息和处理函数联系在一起;

定义了消息以后, 在子线程的执行程序中调用::Post Message () 把消息发送给主线程, 子线程的执行函数可以是这样:

在主线程的消息处理函数On Thread End () 中同样可以弹出一个对话框:

运行这个例子会发现结果和使用全局变量一样, 但是它们的本质却是不同的。使用全局变量是在子线程中将自己中止, 在使用消息机制中却是在主线程中中止了子线程, 这是因为子线程将消息告诉主线程, 主线程响应消息中止了子线程。

3 多线程通信程序的实现步骤

本实现程序创建一个基于对话框的主线程, 用户在其界面上选择“开始”按钮就创建了一个CPU密集型的计数过程来进行没完没了的计数, 直到用户选择“终止”按钮才终止这个耗时非常多的子线程, 其间在进度条控件上显示进度。若不采取线程通信技术, 则主线程将被阻塞相当长的一段时间, 用户什么都干不成, 使用了辅助线程之后, 用户就可以轻松地控制这个没完没了的循环了。具体实现步骤如下:

第一步:创建一个基于单文档的应用程序框架, 取消prin and print preview, 选定Single Document, 工程取名为TT。其余采用App Wizard的默认设置;

第二步:在应用程序中添加一个ID号为IDD_DIA-LOG_MT的普通对话框。其中, 标题为“没有循环”的控件是一个静态控件, ID号为IDC_STATIC_MSG, 进度条控件的ID号为IDC_PROGRESS, 标题为“开始”的按钮控件的ID号为ID_MT_START, 标题为“终止”的按钮控件的ID号为ID_MT_END, “OK”按钮的ID号为IDOK;

第三步:修改菜单IDR_MAINFRAME, 添加一个标题为“测试”的菜单项;

第四步:修改工具条IDR_MAINFRAME, 添加一个工具条按钮, 并使之与ID_MT_TEST相关联;

第五步:双击对话框ID_DIALOG_MT, 为该对话框创建一个类, 基类为Cdialog, 类名为Cmt DIg, 然后为对话框上各个控件生成相应的成员变量和控件通知消息的消息响应函数。

此外, 还要为WM_TIMER消息添加一个消息响应函数, 以便更新进度条显示, 添加WM_INITDIALOG消息的消息响应函数On Init Dialog () , 以便进行初始化;

第六步:修改CMt Dlg类。在该类的头文件 (.h) 的开头添加一个事件对象和辅助线程的回调函数的定义:

定义一个自定义消息, 将消息ID的定义添加在CMt DIg类的实现文件 (.CPP) 中:

添加函数void CMt Dlg::On Thread Stopped () 。

同样在Mt Dlg.cpp的开头定义一个全局HWND类型的变量, 用于存储对话框句柄, 从而使辅助线程也可以访问对话框;

第七步:添加CMt DIg类对象;

第八步:编译并运行该工程TT。

4 结束语

总之, 在用Visual C++ MFC进行多线程通信程序开发时, 所要做的具体编码式工作较少, 产生的代码都是标准化的模块, 只需根据应用的需要完成相应的常量、变量声明、响应函数、消息映射函数的声明, 并且实现各个具体的函数:借助于资源编辑器, 设计好用户界面并将各控件与相应的响应函数连接起来就可得到软件代码。

摘要:多线程通信是程序开发中经常涉及到的基本功能之一。在线程的优先级状态的基础上分析了多线程通信程序的设计技术, 包括使用全局变量、使用用户自定义消息这两种主要通信方式;研究了多线程通信程序的实现步骤。

关键词:多线程通信,MFC程序,微软基础类库

参考文献

[1]杨立峰.基于MFC的多线程编程技术[J].扬州职业大学学报, 2008 (2) .

[2]韩利凯.利用SOCKET进行网络通信程序设计[J].西安联合大学学报, 2002 (4) .

上一篇:听力能力训练下一篇:防雷和抗干扰