当前位置: 首页 > wzjs >正文

苏州优秀网站设计中标建设集团有限公司 网站

苏州优秀网站设计,中标建设集团有限公司 网站,建立网站策划书,百度定位店铺位置怎么设置思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

思维导图

Modbus RTU(先学一点理论)

概念

Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包括RS232/485等工业总线协议。

与Modbus TCP区别

与modbus TCP不同的是RTU没有报文头MBAP字段,但是在尾部增加了两个CRC检验字节(CRC16),因为网络协议中自带校验,所以在TCP协议中不需要使用CRC校验码。

RTU和TCP的总体使用方法基本一致,只是在创建modbus对象时有所不同,TCP需要传入网络socket信息;而RTU需要传入串口相关信息。

特点

1.遵循主从问答的通信方式

2.采用串口的方式进行通信

设置串口参数时要求:(了解,后续还会用)

波特率为9600(波特率是指每秒钟传输的比特数)

8位数据位 (数据位是指每个字符中包含的比特数)

1位停止位 (停止位是指在每个字符传输结束后添加的比特数)

无流控 (流控是指在数据传输过程中控制数据流量的一种机制,无流控表示在该设置下没有额外的控制机制来控制数据流量)

modbus rtu协议格式

地址码 功能码 数据 校验码

地址码(1字节):从机ID

功能码(1字节):和modbus tcp一样(01 02 03 04 05 06 0f 10H)

数据:起始地址、地址、数量、数据、字节计数;和modbus tcp一样。

校验码(2字节):对地址码、功能码、数据进行校验,由函数生成,循环冗余校验 (低字节在前)

