0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于Windows NT多线程实现智能蓄电池远程监控系统的设计

电子设计 来源:电子技术应用 作者:王金廉,谢剑英, 2021-05-28 10:55 次阅读

作者:王金廉,谢剑英,贾青

传统的应用程序都是单线程的,即在程序运行期间,由单个线程独占CPU的控制权,负责执行所有任务。在这种情况下,程序在执行一些比较费时的任务时,就无法及时响应用户的操作,影响了应用程序的实时性能。在监控系统,特别是远程监控系统中,应用程序往往不但要及时把监控对象的最新信息反馈给监视客户(通过图形显示),还要处理本地机与远程机之间的通信以及对控制对象的实时控制等任务,这时 ,仅仅由单个线程来完成所有任务,显然无法满足监控系统的实时性要求。在DOS系统下,这些工作可以由中断来完成。而在Windows NT下,中断机制对用户是不透明的。为此,可引进多线程机制,主线程专门负责消息的响应,使程序能够响应命令和其他事件。辅助线程可以用于完成其他比较费时的工作,如通信、图形显示和后台打印等,这样就不至于影响主线程的运行。

1 Windows NT 多线程概述

Windows NT是一个真正的抢占式多任务操作系统。在 Windows NT中,启动一个应用程序就是启动该应用程序的一个实例,即进程。进程由一个或多个线程构成,拥有内存和资源,但自己不能执行自己,而是进程中的线程被调度执行。进程至少要有一个线程,当创建一个进程时,就创建了一个线程,即主线程。主线程可以创建其他辅助线程,由主线程创建的线程又可创建线程。每个线程都可指定优先级,操作系统根据线程的优先级调度线程的执行。

Windows NT中使用多线程的方法有三种:

· 使用C多线程库函数;

· 使用CreateThread() 等Win32函数;

· 使用MFC类。

本文采用第三种方法。在Visual C++5.0 中,MFC应用程序用CWinThread 对象表示线程。基本操作如下:

· 创建新线程:调用MFC全局函数AfxBeginThread ()创建新线程。AfxBeginThread()启动新线程并返回控制,然后,新线程和调用

AfxBeginThread()的线程同时运行。它的返回值为指向CWinThread对象的指针;

· 暂停/恢复线程:调用CWinThread类成员函数SuspendThread()暂停线程的运行,调用ResumeThread()成员函数恢复线程的运行;

· 终止线程:在线程内部可调用全局函数AfxBeginThread()终止线程的运行,否则,线程执行结束后,线程自动从线程函数返回并释放线程占有的资源。

2 基于TCP/IP的多线程编程

TCP/IP是lnternet上广泛使用的一种协议,可用于异种机之间的互联。TCP/IP协议本身是非常复杂的,然而在网络编程中,程序员不必考虑TCP/IP的实现细节,只需利用协议的网络编程接口Socket.htm“ target=”_blank“ title=”SOCKET货源和PDF资料“》Socket(亦称套接字)即可。在 Windows 中,网络编程接口是 Windows SOCKET.htm” target=“_blank” title=“Socket货源和PDF资料”》Socket?它包含标准的Berkley SOCKET.htm“ target=”_blank“ title=”Socket货源和PDF资料“》Sockets的功能调用的集合,以及为 Windows 所做的一些扩展。TCP/IP协议的应用一般采用客户/服务器模式,面向连接的应用调用如图1所示。

根据上述顺序调用函数建立连接后,通信双方便可交换数据[1]。然而,在调用带*号的函数时,操作常会阻塞,特别是当套接字工作在同步阻塞模式(Blocking Mode)时。这时,程序无法响应任何消息。为了避免出现这种情况,本文引进辅助线程。在执行含有可能阻塞的函数的任务时,动态创建新的线程,专门处理该任务。主线程把任务交给辅助线程后,不再对辅助线程加以控制与调度。本文分别针对connect()、accept()、receive()、send()等可能阻塞的函数创建了相应的线程,如表1所示。

多线程编程常常还要考虑线程间的通信。线程间的通信可以采用全局变量、指针参数和文件映射等方式。本文采用指针参数方式。在调用AfxBeginThread()函数时,通过传递指针参数的方式在主线程与辅助线程间通信。

AfxBeginThread()函数的用法如下:

CWinThread*AfxBeginThread? (AFX_THREADPROC pfnThreadproc,

LPVOID pParam

int nPriority=THREAD_PRIORITY_NORMAL,?

UINT nStackSixe=0,

DWORD dwCreateFlags=0,

LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL);

