1.前言
    使用modbus有些时间了,期间使用过modbus RTU也使用过modbus TCP,通过博文和大家分享一些MODBUS TCP的东西。在嵌入式中实现TCP就需要借助一个以太网协议栈,在这里我选择最简单的uIP协议栈。uIP协议栈简单易用方便上手,相比于LwIP无论是移植还是使用难度都低些,这样就可以把更多的精力花在modbus tcp协议本身而不必花大量的时间研究以太网协议栈。modbus协议栈为freemodbus
 
【其他有用的博文】
    【1】uIP学习笔记
 
【工程代码】
    示例代码托管于GitHub——【Github Clone
    如果有问题我会及时更新。
【使用说明】
    【1】工具链为IAR 6.5
    【2】从机IP为固定IP 192.168.1.15,请保证从机和路由器位于同一个网段中。
    【3】modbus tcp的侦听端口号为502
 
2.MODBUS TCP注意点
2.1 主机和从机、服务端和客户端
图1 MODBUS请求响应模型
【在modbus协议中】
主机发送modbus请求,从机根据请求内容向主机返回响应。在modbus协议中,主机总是主动方,从机总是被动方。
【在网络应用中】
在网络应用中存在客户端和服务器端,客户端(例如浏览器)发送请求到服务器,服务器向客户端返回内容(例如HTML文本)。
【在modbus tcp中】
主机是客户端,而从机是服务器端。千万不要以为服务器端重要,主机也重要,所以主机就是服务器端。
 
2.2 是否可以多主机
    通过前面的分析,主机为客户端那么modbus tcp支持多个主机,在一个局域网中可存在多个主机和多个从机。从机的连接能力(连接主机的数量)由uIP的最大TCP连接个数决定。
 
2.3 modbus TCP协议简述
modbus TCP和modbus RTU基本相同,但是也存在一些区别
    【1】从机地址变得不再重要,多数情况下忽略。从某种意义上说从机地址被IP地址取代
    【2】CRC校验变得不再重要,甚至可以忽略。由于TCP数据包中已经存在校验,为了不重复造轮子,modbus TCP干脆取消了CRC校验。
 
modbus TCP和modbus RTU的区别可使用下图概括
图2 modbus TCP数据包和modbus RTU数据包比较
 
在modbus TCP中包含一个MBAP头,该头包含以下几个部分
区域
长度
描述
客户端
服务器
传输标志
2字节
MODBUS 请求和响应传输过程中
序列号
客户端生成
应答时复制该值
协议标志
2字节
Modbus协议默认为0
客户端生成
应答时复制该值
长度
2字节
剩余部分的长度
客户端生成
应答时由服务器端生成
单元标志
1字节
从机标志(从机地址)
客户端生成
应答时复制该值

【注意】

【1】传输标志可理解为序列号,防止MODBUS TCP通信错位,例如后发生的响应先到了主机,而早发生的响应后到主机
【2】单元标志可理解为从机地址,此时已经不再重要
 
2.4 modbus tcp 和 TCP IP的关系
    modbus TCP可以理解为发生在TCP上的应用层协议,既然是TCP协议那么一个完整的MODBUS TCP报文必然包括TCP首部,IP首部和Ethernet首部。
    下面就通过uIP协议栈来实现modbus TCP
 
3.代码实现
3.1 侦听502端口
  1. BOOL
  2. xMBTCPPortInit( USHORT usTCPPort )
  3. {
  4. BOOL bOkay = FALSE;
  5. USHORT usPort;
  6. if( usTCPPort == 0 )
  7. {
  8. usPort = MB_TCP_DEFAULT_PORT;
  9. }
  10. else
  11. {
  12. usPort = (USHORT)usTCPPort;
  13. }
  14. // 侦听端口 502端口
  15. uip_listen(HTONS(usPort));
  16. bOkay = TRUE;
  17. return bOkay;
  18. }
    【代码说明】
    【1】uip_listen(HTONS(usPort)) 侦听502端口,注意大小端变化。
 