其实modbus rtu协议的格式和modbus tcp是很像,就是把tcp的MBAP报文头去掉,只保留了一个字节的主机ID,最后结尾加上了两个字节的校验码。(校验码没有实际意义,是函数生成的不用管

 以01发送的数据格式为例,可以看到数据位是一样的,上图就是tcp和rtu协议格式的区别。数据接收也是和tcp一样的,所以就不再讲了。

modbus 库

官方文档:libmodbus

1库的安装

第一步和第二步都要运行,第一步是为了安装配置,第二步是为了让你使用这个库更方便,把它放在你的C语言库里。​​​​​

1.1库的安装配置(共四步)

通过网盘分享的文件:sqlite-autoconf-3460000.tar.gz
链接: https://pan.baidu.com/s/1ro8-xbsFitDSEEK6mSYzwQ?pwd=3521 提取码: 3521

直接复制命令,别手打,按顺序

1. (先下载压缩包,CtrlC+V复制到虚拟机任意路径下)在linux中解压压缩包

tar -xvf libmodbus-3.1.7.tar.gz

2. 进入源码目录

cd libmodbus-3.1.7

3.创建文件夹(存放头文件、库文件)

mkdir install

4.执行脚本configure,进行安装配置(指定安装目录)

./configure --prefix=$PWD/install

5. 执行make

make                        //编译

6.执行make install

make install                //安装

执行完成后会在install文件夹下生产对应的头文件、库文件件夹install,用于存放产生的头文件、库文件等

1.2.库的使用

要想编译方便,可以将头文件和库文件放到系统路径下(直接复制命令,别手打,按顺序

sudo cp include/modbus/*.h /usr/include

sudo cp lib/* -r /lib -d

后期编译时,可以直接gcc xx.c -lmodbus(和编译有关线程代码一样)

头文件默认搜索路径:/usr/include/usr/local/include(之前文章库里的内容

库文件默认搜索路径:/lib/usr/lib

2.函数接口

在上面的官方文档里包含所有的函数接口,以下是常用的modbus tcp函数接口,上个文章尝试自己写函数,这里就是使用这些别人写好的库函数(更方便)。

modbus_t* modbus_new_tcp(const char *ip, int port)

功能:以TCP方式创建Modbus实例,并初始化

参数:ip :ip地址

           port:端口号

返回值:成功:Modbus实例

失败:NULL

int modbus_set_slave(modbus_t *ctx, int slave)

功能:设置从机ID

参数:ctx :Modbus实例

           slave:从机ID

返回值:成功:0

               失败:-1

int modbus_connect(modbus_t *ctx)

功能:和从机(slave)建立连接

参数:ctx:Modbus实例

返回值:成功:0

               失败:-1

void modbus_free(modbus_t *ctx)

功能:释放Modbus实例

参数:ctx:Modbus实例

void modbus_close(modbus_t *ctx)

功能:关闭套接字

参数:ctx:Modbus实例

int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest)

功能:读取线圈状态,可读取多个连续线圈的状态(对应功能码为0x01

参数:ctx :Modbus实例

           addr :寄存器起始地址

           nb :寄存器个数

           dest :得到的状态值

返回值:成功:读到的数量

               失败:-1

int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest)

功能:读取输入状态,可读取多个连续输入的状态(对应功能码为0x02

参数:ctx :Modbus实例

           addr :寄存器起始地址

           nb :寄存器个数

           dest :得到的状态值

返回值:成功:返回nb的值

               失败:-1

int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest)

功能:读取保持寄存器的值,可读取多个连续保持寄存器的值(对应功能码为0x03

参数:ctx :Modbus实例

           addr :寄存器起始地址

           nb :寄存器个数

           dest :得到的寄存器的值

返回值:成功:读到寄存器的个数

               失败:-1

int modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest)

功能:读输入寄存器的值,可读取多个连续输入寄存器的值(对应功能码为0x04

参数:ctx :Modbus实例

           addr :寄存器起始地址

           nb :寄存器个数

           dest :得到的寄存器的值

返回值:成功:读到寄存器的个数

               失败:-1

int modbus_write_bit(modbus_t *ctx, int addr, int status);

功能:写入单个线圈的状态(对应功能码为0x05

参数:ctx :Modbus实例

           addr :线圈地址

           status:线圈状态

返回值:成功:1

               失败:-1

int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *src);

功能:写入多个连续线圈的状态(对应功能码为15

参数:ctx :Modbus实例

           addr :线圈地址

           nb :线圈个数

           src :多个线圈状态

返回值:成功:写入的数量

               失败:-1

int modbus_write_register(modbus_t *ctx, int addr, int value);

功能: 写入单个寄存器(对应功能码为0x06

参数: ctx :Modbus实例

            addr :寄存器地址

            value :寄存器的值

返回值:成功:1

               失败:-1

int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src);

功能:写入多个连续寄存器(对应功能码为16

参数:ctx :Modbus实例

           addr :寄存器地址

           nb :寄存器的个数

           src :多个寄存器的值

返回值:成功:写入的数量

               失败:-1

有关读取浮点的就不全举例了,感兴趣可以去查看官方文档

float modbus_get_float_dcba(const uint16_t *src)

功能:读取浮点类型的数据

参数:src:读到数据的存放数组

返回值:转换后的浮点类型

编程

从上往下写就可以连接到Modbus Slave,ip要写主机的IP地址,不要写成虚拟机的IP地址。,你要是在虚拟机运行的Modbus Slave,那就可以写虚拟机地址。

编程步骤

1.创建实例

2.设置从机ID

3.建立连接

4.寄存器操作(按需选择)

5.关闭套接字

6.释放实例

编程实现

1.基础步骤实现:
#include <modbus.h>
#include <stdio.h>int main(int argc, char const *argv[])
{char ip[128] = {"192.168.50.224"};         //IPint port = 502;                            //端口号int slave = 1;                             //从机地址int addr = 0x0000;                         //寄存器地址int nb = 0x0002;                           //寄存器数uint16_t dest[12] = {0};                   //接收数组// 创建实例// IP与端口号可作为命令行传参modbus_t *modbus = modbus_new_tcp(ip, port);if (modbus == NULL){perror("err\n");return -1;}//设置从机IDmodbus_set_slave(modbus, slave);   //建立连接int con = modbus_connect(modbus);if (con == -1){perror("con:\n");return -1;}//寄存器操作int read = modbus_read_registers(modbus, addr, nb, dest);if (read == -1){perror("read:\n");return -1;}for (int i = 0; i < read; i++){printf("%d ", dest[i]);}putchar(10);//关闭套接字modbus_close(modbus);//释放实例modbus_free(modbus);return 0;
}
2.数据采集小项目:

编程实现采集传感器数据和控制硬件设备(传感器和硬件通过slave模拟)

传感器:2个,光线传感器、加速度传感器(x\y\z)

硬件设备:2个,led灯、蜂鸣器

要求:

1.多任务编程:建议多线程

2.循环1s采集一次数据,并将数据打印至终端

3.同时从终端输入指令控制硬件设备

        0 1:led灯打开

        0 0:led灯关闭

        1 1:蜂鸣器开

        1 0:蜂鸣器关

#include <stdio.h>
#include <modbus.h>
#include <unistd.h>
#include <pthread.h>void *handler1(void *arg){            //内不含阻塞,相当于后台运行uint8_t dest1[32] = {0};uint16_t dest2[32] = {0};modbus_t *modbusid = (modbus_t *)arg;int size = 0;while(1){								//读取线圈状态size = modbus_read_bits(modbusid,0,2,dest1);if(size == -1){					//容错判断perror("modbus_read_registers err");break;}printf("LED:%02x 蜂鸣器:%02x\n",dest1[0],dest1[1]);//查询寄存器数值size = modbus_read_registers(modbusid,0,2,dest2);if(size == -1){					//容错判断perror("modbus_read_registers err");break;}printf("温度传感器:%02x 加速度传感器:%02x\n",dest2[0],dest2[1]);sleep(5);                        //5秒打印一次}
}void *handler2(void *arg){                    //用于执行写操作,需要输入指令modbus_t *modbusid = (modbus_t *)arg;int addr,nb,status;int a = 0;				        //标志操作05,06while(1){scanf("%d",&a);				//选择操作if(a == 5){					//操作单个线圈scanf("%d %d",&addr,&status);modbus_write_bit(modbusid,addr,status);}else if(a == 6){			//操作单个寄存器scanf("%d %d",&addr,&nb);modbus_write_register(modbusid,addr,nb);}if(a == -1)break;}
}int main(int argc, const char *argv[])
{//创建实例modbus_t *modbusid = modbus_new_tcp("192.168.43.148",502);if(modbusid == NULL){perror("modbus_new_tcp err");return -1;}//设置从机IDint slave = 1;if(modbus_set_slave(modbusid,slave) == -1){perror("modbus_set_slave err");return -1;}//建立连接if(modbus_connect(modbusid) == -1){perror("modbus_connect err");return -1;}//寄存器操作pthread_t ptid1;pthread_create(&ptid1,NULL,handler1,modbusid);        //创建第一个线程pthread_detach(ptid1);pthread_t ptid2;pthread_create(&ptid2,NULL,handler2,modbusid);        //创建第二个线程pthread_join(ptid2,NULL);//关闭套接字modbus_close(modbusid);//释放实例modbus_free(modbusid);return 0;
}

五秒打印一次,终端还可以输入命令取改变寄存器和线圈值

 

http://www.dtcms.com/wzjs/576386.html

相关文章:

  • 快站优惠券wordpress设置超链接
  • 项目外包+网站开发互联网建站公司
  • 糕点网站策划书wordpress增加访问量
  • 绵阳做手机网站wordpress 主题js
  • 帮别人做非法网站云服务器怎么建网站
  • 网站忘了怎么办啊cms 做网站模板
  • 深圳网站建设网站制作哪家好哪些网站的做的好看的
  • 如何在阿里云云服务器上搭建网站2017商会网站建设方案
  • 做全网影视网站的风险建设我们的网站 教案
  • 品牌网站制作网站公司央企 网站建设 公司
  • 网站模板用什么做申报课题所需的网站怎么做
  • 百度回收网站搭建大宇网络做网站怎么样
  • 长沙做网站建设公司排名织梦网站熊掌号改造怎么做
  • 网站总是跳转网络推广需要做哪些工作
  • 济南网站建设公司 推荐行知科技报价单模板英文
  • 贵州碧江区住房和城乡建设局网站中国空间站官网
  • 网站开发antnw什么是c2c模式
  • 宜兴市网站建设公司注册网上核名通不过
  • 商城网站互动性网站访问权限
  • 百度网站推广怎么样防红跳转短网址生成
  • 给我做网站的人老是给我留点尾巴做网站要建立站点吗
  • 网络做翻译的网站小游戏开发需要多少钱
  • 网站建设关键的问题是php 用什么做网站服务器
  • 做模型的网站有哪些内容新手学做免费网站软件好
  • 奇趣网做网站搞笑网站全站源码
  • 建设一个公司网站需要什么条件网站建设策划怎么沟通
  • 厚街网站建设价格专门做音效的网站
  • 黄石市下陆区建设管理局网站宁波黄页网
  • 不相关的网站做单项链接可以吗青岛市网站建设
  • 网站建设美文数据中台建设方案