Modbus简介

参考:Modbus​协议​深入​讲解 https://www.ni.com/zh-cn/innovations/white-papers/14/the-modbus-protocol-in-depth.html

http://www.sohu.com/a/230628953_315598

官方文档:http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf

Modbus协议包括ASCII、RTU、TCP等,并没有规定物理层。此协议定义了控制器能够认识和使用的消息结构,而不管它们是经过何种网络进行通信的。标准的Modicon控制器使用RS232C实现串行的Modbus。Modbus的ASCII、RTU协议规定了消息、数据的结构、命令和就答的方式,数据通讯采用Maser/Slave方式,Master端发出数据请求消息,Slave端接收到正确消息后就可以发送数据到Master端以响应请求;Master端也可以直接发消息修改Slave端的数据,实现双向读写。

其通信协议理解也比较简单,其帧结构如下

地址码 + 功能码 + 数据区 + 错误校验

常用功能码

最常使用的读写功能码如下;

01   读取单个/多个线圈状态(类似DO:数字输出)

02   读取单个/多个离散输入(类似DI:数字输入)

03   读取单个/多个保存寄存器

04   读取单个/多个输入寄存器(类似AI:模拟输入)

05   写单个线圈状态

06   写单个保存寄存器

15   写多个线圈

16   写多个保存寄存器

FreeModbus简析

FreeMODBUS 提供了RTU/ASCII 传输模式及TCP协议支持。

FreeModbus协议对硬件的需求非常少——基本上任何具有串行接口,并且有一些能够容纳modbus数据帧的RAM的微控制器都足够了。

现支持如下功能码:

  • Read Input Register (0x04)
  • Read Holding Registers (0x03)
  • Write Single Register (0x06)
  • Write Multiple Registers (0x10)
  • Read/Write Multiple Registers (0x17)
  • Read Coils (0x01)
  • Write Single Coil (0x05)
  • Write Multiple Coils (0x0F)
  • Read Discrete Inputs (0x02)
  • Report Slave ID (0x11)

FreeModbus源码解析

参考:https://blog.csdn.net/u014748120/article/details/80313215

待续。。。

Modbus通信实现

本文测试主机为 arm-linux,可以使用 libmodbus 静态库实现modbus通信,为追求可移植性,本文主要使用 freemodbus 来实现。

1. libmodbus使用

ubuntu系统使用libmodbus可以使用以下命令安装

sudo apt-get install libmodbus-dev
# 或者
sudo apt-get install libmodbus5

使用文档参考:https://libmodbus.org/documentation/

库参考手册:https://libmodbus.org/docs/v3.1.4/

移植到arm的话则需下载源码进行交叉编译  http://libmodbus.org/releases/libmodbus-3.1.4.tar.gz

解压安装

tar -xzvf libmodbus-3.1.4.tar.gz
cd libmodbus-3.1.4
# 新建安装文件夹
mkdir -p install
chmod 777 install
./configure --prefix=$(pwd)/install --host=arm-linux --enable-static ac_cv_func_malloc_0_nonnull=yes CC=arm-fsl-linux-gnueabi-gcc
make
make install

在我的应用程序工程里面新建一个 libmodbus 文件夹,将上面安装 install目录下的 include和lib文件夹拷贝过来

我的工程总体结构如下所示

在 mys_src 里面添加 modbus 主机测试程序 modbus_test.c

makefile编写如下所示:

#编译配置,使能为1
CONFIG_MODBUS_BUILD = 1 #当前路径
CUR_DIR := $(shell pwd) #libmodbus目录
LIBMODBUS_DIR := $(CUR_DIR)/../libmodbus # 头文件路径
INCLUDE :=
INCLUDE += -I$(CUR_DIR)/../include/
ifeq ($(CONFIG_MODBUS_BUILD), 1)
INCLUDE += -I$(LIBMODBUS_DIR)/include/modbus/
endif #C编译器的选项
CFLAGS :=
CFLAGS += -g -Wall
CFLAGS += -std=gnu99
CFLAGS += $(INCLUDE) #库文件参数
LDFLAGS :=
#libmodbus共享库链接
#LDFLAGS += -L$(LIBMODBUS_DIR)/lib
#libmodbus静态库链接
ifeq ($(CONFIG_MODBUS_BUILD), 1)
LDFLAGS += $(LIBMODBUS_DIR)/lib/libmodbus.a
endif SRCS += modbus_test.c
OBJS += modbus_test.o
BINS += modbus_test all:$(OBJS) $(BINS) $(OBJS):%.o:%.c
$(CC) -c $(CFLAGS) $^ -o $(OBJ_DIR)/$@ $(BINS):$(OBJS)
$(CC) -o $(BIN_DIR)/$@ $(OBJ_DIR)/$^ $(LDFLAGS)