3.2 uIP循环处理——porttcp.c
  1. void uip_modbus_appcall(void)
  2. {
  3. if(uip_connected())
  4. {
  5. PRINTF("connected!\r\n");
  6. }
  7. if(uip_closed())
  8. {
  9. PRINTF("closed\r\n");
  10. }
  11. if(uip_newdata())
  12. {
  13. PRINTF("request!\r\n");
  14. // 获得modbus请求
  15. memcpy(ucTCPRequestFrame, uip_appdata, uip_len );
  16. ucTCPRequestLen = uip_len;
  17. // 向 modbus poll发送消息
  18. xMBPortEventPost( EV_FRAME_RECEIVED );
  19. }
  20. if(uip_poll())
  21. {
  22. if(bFrameSent)
  23. {
  24. bFrameSent = FALSE;
  25. // uIP发送Modbus应答数据包
  26. uip_send( ucTCPResponseFrame , ucTCPResponseLen );
  27. }
  28. }
  29. }
    【代码说明】
    【1】uip_newdata()返回为True表示存在新的数据
    【2】复制uip_appdate中的数据到ucTCPRequestFrame,该变量为全局变量,通过该全部变量”中转“到modbus处理的缓冲区中。然后向modbus协议栈发送消息,消息内容为EV_FRAME_RECEIVED 。由于没有使用操作系统
    【3】如果处理完成则通过uip_send发送响应。
    【4】ucTCPRequestFrame和ucTCPResponseFrame均为全局数组,用于和modbus缓冲区交换数据。
static UCHAR ucTCPRequestFrame[MB_TCP_BUF_SIZE];
static USHORT ucTCPRequestLen;
static UCHAR ucTCPResponseFrame[MB_TCP_BUF_SIZE];
static USHORT ucTCPResponseLen;
 
3.3 modbus 接收处理
  1. BOOL
  2. xMBTCPPortGetRequest( UCHAR ** ppucMBTCPFrame, USHORT * usTCPLength )
  3. {
  4. *ppucMBTCPFrame = &ucTCPRequestFrame[0];
  5. *usTCPLength = ucTCPRequestLen;
  6. /* Reset the buffer. */
  7. ucTCPRequestLen = 0;
  8. return TRUE;
  9. }
    【代码说明】
    【1】** ppucMBTCPFrame为一个指向数据的指针,而*ppucMBTCPFrame可以指向一个数组,在这里可把ucTCPRequestFrame复制给该变量,配合usTCPLength,那么从uIP接收到的内容就”转移“到freemodbus中。
 
3.4 modbus 发送处理
  1. BOOL
  2. xMBTCPPortSendResponse( const UCHAR * pucMBTCPFrame, USHORT usTCPLength )
  3. {
  4. memcpy( ucTCPResponseFrame , pucMBTCPFrame , usTCPLength);
  5. ucTCPResponseLen = usTCPLength;
  6. bFrameSent = TRUE; // 通过uip_poll发送数据
  7. return bFrameSent;
  8. }
【代码说明】
【1】把传入的内容 pucMBTCPFrame复制给ucTCPResponseFrame,并设置bFrameSent为True,那么在下一次uip_poll时便会把响应发送会主机。
 
4.测试与分析
    【1】连接从机
    选择IP地址为192.168.1.15,端口号为502
图3 打开modbus tcp连接
    【2】尝试读出保持寄存器
图4 读取保持寄存器
    【3】抓包分析
    请使用ip.addr == 192.168.1.15 表达式过滤报文,其中192.168.1.100为PC机,此处为modbus 主机
    【简单分析】
    【1】115行为modbus主机请求,此时传输标志为25.
    【2】116行为modbus从机给出的TCP应答,TCP应答为TCP协议规定的内容,TCP应答中不包含modbus 响应
    【3】117行为modbus从机响应,此时传输标志依然为25.
    【4】118行为modbus主机 TCP应答,同16行。
图5 抓包分析
转摘:http://blog.csdn.net/xukai871105/article/details/21652287

