单片机与PLC 之间通信的研究
- 来源:消费电子 smarty:if $article.tag?>
- 关键字:单片机,PLC,通信 smarty:/if?>
- 发布时间:2021-04-07 11:02
【摘 要】在工业自动化控制领域会经常用到PLC 与触摸屏传感器等通信,很多厂商已在通信协议方面和大多数触摸屏传感器生产厂商做好匹配。但当某些场合数据的采集方案是采用的单片机就无法直接进行协议的匹配,本文研究了PLC 与单片机通信方面进行匹配的方法。
在很多工业自动化控制设备中,需要进行现场数据的采集,来配合其他设备实现工艺参数的调节和控制,在现场控制设备中有多钟多样的数据采集模块,有些产品无法直接进行协议的匹配。本文着重介绍单片机与PLC 通信的方案。首先,说下硬件接口电路的设计,PLC 配置了标准的RS- 232 接口或者RS-485 接口。以RS-232 接口为例它采用的是EIA/TIA-232-E 电平,而单片机的工作电平是TTL 或者CMOS 电平, 这两种不同的电平肯定是不能进行互相通信的,所以我们需要一个电路进行电平转换。比较常用的是 MAX232 串行通信芯片,MAX232 芯片集成双RS-232 驱动接收器并且采用5V 供电,便于与单片机系统采用统一电源进行工作。
硬件接口电路完成后我们来研究下二者实现通信的软件部分如何设计。软件部分我们采用的Modbus 通信协议。之所以使用Modbus 通信协议是因为它目前应用反面不错的应用层协议,它不仅简洁也比较完善。对于之前没有了解过 Modbus 协议层的,最好不要直接移植Modbus,应该先去学习Modbus 文档,经过充分学习了该协议的内容以后,再按照协议要求开发软件部分,比如PLC 的中Modbus 部分与单片机中的Modbus 部分。虽然单片机系统的通信协议可以由编程人员自己开发,但是通过实践应用发现自己定制的协议问题很多,尤其是需要扩展的时候极为困难。所以去借鉴他人的经验当然是一个很好的途径。借鉴他人成熟的经过验证的代码,可以大大减少调试时间。Modbus 通信协议主要有三种模式,分别为ASCII 码通信模式、RTU 通信模式、 TCP 通信模式等,这个协议定义了控制器,这样我们就能认识和使用这个消息结构,这几种协议规定了消息、数据的结构、命令和应答的方式,数据的通信格式用主/ 从通信方式,数据请求消息由主设备发出,然后从设备接收到正确消息后就可以响应主设备的请求;主设备端当然,也可以去修改从设备端的数据,这样就实现双向的读写。接下来我们以RTU 模式为例来讲解,一帧数据由消息头和编码数据组成。而且每帧数据的发送要大于等于3.5 个字符的间隔时间来开始。当波特率固定时,这个时间间隔是比较容易实现的。一帧数据传输的第一个域是设备的地址。每一个设备的地址都是唯一的,在通信期间网络上的所有设备一直侦测总线。当接收到第一个数据时,收到数据的设备都进行解码,判断是否和自己的地址一样。一帧数据传输完之后,结尾以一个大于3.5 个字符时间的间隔表示一帧数据结束。新的一帧数据可在这个时间间隔以后开始。但是如果在一帧数据传输完成以前有大于1.5 个字符的间隔时间,就会导致接收设备刷新完成这个不完整的消息,就会认定接下来的数据是一个新消息的地址。这样就会导致接收到的数据都是错误的。一组数据帧的格式具体如下:初始结构应该大于等于4 个字节的时间,地址码占用1 个字节长度,功能码占用1 个字节长度,数据区根据用户需求占用的字节长度自定,错误校检占用2 字节长度,结束结构大于等于4 个字节的时间。地址码是一帧数据的第一个字节。这个字节数据是由用户设定的,是从机接收信息的地址。所以每个从机的地址码一定是唯一的,如果有雷同的地址码就会导致两台或多台从机端收到同样的信息指令。主机发送的过来的地址码是主机数据要发给从机的地址,对应地址的从机收到信息后回传从机地址以表示数据接收完成。功能码是一个数据帧的第二个字节。协议规定功能号为 1 到127。那么这些功能码到底是什么意思呢?其实很简单就是作为主机请求发送数据命令,用这些功能码来告诉从机去做什么。如果从机发送的功能码大于127,则表明从机没有正确接收到指令或发送出错。数据区是用户自定义的。数据区的数据是根据现场要求来传输的自定义数据。具体数据区的数值是用户在现场应用中自定义的数值。CRC 校验码冗余循环码总共有2 个字节,CRC 校验码是主设备计算,置于发送信息的尾部。当从机接收到后再重新计算CRC 码,计算完成后的结果来和接收到的CRC 校验码进行对比,如果两者不同,则说明接收到的数据出错。以上是RTU 模式的数据格式。
最后我们再来说下单片机编程的CRC 校验如何实现,因为PLC 的CRC 校验可以通过软件设置好就可以了,但是单片机需要自己写程序来实现校验。通过上文我们知道 CRC 校验码包含两个字节,也就是一个16 位的二进制值码。首先定义一个全“1”的16 位寄存器,然后处理消息寄存器中的第一个字节数据。取一个字符和寄存器内容按位相或,然后结果向右移一位,最高有效位补0。提取最低有效位是1 还是0,如果最低有效位是1,则要将寄存器单独和预置的值相或一下,如果最低有效位的值是0,就不需要进行任何的操作。这样一个字节完成后,重复以上步骤。最终得到的寄存器中的值,就是消息中所有的字节数据都执行之后的CRC 值。接下来以一段例程进行讲解,首先包含2 个头文件#include