1 modbus通讯

1.1 modbus 通讯数据格式

地址码 功能码 数据区 校验码
1个字节 1个字节 N个字节 16位CRC

1.2 功能码

功能码 描述 说明 MOUBUS地址
01 读输出线圈寄存器 位操作 00001 ~ 09999
02 读离散输入寄存器 位操作 10001 ~ 19999
03 读保持(输出)寄存器 字操作 40001 ~ 49999
04 读输入寄存器 字操作 30001 ~ 39999
05 写单线圈寄存器 位操作 00001 ~ 09999
07 读取异常状态 获得8个内部线圈的逻辑状态
06 写单线圈保持寄存器 字操作 40001 ~ 49999
10 写多路寄存器 字操作
15 写多线圈寄存器 位操作 00001 ~ 09999
16 写多个保持寄存器 字操作 40001 ~ 49999
17 报告从机标识 可使主机判断从机标识的类型及其该从机运行指示灯的状态

1.3 数据区

1.3.1 格式

数据区格式不固定,一般需要查看从机设备的通讯手册
数据区格式示例:

开始编号/寄存器地址 数据个数 数据1 …… 数据n
2个字节 2个字节 2个字节 2个字节 2个字节

1.3.2 寄存器地址

通常Modbus地址由5位数字组成,包括起始的数据类型代号,以及后面的偏移地址。Modbus Master协议库把标准的Modbus地址映射为所谓Modbus功能号,读写从站的数据。
Modbus Master协议库支持如下地址:

编号范围 含义
00001~09999 数字量输出(线圈)
10001~19999 数字量输入(触点)
30001~39999 输入数据寄存器(通常为模拟量输入)
40001~49999 数据保持寄存器

由上表可知,Modbus通讯的地址是从1开始的,如果遇到从机设备的寄存器编号从0开始,那么就需要考虑给通讯地址加1处理。

即:

Modbus地址 数据地址 (参数地址)
1 0
2 1
n n-1

1.4 CRC校验

1.4.1 CRC校验算法步骤

  • 第一步:设置CRC变量存储器初始值位0xFFFF;
  • 第二步:把第一个参与校验的数据和CRC变量的低八位进行异或运算,结果仍存到CRC存储器中;
  • 第三步:把CRC右移一位,最高位补0;
  • 第四步:检查刚移出的最低位b0,如果b0=1,则CRC变量和0xA001进行异或运算,结果仍存在CRC变量存储器中,然后执行下一步。如果b0=0,则直接执行下一步;
  • 第五步:重复3、4两步,只到右移8次。这样第一个数据处理就完成了,结果仍存在CRC变量存储器中。
  • 第六步:重复2~5步,处理下一个数据,只到参与校验的数据均处理完毕。
  • 注:最后获得的16位CRC校验值,在传输时,低八位在前,高八位在后;

1.4.2 CRC校验算法C语言程序

#include <stdio.h>


#define num 6   //需要生成CRC校验的数据个数 

int main()
{
	//unsigned char buf[8]={0x01,0x06,0x10,0x00,0x27,0x10,0x97,0x36};//最后两位是校验位 
	unsigned char buf[num]={0x01,0x04,0x00,0x0a,0x00,0x0a};//待生成校验位的数据 
	//01 04 00 02 00 02
	int i,n;
	unsigned int crc16;
	unsigned int temp;
	
	crc16=0xffff;//CRC变量初始化为0xffff 
	i=0;n=0;
	
	for(n=0;n<num;n++)//循环给所有数据参与校验 
	{
		crc16 = buf[n]^crc16;	//第一个数据和CRC变量异或运算		
		for(i=0;i<8;i++)//总共移位8次 
		{	
			temp  = crc16 & 0x0001;//把最后一位的状态记住。 
			crc16 = crc16 >> 1;    //循环右移一次 
			if(temp)    //判断刚才移出的最后一位是1? 
			{
				crc16 = 0xa001^crc16;
			} 		
			printf("CRC校验为:%x\n",crc16);			
		}
			printf("---------------------------------\n");		
	}
	printf("CRC校验为:%x\n",crc16);		
} 