freemodbus modbus TCP 学习笔记的更多相关文章

  1. 毕向东tcp学习笔记1

    项目功能: 实现一次发送和接收,服务器接收客户端发送的内容并打印出来 用最通俗的语言讲解下,上图中大椭圆是服务器,A.C是客户端,当客户端和服务器通过socket建立连接后 1.两者之间形成一个通道, ...

  2. [原创]Modbus协议学习笔记

    一.参考资料 1.老罗传奇的2篇博文,写的不错,通俗易懂.链接地址为:http://www.cnblogs.com/luomingui/tag/Modbus/ 2.阿莫论坛精华资料:http://ww ...

  3. Modbus协议学习笔记

    之前也有写过基于 Modbus 通讯协议的控制远程监控程序,但是由于当时时间赶.人手少(软硬件前后台都是在下一人

  4. TCP学习笔记

    TCP/IP 协议分层模型 TCP/IP 协议族按层次分别分为以下 4 层:应用层.传输层.网络层和数据链路层.层次化之后,每个层级只需要考虑自己的任务就可以了,不再需要弄清其他层级的功能了. TCP ...

  5. EasyARM i.mx287学习笔记——通过modbus tcp控制GPIO

    0 前言     本文使用freemodbus协议栈,在EasyARM i.mx287上实现了modbus tcp从机. 在该从机中定义了线圈寄存器.当中线圈寄存器地址较低的4位和EasyARM的P2 ...

  6. uIP学习笔记

    uIP学习笔记 从零开始使用uIP freemodbus modbus TCP 学习笔记

  7. C#ModBus Tcp的学习及Master的实现

    Modbus已经成为工业领域通信协议的业界标准(De facto),并且现在是工业电子设备之间常用的连接方式. 所以这也是我们工控领域软件开发的所必懂的通讯协议,我也是初次学习,先贴上我的学习笔记 一 ...

  8. TCP/IP详解学习笔记

    TCP/IP详解学习笔记(1)-基本概念 TCP/IP详解学习笔记(2)-数据链路层 TCP/IP详解学习笔记(3)-IP协议,ARP协议,RARP协议 TCP/IP详解学习笔记(4)-ICMP协议, ...

  9. TCP/IP协议学习笔记

    计算机网络基础知识复习汇总:计算机网络基础知识复习 HTTP协议的解析:剖析 HTTP 协议 一个系列的解析文章: TCP/IP详解学习笔记(1)-- 概述 TCP/IP详解学习笔记(2)-- 数据链 ...

随机推荐

  1. mysql-5.7.17的最新安装教程

    mysql-5.7.17-winx64是现在最新版本的Mysql,这是免安装的,所以要进行些配置 下载地址:https://cdn.mysql.com//Downloads/MySQL-5.7/mys ...

  2. 自定义音频条形图--p52

    package com.zzw.qunyingzhuan2; import android.content.Context; import android.graphics.Canvas; impor ...

  3. Node.js/Python爬取网上漫画

    某个周日晚上偶然发现了<火星异种>这部漫画,便在网上在线看了起来.在看的过程中图片加载很慢,而且有时候还不小心点到广告,大大延缓了我看的进度.后来想到能不能把先把漫画全部抓取到本地再去看. ...

  4. 条款5.了解c++默默编写并且调用了哪些函数。

    如果想在一个内含reference成员的class内支持赋值操作,必须自己定义copy assignment操作符.而且面对“内含有const成员的”class,编译器的反应也是相同的,由于更改con ...

  5. jsp中解决乱码问题

    解决中文乱码 a) 第一种: String name=new String(name.getBytes("ISO-8859-1"),"UTF-8"); b) 第 ...

  6. js类 的小例子

    class Flyer { constructor(fname, speed) { this.fname = fname; this.speed = speed; } fly(){ console.l ...

  7. 从无到有开发自己的Wordpress博客主题---创建主题

    上一篇教程,我们已经安装了Wordpress,我们可以成功的登录到Wordpress后台,接下来的任务就是创建我们自己的主题. 要想创建一个Wordpress主题,就必须按照Wordpress的规则, ...

  8. 年终盘点:Java今年的大事记都在这里!

    在2017年即将结束之际,我们最好停下脚步来看看过去十二个月Java的发展情况.本文,笔者盘点了IT168企业级一年来对Java的跟踪报道. 这一年对Java来说是不容易的,从Java 9一再延期备受 ...

  9. python3 selenium 安装以及验证

    1. 相关链接 官方网站:http://www.seleniumhq.org GitHub:https://github.com/SeleniumHQ/selenium/tree/master/py ...

  10. 20165222《Java程序设计》——实验二 面向对象程序设计

    20165222<Java程序设计>——实验二 面向对象程序设计 提交点一.JUnit测试用例 知识点:这里就是了解测试代码的应用,测试代码的书写为:@Test assertEquals( ...