FreeModBus源码解析(1)---开篇
一、设计思想
任何通信协议的实现都是基于状态机的设计思想,就是来了一串数据判断是是干啥的在调用相应的处理函数只不过高手一般采用回调处理。
- 如果你熟悉了回调、源码里的状态机的实现又可以理解,那么恭喜你已经掌握了通信协议的实现方法。
- 如果你可以从源妈里体会到分层的设计思想,那么恭喜你已经触碰到了架构师的门槛。
本系列文章就是通过对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)---开篇的更多相关文章
- SuperSocket源码解析之开篇
一 简介 官方介绍:SuperSocket 是一个轻量级, 跨平台而且可扩展的 .Net/Mono Socket 服务器程序框架.你无须了解如何使用 Socket, 如何维护 Socket 连接和 S ...
- SuperSocket源码解析之开篇 (转)
一 简介 官方介绍:SuperSocket 是一个轻量级, 跨平台而且可扩展的 .Net/Mono Socket 服务器程序框架.你无须了解如何使用 Socket, 如何维护 Socket 连接和 S ...
- Spring源码解析系列汇总
相信我,你会收藏这篇文章的 本篇文章是这段时间撸出来的Spring源码解析系列文章的汇总,总共包含以下专题.喜欢的同学可以收藏起来以备不时之需 SpringIOC源码解析(上) 本篇文章搭建了IOC源 ...
- Maven 依赖调解源码解析(一):开篇
本文是系列文章<Maven 源码解析:依赖调解是如何实现的?>第一篇,主要做个开头介绍.并为后续的实验做一些准备.系列文章总目录参见:https://www.cnblogs.com/xia ...
- jQuery整体架构源码解析(转载)
jQuery整体架构源码解析 最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性, ...
- 给jdk写注释系列之jdk1.6容器(5)-LinkedHashMap源码解析
前面分析了HashMap的实现,我们知道其底层数据存储是一个hash表(数组+单向链表).接下来我们看一下另一个LinkedHashMap,它是HashMap的一个子类,他在HashMap的基础上维持 ...
- jQuery整体架构源码解析
最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...
- 顺序线性表 ---- ArrayList 源码解析及实现原理分析
原创播客,如需转载请注明出处.原文地址:http://www.cnblogs.com/crawl/p/7738888.html ------------------------------------ ...
- .NET Core实战项目之CMS 第三章 入门篇-源码解析配置文件及依赖注入
作者:依乐祝 原文链接:https://www.cnblogs.com/yilezhu/p/9998021.html 写在前面 上篇文章我给大家讲解了ASP.NET Core的概念及为什么使用它,接着 ...
随机推荐
- 腾讯云 Serverless 首发 1ms 计费粒度,立省 70% 费用
云函数 SCF 采用按需付费的方式,并首次发布 1ms 计费粒度,真正实现按使用多少计算能力来计费. 云函数(Serverless Cloud Function,SCF)是腾讯云为企业和开发者们提供的 ...
- html为什么用雪碧图的优缺点
CSS Sprite(雪碧图/精灵图) 1 概念解释 将小图标和背景图像合并到一张图片上,然后利用css的背景/定位来显示需要显示的图片部分. 2 优点 ① 减少 ...
- 01-电子商城项目介绍及ssm框架搭建
1.B2C电商项目功能及架构 1.1功能列表 1.2系统架构(soa架构) 2.后台管理系统工程搭建及测试 ypMall,ypMall-manager-web ypMall为父项目,管理子项目的jar ...
- Glob模块使用笔记
一.Glob模块介绍 python中的glob模块用于查找文件目录和文件,并返回一个list.常用的方法有glob.glob()和glob.iglob().与os.listdir()都是查找文件,但有 ...
- python学习笔记(24)-类与对象
#类与对象 #python类的语法 关键字 class #class 类名 类名的规范是:数字字母下划线组成,不能以数字开头 首字母大写 驼峰命名 #类属性 放在类里面的变量值 #类方法 放在类里面的 ...
- 网站TDK三大标签SEO优化
SEO(Search Engine Optimization)汉译为搜索引擎优化,是一种利用搜索引擎的规则提高网站在有关搜索 引擎内自然排名的方式. SEO 的目的是对网站进行深度的优化,从而帮助网站 ...
- 非IoC方式访问Servlet API的两种方法
使用ActionContext访问 ActionContext来自com.opensymphony.xwork2.ActionContext 具体实现代码段如下: <span style=&qu ...
- 吴裕雄--天生自然python学习笔记:python文档操作插入图片
向 Word 文件中插入图片 向 Word 文件插入图片的语法为: 例如,在 cl ip graph.docx 文件的第 4 段插入 ce ll.jpg 图片,井将图片文件保存于 Word 文件内: ...
- Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/5093566007214080
解决办法: 两个方案:1.注册处理函数时,用如下方式,明确声明为不是被动的window.addEventListener('touchmove', func, { passive: false }) ...
- 会议信息|CNKI|AIAA|万方|AIP|CNKI|EI|CPCI|BP|INSPEC
会议论文: 学术文献的三大支柱是期刊.专利和学位论文.会议论文是新的所以发文章快,灰色的,有些只有摘要,所以不容易获取. 有以下二次文献数据库,仅有摘要: CPCI BP:生物医学类 INSPEC在W ...