首页 > 其他分享 >网络高级day01(Modbus 通信协议:Modbus TCP)

网络高级day01(Modbus 通信协议:Modbus TCP)

时间:2024-09-21 14:22:29浏览次数:3  
标签:--- addr day01 通信协议 uint8 TCP Modbus 寄存器

目录

1》modbus分类

1> Modbus RTU

2> Modbus ASCLL

3> Modbus TCP

 2》Modbus TCP的特点

 3》Modbus TCP协议

 1> 报文头(一共7个字节)

 2> 寄存器

3> 功能码

 4> 数据

 01H  功能码分析

 05H 功能码分析

0FH 功能码分析


1》modbus分类

1> Modbus RTU

运行在串口上的协议,采用二进制表现形式以及紧凑的数据结构,通信效率较高,应用比较广泛

2> Modbus ASCLL

 运行在串口上的协议,采用ASCLL码进行传输,并且每个字节的开始和结束都有特殊字符作为标志,传输效率远远低于Modbus RTU,一般只有通讯量比较少的时候才会考虑它。注:在ASCII模式下,每个8位的字节被拆分成两个ASCII字符进行发送,比如十六进制0xAF(1010 1111),会被分解成ASCII字符“A”(0100 0001)和”F”(0100 0110)进行发送,其发送量显然比RTU增加一倍。

3> Modbus TCP

 运行在以太网上的协议

 2》Modbus TCP的特点

1> 主从应答式通信

2> Modbus TCP是应用层协议,基于传输层的TCP进行通信

注:更好的理解网络模型的分层特点:

各层之间独立,每一层不需要知道下一层如何实现

当任何一层发生变化时,只要层间接口关系保持不变,则这层以上或以下层不受影响。

3> Modbus TCP 端口号默认为502

 3》Modbus TCP协议

Modbus TCP 协议包含三部分:报文头、功能码、数据

MBAP:Modbus Application Protocol (modbus报文头)

PDU:Protocol Data Unit(协议数据单元)

Modbus TCP/IP协议最大数据帧长度为260字节

 1> 报文头(一共7个字节)

 2> 寄存器

一共有四种类型的寄存器,分别是:线圈、离散量输入、输入寄存器、保持寄存器。

离散量和线圈其实就是位寄存器(每个寄存器数据占1字节),工业上主要用于控制IO设备。输入和保持寄存器是字寄存器(每个寄存器数据占2个字节),工业上主要用于存储工业设备的值。

1.离散量和线圈其实就是位寄存器(每个寄存器数据占1字节),工业上主要用于控制IO设备

线圈寄存器,类比为开关量。 线圈寄存器支持读也支持写,写在功能码里面又分为写单个线圈寄存器和写多个线圈寄存器。

读单个或多个 写单个 写多个 3个功能码实现

离散输入寄存器,离散输入寄存器就相当于线圈寄存器的只读模式,他也是8个bit表示一个开关量,而他的开关量只能读取输入的开关信号,是不能够写的。比如我读取外部按键的按下还是松开。

对应功能码1个 读单个或多个

2. 输入和保持寄存器是字寄存器(每个寄存器数据占2个字节),工业上主要用于存储工业设备的值

保持寄存器,这个寄存器的单位不再是bit而是两个byte,也就是可以存放具体的数据量的,并且是可读写的。比如空调检测到的室温,这是不可以修改的,因为室温是根据实际的物理环境决定的。

功能码有对应的三个

输入寄存器,这个和保持寄存器类似,但是也是只支持读而不能写。一个寄存器也是占据两个byte的空间。类比我我通过读取输入寄存器获取现在的温度传感器的值

对应的功能码也就一个

3> 功能码

 4> 数据

 01H  功能码分析

读数据:

主机-》从机

报文头---功能码---起始地址---数量

从机-》主机

报文头---功能码---字节计数---数据

 05H 功能码分析

写单个:

主机--》从机

报文头---功能码---地址---通断标志/数据

从机--》主机

原文返回

0FH 功能码分析

写多个:

主机-->从机

报文头---功能码---起始地址---数量---字节计数---数据

从机--->主机

报文头---功能码---起始地址---数量

练习

封装函数实现03,05功能码的作用

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
void set_slaveid(uint8_t *p, uint8_t id);
int sockfd;
void read_registers(uint8_t *p, uint16_t addr, uint16_t num, uint8_t *dest);
void write_coil(uint8_t *p, uint16_t addr, int op, uint8_t *dest);
int main(int argc, char const *argv[])
{

    if (argc != 2)
    {
        printf("usage:<ip>\n");
        return -1;
    }
    // 1.创建套接字
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    printf("sockfd:%d\n", sockfd);
    // 2.填充结构体
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(502);
    saddr.sin_addr.s_addr = inet_addr(argv[1]);
    socklen_t addrlen = sizeof(saddr);
    // 3.连接
    if (connect(sockfd, (struct sockaddr *)&saddr, addrlen) < 0)
    {
        perror("connect err");
        return -1;
    }
    // 创建数组
    uint8_t req[32] = {0};
    uint8_t date[128] = {0};
    set_slaveid(req, 0x01);
    read_registers(req, 0x0000, 0x0002, date);//03
    for (int i = 0; i < date[8]; i++)
    {
        printf("%02x ", date[9 + i]);
    }
    putchar(10);
    write_coil(req,0x0000,1,date);//05
    printf("seq:%02x\n",date[1]);
    return 0;
}

