分享

Modbus通讯协议(二)

 huasum 2022-04-23

电力系统是一个综合化的系统,作为一个熟练的电工,对于通信有着一定的认识。否则很多问题,我们将无从下手。首先我们从广泛应用于现场的Modbus-RTU模式,来开始讲起。

Modbus-RTU模式是指当控制器设为在Modbus网络上以RTU(远程终端模式)模式通信,在消息中的每个8Bit包含两个4Bit的十六进制字符。

说明:

Bit(位),信息的最小单位,简写为b,代表0或1的数位讯号。

Byte(字节),用于计量储存容量的一种计量单位,简写为B,1Byte=8Bits,即1字节等于8位。1字节可以表示的内容个数为2的8次方,即256个。

Word(字),用来计算机一次性处理事务的一个固定长度的位组。对于工业现场控制设备常用的16位系统来说1Word2Byte16Bit计算机中大多数寄存器的尺寸就是一个字长。

一、信息帧的格式

使用RTU模式注意下面两点:

1、信息帧发送至少要以3.5个字符时间的停顿间隔开始。在最后一个字符传输字符之后,一个至少3.5个字符时间的停顿标定了信息帧的结束。一个新的信息帧可在此停顿之后开始。如果一个新消息在小于3.5个字符时间内接着前个消息开始,接受的设备将认为它是前一信息帧的延续,这将导致CRC码的值出错。

2、整个信息帧必须作为一连续的流传输。如果在帧完成之前有超过1.5字符时间的停顿时间,接受设备将刷新不完整的信息帧并认为存在丢包现象。

通过不同的网络波特率来调整不同的间隔时间,这是最容易实现的。其帧格式及传输过程示意图如下所示:

说明:

波特率是指模拟线路信号的速率,以波形每秒的振荡数来衡量。

如果数据不压缩,波特率等于每秒传输的数据位数,与比特率相等。

如数据进行了压缩(为了提高通信速率),被压缩的数据形成码元(根据调制方式不同,码元的位数不一)。

下面举一个例子来说明调制

现在有如下一串01001111,共8Bit。

如果一位一位的来看,那就是有两种不同的离散值0和1,只有高、低电平两种幅度。

现在将每两个bit作为一个符号,也就是两位两位的来看,即把这串信号这样看:01 00 11 11。两位两位来看的话,就从之前只有高、低电平幅度(两种不同的离散值)变成了四种不同的幅度(就是概率里面的排列组合得出2*2=4):00(最低)、01(低)、10(高)、11(最高),有了四种不同的离散值。

上述信号也就变成了「低」「最低」「最高」「最高」,四种幅度对应成0、1、2、3,那么信号串就变成了1、0、3、3 。

上述过程就是调制。

那么在数据进行过压缩的情况下,比特率=波特率*log2(N),其中N表示离散值的数量。

示例:波特率为240Baud,有8种电平与之对应,则其与之对应的比特率为240*log2(8)=720bps

下面来分项来说说信息帧中的各部分:

1、地址码

地址码是信息帧的第一个字节(8位),从0到255。每个从机都必须有唯一的地址。在下行帧中,表明只有符合地址码的从机才能接收由主机发送来的信息。在上行帧中,表明该信息来自于何处。

备注:如果地址为0x00,则认为是一个广播命令,就是所有从机要接收主机发来的信息。规约规定广播命令必须是写命令,并且从站也不发送回答。

2、功能码

功能码是信息帧的第二个字节。ModBus通讯规约定义功能号为1到127。大多数设备只利用其中一部分功能码。下行帧中,通过功能码告诉从机执行什么动作。在上行帧中,从机发送的功能码与主机发送来的功能码一样,并表明从机已响应主机进行的操作,否则表明从机没有响应操作或发送出错。其常用功能码如下所示:

3、数据

它因不同的功能码及不同的从机而不同。数据区可以是实际数据、状态值、参考地址、数据长度等等。

4、CRC码

CRC码由发送设备计算,放置于发送信息的尾部。接受信息的设备再重新计算接收到的信息的CRC码,比较计算得到的CRC码是否与接收到的相符(或将接收到的信息除以约定的除数,应无余数),如果不相符(有余数),则表明出错。它用于保证主机或从机对传送过程中出错的信息起不了作用,增加了系统的安全与效率。

