rt-thread之通讯协议modbus软件包的使用记录(lwip+modbus组合)

前言

  1. 使用freemodbus软件包
  2. 使用网口通讯(sal+lwip)
  3. ip地址使用dhcp动态获取

软件包

在这里插入图片描述

相关宏定义

/*-----------------------------------------NET 宏定义-------------------------------------------*/#define RT_USING_SAL
#define SAL_INTERNET_CHECK
/* Docking with protocol stacks */
#define SAL_USING_LWIP
//#define SAL_USING_TLS
/* end of Docking with protocol stacks */
#define SAL_SOCKETS_NUM 16
#define RT_USING_NETDEV
#define NETDEV_USING_IFCONFIG
#define NETDEV_USING_PING
#define NETDEV_USING_NETSTAT
#define NETDEV_USING_AUTO_DEFAULT
#define NETDEV_IPV4 1
#define NETDEV_IPV6 0
#define RT_USING_LWIP
#define RT_USING_LWIP203
#define RT_USING_LWIP_VER_NUM 0x20003
#define RT_LWIP_MEM_ALIGNMENT 4
#define RT_LWIP_IGMP
#define RT_LWIP_ICMP
#define RT_LWIP_DNS
#define RT_LWIP_DHCP
/* Static IPv4 Address */#define RT_LWIP_IPADDR "192.168.1.30"
#define RT_LWIP_GWADDR "192.168.1.1"
#define RT_LWIP_MSKADDR "255.255.255.0"
/* end of Static IPv4 Address */
#define RT_LWIP_UDP
#define RT_LWIP_TCP
#define RT_LWIP_RAW
#define RT_MEMP_NUM_NETCONN 8
#define RT_LWIP_PBUF_NUM 16
#define RT_LWIP_RAW_PCB_NUM 4
#define RT_LWIP_UDP_PCB_NUM 4
#define RT_LWIP_TCP_PCB_NUM 4
#define RT_LWIP_TCP_SEG_NUM 40
#define RT_LWIP_TCP_SND_BUF 8196
#define RT_LWIP_TCP_WND 8196
#define RT_LWIP_TCPTHREAD_PRIORITY 10
#define RT_LWIP_TCPTHREAD_MBOX_SIZE 8
#define RT_LWIP_TCPTHREAD_STACKSIZE 1024
#define RT_LWIP_ETHTHREAD_PRIORITY 12
#define RT_LWIP_ETHTHREAD_STACKSIZE 1024
#define RT_LWIP_ETHTHREAD_MBOX_SIZE 8
#define LWIP_NETIF_STATUS_CALLBACK 1
#define LWIP_NETIF_LINK_CALLBACK 1
#define SO_REUSE 1
#define LWIP_SO_RCVTIMEO 1
#define LWIP_SO_SNDTIMEO 1
#define LWIP_SO_RCVBUF 1
#define LWIP_SO_LINGER 0
#define LWIP_NETIF_LOOPBACK 0
#define RT_LWIP_USING_PING
/*-----------------------------------------modbus协议----------------------------------------------*/
#define PKG_MODBUS_SLAVE_TCP
#define RT_S_DISCRETE_INPUT_START 0x0
#define RT_S_DISCRETE_INPUT_NDISCRETES 10
#define RT_S_COIL_START 0x0
#define RT_S_COIL_NCOILS 10
#define RT_S_REG_INPUT_START 0x0
#define RT_S_REG_INPUT_NREGS 10
#define RT_S_REG_HOLDING_START 0x0
#define RT_S_REG_HOLDING_NREGS 100

modbus 软件包tcp接口的实现

porttcp的实现