modbus_test.c

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <modbus.h> #define MODBUS_DEV_NAME "/dev/ttymxc3" ///< 串口设备 int main(void)
{
modbus_t *ctx =NULL; // 以串口的方式创建libmobus实例,并设置参数
ctx = modbus_new_rtu(MODBUS_DEV_NAME, 115200, 'N', 8, 1);
if (ctx == NULL) //使用UART4,对应的设备描述符为ttymxc3
{
fprintf(stderr, "Unable to allocate libmodbus contex\n");
return -1;
}
// 使用RS485时需考虑设置串口模式、RTS引脚等
// modbus_rtu_set_serial_mode(MODBUS_RTU_RS485); //设置串口模式 modbus_set_debug(ctx, 1); //设置1可看到调试信息
modbus_set_slave(ctx, 1); //设置slave ID if (modbus_connect(ctx) == -1) //等待连接设备
{
fprintf(stderr, "Connection failed:%s\n", modbus_strerror(errno));
return -1;
} int i,rc;
uint16_t tab_reg[64] = {0}; //定义存放数据的数组
while (1)
{
printf("\n----------------\n");
//读取保持寄存器的值,可读取多个连续输入保持寄存器
rc = modbus_read_registers(ctx, 0, 10, tab_reg);
if (rc == -1)
{
fprintf(stderr,"%s\n", modbus_strerror(errno));
return -1;
}
for (i=0; i<10; i++)
{
printf("reg[%d] = %d(0x%x)\n", i, tab_reg[i], tab_reg[i]);
} usleep(5000000);
}
modbus_close(ctx); //关闭modbus连接
modbus_free(ctx); //释放modbus资源,使用完libmodbus需要释放掉 return 0;
}

编译之后可通过nfs挂载进行测试

modbus从机模拟

Modbus slave测试工具可以用来做modbus从机设备,从而实现arm控制板通过串口与PC端模拟的modbus从机进行通信测试。

Modbus slave下载地址:https://www.modbustools.com/download/ModbusSlaveSetup64Bit.exe

然后设置 setup->slave definition   从机ID、设置为保存寄存器,10条

同时我们也给寄存器设置一些值

开发板运行测试程序后,成功读取modbus从机寄存器值

2.freemodbus在linux上的使用

待续。。。

