基于多线程技术的PLC与PC的通讯方式

0.引言
在现代工业控制系统中, PLC以其高可靠性、适应工业过程现场、强大的联网功能等特点, 被广泛应用 。 可实现顺序控制、PID回路调节、高速数据采集分析、计算机上位管理, 是实现机电一体化的重要手段和发展方向 。 但PLC无法单独构成完整的控制系统, 无法进行复杂的运算和显示各种实时控制图表和曲线, 无良好的用户界面, 不便于监控 。 将个人计算机(PC)与PLC结合起来使用, 可以使二者优势互补, 充分利用个人计算机强大的人机接口功能、丰富的应用软件和低廉的价格优势, 组成高性能价格比的控制系统 。
1.系统构成
推进系统中, PC机选用工控计算机 。 它是整个控制系统的核心, 是上位机 。 其主要利用良好的图形用户界面, 显示从PLC接收的开关量和控制手柄的位置, 进行一些较复杂的数据运算, 并且向PLC发出控制指令 。
PLC是该系统的下位机, 负责现场高速数据采集(控制手柄的位置), 实现逻辑、定时、计数、PID调节等功能, 通过串行通讯口向PC机传送PLC工作状态及有关数据, 同时从PC机接受指令, 向蜂鸣器、指示灯、滑油泵、控制手柄的位置等发出命令, 实现PC机对控制系统的管理, 提高了PLC的控制能力和控制范围, 使整个系统成为集散控制系统 。
2.通讯协议
计算机与PLC之间的通信是建立在以RS232标准为基础的异步双向通信上的, FX系列PLC有其特定的通信格式, 整个通信系统采用上位机主动的通信方式, PLC内部不需要编写专门的通信程序, 只要把数据存放在相应的数据寄存器中即可, 每个数据寄存器都有相应的物理通信地址, 通信时计算机直接对物理通信地址进行操作 。 通信过程中, 传输字符和命令字以ASCⅡ码为准, 常用的字符及其ASCⅡ码对应关系 。
计算机与PLC进行通讯时, 计算机与PLC之间是以帧为单位进行信息交换的, 其中控制字符ENQ、ACK、NAK, 可以构成单字符帧发送和接受, 其余的信息帧发送和接受时都是由字符STX、命令字、数据、字符ETX以及和校验5部分组成 。
校验和在信息帧的尾部用来判断传输的正确与否, 和校验码的计算方法是将命令码到ETX之间的所有字符的ASCⅡ码(十六进制数)相加, 取所得和的最低2位数, 在后面的通信程序设计里面还会提到 。 进行差错检验的方法很多, 常用的有奇偶校验码, 水平垂直冗余校验LRC, 目前广泛使用的是CRC校验码, 它能查处99%以上18位或更长的突出错误, 而在计算机与PLC点对点的短距离通讯时, 出错的几率较小, 因而采用校验和法, 基本能满足要求 。
3.多线程技术及在VC++串口通信程序中的实现
在Windows的一个进程内, 包含一个或多个线程, 每个线程共享所有的进程资源, 包括打开的文件、信号标识及动态分配的内存等等 。
一个进程内的所有线程使用同一个32位地址空间, 而这些线程的执行由系统调度程序控制, 调度程序决定哪个线程可执行和什么时候执行线程 。 线程有优先级别, 优先权较低的线程必须等到优先权较高的线程执行完任务后再执行 。 在多处理器的机器上, 调度程序可以把多个线程放到不同的处理器上运行, 这样可以使处理器的任务平衡, 也提高系统的运行效率 。
Windows内部的抢先调度程序在活动的线程之间分配CPU时间, Windows区分两种不同类型的线程, 一种是用户界面线程(UserInterfaceThread), 它包含消息循环或消息泵, 用于处理接收到的消息;另一种是工作线程(WorkThread)它没有消息循环, 用于执行后台任务、监视串口事件的线程即为工作线程 。
1本系统采用MFC编程方法, MFC是把串口作为文件设备来处理的, 它用CreateFile()打开串口, 并获得一个串口句柄, 用SetCommState()进行端口配置, 包括缓冲区设置, 超时设置和数据格式等 。 然后调用函数ReadFile()和WriteFile()进行数据的读写, 用WaitForSingleObject()监视通信事件 。 在用ReadFile()和WriteFile()读写串口时, 一般采用重叠方式 。 因为同步I/O方式是当程序执行完毕才返回, 这样会阻塞其他线程, 降低程序执行效率 。 而重叠方式能使调用的函数立即返回, I/O操作在后台进行, 这样线程就可以处理其他事务, 同时也实现了线程在同一串口句柄上实现读写操作 。
使用重叠I/O方式时, 线程要创建OVERLAPPED结构供读写函数使用, 该结构最重要的成员是hEvent事件句柄 。 它将作为线程的同步对象使用, 读写函数完成时hEvent处于有信号状态, 表示可进行读写操作;读写函数未完成时, hEvent被置为无信号 。
利用Windows的多线程技术, 在辅助线程中监视串口, 有数据到达时依靠事件驱动, 读入数据并向主线程报告;并且, 依靠重叠读写操作, 让串口读写操作在后台运行 。
4.上位计算机通信程序设计
以读取PLC输出线圈Y0为首的2个字节的数据为例, 编写一个通信程序 。 查PLC软元件地址表可知, 输出线圈Y0的首地址为00A0H, 2个字节的数据即为Y0-Y7和Y10-Y17, 根据返回的数据, 就可以知道PLC此时的状态, 以实现对PLC的监控 。 在每一次读操作之前, 先要进行握手联络 。 对PLC发请求讯号ENQ, 然后读PLC的响应讯号 。 如果读到的响应讯号为ACK, 则表示PLC已准备就绪, 等待接收通讯数据 。
BOOLCPlcComDlg::ReadFromPLC(char*Read_char, char*Read_address, intRead_bytes)
{CSerialSerial;//用于串行通讯的类
if(Serial.Open(1))//初始化串行通讯口COM1
{Serial.SendData(&ENQ_request, 1);//发送联络讯号
Sleep(20);//等待20ms秒
Serial.ReadData(&read_BUFFER, 1);//读取PLC响应讯号
if(read_BUFFER==ACK){
……
Serial.SendData(&STX_start, 1);//向PLC发送“开始”标志代码
Serial.SendData(&CMD0_read, 1);//发送“读”命令代码
datasum_check+=CMD0_read;
for(i=0;i<4;i++){
Serial.SendData(&Read_address[i>, 1);//发送起始元件地址的ASCⅡ代码
……
Serial.SendData(&ETX_end, 1);//发送结束标志代码
Change_to_ASCI