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

< envPaths

cd "${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窗口中设置的离散输入的状态。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

了解红帽认证

红帽公司成立于1993年&#xff0c;是全球首家收入超10亿美元的开源公司&#xff0c;总部位于美国&#xff0c;分支机构遍布全球。红帽公司作为全球领先的开源和Linux系统提供商&#xff0c;其产品已被业界广泛认可并使用&#xff0c;尤其是RHEL系统在业内拥有超高的Linux系统市…

利用Node.js和cpolar实现远程访问,无需公网IP和路由器设置的完美解决方案

文章目录 前言1.安装Node.js环境2.创建node.js服务3. 访问node.js 服务4.内网穿透4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5.固定公网地址 前言 Node.js 是能够在服务器端运行 JavaScript 的开放源代码、跨平台运行环境。Node.js 由 OpenJS Foundation&#xff0…

Dockerfile的介绍和使用

什么是dockerfile? Dockerfile是一个包含用于组合映像的命令的文本文档。可以使用在命令行中调用任何命令。 Docker通过读取Dockerfile中的指令自动生成映像。 docker build命令用于从Dockerfile构建映像。可以在docker build命令中使用-f标志指向文件系统中任何位置的Dockerf…

c语言:理解和避免野指针

野指针的定义&#xff1a; 野指针是指一个指针变量存储了一个无效的地址&#xff0c;通常是一个未初始化的指针或者指向已经被释放的内存地址。当程序尝试使用野指针时&#xff0c;可能会导致程序崩溃、内存泄漏或者其他不可预测的行为。因此&#xff0c;在编程中需要特别注意…

二叉树前中后序遍历——(非)递归写法

文章目录 前言递归实现非递归实现力扣习题 红色&#xff1a;前序遍历顺序绿色&#xff1a;中序遍历顺序蓝色&#xff1a;后续遍历顺序 前言 二叉树遍历也分为两种 广度优先遍历&#xff08;Breadth-first order&#xff09;&#xff1a;尽可能先访问距离根最近的节点&#x…

未成年人保护成为《蛋仔派对》最高优先级工作,与家长携手保护孩子健康成长

《蛋仔派对》于近日发布致家长的第二封信&#xff0c;信中向社会各界公布了正在推出的三大“防沉迷”举措&#xff0c;严防“冒用成年人账号”等行为&#xff0c;针对家长关心的未成年防沉迷、冒用成年人账号、渠道服充值退款难等问题进行回应。 《蛋仔派对》表示始终把未成年…

多窗口文件管理工具Q-Dir安装以及使用教程

软件介绍 Q-Dir 是一款功能强大的Windows资源管理器&#xff0c;可以非常方便的管理你的各种文件。Q-Dir有4 个窗口&#xff0c;特别适用于频繁在各个目录间跳跃复制粘贴的情况&#xff0c;每个窗口都可以方便的切换目录&#xff0c;以不同颜色区分不同类型的文件&#xff0c;…

分销电商结算设计

概述 分销电商中涉及支付与结算&#xff1b;支付职责是收钱&#xff0c;结算则是出钱给各利益方&#xff1b; 结算核心围绕业务模式涉及哪些费用&#xff0c;以及这些费用什么时候通过什么出资渠道&#xff0c;由谁给到收方利益方&#xff1b; 结算要素组成费用项结算周期出…

持续集成交付CICD:Jenkins配置Nexus制品上传流水线

目录 一、实验 1.Jenkins配置制品上传流水线 二、问题 1.上传制品显示名称有误 一、实验 1.Jenkins配置制品上传流水线 (1) 新建流水线项目 &#xff08;2&#xff09;描述 &#xff08;3&#xff09;添加参数 &#xff08;4&#xff09;查看构建首页 &#xff08;5&…

体验一下使用 ArkUI 进行 HarmonyOS 开发并与 Compose 简单对比

前言 最近几年各个技术公众号和技术群都在唱衰原生安卓开发&#xff0c;疯狂贩卖焦虑。 搞得我也焦虑的不行&#xff0c;在谷歌的 Compose 推出后就赶紧去学&#xff0c;但是又觉得好像 Compose 的热度也不算太高&#xff0c;又去学 Flutter 。 转头两个都还没学明白呢&…

