嵌入式软件实战项目开发
**
嵌入式软件实战项目开发(一)
modbus协议项目开发(基础知识讲解)
文章目录
前言
嵌入式软件项目开发,涉及到硬件和软件,还有上位机开发,还有嵌入式操作系统,需要有一定的软件和硬件基础,笔者从事嵌入式软件开发十多年,深知一个项目的开发涉及到太多的知识和太多方面的东西,所以笔者想做一个嵌入式项目的分享,主要一步步讲解嵌入式软件项目如何开发的,其讲解的只是项目嵌入式软件部分,包括文档的设计及下位机软件如何开发,以及上位机软件测试工具如何开发,对嵌入式软件开发人员有一定的参考意义
提示:以下是本篇文章正文内容,下面案例可供参考
一、通信协议是什么?
那通信协议又是什么呢?通信就是双方或多方用同一种语言交流,通信协议就是规定双方或多方需要共同遵守的交流方式。比如现在规定两个人需要用数字来代表文字,目前只定义了1表示“我”,2表示“你”,3表示“他”,然后现在两个人中有个人说了1,另一个立即就知道说的是“我”,但假如有个人不按规定来说话,说了一个4,那另一个人就不明白他在说什么了。这个例子里面,定义的1、2、3的表示,就是一份简单的通信协议。一般的通信协议,如TCP/IP、Profibus dp等比Modbus复杂,但万变不离其宗。
做嵌入式软件涉及到太多通信协议,上面讲的通信协议的协议体系结构可以分为我们讲的ISO七层,但是一般嵌入式软件开发常用的是比较简单的协议,不会涉及到那么多分层,在笔者看来,就是分为硬件层和软件层,因为协议都是需要硬件实现的,比如Moudbus,它的硬件层是RS485总线,也可以是以太网,所以Moubus分为Moubus RTU和MoubusTCP,这个下面会作详细讲解,还有其它的如Canopen,它的硬件层是Can总线,IO-link,其硬件层是串口单总线,它是由专门的硬件芯片实现的。还有我们经常用的串口,IIC和SPI等等,这些都可以简单的分为硬件层和软件层,但是这些一定要搞清楚其硬件时序,这个是我们嵌入式软件开发经常需要使用的,这个后续会定一些相关的文章进行详细的讲解,其基础的知识网上都有,主要是讲解开发过程中遇到的问题以及相关的知识点。
二、Modbus通信协议
Modbus是一种串行通信协议,是Modicon公司(现在的施耐德电气 Schneider Electric)于1979年为使用可编程逻辑控制器(PLC)通信而发表。Modbus已经成为工业领域通信协议的业界标准(De facto),并且现在是工业电子设备之间常用的连接方式。–摘自百度百科
Modbus是一种一主一从的一对一通信方式(主机发一帧,从机回一帧的形式),当然也可以一主多从,但实际也是一对一通信,同一时刻只能有一个从机进行响应。如果需要和多个从机同时通信,这里也支持使用广播,即主机发送指令,所有从机接收指令并执行,但不进行应答。
当进行一主多从通信时,主机通过从机ID号来区分要通信的从机设备。从机ID范围为1-247,0为广播地址,248-255为保留地址。地址 0 为广播地址。所有的子节点必须识别广播地址。Modbus 主节点没有地址,只有子节点必须有一个地址。 该地址必须在 Modbus 串行总线上唯一。
Modbus 协议与协议测试工具软件下载地址为:https://download.csdn.net/download/wang8y8y/90626760
三、Modbus协议分类
Modubs按通信模式分为以下几类:
(1)、Modbus RTU 远程终端单元( Remote Terminal Unit,RTU) 异步串行传输
(2)、Modbus ASCII 异步串行传输
(3)、Modbus TCP 以太网
(4)、Modbus Plus 高速令牌传递网络
Modubs协议体系结构
3.1 Modbus RTU
Modbus RTU:一般是基于串口进行通信。其报文格式是十六进制的,即报文中每个 8 位字节含
有两个 4 位十六进制字符,这种模式的主要优点是较高的数据密度。一帧数据由Slave ID+功能码+数据+CRC校验三部分组成。帧数据结构详见下图。剩下的就是数据校验了,这里用的是CRC校验(循环冗余校验,Cyclic Redundancy Check,简称CRC)。要注意的是,数据部分高位数据在前,低位数据在后,而CRC校验则是低位在前,高位在后.
在 RTU 模式,报文帧由时长至少为 3.5 个字符时间的空闲间隔区分。
3.2 Modbus ASCII
Modbus ASCII: ASCII是一种字符型的通信方式,一般也是基于串口进行通信。其报文格式是以ASCII码编码的,由帧头(:)+Slave ID+数据+LRC校验+帧尾(回车-换行)五部分组成,其中Slave ID、数据部分跟RTU完全一样,只不过是以ASCII编码形式,如Slave ID,RTU是01一个字节的时候,ASCII表示就是30 31两个字节。所以实际工业应用场合很少会用到Modbus/ASCII,因为通信效率太低。另外跟RTU还有个不同的地方,就是这里使用的校验不是CRC校验,而是LRC(纵向冗余校验,Longitudinal Redundancy Check)校验。
对于所有的域,允许传送的字符为十六进制 0–9, A–F (ASCII 编码)。 设备连续的监视总线上的 ‘冒号’ 字符。 当收到这个字符后,每个设备解码后续的字符一直到帧结束。
报文中字符间的时间间隔可以达一秒。如果有更大的间隔,则接受设备认为发生了错误。下图显示了一个典型的报文帧。
3.3 Modbus TCP
TCP是一种网络协议,而Modbus/TCP就是基于网络协议上的一种应用层协议。其报文格式是十六进制的,由报头(2字节的帧序号+2字节的协议类型+2字节的数据长度+1字节的Slave ID)+数据两部分组成。由于该通信方式是基于TCP/IP这种可靠协议上,所以通信不需要有额外的校验机制
说白了,Modbus/TCP是一种协议嵌套,它是嵌在TCP协议里面的,即包括在TCP协议的数据区里面,就它是TCP协议嵌在IP协议里面一样,如果大家对工业协议有研究,就会发现,其实很多协议都是嵌套的,比如EtherCAT CoE(CANover EtherCAT),它是EtherCAT协议中的一种通信协议,它将CANopen应用层协议集成到EtherCAT网络中。PROFINET 是将Profibus的主从结构移植到以太网上,有点跑题了,这里要计是讲解协议嵌套,把一种协议嵌入到另一种协议中去。
Modbus TCP报文格式:
交互(通信)标识:2个字节 为此次通信事务处理标识符,一般每次通信之后将被要求加1以区别不同的通信数据报文。
协议标识:2个字节 表示该条指令遵循ModbusTCP协议,一般都为00 00
报文长度:2个字节 表示后面数据的长度,有几个字节,高字节在前
(前六位Modbus/TCP协议不同功能码通用)
设备标识 :1个字节 设备地址,这个可以用于局域网里面的具体的地址,如果目标机器有固定ip,这个就不起作用,直接上写成 00
功能码:1个字节 功能码在modbus协议用于表示信息帧的功能
数据:N个字节 后面数据根据不同功能码不同。
3.4 Modbus数据类型
Modbus中,数据可以分为两大类,分别为线圈(1位)和寄存器(16位),根据读写方式的不同,又分为只读和读写
这些数据类型的区别在于它们的功能和操作类型不同,输入寄存器 和 离散量输入 只能读取,线圈和 保持寄存器 可以读写,而且 输入寄存器 和 保持寄存器 还区分有符号和无符号两种类型。在实际应用中,根据不同的应用场景和需要采集的数据类型,选择合适的数据类型进行通信和操作
3.5 Modbus功能码
报文格式:地址码+功能码+数据+校验
modbus 常用功能代码
十进制 功能 数据类型
01 读取 多个线圈 1位
02 读取 多个离散量输入量 1位
03 读取 多个保持寄存器 16位
04 读取 多个输入寄存器 16位
05 写入 单个线圈 1 位
06 写入 单个寄存器 16位
15 写入 多个线圈 1位
16 写入 多个寄存器 16位
报文解析:以功能码03为例
主节点发送帧格式:从节点地址 命令类型 寄存器起始地址 寄存器个数 CRC校验
从节点应答帧格式:从节点地址 命令类型 发送字节数L=n*2 第一个寄存器值 … 第N个寄存器值 CRC校验
从节点异常应答格式:从节点地址 命令类型+128 错误码 CRC校验
提示:功能码可以自定义,Modbus协议允许自定义功能码,具体请参看Modubs 协议
3.6 Modbus-RTU报文举例
功能码:0x03 读取一个或多个保持寄存器
模拟量输出读取(一个)
功能:读取当前AO(寄存器)通道1位模拟量输出值
主站请求:发送数据(HEX)01 03 00 00 00 01 84 0A
解释:01 从站地址
03 功能码,读取AO
00 00 起始地址,从AO寄存器第一位开始读
00 01 要读取的寄存器数量,即读取一个寄存器的值
84 0A 16位CRC校验
从站响应:接收数据(HEX)01 03 02 10 D2 35 D9
解释:01 从站地址
03 功能码,读取AO
02 后面所读取数据的字节数,一个寄存器即2个字节
10 D2 转换成十进制=4306,即读取到的模拟量的值为4306
35 D9 16位CRC校验
四、Modbus测试工具
这里主要是介绍上位机测试工具,ModbusPoll软件主要用于仿真Modbus主站或Modbus客户端
ModbusSlave软件主要用于仿真Modbus从站或Modbus服务器,这个测试工具存在一定的局限性,其数据只是简单的显示十进制数据和十六进制数据,对于浮点数显示以及其它数据显示不会那么直观,还有波特率最高也就256000,所以就涉及到上位机开发,上位机开发笔者使用的是QT Creator,这个后续再讲。
ModbusPoll打开界面
状态框:
Tx = 0表示向主站发送数据帧次数,
图中为0次;
Err = 0表示通讯错误次数,图中为0次;
ID = 1表示模拟的Modbus子设备的设备地址,
图中地址为1;
F = 03表示所使用的Modbus功能码,
图中为03功能码;
SR = 1000ms表示发送周期,1S一次。
红字部分,表示当前的错误状态,
“No Connection”表示未连接状态。
单击Setup----Read/Write Definition… 或者按F8进行参数设置,会弹出参数设置对话框。
Slave ID为要访问的Modbus从机的地址,
Function 功能码的选择,
Address 为寄存器起始地址,根据功能码的不同,访问地址不同
Quantity:为访问寄存器个数,
Scan Rate为读取数据周期,轮询发送,单位毫秒
点击 Connection -> Connect或者按“F3”进行连接
Response Timeout,表示读取超时时间,
从站在超时时间内没有返回数据,则认为
通讯失败。
Delay Between Polls,每次扫描的最小间隔
时间,默认为20ms。
Remote Modbus Server,表示TCP/IP模式时
的终端从站设备的网络设置。
IP Address,表示TCP/IP模式时从站IP地址。
Port,表示TCP模式时从站网络端口
Connect Timeout 表示TCP链接超时时间
IPV4/IPV6