下面我就来说一下CRC码是如何计算出来的。

在介绍CRC码的计算过程之前,我们先来谈谈“模2除法”。

A、模2运算

“模2除法”与“算术除法”类似,但它既不向上借位,也不比较除数和被除数的相同位数值大小,只要以相同位数进行相除即可。

“模2加法”为1+1=0,1+0=1,0+0=0,0+1=1;

“模2减法”为1-1=0,1-0=1,0-0=0,0-1=1;

大家仔细看看上面的运算,是否觉得非常像一种逻辑运算?

没错,上述运算相当于二进制中的逻辑异或运算。也就是比较后,两者对应位相同则结果为“0”,不同则结果为“1”。下面以100101除以1110为例,为大家展示一下“模2除法”的运算,如下图示:

上述算式的商为11,余数为1。

B、CRC校验步骤

1、先选择一个用于在接收端进行校验时,对接收的帧进行除法运算的除数。此除数可以随机选择,也可按标准选择。通常以多项式的方式表示,这个多项式也称之为“生成多项式”。

备注:除数的最高位和最低位必须为1。

2、看已选定的除数二进制位数k,,然后在要发送的数据帧(m位)后面加上k-1位“0”,然后用已经加上k-1位“0”的新帧(m+k-1位)以“模2除法”方式除以上面所说的除数,所得到的余数就是该帧的CRC校验码,也称为FCS(帧校验序列)。

备注:余数的位数一定要是比除数位数只能少一位,哪怕前面的位是0,甚至全为0也不能省略。

3、再把这个校验码附加在原在原数据帧后面,构成一个新帧发送到接收端,最后在接收端再把这个新帧以“模2除法”方式除以前面选择的余数,如果没有余数,则该帧在传输过程中没有出错,否则就是出现了差错。(或者重新计算CRC码)。

C、示例

下面举个例子来说明,CRC码的计算过程。

设生成多项式为

问:二进制序列为10110011的CRC校验码是什么?发送序列是什么?

G(x)的位数=最高位的幂次+1=4+1=5,所被除数序列为原序列加上【G(X)的位数-1】个数的“0”,即5-1=4。综上,被除数等于101100110000。

多项式各幂次的系数,由高到低依次排序即为除数。此例中为11001。

开始进行“模2除法运算”,如下图所示:

计算结果:商为11010100,余数为0100。即题干中二进制序列的CRC校验码为0100。

发送序列为101100110100。

备注:http://www./crc.html,在上述网站中可以方便地在线计算CRC码。

二、modbus报文实例解析

注:以下报文的CRC算法为CRC-16/MODBUS。

A、01号命令

下行帧:11 01 00 13 00 25 F9 C8

11为从机地址(1byte),地址号17;

01为功能码(1bye),读线圈状态;

0013为寄存器起始地址(2byte),起始地址19;

备注:程序的起始地址为0。起始地址19实际上是第20号接触器。

0025为数据数量(2byte),37个状态量,需要5个字节的空间;

F9C8为CRC码(2byte)。

释义:读取来自17号从机以20号接触器为起始的37个接触器状态。

上行帧:11 01 05 CD 6B B2 0E 1B 18 8D

11为从机地址(1byte),地址号17;

01为功能码(1byte),读线圈状态;

05为数据区字节数(1byte),5个字节;

CD 6B B2 0E 1B为数据(5byte),仅解析第一个数据(CD),CD转为二进制序列为11001101,从低位到高位读,每一位对应一个接触器的状态,0为分,1为合。

综上数据段中的CD,表示20号接触器合位、21号分位、22号合位、23号合位、24号分位、25号分位、26号合位、27号合位;

18 8D为CRC码(2byte)。

释义:上送来自17号从机的接触器状态,其数据字节数为5,信息为20号接触器合位、21号分位、22号合位、23号合位、24号分位、25号分位、26号合位、27号合位……

备注:

若询问的数据数量不是8的整倍数,那么最高字节的多余位补0,此时的0不代表任何意义。在此例里,数据段中的1B,低位B则表示52号分位,53号合位,54号分位,55号合位;它的高位1表示,56合位,其余位补0,无意义。

B、02号命令

下行帧:11 02 00 13 00 25 F9 40