freemodbus移植、实例及其测试方法的更多相关文章

  1. FreeModbus移植实例(转)

    源:分享FreeRTOS + FreeModbus + UART_RTO FREERTOS 移植学习 入门必备 正点原子官方所有开发板的FreeRTOS教程及其例程正式发布(STM32F103,STM ...

  2. KEIL MDK环境下uCOS-II在LPC17xx上的移植实例

    1. 知识准备 要想对ucos-ii的移植有较深的理解,需要两方面知识: (1)目标芯片,这里是lpc17xx系列芯片,它们都是基于ARMv7 Cortex-M3内核,所以这一类芯片的ucos-ii移 ...

  3. 【HAL库每天一例】freemodbus移植

    例程下载:资料包括程序.相关说明资料以及软件使用截图 百度云盘:https://pan.baidu.com/s/1slN8rIt 密码:u6m1 360云盘:https://yunpan.cn/OcP ...

  4. 第一章 Android系统的编译和移植实例

    第一章 Android系统的编译和移植实例 这一章节主要介绍了Android系统的编译和移植技术,作为建立在Linux内核的基础上的Android操作系统,它的编译和移植不论在过程还是技术方面都和嵌入 ...

  5. FreeModbus 移植于STM32 实现Modbus RTU通信

    http://ntn314.blog.163.com/blog/static/161743584201233084434579/ 毕业设计自己要做个基于STM32的PLC能直接跑语句表的,现在看来好像 ...

  6. freemodbus移植讲解 ZZ

    一   为什么要移植Freemodbus 为什么要移植Freemodbus,这个问题需要从两个方面来回答.第一,modbus是一个非常好的应用层协议,它很简洁也相对完善.对于还没有接触过modbus的 ...

  7. ucosII移植

    移植ucos II 到一个芯片上,只需要修改下面三个文件:OS_CPU.H,OS_CPU_C.C,OS_CPU_A.ASM. 具体来说,移植主要包括以下几项内容 (1).OS_CPU.H :用#def ...

  8. Port of FreeModbus to STM32

    /********************************************************************************* * Port of FreeMod ...

  9. FreeModbus RTU slave & Modbus RTU master

    一.FreeModbus RTU 协议数据格式 FreeModbus RTU是开源的一个协议,并且使用FreeModbus RTU 只能当做从机Slave,RTU协议中的指令由地址码(一个字节),功能 ...

随机推荐

  1. 关于vue3简单状态管理约定引发的思考

    官方文档的代码是这样的 export const store = { debug: true, state: reactive({ message: 'Hello!' }), setMessageAc ...

  2. QT从入门到入土(四)——多线程(QtConcurrent::run())

    引言 在前面对Qt多线程(QThread)做了详细的分析:QT从入门到入土(四)--多线程(QThread) - 唯有自己强大 - 博客园 (cnblogs.com) 但是最近在做项目时候,要将一个函 ...

  3. YOLO-V4 实现口罩识别(附加数据、数据批量处理程序)

    一.YOLO-v4概念 如果想要了解和认识yolo-v4的基本概念,首先要提的就是它的基础版本yolo-v1,对于yolo来说,最经典的算是yolo-v3.如果想要了解它的由来和历史的话,可以自行搜索 ...

  4. Android 自定义属性(attrs)、样式(Style)、主题(Theme)

    Android 自定义属性(attrs).样式(Style).主题(Theme) https://www.cnblogs.com/dandre/p/4507024.html https://blog. ...

  5. 【LeetCode】169. 多数元素

    169. 多数元素 知识点:数组:排序:消消乐:分治: 题目描述 给定一个大小为 n 的数组,找到其中的多数元素.多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素. 你可以假设数组是非空的, ...

  6. Microservices==>Service Mesh==>Serverless,走马观花

    [0] 始有道 话说图灵开天辟地,冯.诺伊曼造石补天! 始有道道生ML Machine LanguageML生汇编 assembler汇编生编译器 compiler编译器生PL Programming ...

  7. 《高性能利器》-32张图带你解决RocketMQ所有场景问题

    一.RocketMQ的基本原理 RocketMQ基本架构图如下 从这个架构图上我们可以知道,RocketMQ有4块核心部分: NameServer:管理Broker的信息,让使用MQ的系统感知到集群里 ...

  8. 从零开始实现简单 RPC 框架 2:扩展利器 SPI

    RPC 框架有很多可扩展的地方,如:序列化类型.压缩类型.负载均衡类型.注册中心类型等等. 假设框架提供的注册中心只有zookeeper,但是使用者想用Eureka,修改框架以支持使用者的需求显然不是 ...

  9. JAVA 调用第三方短信平台接口发送短信

    做了几个调用三方短信平台发送短信的例子,大部分需要 携带参数,向指定URL发送请求 回顾对接第一个平台时痛苦的乱码经历,这里放一份代码,算是个模版,再用到的时候过来copy一下就OK. 在进入主题之前 ...

  10. Redis如何实现分布式锁

    今天我们来聊一聊分布式锁的那些事. 相信大家对锁已经不陌生了,我们在多线程环境中,如果需要对同一个资源进行操作,为了避免数据不一致,我们需要在操作共享资源之前进行加锁操作.在计算机科学中,锁(lock ...