搜索
bottom↓
回复: 72
打印 上一主题 下一主题

freemodbus modbus TCP 学习笔记

  [复制链接]

出0入0汤圆

跳转到指定楼层
1
发表于 2014-3-20 22:52:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
1.前言
    使用modbus有些时间了,期间使用过modbus RTU也使用过modbus TCP,通过博文和大家分享一些MODBUS TCP的东西。在嵌入式中实现TCP就需要借助一个以太网协议栈,在这里我选择最简单的uIP协议栈。uIP协议栈简单易用方便上手,相比于LwIP无论是移植还是使用难度都低些,这样就可以把更多的精力花在modbus tcp协议本身而不必花大量的时间研究以太网协议栈。modbus协议栈为freemodbus
    【发表本文主要目的,还文字债


【其他资料】
    【1】uIP学习笔记
    【2】MODBUS协议整理——汇总

【工程代码】
    示例代码托管于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.    
  6.     USHORT usPort;
  7.     if( usTCPPort == 0 )
  8.     {
  9.         usPort = MB_TCP_DEFAULT_PORT;
  10.     }
  11.     else
  12.     {
  13.         usPort = (USHORT)usTCPPort;
  14.     }
  15.    
  16.     // 侦听端口 502端口
  17.     uip_listen(HTONS(usPort));
  18.    
  19.     bOkay = TRUE;
  20.     return bOkay;
  21. }
复制代码


    【代码说明】
    【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.    
  8.     if(uip_closed())
  9.     {
  10.         PRINTF("closed\r\n");
  11.     }
  12.    
  13.     if(uip_newdata())
  14.     {
  15.         PRINTF("request!\r\n");
  16.         // 获得modbus请求
  17.         memcpy(ucTCPRequestFrame, uip_appdata, uip_len );
  18.         ucTCPRequestLen = uip_len;
  19.         // 向 modbus poll发送消息
  20.         xMBPortEventPost( EV_FRAME_RECEIVED );
  21.     }
  22.    
  23.     if(uip_poll())
  24.     {
  25.         if(bFrameSent)
  26.         {
  27.             bFrameSent = FALSE;
  28.             // uIP发送Modbus应答数据包
  29.             uip_send( ucTCPResponseFrame , ucTCPResponseLen );
  30.         }
  31.     }
  32. }
复制代码

    【代码说明】
    【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.    
  7.     /* Reset the buffer. */
  8.     ucTCPRequestLen = 0;
  9.     return TRUE;
  10. }
复制代码

    【代码说明】
    【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.    
  7.     bFrameSent = TRUE; // 通过uip_poll发送数据
  8.     return bFrameSent;
  9. }
复制代码

【代码说明】
【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 抓包分析


5.总结

6.参考资料
基于EncEthernet的FreeModbus-TCP 在stm32上的移植与测试
simple modbus


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

2
发表于 2014-3-20 23:06:48 | 只看该作者
顶一下楼主。

出0入0汤圆

3
发表于 2014-3-20 23:31:47 | 只看该作者
好东西必须支持

出0入0汤圆

4
发表于 2014-3-21 07:56:14 来自手机 | 只看该作者
楼主,这么好帖,让大家都看到。

出10入0汤圆

5
发表于 2014-3-21 08:09:16 | 只看该作者
mark
最近在学这个
板凳学习

出0入0汤圆

6
发表于 2014-3-21 08:10:01 | 只看该作者
好东西,顶楼主

出0入4汤圆

7
发表于 2014-3-21 08:16:53 | 只看该作者
看起来很牛x,留个脚印先

出0入0汤圆

8
发表于 2014-3-25 09:58:28 | 只看该作者
好资料,最近也在学习Modbus-TCP的实现。

出0入0汤圆

9
发表于 2014-3-25 14:50:04 | 只看该作者
好东西啊,学习!!!!

出0入12汤圆

10
发表于 2014-3-26 10:34:29 | 只看该作者
怎么区分主机的命令还是从机的响应?

出0入0汤圆

