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://www.mzph.cn/news/751440.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端框架vue的样式操作,以及vue提供的属性功能应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

【Linux】环境基础开发工具使用

目录 Linux软件管理器 yum 1.什么是软件包 2.查看软件包 3安装与卸载 vim-Linux编辑器 1.vim基础概念 2.vim的基础操作 命令模式基本操作 底层模式基本操作 3、其它模式 Linux编译器 gcc/g 1.如何进行编译 2.编译的四个过程 预处理(-E) 编译(-S) 汇编(-c) 链接…

python二级备考(2)-简单应用题

第1套 使用turtle库的turtle. right()函数和turtle.fd()函数绘制一个菱形&#xff0c;边长为200像素&#xff0c;4个内角度数为2个60度和2个120度 键盘输入一组人员的姓名、性别、年龄等信息&#xff0c;信息间采用空格分隔&#xff0c;每人一行&#xff0c;空行回车结束录入&a…

EMQX 实践

MQTT 核心概念 发布订阅 MQTT 基于发布订阅模式&#xff0c;它解耦了消息的发送方&#xff08;发布者&#xff09;和接收方&#xff08;订阅者&#xff09;&#xff0c;引入了一个中间代理的角色来完成消息的路由和分发。发布者和订阅者不需要知道彼此的存在&#xff0c;他们…

mybatis实践篇(一)

日志&#xff08;logImpl&#xff09; StdOutImpl <setting name"logImpl" value"org.apache.ibatis.logging.stdout.StdOutImpl"/>Slf4jImpl <setting name"logImpl" value"org.apache.ibatis.logging.slf4j.Slf4jImpl"/&…

cannot find -xml2: No such file or directory的解决方法

一&#xff0c;问题现象 在编译库的时候出现如下图所示的报错&#xff1a;C:/msys64/mingw32/bin/…/lib/gcc/i686-w64-mingw32/13.2.0/…/…/…/…/i686-w64-mingw32/bin/ld.exe: ca nnot find -lxml2: No such file or directory collect2.exe: error: ld returned 1 exit s…

146 Linux 网络编程2 ,Socket编程,如何创建Linux 服务器 和linux 客户端

IPport 就是一个程序在网络上的身份证号码。 这意味着我们需要如果写一个服务器&#xff0c;至少需要将这台服务器的ip 和 端口号写到程序里面。 实际上更细化的说&#xff1a;应该是将这三都写进程序里面 &#xff1a; IP类型&#xff08;IPV4或者IPV6&#xff09;&#xff…

linux——进程(1)

目录 一、概念 1.1、认识进程 1.2、进程描述符&#xff08;PCB&#xff09; 1.3、进程的结构体&#xff08;task_struct&#xff09; 二、查看进程 三、获取进程的Pid和PPid 3.1、通过系统调用获取进程的PID和PPID 四、创建进程 4.1、fork() 4.2、用if进行分流 五、…

NCV1117ST50T3G线性稳压器芯片中文资料规格书PDF数据手册引脚图图片价格参数

产品概述&#xff1a; NCP1117系列为低压差&#xff08;LDO&#xff09;正向线性电压稳压器&#xff0c;能够提供超过1.0A的输出电流&#xff0c;800mA时温度范围内最大压差为1.2V。这一系列包括八个固定输出电压&#xff1a;1.5V、1.8V、2.0V、2.5V、2.85V、3.3V、5.0V 和 12…

2024/3/15 记录简版抖音部署遇到的问题

1、Centos连不上网 参考这一篇&#xff1a;虚拟机 CentOS 有线连接图标直接消失&#xff0c;网络连接不上&#xff0c;网络连接失败的解决方案&#xff08;亲测有效&#xff09;_centos网络图标不见了-CSDN博客 2、SQLyog连接不到docker中的mysql 原因是对密码有加密过程 &a…

STM32F407_多点电容触摸(GT911)驱动

目录标题 前言1、简单介绍2、触摸芯片与主机的硬件连接3、内部寄存器3.1、控制寄存器&#xff08;0X8040&#xff09;3.2、配置寄存器组&#xff08;0X8047~0X8100&#xff09;3.3、状态寄存器(0x814E)3.4、坐标寄存器(0x8150-0x8177) 4、初始化流程4.1、IIC地址选择4.2、更新G…

html--简历

文章目录 html html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"maximum-scale1.0,minimum-scale1.0,user-scalable0,widthdevice-width,initial-scale1.0&qu…

字母异位词分组【每日一题】

可以通过案例找到规律&#xff0c;每个词排序完后是同一个&#xff0c;所以通过hasmap存储排序过的值做key&#xff0c;值是存储单词集合。 package HasTable;import java.util.*;class Solution {static List<List<String>> groupAnagrams(String[] strs) {Map&l…

jupyter notebook 突然莫名奇妙的白屏

jupyter notebook 突然莫名奇妙的白屏 事件背景&#xff1a; 最近在折腾openai&#xff0c;哎&#xff0c;一言难尽&#xff0c;使用的是conda管理python版本的切换&#xff0c;使用jupyter notebook来运行python程序&#xff0c;其实PyCharm也行&#xff0c;但是&#xff0c;…

【递归搜索回溯专栏】专题二:二叉树中的深搜----二叉树剪枝

本专栏内容为&#xff1a;递归&#xff0c;搜索与回溯算法专栏。 通过本专栏的深入学习&#xff0c;你可以了解并掌握算法。 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;递归搜索回溯专栏 &#x1f69a;代码仓库&#xff1a;小小unicorn的代…

redis发布订阅与stream类型

发布订阅 redis发布订阅(pub/sub)是一种消息通信模式&#xff1b;发送者(pub)发送消息&#xff0c;订阅者(sub)接收消息。redis客户端可以订阅任意数量的频道。 基础命令&#xff1a; 语法 redis publish命令基本语法如下&#xff1a; redis 127.0.0.1:6379> PUBLISH ch…

Matlab|考虑可再生能源消纳的电热综合能源系统日前经济调度模型

目录 1 主要内容 模型示意图 目标函数 程序亮点 2 部分程序 3 程序结果 4 下载链接 1 主要内容 本程序参考文献《考虑可再生能源消纳的建筑综合能源系统日前经济调度模型》模型&#xff0c;建立了电热综合能源系统优化调度模型&#xff0c;包括燃气轮机、燃气锅炉、余热…

Python基础(七)之数值类型集合

Python基础&#xff08;七&#xff09;之数值类型集合 1、简介 集合&#xff0c;英文set。 集合&#xff08;set&#xff09;是由一个或多个元素组成&#xff0c;是一个无序且不可重复的序列。 集合&#xff08;set&#xff09;只存储不可变的数据类型&#xff0c;如Number、…

修改yolov9的模型打印不出来Gflops的解决办法

正在修改yolov9的模块&#xff0c;发现修改后的模型没有GFlops这个参数 解决办法&#xff1a; 找到utils/torch_utils.py这个文件&#xff0c;有一个model_info函数 然后将其中的stride改为固定的640就可以打印了。 stride max(int(model.stride.max()), 32) if hasattr(mo…