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

EPICS modbus 模块数字量读写练习

本文使用modbus slave软件模拟一个受控的modbus设备,此模拟设备提供如下功能:

1、线圈组1,8个线圈,起始地址为0,数量为8,软件设置如下(功能码1),用于测试功能码5,一次写一个线圈:

2、线圈组2,8个线圈,起始地址为8,数量为8,软件设置如下(功能码1),用于测试功能码15,一次写多个线圈。:

3、离散输入组,8个二进制离散输入,起始地址为0,数量为8,软件设置如下(功能码2):

使用EPICS Modbus模块对以上modbus设备进行读写,过程如下:

使用makeBaseApp.pl构建IOC程序框架,并且在configure/RELEASE中指定base所在路径以及所需要的支持模块modbus路径。在程序的src路径下Makefile中指定要添加的数据块定义文件和库文件。

在程序的Db目录下,编写如下模板文件:

1) bo_bit.template:用于写modbus设备的单线圈

record(bo,"$(P)$(R)") {field(DTYP,"asynUInt32Digital")field(OUT,"@asynMask($(PORT) $(OFFSET) 0x1)")field(ZNAM,"$(ZNAM)")field(ONAM,"$(ONAM)")
}

2)bi_bit.template:用于读modbus设备的线圈状态或者离散输入状态

record(bi,"$(P)$(R)") {field(DTYP,"asynUInt32Digital")field(INP,"@asynMask($(PORT) $(OFFSET) 0x1)")field(SCAN,"$(SCAN)")field(ZNAM,"$(ZNAM)")field(ONAM,"$(ONAM)")field(ZSV,"$(ZSV)")field(OSV,"$(OSV)")
}

3)wfo_bit.template:用于一次写modbus设备的多个线圈

record(waveform,"$(P)$(R)") {field(DTYP,"asynInt32ArrayOut")field(INP,"@asyn($(PORT) $(OFFSET=0))MODBUS_DATA")field(FTVL,"ULONG")field(NELM,"$(NELM)")
}

4) wfi_bit.template:用于读取modbus设备多个线圈状态或这多个离散输入状态。

record(waveform,"$(P)$(R)") {field(DTYP,"asynInt32ArrayIn")field(INP,"@asyn($(PORT) $(OFFSET=0))MODBUS_DATA")field(SCAN,"$(SCAN)")field(FTVL,"ULONG")field(NELM,"$(NELM)")
}

将以上模板文件添加到相同路径下Makefile文件中:

...
DB +=  bo_bit.template
DB +=  bi_bit.template
DB +=  wfo_bit.template
DB +=  wfi_bit.template
...

回到IOC顶层目录,执行make命令,编译这个IOC。

进入到启动目录iocBoot/iocmodbusbit中,编写记录实例化文件:

1)coil_bo_bits.substitutions:用于实例化8个bo记录,每个bo写modbus设备1个线圈。

file "../../db/bo_bit.template" { pattern
{P,        R,             PORT,       OFFSET,   ZNAM,   ONAM}
{COUT:,    CO0B,     C0_Out_Bits,     0,        Low,    High}
{COUT:,    CO1B,     C0_Out_Bits,     1,        Low,    High}
{COUT:,    CO2B,     C0_Out_Bits,     2,        Low,    High}
{COUT:,    CO3B,     C0_Out_Bits,     3,        Low,    High}
{COUT:,    CO4B,     C0_Out_Bits,     4,        Low,    High}
{COUT:,    CO5B,     C0_Out_Bits,     5,        Low,    High}
{COUT:,    CO6B,     C0_Out_Bits,     6,        Low,    High}
{COUT:,    CO7B,     C0_Out_Bits,     7,        Low,    High}
}

2)coil_bi_bits.substitutions:用于实例化16个bi记录,每个bi读取modbus设备1个线圈状态。