11
发表于 2014-3-27 14:07:31 | 只看该作者
谢谢楼主分享。

出0入0汤圆

12
发表于 2014-3-27 14:08:34 | 只看该作者
卧槽,又更新了,屌炸天了!

出0入0汤圆

13
 楼主| 发表于 2014-3-28 14:07:37 | 只看该作者
waterx3 发表于 2014-3-26 10:34
怎么区分主机的命令还是从机的响应?

您的问题,我没有理解??

出0入12汤圆

14
发表于 2014-3-28 14:23:34 | 只看该作者
modbus发送和接收都带着功能号,怎么能知道数据帧是命令还是从机响应?

出0入0汤圆

15
发表于 2014-3-28 22:30:08 来自手机 | 只看该作者
谢谢楼主无私分享。太牛了

出0入0汤圆

16
发表于 2014-4-2 12:16:58 | 只看该作者
无私的楼主 感谢

出0入0汤圆

17
发表于 2014-4-2 13:38:57 | 只看该作者
这个必须要顶!

出0入0汤圆

18
发表于 2014-4-3 16:11:54 | 只看该作者
好帖子

出0入0汤圆

19
发表于 2014-4-3 18:56:38 | 只看该作者
不错,力作.......

出0入16汤圆

20
发表于 2014-4-3 19:55:00 | 只看该作者
MODBUS差不多是最为简单的通讯协议了,格式固定,命令也就那么几个。觉得协议栈复杂完全可以自己写代码实现。
我当年就是自己手敲的代码写了MODBUS的TCP和RTU的接口协议,主要麻烦的是几百个寄存器的读写操作实现。

出0入0汤圆

21
发表于 2014-4-4 10:33:26 | 只看该作者
问一个问题,一个工程中 既要用到modbus tcp 也要用到 modbus rtu,可以实现吗?比如一个典型应用,rtu与hmi连接,tcp与pc连接,谢谢。

出0入0汤圆

22
 楼主| 发表于 2014-4-4 13:51:40 | 只看该作者
icemagicisme 发表于 2014-4-4 10:33
问一个问题,一个工程中 既要用到modbus tcp 也要用到 modbus rtu,可以实现吗?比如一个典型应用,rtu与hm ...

如果使用STM32我看实现起来比较困难,但是使用linux的话实现起来非常简单。
可能刚开始熟悉linux需要些时间,但是过了这个阶段就好了!

如果你不嫌弃,看看这个

树莓派学习笔记——实现modbus RTU从机
MODBUS学习笔记——modbus tk modbus TCP主机实现

出0入0汤圆

23
发表于 2014-4-5 10:20:14 | 只看该作者
价值好帖!

出0入0汤圆

24
发表于 2014-4-30 15:32:10 | 只看该作者
Lz看过你的帖子,我刚刚接触modbus,我想请教一下,modbus能不能在单片机之间传大量的数据(不是操作寄存器,io口什么的),怎么没看到传输数据的功能码??

出0入0汤圆

25
发表于 2014-5-1 21:03:30 | 只看该作者
这个必须得顶

出0入0汤圆

26
发表于 2014-5-2 02:11:13 | 只看该作者
先定了 再说。。。

出0入0汤圆

27
 楼主| 发表于 2014-5-2 23:56:09 | 只看该作者