void set_slaveid(uint8_t *p, uint8_t id)
{
    p[6] = id;
}
void read_registers(uint8_t *p, uint16_t addr, uint16_t num, uint8_t *dest)
{
    p[5] = 0x06;
    p[7] = 0x03;
    p[9] = addr;
    p[8] = addr >> 8;
    p[11] = num;
    p[10] = num >> 8;
    send(sockfd, p, 12, 0);
    recv(sockfd, dest, 128, 0);
}
void write_coil(uint8_t *p, uint16_t addr, int op, uint8_t *dest)
{   
    p[1]=0x01;
    p[5] = 0x06;
    p[7] = 0x05;
    p[9] = addr;
    p[8] = addr >> 8;
    if (op == 1)
    {
        p[10] = 0xFF;
    }
    else
    {
        p[10] = 0x00;
    }
    p[11] = 0x00;
    send(sockfd, p, 12, 0);
    recv(sockfd, dest, 128, 0);
}

今天的分享就到这里结束啦,如果有哪里写的不好的地方,请指正。
如果觉得不错并且对你有帮助的话点个关注支持一下吧!

标签:---,addr,day01,通信协议,uint8,TCP,Modbus,寄存器
From: https://blog.csdn.net/dghbs/article/details/142368016

相关文章

  • day02(网络高级)Modbus RTU
    目录ModbusRTU与ModbusTCP的区别ModbusRTU特点ModbusRTU协议格式模拟器的使用代码实现RTU通信打开模拟的RTU从机linux端使用代码实现和串口连接框架搭建代码ModbusRTU与ModbusTCP的区别在一般工业场景使用modbusRTU的场景还是更多一些,modbusRTU基......
  • Day01-标题、字体、引用、分割线、图片、超链接、列表、表格、代码
    Day01-标题、字体、引用、分割线、图片、超链接、列表、表格、代码标题一级标题:一个井号空格回车二级标题:两个井号空格回车二级标题三级标题:三个井号空格回车三级标题......(最多到6级标题)字体HelloWorld!!!!!!!斜体:字体两......
  • modbus设备数据 转 profinet IO项目案例
    目录1 案例说明 12 VFBOX网关工作原理 13 准备工作 24 设置网关采集MODBUS从站数据 25 用PROFINETIO协议转发数据 86 案例总结 101 案例说明设置网关采集Modbus设备数据把采集的数据转成profinetIO协议转发给其他系统。2 VFBOX网关工作原理VFBOX网关是协议转换网关......
  • day01
    Java第一天的学习笔记第一章:Java概述Java语言简介Java,由JamesGosling在1995年创建,是一种高级的、面向对象的编程语言。Java的设计理念是“一次编写,到处运行”,这得益于其跨平台的特性和Java虚拟机(JVM)的功劳。Java的发展史JamesGosling:Java之父,1995年发布Java。Java版本......
  • Modbus_RTU和Modbus库
    目录一.Modbus_RTU1. 与ModbusTCP的区别2. ModbusRTU特点     3. ModbusRTU协议格式4. 报文详解5. 代码实现RTU通信1. 打开模拟的RTU从机2. linux端使用代码实现和串口连接2.1. 框架搭建      2.2代码二.Modbus库1.库函数一.......
  • Modbus RTU
    一、与ModbusTCP的区别在一般工业场景使用modbusRTU的场景还是更多一些,modbusRTU基于串行协议进行收发数据,包括RS232/485等工业总线协议。与modbusTCP不同的是RTU没有报文头MBAP字段,保留从机地址,在尾部增加了两个CRC检验字节(CRC16),因为网络协议中自带校验,所以在ModbusTC......
  • 正式一刷代码随想录-day01
    数组T35 搜索插入位置1.想清楚边界,是否需要left<=right2.想清楚如果没有找到的几种情况,有没有遗漏的情况。3.此题需要注意返回的不可超过边界值。T34  在排序数组中查找元素的第一个和最后一个位置1.分析题目:三种情况:1.target不在数组大小的范围内2.在范围内但不在数......
  • ModbusTCP报文详解
    ModbusTCP与ModbusRtu(ASCI)数据帧的区别总结:ModbusTCP就是在ModbusRtu(ASCI)基础上去掉CRC,再加上六个0一个6ModbusTCPMBAP报文头域长度描述客户机服务器事务处理标识符2字节Modbus请求/响应事务处理的识别客户机启动服务器从接收的请求中重新复制协议标识符2字节0=M......
  • modbus
    一、起源Modbus由Modicon公司于1979年开发,是一种工业现场总线协议标准。Modbus通信协议具有多个变种,其中有支持串口,以太网多个版本,其中最著名的是ModbusRTU、ModbusASCII和ModbusTCP三种其中ModbusTCP是在施耐德收购Modicon后1997年发布的。二、分类1)ModbusRTU......
  • 基于通信协议与技术架构的API接口分类探讨
    API的全称是“ApplicationProgrammingInterface”,意为“应用程序编程接口”API接口的分类:按照技术分WebAPI:基于Web的API,通过HTTP和HTTPS协议与应用程序交互,如RESTfulAPI和SOAPAPI。云API:用于在云计算环境中管理和操作云服务,例如AmazonWebServicesAPI和MicrosoftA......