一、设计思想

  任何通信协议的实现都是基于状态机的设计思想,就是来了一串数据判断是是干啥的在调用相应的处理函数只不过高手一般采用回调处理。

  • 如果你熟悉了回调、源码里的状态机的实现又可以理解,那么恭喜你已经掌握了通信协议的实现方法。
  •   如果你可以从源妈里体会到分层的设计思想,那么恭喜你已经触碰到了架构师的门槛。

  本系列文章就是通过对FreeModeBus源码进行解析来掌握以上技能。

二、ModBus协议简介以及状态机的实现

  为啥把ModBus协议简介与状态机的实现放在一起呢??? 

  状态机编写当然是基于通信协议标准。

  如果通信数据格式、功能码、处理流程都搞不清楚,你编出来的状态机也是你“个人版的通信协议标准”,与符合ModBus通信协议标准的设备也是通信不上的。

1、  ModBus  设备间通信处理流程如下:

  •   主设备向从设备发送请求
  •   从设备分析并处理主设备的请求,然后向主设备发送结果
  •   如果出现任何差错,从设备将返回一个异常功能码

这里不对ModBus协议进行过多介绍,网上有很多资料。但有个疑点还是有必要搞清楚。在ModbusTCP里什么是主站(主设备)?什么是从站(从设备)??

我相信会有人不假思索地说主站不就是服务器,从站不就是客户端码???

 哈哈,如果你仔细读了  ModBus  设备间通信处理流程的话,你可以搞懂的。俺老李就不老生常谈了。

2、状态机的实现解析

  首先从网上下载modbus协议源码文件,打开文件夹如下:

  

首先使用Source Insight编辑器打开mb.c文件(一般重要的文件放在工程的根目录下相相当于main函数,这个和人类的编程习惯有关)。

   打开之后。嗯分析文件之前先说下状态机,状态机的运行是要轮询poll是否建立modbus通信、判断通信数据是接收请求还是请求响应。

注意关键字poll在编辑器的左下角找到带有poll的函数。

就是eMBPoll函数,这里面就有实现设备间Modbus通信状态机源代码以及相应的简单注释如下所示:

   /* Check if the protocol stack is ready. */
//判断协议栈硬件环境有没有准备。好比如ModBusTCP协议里基于W5500以太网芯片的初始化,sockt通信建立提供TCP服务。
if( eMBState != STATE_ENABLED )
{
return MB_EILLSTATE;
} /* Check if there is a event available. If not return control to caller.
* Otherwise we will handle the event. */
    //通过xMBPortEventGet函数处理如果有事件发生得到状态机的状态值并赋值给eEvent,
    //然后通过switch语句运行状态机调用相应函数进行处理,当然这里用了函数指针、回调。
if( xMBPortEventGet( &eEvent ) == TRUE )
{
      //
switch ( eEvent )
{
case EV_READY:
break; case EV_FRAME_RECEIVED:
eStatus = peMBFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength );
if( eStatus == MB_ENOERR )
{
/* Check if the frame is for us. If not ignore the frame. */
if( ( ucRcvAddress == ucMBAddress ) || ( ucRcvAddress == MB_ADDRESS_BROADCAST ) )
{
( void )xMBPortEventPost( EV_EXECUTE );
}
}
break; case EV_EXECUTE:
ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF];
eException = MB_EX_ILLEGAL_FUNCTION;
for( i = ; i < MB_FUNC_HANDLERS_MAX; i++ )
{
/* No more function handlers registered. Abort. */
if( xFuncHandlers[i].ucFunctionCode == )
{
break;
}
else if( xFuncHandlers[i].ucFunctionCode == ucFunctionCode )
{
eException = xFuncHandlers[i].pxHandler( ucMBFrame, &usLength );
break;
}
} /* If the request was not sent to the broadcast address we
* return a reply. */
if( ucRcvAddress != MB_ADDRESS_BROADCAST )
{
if( eException != MB_EX_NONE )
{
/* An exception occured. Build an error frame. */
usLength = ;
ucMBFrame[usLength++] = ( UCHAR )( ucFunctionCode | MB_FUNC_ERROR );
ucMBFrame[usLength++] = eException;
}
if( ( eMBCurrentMode == MB_ASCII ) && MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS )
{
vMBPortTimersDelay( MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS );
}
eStatus = peMBFrameSendCur( ucMBAddress, ucMBFrame, usLength );
}
break; case EV_FRAME_SENT:
break;
}
}

从程序源码里面解析框架图如下:

大家可以根据上图理解状态机的结构框架,本文解析到此结束。关于相关在状态机里面怎么回调相关处理函数的下章解析。

