ModbusTCP报文格式说明

modbus tcp数据报文结构

请求:00 00 00 00 00 06 09 03 00 00 00 01

响应:00 00 00 00 00 05 09 03 02 12 34

  一次modbus tcp读取保持寄存器的通信分析(省略了ip/tcp头):从左向右分析该数据报文:

请求:

00 00为此次通信事务处理标识符,一般每次通信之后将被要求加1以区别不同的通信数据报文;

00 00表示协议标识符,00 00为modbus协议;

00 06为数据长度,用来指示接下来数据的长度,单位字节;

09为设备地址,用以标识连接在串行线或者网络上的远程服务端的地址。以上七个字节也被称为modbus报文头;

03为功能码,此时代码03为读取保持寄存器数据;

00 00为起始地址;

00 01为寄存器数量,(word数量)。

响应:

00 00为此次通信事务处理标识符,应答报文要求与先前对应的请求保持一致;

00 00为协议标识符,与先前对应的请求保持一致;

00 05为数据长度,用来指示接下来数据的长度,单位字节;

09为设备地址,应答报文要求与先前对应的请求保持一致;

03为功能码,正常情况下应答报文要求与先前对应的请求保持一致,如果出错则返回80h+先前的功能码;

02指示接下来数据的字节长度;

12 34为被读取的保持寄存器中的数据值,即要求被读取的地址为00 00的保持寄存器中的数值为1234h。

参考资料:https://www.cnblogs.com/ioufev/articles/10830028.html


Modbus常用功能码备查

Modbus功能码

功能码 名称 寄存器PLC地址 位操作/字操作 作用 操作数量
01 读线圈状态 00001-09999 取得一组逻辑线圈的当前状态(ON/OFF) 单个或多个
02 读离散输入状态 10001-19999 取得一组开关输入的当前状态(ON/OFF) 单个或多个
03 读保持寄存器 40001-49999 整型、字符型、状态字、浮点型 在一个或多个保持寄存器中取得当前的二进制值 单个或多个
04 读输入寄存器 30001-39999 整型、状态字、浮点型 在一个或多个输入寄存器中取得当前的二进制值 单个或多个
05 写单个线圈 00001-09999 强置一个逻辑线圈的通断状态 单个
06 写单个寄存器 40001-49999 整型、字符型、状态字、浮点型 把二进制值装入一个保持寄存器 单个
15 写多个线圈 00001-09999 强置一串连续逻辑线圈的通断 多个
16 写多个保持寄存器 40001-49999 整型、字符型、状态字、浮点型 把具体的二进制值装入一串连续的保持寄存器 多个

Modbus寄存器地址规则

Modbus协议定义的寄存器地址是5位十进制地址,即:

线圈(DO)地址:00000~09999

触点(DI)地址:10000~19999

输入寄存器(AI)地址:30000~39999

输出寄存器(AO)地址:40000~49999

由于上述各类地址是唯一对应的,因此有些资料就以其第一个数字区分各类地址,即:0x代表线圈(DO)类地址,1x代表触点(DI)类地址、 3x代表输入寄存器(AI)类地址、4x代表输出寄存器(AO)类地址。

在实际编程中,由于前缀的区分作用,所以只需说明后4位数,而且需转换为4位十六进制地址。


Arduino中字符串常见操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
isAlphaNumeric()  // 判断是否为字母数字

isAlpha() // 判断是否为字母

isAscii() // 判断是否为 ASCII 码

isWhitespace() // 判断是否为空格符

isControl() // 判断是否为控制字符

isDigit() // 判断是否为数字

isGraph() // 判断是否为可打印的字符,不是空格

isLowerCase() // 判断是否为小写

isPrintable() // 判断是否为可打印的字符

isPunct() // 判断是否为标点符号

isSpace() // 判断是否为空格

isUpperCase() // 判断是否为大写

isHexadecimalDigit() // 判断是否为十六进制数字(i.e. 0 - 9, a - F, or A - F)
  1. 字符串转char *
1
2
3
4
String str = "Hello";
int str_len = str() + 1;
char str_char[str_len];
str.toCharArray(str_char, str_len);
  1. 字符串转整型
1
2
String str = "65535";
int intValue = str.toInt();
  1. 字符串切割
1
2
3
4
5
6
7
8
9
10
11
12
String str = "Hello, World";
int str_len = str() + 1;
char str_char[str_len];
strcpy(str_char, str());
const char split_token[2] = ".";
int charArray[str_len];
int i = 0;
char *charValue = strtok(str_char, split_token);
while( charValue != NULL ) {
charArray[i++] = charValue;
charValue = strtok(NULL, split_token);
}

参考连接: https://www.jianshu.com/p/5d4c5f318b73


jenkins更新新版本速度慢
  • Linux
    cd /root/.jenkins/updates/

  • OSX
    cd /Users/Shared/Jenkins/Home/updates
    cd ~/.jenkins/updates

sed -i ‘s/http:\/\/updates.jenkins-ci.org\/download/https:\/\/mirrors.tuna.tsinghua.edu.cn\/jenkins/g’ default.json && sed -i ‘s/http:\/\/www.google.com/https:\/\/www.baidu.com/g’ default.json


Linux下查看ssh的用户登录日志

linux查看日志:

cd /var/log

less secure

或者

less messages

最近登录的日志:

last


是谁没事儿尝试来我家开锁?
1
grep "Failed password for invalid user" /var/log/secure | awk '{print $13}' | sort | uniq -c | sort -nr | more

U8G2详解

U8g2简介

U8g2是嵌入式设备的单色图形库,一句话简单明了。主要应用于嵌入式设备,包括我们常见的单片机。
    

阅读更多
NodeMCU使用OLED

硬件准备:

  1. NodeMCU
  2. I2c-12864-oled液晶屏模块 0.96寸 (12864就是128*64点阵的屏幕,所以叫12864!)

  3. 母对母杜邦线4根

  4. microUSB口-用来连接ESP8266

软件准备:
Win:https://github.com/nodemcu/nodemcu-flasher/tree/master/Win64/Release
Mac:https://github.com/marcelstoer/nodemcu-pyflasher/releases

阅读更多
Linux查找并终止指定进程

ps -ef | grep php | grep -v ‘grep’ | awk ‘{print $2}’| xargs kill -9