11为从机地址(1byte),地址号17;

02为功能码(1byte),读离散输入状态;

0013为寄存器起始地址(2byte),起始地址19;

0025为数据数量(2byte),37个状态量,需要5个字节的空间;

F940为CRC码(2byte)。

释义:读取来自17号从机以20号开关为起始的37个断路器状态。

说明:

01读取的是线圈状态,只能代表电保持的开关器件的状态,如是断路器这种只需要短时合闸脉冲,线圈不需要长期得电,无法用01取得位置信号。

02读取的是开入状态,可以是断路器的辅助触点,也可以行程开关等等器件,所以可以读取机械保持的断路器的位置信号。

上行帧:11 02 05 CD 6B B2 0E 1B 1B BD

11为从机地址(1byte),地址号17;

02为功能码(1byte),读离散输入状态;

05为数据区字节数(1byte),5个字节;

CD 6B B2 0E 1B为数据(5byte),此次解析第二个数据(6B),6B转为二进制序列为01101011,从低位到高位读,每一位对应一个断路器的状态,0为分,1为合。

综上数据段中的6B,表示28号断路器合位、29号合位、30号分位、31号合位、32号分位、33号合位、34号合位、35号分位;

1BBD为CRC码(2byte)。

释义:上送来自17号从机的断路器状态,其数据字节数为5,信息为20号断路器合位、21号分位、22号合位、23号合位、24号分位、25号分位、26号合位、27号合位……

C、03号命令

下行帧:11 03 00 6B 00 03 FF 8C

11为从机地址(1byte),地址号17;

03为功能码(1byte),读保持寄存器;

006B为寄存器起始地址(2byte),起始地址107;

0003为数据数量(2byte),3个模拟量;

FF 8C为CRC码(2byte)。

释义:读取17号从机中以107号仪表为起始的3个仪表的模拟量。

上行帧:11 03 06 00 DC 00 DC 00 DC FD D1

11为从机地址(1byte),地址号17;

03为功能码(1byte),读保持寄存器;

06为数据区字节数(1byte),6个字节;

00 DC 00 DC 00 DC数据(6byte),表示第108号的模拟量为220,第109号的模拟量为220,第110号的模拟量为220;

备注:一个模拟量的标准长度为2个字节。

FD D1为CRC码(2byte)。

释义:上送来自17号从机中的模拟量,其数据字节数为6,信息为表示第108号模拟量为220,第109号模拟量为220,第110号模拟量为220。此条数据显然是电压表的三相相电压数据。

D、04号命令

a) 模拟信号

下行帧:11 04 00 6B 00 03 47 C3

11为从机地址(1byte),地址号17;

04为功能码(1byte),读输入寄存器;

006B为起始地址(2byte),地址号107;

0003为数据数量(2byte),3个模拟量;

47C3为CRC码(2byte)。

释义读取17号从机的108传感器为起始的3个温度传感器输出信号。

上行帧:11 04 06 00 0A 00 0B 00 09 96 84

11为从机地址(1byte),地址号17;

04为功能码(1byte),读输入寄存器;

06为数据区字节数(1byte),6个字节;

00 0A00 0B 00 09为数据(6byte),表示108号、109号、110号温度传感器输出信号分别为10mA、11mA、9mA。

设温度传感器的温度与电流之间关系为I=16T/200+4,则可得108号、109号、110号温度传感器温度值为75℃、87.5℃、62.5℃;

9684为CRC码(2byte)。

释义:上送17号从机的108传感器为起始的3个温度传感器测值,依次分别为75、87.5、62.5℃。

b)SOE数据

1、SOE简介

SOE(Sequence Of Event),事件顺序记录,记录故障发生的时间和事件的类型。在电力系统,一旦在系统联调或生产运行过程中发生停机,需要立即查找事故原因,但由于电力系统的保护动作过程复杂,实时性高,一般的报警记录及历史记录已无法用来进行准确的事故分析。

这时就需要分辨率高的SOE进行事故的事后分析,查找事故的第一原因。其电平变化分辨率可达1ms甚至更低。

GPS时钟同步性能的优劣会对SOE的精确性产生至关重要的影响。

2、 读SOE功能实现方式