参数pfnThreadProc指定线程函数?必须如下定义:

UINT MyControllingFunction?(LPVOID pParam); ?

参数pParam 是调用线程传递给线程函数pfThreadProc的参数;

其他参数一般只需采用缺省值。

指针参数通信方式就是通过参数pParam在线程间通信的,它可为指向任何数据类型的指针。本文中,定义了一个名叫EXCHANGE_INFO的结构如下:

typedef struct

?{ SOCKET sServerSOCKET.htm” target=“_blank” title=“Socket货源和PDF资料”》Socket;?

SOCKET ?*pcCoientSOCKET.htm“ target=”_blank“ title=”Socket货源和PDF资料“》Socket;?

SOCKADDR_IN ?*pClientAddr;?

BOOL *pbConnected;

unsigned char *pucBuffer?;

int *pnMessageLen?;

?} EXCHANGE_INFO;

在需要通信时,先声明一个结构变量,再把变量的指针作为pParam参数,调用AfxBeginThread((AFX_THREADPROC)

CSOCKET.htm” target=“_blank” title=“Socket货源和PDF资料”》SocketThread::?WaitFor ConnectThread,(LPVOID)& m_Exchangeinfo)函数即可。

为了利用面向对象技术编程所具有的模块性强、便于修改、可移植性好等优点,本文还把表1中的线程封装为父类为CWinThread的自定义类CSOCKET.htm“ target=”_blank“ title=”Socket货源和PDF资料“》SocketThread中。还自定义了一个叫CSOCKET.htm” target=“_blank” title=“Socket货源和PDF资料”》SocketComm的新类,封装了一些函数,如CreateSOCKET.htm“ target=”_blank“ title=”Socket货源和PDF资料“》Socket、ConnectToServer、WaitForClient、ReadMessage、SendMessage等,这些函数屏蔽了面向连接的通信程序的实现细节,如创建、连接、发送和接收等,在这些函数里,动态创建辅助线程。

下面以CSOCKET.htm” target=“_blank” title=“Socket货源和PDF资料”》SocketComm类中的等待客户连接请求的函数WaitForClient()为例,注释说明多线程编程的具体细节。

BOOL CSOCKET.htm“ target=”_blank“ title=”Socket货源和PDF资料“》SocketComm::WaitForClient?

{

if(m_bConnected)return?( TRUE );?

//配置bind函数的参数?即服务器的套接字地址结构

SOCKADDR_IN Addr?;

memset(&Addr,0,sizeof(SOCKADDR_IN));?

Addr.sin_family=AF_INET;

ADDR.SIN_port= htonl?(m_nPort); ?

Addr.sin_addr.s_addrr = htonl(INADDR_ANY); ?

//将套接字地址结构赋予套接字(绑定),以指定本地半相关

int nReturnValue;

nReturnValue =::bind?( m_sSserverSOCKET.htm” target=“_blank” title=“Socket货源和PDF资料”》Socket,( LPSOCKADDR)&Addr,sizeof (SOCKADDR_IN )); ?

if?(nReturnValue == SOCKET_ERROR) returu?( FALSE );?

//配置传给WaitForConnectThread线程函数的参数m_Exchangeinfo

m_Exchangeinfo.sServerSOCKET.htm“ target=”_blank“ title=”Socket货源和PDF资料“》Socket = m_sserverSOCKET.htm” target=“_blank” title=“Socket货源和PDF资料”》Socket;?

m_Exchangeinfo.psClientSOCKET.htm“ target=”_blank“ title=”Socket货源和PDF资料“》Socket = &m_sClientSOCKET.htm” target=“_blank” title=“Socket货源和PDF资料”》Socket;?

m_Exchangeinfo.pClientAddr = &m_ClientAddr;?

m_Exchangeinfo.pbConnected = &m_bConnected;?

//以m_Exchangeinfo的指针为参数调用WaitforConnectThread线程等待客户端连接

AfxBeginThread?((AFX_THREADPROC)CSOCKET.htm“ target=”_blank“ title=”Socket货源和PDF资料“》SocketThread::

WaitForConnectThread,?(LPVOID) &m_Exchanginfo); ?

returi?( TRUE )?

?}

//等待连接线程

UINT CSOCKET.htm” target=“_blank” title=“Socket货源和PDF资料”》SocketThread::WaitForConnectThread?(LPVOIDpParam)