良马一号 发表于 2014-4-30 15:32
Lz看过你的帖子,我刚刚接触modbus,我想请教一下,modbus能不能在单片机之间传大量的数据(不是操作寄存器 ...

modbus不适合传输大数据量内容!如果需要传输大数据量内容,请参考其他协议。
如果是linux系统的话,FTP就可以了,简单方便容易实现。

出0入0汤圆

28
发表于 2014-5-3 08:35:12 | 只看该作者
收藏了   

出50入0汤圆

29
发表于 2014-5-3 10:25:53 | 只看该作者
谢谢分享,、、、、

出0入0汤圆

30
发表于 2014-5-14 21:01:49 | 只看该作者
又看到楼主大作了,楼主的RTU还没看懂,TCP就来了!

出0入0汤圆

31
 楼主| 发表于 2014-5-19 08:31:40 | 只看该作者
larry.wong 发表于 2014-5-14 21:01
又看到楼主大作了,楼主的RTU还没看懂,TCP就来了!

称不上大作,简单的一个例子!

出0入0汤圆

32
发表于 2014-5-19 08:41:32 | 只看该作者
感谢楼主分享经验,

出0入0汤圆

33
发表于 2014-5-19 08:56:19 来自手机 | 只看该作者
楼主威武,楼主好人

出0入0汤圆

34
发表于 2014-5-21 13:49:01 | 只看该作者
收藏先,三克LZ

出0入0汤圆

35
发表于 2014-5-21 15:48:58 | 只看该作者
非常感谢无私的分享

出0入0汤圆

36
发表于 2014-6-4 11:12:39 | 只看该作者
楼主,能不能贴一下,ModbuBus TCP 的源码,谢谢。

出0入0汤圆

37
 楼主| 发表于 2014-6-11 12:44:05 | 只看该作者
A644072458 发表于 2014-6-4 11:12
楼主,能不能贴一下,ModbuBus TCP 的源码,谢谢。

请到Github上clone或者下载zip包!
这样的方式可能你没用过,不过慢慢会习惯的!

出0入0汤圆

38
发表于 2014-6-11 19:34:24 | 只看该作者
mark,正好在找这个东西。顶!

出0入0汤圆

39
发表于 2014-6-12 09:31:10 | 只看该作者
mark freemodbus modbus TCP 学习笔记

出0入0汤圆

40
发表于 2014-6-20 17:32:02 | 只看该作者
楼主什么时候能分享一下程序,期待中。。。

出0入0汤圆

41
发表于 2014-6-21 10:31:30 | 只看该作者
感觉TCP/IP协议的什么东西都好难的样子

出0入0汤圆

42
 楼主| 发表于 2014-6-26 19:52:38 | 只看该作者
yzb1019 发表于 2014-6-21 10:31
感觉TCP/IP协议的什么东西都好难的样子

网络非常好用也很有用,并且modbus tcp比modbus RTU简单。

出0入0汤圆

43
发表于 2014-7-7 17:20:18 | 只看该作者
  报告版主,该文得置酷。

自从学习了楼主移植FreeModbus教程,现在自己学着移植到PIC的MCU上,替换掉自己写的MODBUS,再也不丢帧了。跟着也学习了源码的编程思路。用起来爽爽的

出0入0汤圆

44
发表于 2014-7-7 21:10:22 | 只看该作者
占座留名,以备后用

出0入0汤圆

45
发表于 2014-7-31 16:15:40 | 只看该作者
请教,MODBUS TCP连接多从机的时候实时性如何,从机数量大于50?

出0入0汤圆

46
 楼主| 发表于 2014-8-1 08:41:02 | 只看该作者
Myheartisbroken 发表于 2014-7-31 16:15
请教,MODBUS TCP连接多从机的时候实时性如何,从机数量大于50?

如果是uIP+STM32的话。同时接入50个从机,从我个人的认知范围来说是很难实现的。

我建议,linux系统,至少128M内存。保守些,一个从机占用2M 内存高,50个消耗100M,还有可怜的28M留给内核。

出0入0汤圆

47
发表于 2014-8-1 13:07:28 | 只看该作者
支持下楼主的好文

出5入42汤圆

48
发表于 2014-8-7 15:00:11 | 只看该作者
请教楼主,我现在也要移植MODBUS TCP,看了一些文档,确定要使用到porttcp.c这个文件,但是下载的freemodbus代码包里面没有该文件。请问这是为何?

出0入0汤圆

49
发表于 2014-8-7 15:27:35 | 只看该作者

出0入0汤圆

50
发表于 2014-11-27 04:08:32 | 只看该作者
支持下楼主的好文!!!

出0入0汤圆

51
发表于 2014-11-30 06:29:25 | 只看该作者
楼主的MODBUS RTU程序,我在STM32和STC单片机上均移植成功了,最近在调试MODBUS TCP的移植,感谢楼主1

出0入0汤圆

52
发表于 2014-12-1 10:51:52 | 只看该作者
楼主好厉害,!!!

出0入0汤圆

53
发表于 2014-12-1 10:58:09 | 只看该作者
感谢分享!

出0入0汤圆

54
发表于 2014-12-29 21:28:18 | 只看该作者
楼主好强大,有没有lwip modbus的哪,拜谢

出0入0汤圆

55
发表于 2015-2-6 13:48:35 | 只看该作者
感谢分享!

出0入0汤圆

56
发表于 2015-2-6 14:59:10 | 只看该作者
感谢楼主。

出0入0汤圆

57
发表于 2015-3-3 11:53:26 | 只看该作者
你好前辈!问个modbus RTU中保持寄存器的问题,当主机间隔一秒一次读取从机的保持寄存器地址0-9的10个数据时,当主机一来读取时而我这时只更新了前5个新数据,这时后面的5个还是旧的历史数据。而这10个数据是一个联合数据,必须整体判断执行的结果。我想了,从机要是关中断后再去一次刷新10个值也不可行,因为这时主机有可能正在读取数据,并读取了一部分。请问有没有好的办法保证数据的完整性?谢谢!

出0入0汤圆

58
发表于 2015-3-3 13:23:47 | 只看该作者
modules RTU还是很不错,现在看看TCP协议

出0入0汤圆

59
 楼主| 发表于 2015-3-5 11:13:00 | 只看该作者
whm_WUHAN 发表于 2015-3-3 13:23
modules RTU还是很不错,现在看看TCP协议

我觉得modbus tcp更好用一点

出0入0汤圆

60
发表于 2015-3-5 12:11:34 | 只看该作者
MARK   。。。

出0入0汤圆

61
发表于 2015-6-27 17:30:46 | 只看该作者
Modbus的从机是TCP的服务器。STM32是工作在TCP服务器模式和Modbus的从机模式。

出0入0汤圆

62
发表于 2015-12-9 15:25:27 | 只看该作者
本帖最后由 szszjdb 于 2015-12-9 15:37 编辑
xukai871105 发表于 2015-3-5 11:13
我觉得modbus tcp更好用一点


多谢楼主,GIT上的代码好像无法下载了,能否请楼主放到AMO上来?或者EMAI : 13603052469@139.com, 多谢!

出0入0汤圆

63
发表于 2017-1-10 21:00:02 | 只看该作者
MARK,MODBUS-TCP

出0入0汤圆

64
发表于 2017-1-10 21:14:22 | 只看该作者
freemodbus modbus TCP  mark

出0入0汤圆

65
发表于 2017-1-11 10:51:11 | 只看该作者
总结得非常好,收藏备用~~~~~~~~~~~~~~~

出0入0汤圆

66
发表于 2017-1-11 11:17:43 | 只看该作者
非常完整,lz用心了

出0入24汤圆

67
发表于 2017-1-11 14:42:29 | 只看该作者
Mark!最近在做tcp modbus,学习,谢谢楼主!

出0入0汤圆

68
发表于 2017-1-11 20:27:41 | 只看该作者
MARK,MODBUS-TCP

出0入0汤圆

69
发表于 2017-1-12 10:46:10 | 只看该作者
学习学习

出0入0汤圆

70
发表于 2017-9-21 18:45:15 | 只看该作者
MARK  嗯嗯 嗯嗯

出0入0汤圆

71
发表于 2017-10-6 18:55:55 | 只看该作者
真是厉害,下过来学习

出0入0汤圆

72
发表于 2022-7-27 22:50:39 | 只看该作者
谢谢,学习一下
最近研究arduino modbus

出0入0汤圆

73
发表于 2022-7-28 09:23:47 | 只看该作者
楼主强大 是否有试过用这个显示出Camera画面? 只显示一张图也行?
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-26 15:53

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表