由于在标准中没有定义读SOE数据的功能码和帧格式,那么很多厂家会自定义一些功能码或着使用04或03而改变其帧格式。所以读SOE功能的实现也可以说是八仙过海。本文中仅举一例来讲解上位机读PLC中SOE信号的实现。

①  PLC初始化时将事件交换字(通俗的说法即是SOE未读数量)置0,同时开辟一个SOE缓冲数据区(存储无法及时上传的事件),可循环存放50SOE数据(通俗的说就是SOE数据就存50条,等超过50条指针就归零,然后在一条一条的往上走把旧的覆盖,此时没有覆盖的旧的还是存在的,直到指针更新到该条此指针跟随上位机的读指令移动)

  当上位机需要读取因通讯中断等原因导致滞留SOE数据时,首先读取事件交换字,检查是否为0。当事件交换字不为0时,读取事件记录,并进行处理。完毕后将事件交换字置0。

3、报文实例解析

设事件交换字存储地址为0,SOE读指针地址为1,大小均为1个字;SOE读指针指针指向46时,对应地址为256;电平变化分辨率为0.1ms。装置部分点表如下所示:

下面开始报文分析:

下行帧11 04 00 00 00 01 5A 33

11为从机地址(1byte),地址号17;

04为功能码(1byte),读输入寄存器;

0000为事件交换字地址(2byte),地址号0;

0001为SOE读指针地址(2byte),地址号1;

5A33为CRC码(2byte)

释义询问17号从机的事件交换字及当前SOE位置

上行帧11 04 04 00 02 00 2e 5A AA

11为从机地址(1byte),地址号17;

04为功能码(1byte),读输入寄存器;

04为数据区字节数(1byte),4个字节;

0002为事件交换字(2byte),表示有2个SOE数据滞留在SOE缓冲区内;

002e为当前指针位置(2byte),表示指针移动到46的位置;

5AAA为CRC码(2byte)。

释义17号从机回应主机事件交换字2当前SOE指针位置46

下行帧:11 04 01 00 00 10 AA F2

11为从机地址(1byte),地址号17;

04为功能码(1byte),读输入寄存器;

0100为指针46位置对应的地址,地址号256;

0010为数据占用寄存器个数,16个;

AAF2为CRC码(2byte)。

释义17号从机的256为起始地址的SOE数据,共16个寄存器。

上行帧:11 04 20 02 01 09 02 0B 0C 0E 0D 01 02 00 02 00 01 00 0001 03 09 02 0C 0B 09 0F 03 14 00 04 01 01 00 00 2E 7D

11为从机地址(1byte),地址号17;

04为功能码(1byte),读输入寄存器;

20为数据区字节数(1byte),32字节;

02 01 09 02 0B 0C 0E 0D 01 02 00 02 00 01 00 00第一组SOE数据,其中尾部的四个字节00 01 00 00为备用数据,无任何意义。第一个字节为SOE类型,第二个字节为SOE的源,随后8个字节为时标,而后两个字节为SOE的测点。

表示2009年2月11日12点14分13秒25.8毫秒2号开关手动分闸。

01 03 09 02 0C 0B 09 0F 03 14 00 04 01 01 00 00 第二组SOE数据其中尾部的四个字节01 01 00 00为备用数据,无任何意义。第一个字节为SOE类型,第二个字节为SOE的源,随后8个字节为时标,而后两个字节为SOE的测点。

表示2009年2月12日11点9分15秒78.8毫秒4号开关通讯合闸。

2E7D为CRC码。

释义:17从机32字节SOE数据:2009年2月11日12点1413秒25.8毫秒2号开关手动分闸;2009年2月12日11点9分15秒78.8毫秒4号开关通讯合闸

E、05号命令

下行帧:11 05 00 AC FF 00 F3 F6

11为从机地址(1byte),地址号17;

01为功能码(1byte),写单个线圈;

00AC为下置的寄存器地址(2byte),寄存器地址号为172;

FF00为下置的数据;

F3F6为CRC码(2byte)。

释义:合上17号从机的173号开关。

备注:开关的分闸命令为0x00,合闸命令为FF00,其余数值均为非法。

上行帧:11 05 00 AC FF 00 F3 F6

此帧完全重复下行帧的命令,相当于确认命令已执行。