?{

EXCHANGE_INFO?*pExchangelnfo=(EXCHANGE_INFO*) pParam;?

int nReturnValue, nClientAddrSize= Sizeof?( SOCKADDR_IN);

//侦听连接

nReturnValue=:: listen?(pExchangelnfo ->sServerSOCKET.htm“ target=”_blank“ title=”Socket货源和PDF资料“》Socket, 1); ?

if?( nReturnValue == SOCKET_ERROR )return?(0);?

//阻塞调用accept,直至有客户连接请求

? *pExchangelnfo->psClitentSOCKET.htm” target=“_blank” title=“Socket货源和PDF资料”》Socket=:: accept?(pExchangelnfo->sServerSOCKET.htm“ target=”_blank“ title=”Socket货源和PDF资料“》Socket,? ?(LPSOCKADDR) pEchangelnfo ->pClientAddr,?&nClientAddrSize); ?

if?(( *pExchangelnfo->psClitentSOCKET.htm” target=“_blank” title=“Socket货源和PDF资料”》Socket)!= INVALID_SOCKET)

//通过pExchangelnfo的指针在线程间通信

? * pExchangelnfo->pbConnected TRUE;

return?( 0 );?

3 应用实例-高层协议的设计

在电厂和电站中,为了保证安全工作,保护系统必不可少。保护系统的电源供应通常使用两种方式。一般情况下,使用交流电系统对保护系统进行供电;当交流电系统出现故障时?立即使用后备的蓄电池系统对保护系统进行供电。为了对蓄电池系统进行监控和管理,以保证蓄电池在关键时刻能正常工作,设计了在Windows NT环境下具有远程通讯功能和动态人机界面的智能蓄电池远程监控系统 。该系统由蓄电池智能管理、充电机控制、母线绝缘在线检测、声光报警、系统组态、远程通信等子系统组成,实现对蓄电池/充电机智能化远程管理和控制,对整个系统的运行状态进行实时监控,具有多媒体报警、事件处理、动态数据库、趋势画面和动态画面显示、操作提前提醒等功能。系统框图如图2所示。

在远程通信模块中,远程监控机需把监控客户的操作命令及时传给本地机,本地机根据命令控制充电机,使之按照一定的方式工作,而本地机需定时向远程监控机反馈实时的充电机状态信息。它们之间的通信是基于TCP/IP的广域网通信,而且,我们引进了多线程机制以保证系统具有良好的实时性。

下面以其中的充电机控制系统为例谈谈如何使用CSOCKET.htm“ target=”_blank“ title=”Socket货源和PDF资料“》SocketComm类进行远程通信。为简单起见,假定本地机与远程监控机之间通信的信息仅有下面三种类型:

·本地机接收到该命令后,控制充电机按照稳压模式运行,输出电压为电压给定值;

·本地机接收到该命令后,控制充电机按照稳流定时模式运行,输出电流为电流给定值;

·本地机向远程监控机发送充电机的实时状态数据(包括输出电压、输出电流、状态指示和故障类型指示)。

在基于TCP/IP的面向连接的网络通信中,客户与服务器之间传送的是有序可靠的字节流(Byte Stream),所以程序员有必要在传输层TCP上定义自己的高层协议,设计帧结构,将字节流变成有意义的信息。在CSOCKET.htm” target=“_blank” title=“Socket货源和PDF资料”》SocketComm类中由AssembleMessage()函数把数据组合成一定的帧结构。帧结构为:



其中@为帧起始标志,#为帧终结标志对应的结构定义如下:

typedef struct

?{ int MessageType;? //信息类型

int ChargerNo;? //充电机编号

int DataNo;? //数据类型

float Data;? //数据

?}MessageStruct;?

需要通信时,先声明一个MessageStruct变量,根据信息内容对各成员变量赋值,传给 AssembleMessage()函数组合成帧,再调用SendMessage()函数发送给接受方。接受方接到数据后,对数据内容的解释,是由CsocketComm类中的AnalyzeMessage()函数完成的。AnalyzeMessage()函数返回一个MessageStruct变量。应用程序就可根据它的各成员变量控制充电机或动态显示充电机的状态。

总之,把多线程机制引进通信,有利于提高应用程序的实时性,充分利用系统资源。对于大型的工程应用来说,不同的线程完成不同的任务,也有利于提高程序的模块化,便于维护和扩展。本文给出了一种在Windows NT下基于TCP/IP协议的多线程通信的基本方法,根据该方法进行修改和扩充,便可设计出符合具体应用的高质量的多线程通信程序。

责任编辑:gt

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 监控系统
    +关注

    关注

    21

    文章

    3912

    浏览量

    174623
  • 线程
    +关注

    关注

    0

    文章

    504

    浏览量

    19682
  • 电池
    +关注

    关注

    84

    文章

    10567

    浏览量

    129596
收藏 人收藏

    评论

    相关推荐

    用单片机实现蓄电池远程数据采集系统

    本帖最后由 eehome 于 2013-1-5 10:11 编辑 <strong>用单片机实现蓄电池远程数据采集系统</strong>
    发表于 09-17 15:23

    LEM蓄电池在线监测设计方案

    ,同时也是不间断供电系统里面最不安全的因素。从系统理论我们知道,系统的安全程度取决于系统中最不安全的因素,也就是我们经常引用的“木桶理论”。 二、
    发表于 03-10 10:22

    基于无线通信传输的蓄电池定位防盗系统

    康研发的蓄电池定位防盗器是将GPS定位器紧贴在蓄电池的侧面,当定位数据超过设定范围,系统立即上传到监控中心,定位防盗追踪和伪装效果都非常好。     
    发表于 09-05 17:04

    BM-3000系列UPS/EPS蓄电池监测管理系统

    BM-3000系列UPS/EPS蓄电池监测管理系统,凝聚巨成多年技术成果,针对UPS/EPS电源系统特点,完成了真正意义的蓄电池实时监控。B
    发表于 09-21 17:31

    蓄电池定位防盗器 蓄电池的守护神

    为化学能,需要放电时再次把化学能转换为电能输出。蓄电池是通信基站供电系统的主要蓄电手段,由于全国电力资源紧缺,供电部门频繁实施错峰拉闸限电措施,经常出现基站大面积停电,这个时候就需要用到蓄电池
    发表于 10-24 14:29

    蓄电池测试仪在在线系统的应用案例

    福禄克公司最新的蓄电池测试仪KUNLUN产品提供试用活动,他们当即决定带福禄克工程师及测试仪器到现场进行巡检。  此次巡检的灾备机房配有超过4千节电池,并全部配有某品牌的在线蓄电池监控
    发表于 08-10 15:43

    莱姆电子蓄电池监控智能传感器

      要点:•监测单只铅酸蓄电池的内阻、电压和内部温度•大大降低整体蓄电池监控系统的成本•能够延长蓄电池寿命•有助于增强后备电源
    发表于 10-26 16:17

    莱姆电子蓄电池监控智能传感器

      莱姆电子推出目前业界最完备的蓄电池监控智能传感器Sentinel。该产品设计用于备用蓄电池监控,可测量每只
    发表于 12-03 10:17

    多线程在VC++串口通信程序中的应用

    本文通过一机房监控系统程序中串口通信对多线程的应用来介绍Windows 9X/NT操作系统
    发表于 09-03 11:45 27次下载

    机车蓄电池检测与地面监控系统

    在机车辅助供电系统中,检测蓄电池工作状态,找出不良蓄电池是很重要的。本文以东风8B型内燃机车为对象,设计了一套蓄电池智能检测
    发表于 07-14 16:16 15次下载

    基于现有监控系统蓄电池精确监控与故障预测方法

    摘要:现有动力环境监控系统蓄电池监控功能相对薄弱,没有实现智能
    发表于 02-15 14:48 22次下载

    通信电源监控系统蓄电池监控模块的设计

    通信电源集中监控系统作为通信电源运行维护的重要支撑手段,将发挥越来越重要的作用。文章对本地用通信电源监控系统蓄电池
    发表于 12-26 10:34 3223次阅读

    汽车蓄电池电压监控系统

    电子设计一个汽车蓄电池电压监控系统完整资料。
    发表于 12-30 15:55 2次下载

    监控机房蓄电池的主要作用及内容

    可以提前进行报警,方面管理查看; 2,蓄电池数据可以24实时检测,测量准确数据,掌握电池的各种情况,减少人工维护工作量 3,可以进行自动换管理,实现远程的数据
    发表于 12-19 21:12 2926次阅读

    UPS蓄电池远程监测系统解决方案

    。 UPS蓄电池远程监测系统是一种集成了数据采集、远程监控、故障预警、数据分析与报告等功能于一体的智能
    的头像 发表于 12-23 15:16 94次阅读