>
摘要: 本文给出了一种基于计算机和单片机远程通信的分布式网络结构,重点介绍中心站计算机应用MSComm控件读写串口,并控制Modem实现远程通信.本系统已用于环境监测部门.
关键字: MSComm ;串行通信;Modem ;远程通信
1 酸雨环境监测系统
1.1系统结构设计
微型计算机的发展和计算机通信技术的提高,使得各种信息采集技术的自动化,实时性变为可能。本文运用微型计算机和单片机组成主从式微机网络,构成分布式酸雨监测系统。
以单片机为核心的酸雨数据采集基站分布在一个城市或地区的四周和中心,中心站则位于该城市或地区的环境监测总站,由计算机控制。中心站主机通过电话线经Modem与单片机建立远程通信连接。酸雨环境监测系统结构如图1所示。
1.2 系统工作方式
中心站微机和基站单片机利用Modem通过电话线建立双工远程通信。各基站单片机接收酸雨计采集的酸雨特征数据,可以随时或定时自动向中心站传送采集的酸雨数据,从而使上百公里甚至更远的远程通信经济可靠,现实可行。
2 酸雨环境监测系统串行通信
2.1 基站单片机串行通信
基站单片机通过RS-232串行口向Modem内部控制寄存器发送AT命令,初始化基站Modem于自动等待连接状态,或远程呼叫中心站Modem. 在建立远程通信连接后,再通过串行口发送数据.
2.2 中心站微机串行通信
中心站计算机通过RS-232串行口向Modem内部控制寄存器发送AT命令,初始化中心站Modem于自动等待连接状态或远程呼叫基站Modem. 在建立远程通信连接后,从串口读取基本发送来的数据.
3 中心站微机串行通信
3.1 微机串行通信的基本机制
常用的微机串行通信程序利用BIOS的INT14中断,以查询I/O方式完成异步串行通信.在Windows下系统提供中断方式驱动的串行通信驱动程序Comm.drv.通信程序无需直接对串行口进行操作,而是通过驱动程序这一编程接口进行间接操作.
用户 | |
输入缓冲区 |
输出缓冲区 |
Windows通信驱动模块(Comm.drv) | |
串行口 |
图2 用户与Windows通信模块的关系
Windows操作系统中,用户与Windows的关系如如图2,串行通信采用 “事件通知”方式支持数据块的传送.进行通信时,Windows开辟一个用户定义的输入输出缓冲区,接收一个字符就产生一个低级硬件中断,串行驱动程序立即取得控制权,并将字符放入输入缓冲区,然后将控制权返还正在运行的应用程序.如果输入数据缓冲区满了,驱动程序用当前定义的流控机制通知发送方停止发送数据.发送数据也采用类似的处理方式.应用程序将需要发送的数据放入输出数据缓冲区,然后由Windows来负责传送,每发送一个字符就产生一个低级硬件中断.这一切均在后台进行,无需用户介入,用户看到的只是输入输出缓冲区.
串行通信的Windows应用程序的实现分为两个部分,即初始化串口和串口消息处理.
3.2 MSComm通信控件
MSCcomm控件通过串行端口传输和接收数据,为应用程序提供串行通信功能. MSCcomm控件串行通信功能的实现实际上是调用了API函数,API函数再由Comm.drv解释并传送给设备驱动程序.
和所用其它的ActiveX控件一样, MSCcomm.ocx定义了一系列的属性和接口.在VC++中,用户用Set函数设置属性值,用Get…函数得到属性的当前值.该控件定义了27个属性,大部份与Modem连接相关.
MSCcomm控件提供了两种串行口消息处理方法:一是查询,一是事件驱动.对于较简单的通信任务,可通过查询串行口的CommEvent属性来了解最近发生的事件或错误并进行相应的处理.较复杂的通信任务就应使用事件驱动接口,它只响应 “OnComm”事件,该事件可对已发生的事件或错误进行处理,与 CommEvent属性密切相关.在VC++中实现事件驱动方法时,要定义CMSComm控件变量,以后针对此对象操作即可.
3.3 应用MSCcomm控件实现上位机串行通信
3.3.1 初始化串行口
定义CMSComm控件类变量m_Com,针对该对象属性操作初始化串口.
void CEnviromentInspectSysView::OnInitialUpdate()
{…
m_Com.SetCommPort(1); //选择COM1
m_Com.SetHandShaking(0)//设置通信协议
m_Com.SetInBufferSize(1024); //设置输入缓冲区的大小,Bytes
m_Com.SetOutBufferSize(512); //设置输入缓冲区的大小,Bytes
m_Com.SetRThreshold(1);//为1表示一个字符引发一个事件
m_Com.SetInputMode(1);//设置输入方式为二进制
m_Com.SetSettings(“9600,n,8,1”);//设置数据传输输率,奇偶校验等参数
m_Com.SetInputLen(0);//设置读取缓冲区全部内容
if(!m_Com.GetPortOpen())//打开串口
m_Com.SetPortOpen(TRUE);
…
}
3.3.2 捕捉串口事件
在程序中利用事件驱动接口,用ClassWizard为CMSComm控件添加OnComm消息映射函数:
void CEnviromentInspectSysView::OnCommMscomm()
{
switch(m_Com.GetCommEvent()){
case 2: //收到大于RTHresshold个字符
…..//串口接收缓冲区中数据接收,处理
break;
case 3: //CTS线状态发生了变化
break;
case 4: //DSR线状态发生了变化
break;
case 5: //CD线状态发生了变化
break;
case 6: //Ring Indicator发生变化
break; }
}
3.3.3 串口读写
完成串行口读写的函数很简单,GetInput()和SetOutput()就可.两个函数的原型是:VARIANT GetInput()及 void SetOutput(const VARIANT& newValue);都要使用VARIANT类型(所有Idispatch::Invoke的参数和返回值在内部都是作为VARIANT对象处理的).以下给出读取串口数据,并以字符串或16进制形式保存.
void CEnviromentInspectSysView::OnRecieve()
{ VARIANT variant_inp;
COleSafeArray safearray_inp;
LONG len,k;
BYTE rxdata[2048]; //设置BYTE数组
CString strtemp;
if(bReceive){//接收标志
variant_inp = m_Com.GetInput(); //读缓冲区
safearray_inp = variant_inp; //VARIANT型变量转换为ColeSafeArray型变量
len=safearray_inp.GetOneDimSize();//得到有效数据长度
for(k=0;k
safearray_inp.GetElement(&k,rxdata+k);
//转换为BYTE型数组
for(k=0;k
BYTE bt=*(char*)(rxdata+k); //字符型
if(bHex) strtemp.Format("%02X ",bt);
//将字符以十六进制方式送入临时变量strtemp存放
else strtemp.Format("%c",bt);
//将字符送入临时变量strtemp存放
m_strReceive+= strtemp;} //加入接收字符串变量
}
3.3.4 关闭串口
使用完MSComm控件对象后,要将通信端口关闭.可以用下面的语句来实现这个功能:
m_Com.SetPortOpen(FALSE);
4 中心站微机远程通信
酸雨采集系统中心站主机软件用Visual C++ 6.0 编制,运行于windows98/2000环境。整个软件由数据库管理、站点通信连接、报表处理、曲线生成等模块构成,操作平台如图3所示。
图3酸雨采集系统中心站主机操作平台
上下位机远程通信的建立由程序利用MSComm控件向串口发送控制Modem的AT命令实现.根据实际需要,上位机可以选用主动通信和被动通信两种工作方式,分别对应于基站自动等待连接和定时或随时自动向上位机拨号两种工作方式.
4.1主动通信方式
中心站主机通过电话线向基站单片机拨号,经Modem建立连接后由基站单片机中断传送采集的酸雨特征数据称为主动通信。在图3中选择好站点、串口,键入电话号码,按下“呼叫站点”按钮拨号,连接状态显示“ADDT****”的拨号命令,成功建立连接后,连接状态提示“CONNECT 9600 baud” 的反馈信息。此时基站单片机检测到连接成功的载波信号,进中断向中心站发送数据。
主动通信呼叫站点程序如下:
void CEnviromentInspectSysView::OnDial()
{
CString strTemp;
if(bStationSelected){//选择了站点
if(!bOpen){//端口已经打开
bOpen = TRUE;
//向Modem发送拨号指令
strTemp="ATDT" + m_strPhoneNumber + "\r\n";
m_Com.SetOutput(COleVariant(strTemp));
m_ctrlDial.SetWindowText("挂断");}
else{//发送Modem挂机命令
m_Com.SetOutput(COleVariant("+++"));
m_Com.SetOutput(COleVariant("ATH0\r\n"));
bOpen = FALSE;
m_ctrlDial.SetWindowText("拨号");}
}
else
AfxMessageBox("请先选择站点,再拨号!");
}
4.2 被动通信方式
被动通信是指平时中心站主机一直处在自动应答状态,随时等待基站的呼叫。所以要在中心站程序中首先初始化Modem于自动应答状态。初始化成功时,连接状态指示:OK,当成功建立连接时,连接状态指示:CONNECT 9600 baud。基站单片机检测到连接成功的载波信号(CD),进中断向中心站发送数据。
被动通信Modem初始化主要程序:
void EnviromentInspectSysView::OnInitialUpdate()
{ …
if(!m_Com.GetPortOpen()){ //打开串口
m_Com.SetPortOpen(TRUE);
//Modem自动等待连接,震铃信号响一次后建立连接
m_Com.SetOutput(COleVariant("ATS0=1\r\n"));}
else
AfxMessageBox("该串口已被占用,请选择其他串口");
…
}
4.3 串口数据的接收,处理
串口数据的接收,处理由串口缓冲区是否接收到字符事件驱动,在CMSComm控件对象的OnComm消息映射函数中处理.
5 结束语
本系统已用于环境监测部门。它具有实时性好,信息传递远,自动化程度高,电路简单,成本低等优点。它可以推广用于其它需要信息采集及远程监控的部门,如气象部门温度和风速采集;水文部门水位和雨量的监测;电力部门电网监测;铁路部门信号监测等。