释义:17号从机的173号开关已合闸。

F、06号命令

下行帧:11 06 00 01 00 32 79 B9

11为从机地址(1byte),地址号17;

06为功能码(1byte),写单个保持寄存器;

0001为下置的寄存器地址(2byte),寄存器地址号为1;

0032为下置的数据,数据为50;

79B9为CRC码(2byte)。

释义:将17号从机里地址为1的保持寄存器中数据置为50。此条数据可以是将18号从机的第2号变频器的输出频率置为50HZ。

上行帧:11 06 00 01 00 32 79 B9

释义:表示置位成功,即17号从机的第2号变频器的输出频率已置为50HZ。

G、15号命令

下行帧:110F 00 13 00 02 01 01 98 9B

11为从机地址(1byte),地址号17;

0F为功能码(1byte),写多个线圈;

0013为起始地址(2byte),起始地址为19;

0002为强置个数(2byte),个数为2;

01为强置字节数(1byte),1个字节;

01为强置数据(1byte),强置数据为0001,由于强置个数为2个,所以第一位与第二位无效;

989B为CRC码(2byte)。

释义:合上17号从机的20号开关,分开其21号开关。此命令可以消防联动,将风出风口阀门配置21号开关,防排烟风机的启动开关配置为20号开关,可组成最简单的消防联动。

上行帧11 0F 00 13 00 02 5F 27

11为从机地址(1byte),地址号17;

0F为功能码(1byte),写多个线圈;

0013为起始地址(2byte),起始地址为19;

0002为强置个数(2byte),个数为2;

5F23为CRC码(2byte)。

释义合上17号从机的20号开关,已分开其21号开关。

H、16号命令

设系统时间地址为10000~10004。

下行帧:11 10 27 10 00 05 0A 07 D2 0A 09 00 0C 0E 0D 00 00 DD D5

11为从机地址(1byte),地址号17;

10为功能码(1byte),写多个保持寄存器;

2710为起始地址(2byte),起始地址为10000;

0005为写寄存器个数,占用5个寄存器;

0A为数据区字节数,10个字节;

07 D2 0A 09 00 0C 0E 0D 00 00为数据(10byte),表示2002年9月10日12点14分13秒0毫秒;

DDD5为CRC码(2byte)。

释义:将系统时间置为2002年9月10日12点14分13秒0毫秒。

上行帧11 10 27 10 00 05 EB 09

11为从机地址(1byte),地址号17;

10为功能码(1byte),写多个保持寄存器;

2710为起始地址(2byte),起始地址为10000;

0005为写寄存器个数,占用5个寄存器;

EB09为CRC码(2byte)。

释义系统时间已成功重置。

三、系统的架构与数据读取循环周期

A、系统的架构流程

当我们在现场需要搭建一个PLC与多个电力仪表进行数据交换的网路时,我们要完成哪些事情呢?此电力仪表需支持RS485及ModBus-RTU。

第一步:按菊花瓣结构的通信链路要求去接线,将PLC的通信接口与N个电力仪表连接起来,最后一个电力仪表的末端和PLC端要配置120Ω的终端电阻;

说明:

菊花瓣结构如下图所示:

每个中间站的接线其实就是一个节点,节点中既有1条进线,也有一条出线,还有引至自身的内部引线,这样的接法即是菊花瓣接法。

菊花瓣接法有着以下的特点:

1、任何一个节点如果出现断路,则后续的节点无法进行通信;

2、通信介质头尾都安装了120Ω的终端电阻,用途是吸收反射波,建立稳定的电平关系;

3、通信线缆的屏蔽层需要接地,而且只能存在1个接地点,若存在两个接地点,则接地点之间可能会存在环流,引起干扰;

4、通信介质必须采用双绞线。采用双绞线的目的是利用电感效应来中和分布电容。

第二步:在电力仪表中设置好各自的地址,地址依次递增;

第三步:在编程软件中设定好与电力仪表相匹配的通信速率;

第四步:在编程软件中按电力仪表的数据区地址码设定好Modbus通信码,以及各个子站的循环关系;

第五步:在PLC的内存中开辟专用的数据区,存放从电力仪表读取到并处理的信息,以便让更高层的总站来读取信息。解释此数据区的定义的便是点表了。

