运用VC++技术实现上位机与OMRON品牌PCL的串行通讯
2009-01-12林涛张声兴
林 涛 张声兴
摘要:文章介绍了可编程控制器(PCL)与上位机(PC机)实现串行通信功能的硬件组成、通信协议,重点阐明在上位机(PC机)上基于VC++6.0的编程实现细节,并进一步展望PLC对控制系统应用的前景。
关键词:可编程控制器(PCL);VC++
中图分类号:TP312文献标识码:A文章编号:1006-8937(2009)08-0112-02
鉴于目前由可编程控制器(PCL)和PC机所构成的监控系统在工业控制领域得以广泛的运用,文章将对PCL作下位机,完成现场设备的直接控制、数据收集等工作,PC机作上位机,完成数据的分析存储、状态显示等工作进行技术探讨,通过上位机对PLC的读写操作,从而完成现场数据的接收、传达与监控功能。文章以OMRON公司的CJ1G型PLC作下位机,以PC机为上位机,重点研究此分布式控制系统的通讯方式。
1硬件互联技术细节
1.1PLC与PC的硬件互联
经过对该品牌PLC的分析,可知PLC本身配有RS-232接口,大大方便了与PC机串口通信的硬件连接,文章直接采用自制电缆将PLC的RS-232口与PC机RS-232口相连,引脚对应关系图如图1:
1.2设定PLC通信方式,确定通信协议帧
CJ系列PLC单元支持以下5种串行通信功能:上位机链接通信、无协议通信、1:N或1:1链接通信、外设总线通信和串行PLC链接通信,其中上位机链接通信功能适用于上下位机并以会话的方式进行实时数据通信。
一般在控制系统中,采用单台PLC与PC机通信,上位机担当命令发起端,通过向PLC发送不同格式的命令帧,完成对PLC寄存器的读写操作。因此文章选择主机-->PLC的主链接命令通信方式。
该系统使用RS一232C端口进行通信。RS一232C端口的缺省设定是:上位机链接模式、1启动位、7数据位、偶校验、2停止位和9 600bps的波特率。用户可以通过编程工具或者SETUP(237)指令改变RS一232C端口的设定。我们首先用编程工具对PLC进行设置,其中PLC的操作模式设定为监控模式;然后断开电源,将主机与PLC的CPU单元连接,并将CPU单元DIP的引脚5设定为OFF;最后接通电源,从主机发布主链接命令,进行上下位机的通信。
由于整个通信系统采用上位机主动的通信方式。上位机与PLC的通信是通过使用命令帧(command)和响应帧(response)进行数据的发送和接收。帧的发送与接收图2所示:
命令的格式如图3所示,命令必须以@开始,机号No为2个十进制数,表示上位机识别所连接PLC的机号。识别码是2个字符的命令码,如RR表示读取CIO区域的内容。正文部分为设定命令的参数,对于不同的命令,正文的内容和长度可能有所不同。FCS是2个字符的帧检查序列。命令的最后2个字符是终端,表示命令的结束,由“*”和CR码组成。命令格式图3所示:
图3 命令格式
响应的格式与命令的格式相似,只是在识别码后面多了2个十六进制字符的结束码,用于返回命令的执行状态(有无错误及错误的原因)。一个帧最多由131个ACSⅡ字符组成,如果需要发送的字符超出131个,必须将数据分成若干个帧,第一帧和中间帧的结尾用分界符(CR)代替结束符(*CR)。
VC++6.0软件实现VC++6.0开发环境为串口通讯已经提供了ActiveX控件,名为MSComm控件。下面阐述对该控件属性的初始化设置以及相关实现代码。限于篇幅,此文只将重要的实现代码罗列如下:
{
My_Comm.SetCommPort(1);//选择 COM1口
My_Comm.SetSettings( 9600,E,7,1 );//设置通信参数
My_Comm.SetlnputMode(1);//设置二进制输入模式
My_Comm.SetInBufferSize(1024);//设置输入缓冲区大小
My_Comm.SetlnputLen(0);//使用Input将使MSComm控件读取接收缓冲区中的全部内容
My_Comm.SetOutBufferSize(1024);//设置输出缓冲区大小
My_Comm.SetRThreshold(1);//设置每接收一个字符触发一次OnComm事件
My_Comm.SetDTREnable(TRUE);//置DTR有效
int timeRes;
if(!My_Comm.GetPortOpen()) //如果没有开
My_Comm.SetPortOpen(TRUE);//手工打开串口
My_Comm.Getlnput();//清空输入缓冲区
timeRes=SetTimer(2,500,NULL);//安装定时器
if(timeRes==0)
{
MessageBox( “设置定时器出错” );
return ;
}
}
主要实现代码处于在WM_TIMER消息的处理函数上
void CPLCCommDlg::OnTimer(UINT nlDEvent)
{
int len;
long j;
VARIANT inputdatal:
COleSafeArray inputdata2;
BYTE datatempl,datatemp2;
BYTE commstr[17]={ ‘@ ,0,‘0,R,D,0, 0, 0, 0, 0, 0, 0,2,0x00,0x00,*,0x0d}
//初始化命令参数
My_Comm.SetRTSEnable(TRUE);//设置RTS线有效,请求允许发送数据
verifcation(commstr,17);//对发送的命令进行帧校验
CByteArray cbaArraylnsA;
cbaArraylnsA.RemoveAll();
for(int nlndex:0;nlndex<17;++nlndex)
{
cbaArraylnsA.Add(commstr[nIndex]);
}
My_Comm.SetOutput(COleVariant(cbaArraylnsA));//发送读取数据的命令
My_Comm.SetRTSEnable(FALSE);//设置RTS线无效,不允许发送数据
inputdatal= My_Comm.Getlnput();//读取接收缓冲区的数据
inputdata2=inputdatal;
len=inputdata2.GetOneDimSize();
for(j=0;j { inputdata2.GetElement(&j,inputdata+j); } datatempl=inputdata[15]; datatemp2=inputdata[16]; verfunction(inputdata,19);//计算接收数据的帧校验码 if(datatempl! = inputdata [15] || datatemp2 1=inputdata[16]) { MessageBox(”Receive data invalid! );//判断接收数据是否有效 } else { for(i=0;j<8;j++) { OutputData[j]=inputdata[j+7];//将数据存储到上位机的数据存储区中 } } incount=0; CDialog::OnTimer(nlDEvent); } 上述函数所调用的对帧进行校验的函数verifcation代码如下: CPLCCommDlg::verfunction(BYTE vdata[],int K) { BYTE sum=0x00,vl=0x0f, v2=0xf0; for(int i=0;i { sum^=vdata[i]; } V1& =sum; V2& =sum; v2> > =4; if(vl>=0&& vl<=9) V1+ =0x30; else V1+ =0x37; if(v2>=0&& v2<=9) V2+ =0x30; else V2+=0x37; vdata[K-3]=vl;//帧贞校验码低位字节 vdata[K-4]=v2;//帧校验码高位字节 } 2结语 采用这种方法开发出了上位机与PCL的通信系统,实现了上位机和PLC的数据交换功能。文章尝试为一般化控制系统提供统一通信控制框架,这也是下一步研究方向,希望通过此类努力为硬件通讯提供一个方便调用的软件接口,从而降低开发难度,提供开发效率。