机器学习入门笔记

文章目录 背景具体步骤1.环境搭建2.写个demo1.数据处理2.分割数据集3.用模型训练数据&#xff0c;并得到预测结果4.绘制结果5.评估 背景 最近学习了一些关于机器学习的内容&#xff0c;做个笔记。 具体步骤 1.环境搭建 需要用到的工具&#xff1a;pycharm&#xff0c;anaco…

YOLOv5目标检测

文章目录 软硬件环境前言安装GPU环境安装pytorch的GPU版本YOLOv5测试v3.0版本参考资料 软硬件环境 ubuntu 18.04 64bitanaconda with 3.7nvidia gtx 1070Ticuda 10.1pytorch 1.5YOLOv5 前言 YOLOv4还没有退热&#xff0c;YOLOv5就已经来了&#xff01; 6月9日&#xff0c…

【力扣】141和142环形链表

141.环形链表 法一&#xff1a;快慢指针 思路&#xff1a; 用两个指针slow,fast,后者能比前者多走一步路&#xff0c;那判断是不是有环&#xff0c;只需要判断是否会相遇。 就是有一个能比乌龟跑2倍快的兔子&#xff0c;两小只都在有环的路上跑&#xff0c;那是不是肯定会相…

流水号的获取

软件中&#xff0c;常常使用流水号&#xff0c;通常流水号是一组参数的组合&#xff0c;如&#xff1a;评估报告的编号结构&#xff1a; 区编号-机构类型-年份-性别-流水 如&#xff1a;03-01-2023-W-0001 03-01-2023-M-0002 03-01-2023-M-0003 。。。。。。 编程时&#xff0c…

提示msvcp90.dll丢失的解决方法,找不到msvcp90.dll问题全方面分析

今天我想和大家分享的主题是关于在使用软件时遇到的一个问题——msvcp90.dll丢失。相信很多老师在使用电脑时都遇到过这个问题&#xff0c;那么接下来我将从三个方面为大家介绍&#xff1a;msvcp90.dll文件是什么、msvcp90.dll丢失原因以及msvcp90.dll丢失的5个解决方案。 首先…

中科院分区和JCR分区有什么区别

文章目录 名词解释学科划分不同参考的影响因子不同期刊分区不同期刊分区阈值不同 名词解释 中科院分区&#xff1a;又称“中科院JCR分区”&#xff0c;是中国科学院文献情报中心世界科学前沿分析中心的科学研究成果&#xff0c;期刊分区表数据每年底&#xff08;每年12月中下旬…

windows错误事件 98、41、7000、55、153解决办法

事件错误&#xff1a;98、55、153 疑难解答清单 在系统事件日志中&#xff0c;搜索新技术文件系统 (NTFS) 和磁盘相关的警告和错误。 例如&#xff0c;事件 ID 55、153 或 98。 管理员身份打开CMD&#xff0c;运行命令 chkdsk /scan 并检查结果。 该 chkdsk /scan 命令是只读…

[渗透测试学习] Devvortex - HackTheBox

文章目录 信息搜集解题步骤提交flag 信息搜集 扫描端口 nmap -sV -sC -p- -v --min-rate 1000 10.10.11.242发现80端口有http服务&#xff0c;并且是nginx服务 尝试访问web界面&#xff0c;发现跳转到http://devvortex.htb/无法访问 我们用vim添加该域名即可 sudo vim /etc/…

课后作业7.3.1:构造一个自己的小操作系统

构造一个自己的 mini 操作系统 任务描述 请实现如下功能: 1.写一个命令解释器程序 mysh.c ,其功能是接收用户输入的命令并给出反馈。要求该程序既支持内部命令 cd、sync、exit ;也支持外部命令,即可以接收 cat、ls 等命令,然后执行相应的可执行程序。要求首先在 Ubuntu 中…

电源小白入门学习1——电源系统架构和相关指标

电源小白入门学习1——电源系统架构和相关指标 电源系统架构电源系统的指标及测量方法电源的效率电源的静态电流输出电压调整率纹波测量的注意事项动态负载测试 在开始本期内容之气&#xff0c;我先简单介绍一下我们电源小白学习系列内容&#xff1a;首先我是一个嵌入式小白&am…