file "../../db/bi_bit.template" { pattern
{P,        R,          PORT,         OFFSET,   ZNAM,   ONAM,  ZSV,       OSV,    SCAN}
{CIN:,    CI00B,     C0_In_Bits,     0,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI01B,     C0_In_Bits,     1,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI02B,     C0_In_Bits,     2,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI03B,     C0_In_Bits,     3,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI04B,     C0_In_Bits,     4,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI05B,     C0_In_Bits,     5,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI06B,     C0_In_Bits,     6,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI07B,     C0_In_Bits,     7,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI08B,     C1_In_Bits,     0,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI09B,     C1_In_Bits,     1,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI10B,     C1_In_Bits,     2,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI11B,     C1_In_Bits,     3,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI12B,     C1_In_Bits,     4,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI13B,     C1_In_Bits,     5,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI14B,     C1_In_Bits,     6,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI15B,     C1_In_Bits,     7,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
}

3)dis_bi_bits.substitutions:用于实例化8个bi记录,每个bi取modbus设备离散输入状态。

file "../../db/bi_bit.template" { pattern
{P,        R,          PORT,         OFFSET,   ZNAM,   ONAM,  ZSV,       OSV,    SCAN}
{DIN:,    DI00B,     D0_In_Bits,     0,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{DIN:,    DI01B,     D0_In_Bits,     1,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{DIN:,    DI02B,     D0_In_Bits,     2,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{DIN:,    DI03B,     D0_In_Bits,     3,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{DIN:,    DI04B,     D0_In_Bits,     4,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{DIN:,    DI05B,     D0_In_Bits,     5,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{DIN:,    DI06B,     D0_In_Bits,     6,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{DIN:,    DI07B,     D0_In_Bits,     7,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
}

4)coil_wfo_bits.substitutions:实例化一个waveform记录,用于一次最多设置modbus设备8个线圈。

file "../../db/wfo_bit.template" { pattern
{P,        R,             PORT,       OFFSET,   NELM}
{COUT:,    WFO,            C0_Out_WF,         0,        8}
}

5) dis_wfi_bits.substitutions:实例化一个waveform记录,用于读取modbus设备8个离散输入的状态。

file "../../db/wfi_bit.template" { pattern
{P,        R,          PORT,         OFFSET,   , NELM ,    SCAN}
{DIN:,    WFI,         D0_In_Bits,     8,       8,  "I/O Intr"}
}

编写启动脚本st.cmd:

#!../../bin/linux-x86_64/modbuspoll#- You may have to change modbuspoll to something else
#- everywhere it appears in this file< envPathscd "${TOP}"## Register all support components
dbLoadDatabase "dbd/modbuspoll.dbd"
modbuspoll_registerRecordDeviceDriver pdbbase# 连接modbus设备
drvAsynIPPortConfigure("mpoll","192.168.3.15:502",0,0,1)
# 使用modbus tcp类型
modbusInterposeConfig("mpoll", 0 ,2000,0)# 用于写线圈,起始地址0,每次写1个,一共写8次
drvModbusAsynConfigure("C0_Out_Bits", "mpoll", 0, 5,  0, 8, 0,  100, "mpoll")
# 用于写线圈,起始地址8,一次写8个线圈
drvModbusAsynConfigure("C0_Out_WF",   "mpoll", 0, 15, 8, 8, 0,  100, "mpoll")# 用于读线圈,起始地址0,每次读取一个,一共读8次,轮询时间为500ms
drvModbusAsynConfigure("C0_In_Bits",  "mpoll", 0, 1,  0, 8, 0,  500, "mpoll")
# 用于读线圈,起始地址8,每次读取一个,一共读8次,轮询时间为500ms
drvModbusAsynConfigure("C1_In_Bits",  "mpoll", 0, 1,  8, 8, 0,  500, "mpoll")# 用于读取离散输入,起始地址0,每次读取一个,读取8次,轮询时间100ms
drvModbusAsynConfigure("D0_In_Bits", "mpoll",  0,  2, 0, 8, 0,  100, "mpoll")cd "${TOP}/iocBoot/${IOC}"
# 加载实例化记录
# 写线圈
dbLoadTemplate("coil_bo_bits.substitutions")
# 写线圈
dbLoadTemplate("coil_wfo_bits.substitutions")
# 读线圈
dbLoadTemplate("coil_bi_bits.substitutions")
# 读离散输入
dbLoadTemplate("dis_bi_bits.substitutions")
# 读离散输入
dbLoadTemplate("dis_wfi_bits.substitutions")iocInit

启动这个IOC:

[root@localhost iocmodbusbit]# ../../bin/linux-x86_64/modbuspoll st.cmd
#!../../bin/linux-x86_64/modbuspoll
...
# bit write
drvModbusAsynConfigure("C0_Out_Bits", "mpoll", 0, 5,  0, 8, 0,  100, "mpoll")
# bit array write
drvModbusAsynConfigure("C0_Out_WF",   "mpoll", 0, 15, 8, 8, 0,  100, "mpoll")
# Coil bit Read
drvModbusAsynConfigure("C0_In_Bits",  "mpoll", 0, 1,  0, 8, 0,  500, "mpoll")
drvModbusAsynConfigure("C1_In_Bits",  "mpoll", 0, 1,  8, 8, 0,  500, "mpoll")
# Discrete bit Read
drvModbusAsynConfigure("D0_In_Bits", "mpoll",  0,  2, 0, 8, 0,  100, "mpoll")
cd "/usr/local/EPICS/program/modbuspoll/iocBoot/iocmodbusbit"
dbLoadTemplate("coil_bo_bits.substitutions")
dbLoadTemplate("coil_wfo_bits.substitutions")
dbLoadTemplate("coil_bi_bits.substitutions")
dbLoadTemplate("dis_bi_bits.substitutions")
dbLoadTemplate("dis_wfi_bits.substitutions")
iocInit
Starting iocInit
...
## Start any sequence programs
#seq sncxxx,"user=blctrl"
epics> dbl
COUT:CO0B
COUT:CO1B
COUT:CO2B
COUT:CO3B
COUT:CO4B
COUT:CO5B
COUT:CO6B
COUT:CO7B
COUT:WFO
DIN:WFI
CIN:CI00B
CIN:CI01B
CIN:CI02B
CIN:CI03B
CIN:CI04B
CIN:CI05B
CIN:CI06B
CIN:CI07B
CIN:CI08B
CIN:CI09B
CIN:CI10B
CIN:CI11B
CIN:CI12B
CIN:CI13B
CIN:CI14B
CIN:CI15B
DIN:DI00B
DIN:DI01B
DIN:DI02B
DIN:DI03B
DIN:DI04B
DIN:DI05B
DIN:DI06B
DIN:DI07B

1) COUT:CO0B~COUT:CO7B:bo记录,每个bo记录用于写一个线圈。

2)COUT:WF:waveform记录,用于一次写8个线圈。

3)DIN:WFI:waveform记录,用于读取8个离散输入。

4)CIN:CI00B~CIN:CI15B:bi记录,每个bi记录读取一个线圈状态。

5)DIN:DI00B~DIN:DI00B,bi记录,每个bi记录读取一个离散输入。

用css绘制控制界面,进行记录连接后,如下所示:

1)顶层窗口区域:Coil Out按钮写线圈,Coil In回读线圈状态