FreeModBus源码解析(1)---开篇的更多相关文章

  1. SuperSocket源码解析之开篇

    一 简介 官方介绍:SuperSocket 是一个轻量级, 跨平台而且可扩展的 .Net/Mono Socket 服务器程序框架.你无须了解如何使用 Socket, 如何维护 Socket 连接和 S ...

  2. SuperSocket源码解析之开篇 (转)

    一 简介 官方介绍:SuperSocket 是一个轻量级, 跨平台而且可扩展的 .Net/Mono Socket 服务器程序框架.你无须了解如何使用 Socket, 如何维护 Socket 连接和 S ...

  3. Spring源码解析系列汇总

    相信我,你会收藏这篇文章的 本篇文章是这段时间撸出来的Spring源码解析系列文章的汇总,总共包含以下专题.喜欢的同学可以收藏起来以备不时之需 SpringIOC源码解析(上) 本篇文章搭建了IOC源 ...

  4. Maven 依赖调解源码解析(一):开篇

    本文是系列文章<Maven 源码解析:依赖调解是如何实现的?>第一篇,主要做个开头介绍.并为后续的实验做一些准备.系列文章总目录参见:https://www.cnblogs.com/xia ...

  5. jQuery整体架构源码解析(转载)

    jQuery整体架构源码解析 最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性, ...

  6. 给jdk写注释系列之jdk1.6容器(5)-LinkedHashMap源码解析

    前面分析了HashMap的实现,我们知道其底层数据存储是一个hash表(数组+单向链表).接下来我们看一下另一个LinkedHashMap,它是HashMap的一个子类,他在HashMap的基础上维持 ...

  7. jQuery整体架构源码解析

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  8. 顺序线性表 ---- ArrayList 源码解析及实现原理分析

    原创播客,如需转载请注明出处.原文地址:http://www.cnblogs.com/crawl/p/7738888.html ------------------------------------ ...

  9. .NET Core实战项目之CMS 第三章 入门篇-源码解析配置文件及依赖注入

    作者:依乐祝 原文链接:https://www.cnblogs.com/yilezhu/p/9998021.html 写在前面 上篇文章我给大家讲解了ASP.NET Core的概念及为什么使用它,接着 ...

随机推荐

  1. Normally Distributed|

    6.1Introducing Normally Distributed Variables Why the word “normal”? Because, in the last half of th ...

  2. Helvetic Coding Contest 2019 差A3 C3 D2 X1 X2

    Helvetic Coding Contest 2019 A2 题意:给一个长度为 n 的01序列 y.认为 k 合法当且仅当存在一个长度为 n 的01序列 x,使得 x 异或 x 循环右移 k 位的 ...

  3. 网页元素检测工具:Spy_for_InternetExplorer下载地址

    本工具用于实时查看IE浏览器中打开的网页中元素的信息.支持iframe.frame框架. 下载地址: Spy_for_InternetExplorer.rar

  4. Springmvc多视图

    Springmvc多视图 多视图是一个方法可以返回json/xml等格式的数据 第一步:导入xml格式支持的jar包 spring-oxm-3.2.0.RC2.jar 第二步:配置支持多视图 < ...

  5. kettle的基本使用

    一.下载下载kettlehttp://sourceforge.net/projects/pentaho/files/Data%20Integration/7.0/pdi-ce-7.0.0.0-25.z ...

  6. html5页面编码如何确定

    页面乱码问题建站学之前曾经多次发教程说明,对于新的html5来说我们的编码要如何做才能解决乱码问题呢?作为一个前端工程师,你是如何指定一个页面的编码的呢?你知道浏览器是怎么识别编码的吗? 首先,一个很 ...

  7. XGBoost使用篇(未完成)

    1.截止到本文(20191104)sklearn没有集成xgboost算法,需要单独安装xgboost库,然后导入使用 xgboost官网安装说明 Pre-built binary wheel for ...

  8. 高可用(keepalived+lvs)

    博主本人平和谦逊,热爱学习,读者阅读过程中发现错误的地方,请帮忙指出,感激不尽 架构图: 本次实验严格按照下图完成 1.系统环境设置 1.1SELinux设置 vim /etc/selinux/con ...

  9. sqlserver多表联查分页

    select * from(select H_order.Id ,H_order.userID, ROW_NUMBER() over (order by H_order.Id Desc) as row ...

  10. 为什么前两年大热的VR创业突然冷了?

    不得不说,如果不是<头号玩家>在国内的热映,人们似乎都要忘记VR这个行业了.<头号玩家>中那些带有极强真实色彩的游戏,其实就是VR进化的目标,甚至是巅峰!而里面的角色佩戴的设备 ...