#include "port.h"#ifdef PKG_MODBUS_SLAVE_TCP
/* ----------------------- Modbus includes ----------------------------------*/
#include "mbport.h"
#include "lwip/sockets.h"#define DBG_ENABLE
#define DBG_TAG "app.server"
#define DBG_LVL DBG_LOG#include "rtdbg.h"
/* ----------------------- Defines  -----------------------------------------*/
#define MB_TCP_DEFAULT_PORT     502
#define MB_TCP_BUF_SIZE     ( 256 + 7 )
#define MB_TCP_CLIENT_TIMEOUT  (30*RT_TICK_PER_SECOND)  /*超时时间30s*/
/* ----------------------- Static variables ---------------------------------*/
/*** @var local_sock  本地套接字描述符*/
int local_sock = -1;
/*** @var remote_sock 远端套接字描述符*/
int remote_sock = -1;
/*** @var local_listen_port 监听端口号,默认是502*/
static rt_uint16_t local_listen_port = MB_TCP_DEFAULT_PORT;
/*** @var mb_thread 线程指针*/
static rt_thread_t mb_thread = RT_NULL;
/*** @var local_addr 本地套接字地址结构体*/
static struct sockaddr_in local_addr;
/*** @var client_addr 客户端套接字结构体*/
static struct sockaddr_in client_addr;
/*** @var prvvTCPBuf 接收数据缓存区*/
static UCHAR    prvvTCPBuf[MB_TCP_BUF_SIZE];
/*** @var prvvTCPLength 接收数据长度*/
static USHORT   prvvTCPLength;static void lwip_server_entry(void *parameter) {static rt_tick_t recv_tick = 0;int result;socklen_t sin_size;begin:local_sock = socket(AF_INET, SOCK_STREAM, 0);if (local_sock < 0) {LOG_E("Socket error\n");goto __exit;}local_addr.sin_family = AF_INET;local_addr.sin_addr.s_addr = INADDR_ANY;local_addr.sin_port = htons(local_listen_port);memset(&(local_addr.sin_zero), 0, sizeof(local_addr.sin_zero));if (bind(local_sock, (struct sockaddr *) &local_addr, sizeof(struct sockaddr)) == -1) {LOG_E("Unable to bind\n");goto __exit;}if (listen(local_sock, 5) == -1) {LOG_E("Listen error\n");goto __exit;}while (1) {sin_size = sizeof(struct sockaddr_in);remote_sock = accept(local_sock, (struct sockaddr *) &client_addr, &sin_size);LOG_I("new client connected from (%s, %d)\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));{int flag = 1;// 不使用Nagle算法// Nagle算法的主要目的是为了预防小分组的产生,因为在广域网中,小分组会造成网络拥塞。setsockopt(remote_sock, IPPROTO_TCP, TCP_NODELAY, (void *) &flag, sizeof(int));flag = 1;ioctlsocket(remote_sock, FIONBIO, &flag); /*配置成非阻塞模式*/}recv_tick = rt_tick_get();while (1) {result = recv(remote_sock, &prvvTCPBuf, MB_TCP_BUF_SIZE, 0);if (result == 0) { /*表示连接关闭*/LOG_I("client(%s) disconnected", inet_ntoa(client_addr.sin_addr));break;} else if (result == -1) { /*表示未接收到数据*/if (abs((int) (rt_tick_get() - recv_tick)) > MB_TCP_CLIENT_TIMEOUT) /* set timeout x */{LOG_D("timeout close client(%s) connect", inet_ntoa(client_addr.sin_addr));break; /*超时跳出循环*/}rt_thread_delay(20);} else if (result > 0) {LOG_D("recv %d len data\n", result);prvvTCPLength = result;xMBPortEventPost(EV_FRAME_RECEIVED);} else {LOG_E("unknown error:%d", result);break;}/*todo 判断是否网线拔掉的情况?*/}if (remote_sock >= 0) {closesocket(remote_sock);remote_sock = -1; /*重置为-1*/}}__exit:if (local_sock >= 0) closesocket(local_sock);rt_thread_mdelay(1000);/*等待1ms*/goto begin;}BOOL
xMBTCPPortInit(USHORT usTCPPort)
{if (usTCPPort == 0)usTCPPort = MB_TCP_DEFAULT_PORT;local_listen_port = usTCPPort;if (mb_thread == NULL) {/*创建任务*/mb_thread = rt_thread_create("modbus_thread",lwip_server_entry,RT_NULL,1024,15, 10);if (mb_thread) {rt_thread_startup(mb_thread);} else {LOG_E("modbus thread create error");return FALSE;}}return TRUE;
}void
vMBTCPPortClose(void)
{closesocket(local_sock); 
}void
vMBTCPPortDisable(void)
{closesocket(remote_sock);remote_sock = -1;
}BOOL
xMBTCPPortGetRequest(UCHAR **ppucMBTCPFrame, USHORT *usTCPLength)
{*ppucMBTCPFrame = &prvvTCPBuf[0];*usTCPLength = prvvTCPLength;return TRUE;
}BOOL
xMBTCPPortSendResponse(const UCHAR *pucMBTCPFrame, USHORT usTCPLength)
{rt_int16_t ret;BOOL bFrameSent = FALSE;/*如果远端*/if (remote_sock > 0){ret = send(remote_sock, (void *) pucMBTCPFrame, usTCPLength, 0);if (ret == usTCPLength)bFrameSent = TRUE;}return bFrameSent;
}
#endif

modbus线程的编写

//
// Created by shchl on 2024/3/17.
//
#include "app_config.h"
#include "sal_socket.h"
#include "netdev.h"
#include "mb.h"#define DBG_ENABLE
#define DBG_TAG "mb.server"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>#define MB_POLL_THREAD_PRIORITY  10
#define MB_POLL_CYCLE_MS 200
static struct netdev *netdev;static void mb_slave_poll(void *parameter) {netdev = netdev_get_by_name("e0");if (netdev == NULL) {LOG_E("get netdev failed");}/*等待ip地址和网关配置完成*/while (netdev->ip_addr.addr == 0x0 || netdev->gw.addr == 0x0) {LOG_W("netdev is not config finished,waiting 1 s");rt_thread_mdelay(1000);}eMBTCPInit(0); /*使用默认端口503*/eMBEnable();while (1) {eMBPoll();rt_thread_mdelay(MB_POLL_CYCLE_MS);}
}static int mb_slave_tcp() {static rt_uint8_t is_init = 0;rt_thread_t tid1 = RT_NULL;tid1 = rt_thread_create("mb_slave_tcp", mb_slave_poll, NULL, 1024, MB_POLL_THREAD_PRIORITY, 10);if (tid1 != RT_NULL) {rt_thread_startup(tid1);} else {}return RT_EOK;}INIT_APP_EXPORT(mb_slave_tcp);

modbus tcp 部分源码分析记录

在这里插入图片描述在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2871121.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

App拉新必备!Xinstall渠道追踪,让每一分钱都花在刀刃上

在移动互联网时代&#xff0c;App已经成为人们日常生活中不可或缺的一部分。然而&#xff0c;对于App开发者来说&#xff0c;如何有效地进行拉新&#xff0c;提高用户留存率&#xff0c;一直是一个难题。而渠道追踪&#xff0c;作为App推广过程中的重要环节&#xff0c;往往被忽…

Prometheus + Grafana 监控解决方案介绍及部署

Prometheus Grafana 监控解决方案介绍 Prometheus&#xff08;普罗米修斯&#xff09;是一套开源的 监控&报警&时间序列 数据库 的组合&#xff0c;起始是由SoundCloud公司开发。 随着发展&#xff0c;越来越多公司和组织接受采用Prometheus&#xff0c;社区也十分活…

【Spark编程基础】RDD 编程初级实践(附源代码)

目录 一、实验目的二、实验平台三、实验内容1.spark-shell 交互式编程2.编写独立应用程序实现数据去重3.编写独立应用程序实现求平均值问题 一、实验目的 1、熟悉 Spark 的 RDD 基本操作及键值对操作&#xff1b; 2、熟悉使用 RDD 编程解决实际具体问题的方法 二、实验平台 …

【LabVIEW FPGA入门】浮点数类型支持

如今&#xff0c;使用浮点运算来设计嵌入式系统的需求变得越来越普遍。随着 FPGA 因其固有的大规模并行性而在浮点性能方面继续超越微处理器&#xff0c;这种情况正在加剧。线性代数和数字信号处理 (DSP) 等高级算法可以受益于浮点数据类型的高动态范围精度。LabVIEW FPGA 通过…

【Godot4自学手册】第二十五利用PointLight2D节点点缀夜晚灯光

夜晚来临了&#xff0c;少不了灯光的出现&#xff0c;今天就用PointLight2D节点来实现夜晚的忽闪忽闪灯光效果。 一、添加场景 1、添加PointLight2D场景 单击添加新节点按钮&#xff0c;在场景面板中选择其他节点&#xff0c;在弹出创建Node对话框中选择 PointLight2D&#…

Vue中使用Lodash

Vue中使用Lodash 前言安装Lodash引用方法vue中使用1、cloneDeep 深拷贝2、uniq 数组去重3、uniqWith 数组对象去重 isEqual 深度比对4、intersection 提取数组相同元素5、chunk 数组切分6、compact去除假值7、reject:根据条件删除指定的值8、find:查找结果的第一个值9、filter:…

基于sortablejs实现拖拽element-ui el-table表格行进行排序

可以用原生的dragstart、drag、dragend、dragover、drop、dragleave实现这个效果&#xff0c;但是有现成的轮子就不要重复造了&#xff0c;看效果&#xff1a; <template><el-table :class"$options.name" :data"tableData" ref"table"…

Android Kotlin知识汇总(一)编程语言

在 2019 年 Google I/O 大会上宣布今后将优先采用 Kotlin 进行 Android 开发。Kotlin 是一种富有表现力且简洁的编程语言&#xff0c;不仅可以减少常见代码错误&#xff0c;还可以轻松集成到现有应用中。如果您想构建 Android 应用&#xff0c;建议您从 Kotlin 开始着手&#x…

java.lang.NoSuchMethodException异常解决

标题 java.lang.NoSuchMethodException异常的正确解决方法摘要&#x1f680; 异常介绍&#x1f9d0; 异常原因分析&#x1f6e0; 解决方法核对方法名称和参数使用正确的方法签名调整方法访问权限 &#x1f4dd; 解决步骤详解&#x1f5a5; 代码案例演示❓ QA部分Q: 如何区分jav…

使用canvas实现图纸标记及回显

图纸 图纸标记后的效果图 最近做的一个qms项目里面&#xff0c;需要前端在图纸上实现标记及标记后的内容还要能够回显&#xff0c;然后后端通过标记的点&#xff0c;去读取标记图纸的内容&#xff0c;如一些公式、数据之类的&#xff0c;目前实现的功能有 在图纸上面进行矩形…

【论文阅读】DiffSpeaker: Speech-Driven 3D Facial Animation with Diffusion Transformer

DiffSpeaker: 使用扩散Transformer进行语音驱动的3D面部动画 code&#xff1a;GitHub - theEricMa/DiffSpeaker: This is the official repository for DiffSpeaker: Speech-Driven 3D Facial Animation with Diffusion Transformer paper&#xff1a;https://arxiv.org/pdf/…

MyBatis基础使用

MyBatis 是一款优秀的持久层框架&#xff0c;它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO&#xff08;Plain Old Java Objects&am…

2024 年(第 12 届)“泰迪杯”数据挖掘挑战赛——A 题:生产线的故障自动识别与人员配置具体思路以及源代码分析

一、问题背景 随着新兴信息技术的大规模应用&#xff0c;工业生产线的智能化控制技术日益成熟。自动生产线 可以自动完成物品传送、物料填装、产品包装和质量检测等过程&#xff0c;极大地提高了生产效率和 产品质量&#xff0c;减少了生产成本。自动生产线融入故障智能报警…

HTML CSS入门:从基础到实践

&#x1f310; HTML & CSS入门&#xff1a;从基础到实践 &#x1f3a8; &#x1f4d6; 引言 HTML和CSS是构建网页的基石。HTML&#xff08;超文本标记语言&#xff09;用于创建网页内容&#xff0c;而CSS&#xff08;层叠样式表&#xff09;则用于美化这些内容。无论你是…

Blocks —— 《Objective-C高级编程 iOS与OS X多线程和内存管理》

目录 Blocks概要什么是BlocksOC转C方法关于几种变量的特点 Blocks模式Block语法Block类型 变量截获局部变量值__block说明符截获的局部变量 Blocks的实现Block的实质 Blocks概要 什么是Blocks Blocks是C语言的扩充功能&#xff0c;即带有局部变量的匿名函数。 顾名思义&#x…

Day18 Java学生管理系统

Day18 Java学生管理系统 一、需求分析 考虑的方面&#xff1a; 用户需求、功能需求、非功能性需求、约束条件、优先级和权衡、可追踪性、需求验证。 二、项目搭建 搭建学生管理系统 1、创建项目的main ;pojo ; sms ; utils包。 2、编写系统的 增&#xff08;涉及到扩容–…

17.WEB渗透测试--Kali Linux(五)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;16.WEB渗透测试--Kali Linux&#xff08;四&#xff09;-CSDN博客 1.ettercap简介与使用…

【技术类-04】python实现docx表格文字和段落文字的“手动换行符(软回车)”变成“段落标记(硬回车)”

作品展示&#xff1a; 背景需求&#xff1a; 把python实现docx表格文字和段落文字的“手动换行符&#xff08;软回车&#xff09;”变成“段落标记&#xff08;硬回车&#xff09;合并在一起统计数量 【技术类-02】python实现docx段落文字的“手动换行符&#xff08;软回车&a…

一起玩儿3D打印机——03 Marlin固件的获取和安装环境的配置

摘要&#xff1a;本文介绍Marlin固件的获取和安装环境的配置 Marlin是一款开源软件&#xff0c;其主页为&#xff1a;https://marlinfw.org/&#xff0c;首页正中就是下载连接&#xff0c;如下图所示&#xff1a; 单击下面的“Download Marlin 2.1.2.2”按钮就会进入下载页面&a…

彻底学会系列:一、机器学习之梯度下降(1)

1 梯度下降概念 1.1 概念 梯度下降是一种优化算法&#xff0c;用于最小化一个函数的值&#xff0c;特别是用于训练机器学习模型中的参数&#xff0c;其基本思想是通过不断迭代调整参数的值&#xff0c;使得函数值沿着梯度的反方向逐渐减小&#xff0c;直至达到局部或全局最小…