2)中间窗口区域:Coil Array Out可以一次最多写8个线圈,Coil In回读线圈状态。

3)底层窗口区域:用于读取离散输入,离散输入状态需要在modbus slave窗口中设置 ,Discrete Bit in 和Discrete Bit Array In都回读modbus slave窗口中设置的离散输入的状态。

相关文章:

EPICS modbus 模块数字量读写练习

本文使用modbus slave软件模拟一个受控的modbus设备&#xff0c;此模拟设备提供如下功能&#xff1a; 1、线圈组1&#xff0c;8个线圈&#xff0c;起始地址为0&#xff0c;数量为8&#xff0c;软件设置如下(功能码1)&#xff0c;用于测试功能码5&#xff0c;一次写一个线圈&am…...

万界星空科技低代码平台:搭建MES系统的优势

低代码MES系统&#xff1a;制造业数字化转型的捷径 随着制造业的数字化转型&#xff0c;企业对生产管理系统的需求逐渐提高。传统的MES系统实施过程复杂、成本高昂&#xff0c;已经无法满足现代企业的快速发展需求。而低代码搭建MES系统的出现&#xff0c;为企业提供了一种高…...

【ArcGIS微课1000例】0078:创建点、线、面数据的最小几何边界

本实例为专栏系统文章:讲述在ArcMap10.6中创建点数据最小几何边界(范围),配套案例数据,持续同步更新! 文章目录 一、工具介绍二、实战演练三、注意事项一、工具介绍 创建包含若干面的要素类,用以表示封闭单个输入要素或成组的输入要素指定的最小边界几何。 工具位于:数…...