1.5 MODBUS主问从答

1.5.1 读输出线圈

  • 主机询问格式
从机地址 功能码 寄存器起始地址 寄存器个数 CRC校验
01 01 00 02 00 01 5C 0A
  • 从机应答格式
从机地址 功能码 字节个数 数据1 CRC校验
01 01 01 01 - -

1.5.2 读输入线圈

  • 主机询问格式
从机地址 功能码 寄存器起始地址 寄存器个数 CRC校验
01 02 00 01 00 01 E8 0A
  • 从机应答格式
从机地址 功能码 字节个数 数据1 CRC校验
01 02 01 FF - E1 C8

1.5.3 读输出寄存器

  • 主机询问格式
从机地址 功能码 寄存器起始地址 寄存器个数 CRC校验
01 03 00 01 00 01 D5 CA
  • 从机应答格式(数据字节个数为偶数)
从机地址 功能码 字节个数 数据1 数据2 CRC校验
01 03 02 02 05 - 79 27

1.5.4 读输入寄存器

  • 主机询问格式
从机地址 功能码 寄存器起始地址 寄存器个数 CRC校验
01 04 00 04 00 01 70 0B
  • 从机应答格式(数据字节个数为偶数)
从机地址 功能码 字节个数 数据1 数据2 CRC校验
01 04 02 55 99 - 16 0A

1.5.5 主机写当个线圈寄存器

  • 主机询问格式
从机地址 功能码 寄存器起始地址 寄存器个数 CRC校验
01 05 00 03 FF 00 7C 3A
  • 从机应答格式
    无应答
    该节与1.5.1 读输出线圈互为读写

2 西门子PLC Modbus通讯

2.1 S7-200SMART地址转换MODBUS地址

Modbus地址 S7-200数据区
00001~00128 Q0.0~Q15.7
10001~10128 I0.0~I15.7
30001~30032 AIW0~AIW62
40001~4xxxx 如下

Modbus地址映射中:40001表示保持性寄存器,是一个字(两个字节),若对应是VW0。这 40001的高位字节存在VB0中,低位字节存在VB1中,而一个字节里位的权重是一样的,也就是一一对应。因此40001的第0位对应VB1的第0位,40001的第15位对应VB0的第7位。简言之,近似下面的表达:
40001.0 = V1.0
40001.1 = V1.1
40001.2 = V1.2
40001.3 = V1.3
40001.4 = V1.4
40001.5 = V1.5
40001.6 = V1.6
40001.7 = V1.7
40001.8 = V0.0
40001.9 = V0.1
40001.10 = V0.2
40001.11 = V0.3
40001.12 = V0.4
40001.13 = V0.5
40001.14 = V0.6
40001.15 = V0.7

2.2 CM1241模块

  • CM1241指示灯
  • DIAG指示灯:
  • 亮红色:模块没有被PLC识别;
  • 亮绿色闪烁:模块已经被PLC识别,但是软件没有进行配置;
  • 亮绿色常亮:模块已经被PLC识别,而且软件中配置正确;
    cm1241最多带12个485从机设备

2.3 S7-1200 MODBUS通讯指令介绍

MB_COMM_LOAD指令:用于设置Modbus(RTU)端口。
在这里插入图片描述

参数 说明
EN 使能
REQ 上升沿启动该指令
PORT 扩展模块的硬件标识符
BAUD 波特率
PARITY 0:无校验;1:奇校验;2:偶校验
RESP_TO 每个从站的读取延时时间
MB_DB MB_MASTER / MB_SLAVE 指令的背景数据块

一个端口只能执行一次这个指令,可以选择放置到OB100中。

MB_MASTER指令
在这里插入图片描述

参数 说明
EN 使能
REQ 上升沿发送有一个读/写请求
MB_ADDR 从站地址
MODE 读写控制位;0:读;1:写;
PARITY 0:无校验;1:奇校验;2:偶校验
DATA_ADDR 将要读/写的从机寄存器地址
DATA_LEN 访问寄存器的连续数量
DNE 完成标志位,可以用来激活下一个指令
BUSY 繁忙标志位
ERROR 错误标志位
STAUS 错误代码
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