B、数据读取循环周期

某电力仪表组,个数为30,地址是01H-1E。在电力仪表内存第2000的位置上,放置了三相电流和三相电压等6个数据,每个数据占用两个字节,共12个字节。此电力仪表的通讯速率为9600bps。串口通信中不使用奇偶校验位。上行帧与下行帧之间的间隔时间位10ms。

现截取一段通讯报文如下所示:

下行帧:01 03 07 D0 00 06 C5 45

上行帧:01 03 0C 00 64 0064 0064 00 DC 00 DC 00 DC D6 F5

现问:PLC轮询完所有电力仪表需要多少时间?

1个字节有8个数据位,1个起始位,1个奇偶校验位(实际使用中此位常常取消),1个停止位。

由于题干中说明了其奇偶校验位取消,则1个字节长度为10Bit。由于比特率位9600bps,所以1秒钟可以传输960个字节。

一轮对话中的字节数为下行帧(8byte)+上行帧(17byte)=25byte。所以传送上、下行帧总耗时为25/960=38.4≈26.04ms,加上等待的时间(10ms)。

完成一轮对话的时间为26.04+10=36.04ms

所以轮询完30个电力仪表的时间是30*36.04ms≈1.1s。

因为忽略一轮对话结束后主机再次发下行帧的等待时间,所以实际时间会比理论值稍微大一点。

顺带把报文翻译一下:

下行帧:读1号电力仪表中以2000为起始地址的连续6个模拟量。

上行帧:1号电力仪表中连续的6个模拟量依次为:220、220、220、100、100、100。

显然前三个数值是三相电压,后三个数值是三相电流。

说明:

有朋友会问我们查看报文时,看不到有什么起始位、奇偶校验位、停止位,这是怎么回事?

起始位,停止位,奇偶校验位,空闲位的信号,由“发送移位寄存器”自动插入,在接收方,“接收移位寄存器”接收到一帧完整的信息(起始、数据、校验、停止)后,仅把数据位的各位送入“数据输入寄存器”,即CPU从“数据输入寄存器”中读到的信息,只是有效数据,不包含起始位、奇偶校验位与停止位。

通俗的说,我们能看到的是应用层,而起始位、停止位、奇偶校验位属于物理层,所以是看不到这些位的,如果非要看的话,就需要用示波器了。

结合下面通信中的过程图,来简要说明一下这种物理层的校验方式:

1、当通信开始时,信号线为空闲(逻辑1),当检测到由1跳变至0时,开始“接收时钟”计数。

2、当计到8个时钟时,对输入信号进行检测,若依旧为低电平,则确认此跳变信号为“起始位(B)”信号(逻辑0),而不是干扰信号。

3、当接收端检测到起始位后,隔16个接收时钟,对输入信号检测一次,把对应的值作为D0位数据。

4、再隔16个接收时钟,对输入信号检测一次,把对应的值作为D1位数据,直到全部数据位都输入完毕。

注意:在发送时,顺序为LSB发至MSB,即由低往高发。如图中所示,其数据是45H=0100 0101,但其发送顺序是1010 0010,切莫倒置。

5、接收奇偶校验位。

6、当接收完规定的数据位个数和校验位后,通信接口电路希望收到停止位S(逻辑1),若此时未收到逻辑1,说明出现了错误,在状态寄存器中置“帧错误”标志。若没有错误,对全部数据进行奇偶校验,校验无错误时,把数据位从移位寄存器送入数据输入寄存器,若校验错误,在状态寄存器中置奇偶错误标志。

还是以上图数据45H为例,说明一下奇偶校验。45H的二进制序列为0100 0101。

如果采用奇校验,奇偶校验位就是0。这样才能保证发送出去的数据“1”的个数为奇数,本例中数据中“1”个数为3,所以奇偶校验位就是0。

如果采用偶校验,奇偶校验位就是1,这样才能保证发送出去的数据“1”的个数为偶数,本例中数据中“1”个数为3,所以奇偶校验位就是1,这样数据中就有了4个“1”,这样才能满足偶校验

7、本帧信息接收完毕,把线路上的高电平作为空闲位。

备注:本段文字中提到的时钟,是指时钟周期,是晶振频率的倒数。它是计算机中最基本,最小的时间单位。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多