五花八门客户问题(BUG) - 数据库索引损坏

问题 曾经有个客户问题&#xff0c;让我们开发不知所措了很久。简单点说就是客户的index周期性的损坏&#xff0c;即使全部重建后经历大约1~2周数据update后也会坏掉。导致的直接结果&#xff1a;select出来的数据不对。问题很严重。 直接看损坏的index文件看不出什么蛛丝马迹…...

mysql select count 非常慢

MySQL select count 性能分析 问题&#xff1a;mysql 在count时发现非常慢 select count(*) from xxx; 无论执行多少次&#xff0c;查询速度基本稳定在10-12秒之间 环境说明 windows11 x64SSD硬盘MySQL8.0.35数据库引擎为InnoDB数据行数不到3万行&#xff0c;但是数据量将近…...

Tomcat管理功能使用

前言 Tomcat管理功能用于对Tomcat自身以及部署在Tomcat上的应用进行管理的web应用。在默认情况下是处于禁用状态的。如果需要开启这个功能&#xff0c;需要配置管理用户&#xff0c;即配置tomcat-users.xml文件。 &#xff01;&#xff01;&#xff01;注意&#xff1a;测试功…...

kyuubi整合flink yarn session mode

目录 概述配置flink 配置kyuubi 配置kyuubi-defaults.confkyuubi-env.shhive 验证启动kyuubibeeline 连接使用hive catlogsql测试 结束 概述 flink 版本 1.17.1、kyuubi 1.8.0、hive 3.1.3、paimon 0.5 整合过程中&#xff0c;需要注意对应的版本。 注意以上版本 配置 ky…...

err_connect_length_mismatch错误

原因: 官网解释为&#xff1a;err_content_length_mismatch:错误的内容长度不匹配&#xff08;请求的Heather 里content-length长度与返回的content-length不一致&#xff09; 问题截图: 分析: 由截图可见,静态资源加载错误,提示err_content_length_mismatch,经排查,网络页签…...

dva的学习总结

公司的项目源码用的是react和dva&#xff0c;所以我必须抓紧时间学习一下dva了&#xff0c;一天时间&#xff0c;看看我学到了什么&#xff08;dva官网DvaJS&#xff09;[这是很久之前就打算写的了&#xff0c;一直没时间&#xff0c;一直存着草稿&#xff0c;今天发出来吧] 1…...

Docker部署.NET6项目

Docker的三大核心概念 1、docker仓库&#xff08;repository&#xff09; docker仓库&#xff08;repository&#xff09;类似于代码库&#xff0c;是docker集中存放镜像的场所。实际上&#xff0c;注册服务器是存放仓库的地方&#xff0c;其上往往存放着很多仓库。每个仓库集…...

Pandas 打开有密码的Excel

安装包 pip isntall msoffcrypto-tool msoffcrypto库的简单介绍 msoffcrypto提供了对Microsoft Office文件进行加密和解密的功能。它支持对Word、Excel和PowerPoint文件进行加密和解密操作。 msoffcrypto的原理是利用Microsoft Office文件的加密算法对文件进行加密和解密。它能…...

CCF 202104-2:邻域均值--C++

#include<iostream> #include<bits/stdc.h>using namespace std;int A[601][601]; int n;//长宽都为n个像素double FindNeighborSum(int i,int j,int r,int A[][601]) {int sum0;//像素和 int gs0;//领域 中的像素个数 for(int xi-r;x<ir;x)//找到每一个领域像素…...

基于JAVA+SpringBoot+Vue的前后端分离的医院信息智能化HIS系统

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 随着科技的不断发展&a…...

Kotlin Flow 操作符

前言 Kotlin 拥有函数式编程的能力&#xff0c;使用Kotlin开发&#xff0c;可以简化开发代码&#xff0c;层次清晰&#xff0c;利于阅读。 然而Kotlin拥有操作符很多&#xff0c;其中就包括了flow。Kotlin Flow 如此受欢迎大部分归功于其丰富、简洁的操作符&#xff0c;巧妙使…...

HarmonyOS4.0从零开始的开发教程08构建列表页面

HarmonyOS&#xff08;六&#xff09;构建列表页面 List组件和Grid组件的使用 简介 在我们常用的手机应用中&#xff0c;经常会见到一些数据列表&#xff0c;如设置页面、通讯录、商品列表等。下图中两个页面都包含列表&#xff0c;“首页”页面中包含两个网格布局&#xff…...

分布式环境下的session 共享-基于spring-session组件和Redis实现

1、问题概述 不是所有的项目都是单机模式的&#xff0c;当一个项目服务的局域比较广&#xff0c;用户体量比较大&#xff0c;数据量较大的时候&#xff0c;我们都会将项目部署到多台服务器上&#xff0c;这些个服务器都是分布在不同的区域&#xff0c;这样实现了项目的负载和并…...

docker基本管理和相关概念

docker是什么&#xff1f; docker是开源的应用容器引擎。基于go语言开发的。运行在Linux系统当中开源轻量级的“虚拟机”。 docker的容器技术可以在一台主机上轻松的为任何应用创建一个轻量级的&#xff0c;可移植的&#xff0c;自给自足的容器。 docker的宿主机是Linux系统…...

Linix服务器添加dns解析

Linix开通互联网域名地址出现&#xff0c;如下错误&#xff1a; 需要访问的服务器上添加dns解析 vim /etc/sysconfig/network-scripts/ifcfg-ens192 添加如下配置&#xff1a; DNS1202.96.134.13 重启网卡&#xff1a; systemctl restart network 注意如果是docker服务部署…...

llama.cpp部署(windows)

一、下载源码和模型 下载源码和模型 # 下载源码 git clone https://github.com/ggerganov/llama.cpp.git# 下载llama-7b模型 git clone https://www.modelscope.cn/skyline2006/llama-7b.git查看cmake版本&#xff1a; D:\pyworkspace\llama_cpp\llama.cpp\build>cmake --…...

STM32CubeMX+micro_ros_stm32cubemx_utils库

GitHub - micro-ROS/micro_ros_stm32cubemx_utils at humble 这个就是下载这个代码库以后的文件结构。其中sample_project.ioc就是平时STM32CubeMX的工程文件。类似于visual studio里面的项目文件 。打开以后是这个样子的&#xff1a; 可以看到跟本文后面的那些配置是几乎一模一…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码&#xff0c;写上注释 当然可以&#xff01;这段代码是 Qt …...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

mac 安装homebrew (nvm 及git)

mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用&#xff1a; 方法一&#xff1a;使用 Homebrew 安装 Git&#xff08;推荐&#xff09; 步骤如下&#xff1a;打开终端&#xff08;Terminal.app&#xff09; 1.安装 Homebrew…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...