这个subroutine记录用于调用一个C初始化程序和一个重复出现的扫描程序。没有设备支持对应这个记录。

参数字段

在以下描述记录专用字段,按功能分组。

扫描参数

subroutine记录有用于指定这个记录在什么情况下将被运行的标准字段。

读取字段

subroutine记录有12格输入记录(INPA-INPL),每个输入链接有一个对应的值字段(A-L)。这些字段用于此记录调用获取和存储能够被传递给这个subroutine的值。

输入链接可以时通道访问或数据库链接或常数。当常数时,用这个常数值初始化对应这个链接的相应值字段,并且在运行时通过dbPuts可以更改这个字段的值。否则,当运行这个记录时从输入链接为(A-F)获取值。

subroutine连接

这些字段用于连接到C子程序。在SNAM字段中应该输入这个子程序的名称。

操作显示参数

这些参数用于向操作显示有意思数据。它们以文本地或图形地显示这个subroutine的值或其它参数。EGU是最长16个字符的字符串,它描述这个subroutine记录使用的任何单位。通过get_units记录支持程序获取它。

HOPR和LOPR字段是用于VAL, A-L, LA-LL, HIHI, LOLO, LOW和HIGH字段的上下显示限制。get_graphic_double和get_control_double记录支持程序都获取这些字段。

PREC字段决定了用什么浮点精度显示VAL。当调用get_precision记录支持时,使用它。

警报参数

对于subroutine记录的可能警报情况是SCAN,READ,limit警报以及如果subroutine返回一个负值能被触发的警报。SCAN和READ警报是被记录或设备支持程序调用。限制的警报是由用户使用数值在HIHI,LOLO,HIGH和LOW字段中配置的。它们应用于VAL字段。对于这些字段中每一个字段,有一个相应的严重性字段,其可以是NO_ALARM, MINOR或MAJOR。

BRSV字段是在这个routine返回一个负值时用户能够设置警报严重性的地方。

警报的字段类列出了与所有记录类型都共有的警报关联。

用于监视的参数

这些参数用于决定何时发出放置于VAL字段上的监视。当VAL不同于在ALST和MLST运行时字段中的值时,调用合适的监视,即是:当VAL的值变化超过了在这些字段中指定的死区时。ADEL和MEDL字段指定在调用值变化监视前这个变化必须超过的最小差值。如果这些字段有一个0值,每次值变化,将触发一个监视;如果它们有一个-1值,每次记录运行,触发监视。ADEL字段被存档监视使用,MDEL字段用于所有其它类型的监视。

运行时参数

这些参数被运行时代码使用,用于运行这个subroutine记录。不能使用数据库配置工具配置它们。它们代表这个记录的当前状态。它们中很多被记录processing程序或监视使用。

VAL字段应该被subroutine设置。SADR保存这个subroutine地址并且由这个记录processing程序设置。

余下字段LALM,ALST,MLST和LA-LL用于实现监视。例如,当LA不等于A,调用对应那个字段的值变化监视。

记录支持

记录支持程序

1) init_record

  long (*init_record)(struct dbCommon *precord, int pass)

对于每个常数输入链接,用这个常数值初始化相应的值字段。对于为类型PV_LINK的每个输入链接,创建一个通道访问。如果定义了一个初始化subroutine,找到并且调用它。进行处理的subroutine被找到并且其地址存储在SADR中。

2) process

  long (*init_record)(struct dbCommon *precord, int pass)

见以下"记录运行""

3) get_units

 long (*get_units)(struct dbAddr *paddr, char *units)

4) get_precsion

 long (*get_precision)(const struct dbAddr *paddr, long *precision)

当VAL时被引用的字段时,获取PREC。否则,调用recGblGetPrec()。

5)  get_graphic_double

 long (*get_graphic_double)(struct dbAddr *paddr, struct dbr_grDouble *p)

为一个字段设置上显示和下显示限制。如果字段是VAL,A-L,LA-LL,HIHI,HIGH,LOW或LOLO,这些限制被设置成HOPR和LOPR,另外如果字段有定义的上和下限制,将使用它们,否则将使用对应这个字段类型的上和下最大值。

6)  get_control_double 

为一个字段设置上显示和下控制限制。如果字段是VAL,A-L,LA-LL,HIHI,HIGH,LOW或LOLO,这些限制被设置成HOPR和LOPR,另外如果字段有定义的上和下限制,将使用它们,否则将使用对应这个字段类型的上和下最大值。

  long (*get_control_double)(struct dbAddr *paddr, struct dbr_ctrlDouble *p)

7) get_alarm_double

  long (*get_alarm_double)(struct dbAddr *paddr, struct dbr_alDouble *p)

设置以下值:

upper_alarm_limit = HIHI
upper_warning_limit = HIGH
lower_warning_limit = LOW
lower_alarm_limit = LOLO

记录运行

程序Process实现以下算法:

1) 如果PACT为FALSE,则获取所有参数。

2) 调用这个subroutine并且检查返回值。

  • 调用subroutine
  • 设置PACT为TRUE
  • 如果返回值是1,返回

3) 检查警报。这个routine检查新的VAL是否引起警报状态和严重性变化。如果发生了,设置NSEV,NSTA和LALM。它也遵守警报回滞因子(HYST)。因而,在警报状态和验证性被降低前,这个值必须变化超过HYST。

4) 检查是否应该调用监视

  • 如果警报状态或严重性发生变化,调用警报监视
  • 如果ADEL和MDEL条件满足了,调用存档和值变化监视
  • 如果A-L的值变化了,调用对应A-L的监视
  • 重置NSEV和NSTA回0

5) 如果需要,扫描forward链接。设置PACT为FALSE并且返回。

示例同步subroutine

这是一个在每次调用process时仅对VAL加1的示例subroutine。

在blctrl用户家目录中的exer目录下创建一个子目录exer2,并且使用makeBaseApp.pl产生一个应用程序目录和一个IOC启动目录:

[blctrl@main-machine ~]$ mkdir exer/exer2
[blctrl@main-machine ~]$ cd exer/exer2
[blctrl@main-machine exer2]$ /usr/local/EPICS/base/bin/linux-x86_64/makeBaseApp.pl -t ioc exer2
[blctrl@main-machine exer2]$ /usr/local/EPICS/base/bin/linux-x86_64/makeBaseApp.pl -i -t ioc exer2
Using target architecture linux-x86_64 (only one available)
The following applications are available:exer2
What application should the IOC(s) boot?
The default uses the IOC's name, even if not listed above.
Application name?
[blctrl@main-machine exer2]$ ls
configure  exer2App  iocBoot  Makefile

进入exer2App/src路径下,编写两个文件 subRecordExample.c和subRecordExample.dbd,其内容如下:

 subRecordExample.c:

#include <stdio.h>
#include <dbDefs.h>
#include <registryFunction.h>
#include <subRecord.h>
#include <epicsExport.h>int mySubDebug = 0;static long mySubInit(struct subRecord *precord)
{if (mySubDebug){printf("Record %s called mySubInit(%p)\n", precord->name, (void *)precord);}printf("subInit was called\n");return 0;
}static long mySubProcess(struct subRecord * precord)
{if(mySubDebug){printf("Record %s called mySubProcess(%p)\n", precord->name,(void *)precord);}precord->val++;return 0;
}epicsExportAddress(int, mySubDebug);
epicsRegisterFunction(mySubInit);
epicsRegisterFunction(mySubProcess);

subRecordExample.dbd:

variable(mySubDebug)
function(mySubInit)
function(mySubProcess)

为在与以上两个文件相同路径下的Makefile文件添加以下两行:

TOP=../..include $(TOP)/configure/CONFIG
#----------------------------------------
#  ADD MACRO DEFINITIONS AFTER THIS LINE
#=============================#=============================
# Build the IOC applicationPROD_IOC = exer2
# exer2.dbd will be created and installed
DBD += exer2.dbd# exer2.dbd will be made up from these files:
exer2_DBD += base.dbd# Include dbd files from all support applications:
#exer2_DBD += xxx.dbd
exer2_DBD += subRecordExample.dbd   # 添加行1exer2_SRCS += subRecordExample.c    # 添加行2# Add all the support libraries needed by this IOC
#exer2_LIBS += xxx# exer2_registerRecordDeviceDriver.cpp derives from exer2.dbd
exer2_SRCS += exer2_registerRecordDeviceDriver.cpp# Build the main IOC entry point on workstation OSs.
exer2_SRCS_DEFAULT += exer2Main.cpp
exer2_SRCS_vxWorks += -nil-# Add support from base/src/vxWorks if needed
#exer2_OBJS_vxWorks += $(EPICS_BASE_BIN)/vxComLibrary# Finally link to the EPICS Base libraries
exer2_LIBS += $(EPICS_BASE_IOC_LIBS)#===========================include $(TOP)/configure/RULES
#----------------------------------------
#  ADD RULES AFTER THIS LINE

进入到路径exer2/exer2App/Db路径下,添加以下一个文件dbSubExample.db,内容如下:

record(sub,"$(user):subExample")
{field(INAM,"mySubInit")field(SNAM,"mySubProcess")
}

并且在与上面文件相同路径下的Makefile中添加如下一行:

TOP=../..
include $(TOP)/configure/CONFIG
#----------------------------------------
#  ADD MACRO DEFINITIONS AFTER THIS LINE#----------------------------------------------------
# Create and install (or just install) into <top>/db
# databases, templates, substitutions like this
#DB += xxx.db
DB += dbSubExample.db   # 添加这一行
#----------------------------------------------------
# If <anyname>.db template is not named <anyname>*.template add
# <anyname>_template = <templatename>include $(TOP)/configure/RULES
#----------------------------------------
#  ADD RULES AFTER THIS LINE

然后切换到这个程序的顶层路径,执行make:

[blctrl@telecom exer2]$ make
make -C ./configure install
make[1]: Entering directory `/home/blctrl/exer/exer2/configure'
perl -CSD /usr/local/EPICS/base/bin/linux-x86_64/makeMakefile.pl O.linux-x86_64 ../..
...
make[2]: Leaving directory `/home/blctrl/exer/exer2/iocBoot/iocexer2'
make[1]: Leaving directory `/home/blctrl/exer/exer2/iocBoot'

接着切换到iocBoot/iocexer2路径下,编辑st.cmd文件:

#!../../bin/linux-x86_64/exer2#- You may have to change exer2 to something else
#- everywhere it appears in this file< envPathscd "${TOP}"## Register all support components
dbLoadDatabase "dbd/exer2.dbd"
exer2_registerRecordDeviceDriver pdbbase## Load record instances
#dbLoadRecords("db/xxx.db","user=blctrl")
dbLoadRecords("db/dbSubExample.db","user=TEST")  # 添加这一行,加载记录cd "${TOP}/iocBoot/${IOC}"
iocInit

用以下命令启动这个IOC程序:

[blctrl@telecom iocexer2]$ ../../bin/linux-x86_64/exer2 st.cmd
#!../../bin/linux-x86_64/exer2
< envPaths
epicsEnvSet("IOC","iocexer2")
epicsEnvSet("TOP","/home/blctrl/exer/exer2")
epicsEnvSet("EPICS_BASE","/usr/local/EPICS/base")
cd "/home/blctrl/exer/exer2"
## Register all support components
dbLoadDatabase "dbd/exer2.dbd"
exer2_registerRecordDeviceDriver pdbbase
## Load record instances
#dbLoadRecords("db/xxx.db","user=blctrl")
dbLoadRecords("db/dbSubExample.db","user=TEST")
cd "/home/blctrl/exer/exer2/iocBoot/iocexer2"
iocInit
Starting iocInit
############################################################################
## EPICS R7.0.3.1
## EPICS Base built Aug 28 2022
############################################################################
subInit was called
iocRun: All initialization complete
## Start any sequence programs
#seq sncxxx,"user=blctrl"
epics>

测试这个IOC下是否加载了指定的记录:

epics> dbl
TEST:subExample

再开一个命令行终端,测试这个加载的记录:

[root@telecom ~]# caget TEST:subExample
TEST:subExample                0
[root@telecom ~]# cainfo TEST:subExample
TEST:subExampleState:            connectedHost:             localhost:5064Access:           read, writeNative data type: DBF_DOUBLERequest type:     DBR_DOUBLEElement count:    1
[root@telecom ~]# caput TEST:subExample.PROC 1
Old : TEST:subExample.PROC           0
New : TEST:subExample.PROC           1
[root@telecom ~]# caget TEST:subExample
TEST:subExample                1

EPICS简单实例2 -- subroutine记录(sub)介绍与使用相关推荐

  1. mysql 实例复制_MYSQL教程MySQL 复制详解及简单实例

    <MysqL教程MysqL 复制详解及简单实例>要点: 本文介绍了MysqL教程MysqL 复制详解及简单实例,希望对您有用.如果有疑问,可以联系我们. MysqL 复制详解及简单实例 主 ...

  2. (三)AJAX基本介绍和简单实例03

    (三)AJAX基本介绍和简单实例03-----Ajax与数据库的动态应用 前台显示界面: 选择所有客户之后: 选择其中一个客户---杜森: Demo03.html代码 <html> < ...

  3. Log4j2日志记录框架的使用教程与简单实例

    1.Log4j2的使用教程 1.1 简介 Log4j的1.x版本虽然已经被广泛使用于很多应用程序中,但由于出现内存泄漏等bug,代码难以维护,以及需要使用老版本的jdk等劣势,在2015年8月已经玩完 ...

  4. ActiveMQ简单介绍+简单实例

    本文出自:http://www.open-open.com/lib/view/open1388994166156.html 1. JMS基本概念      JMS(Java Message Servi ...

  5. Hibernate搭建开发环境+简单实例(二)

    2019独角兽企业重金招聘Python工程师标准>>> Hibernate是非常典型的持久层框架,持久化的思想是非常值得我们学习和研究的.这篇博文,我们主要以实例的形式学习Hiber ...

  6. 程序设计-在校整理-06 最常公共子序列与子串+2048小游戏+KNN简单实例

    [在校整理-06 最常公共子序列与子串+2048小游戏+KNN简单实例](注:仅供参考学习使用) 一.课题内容和要求 1.问题描述 1.1最长公共子序列与子串 1.2 2048小游戏 1.3 K-NN ...

  7. pytorch生成对抗网络GAN的基础教学简单实例(附代码数据集)

    1.简介 这篇文章主要是介绍了使用pytorch框架构建生成对抗网络GAN来生成虚假图像的原理与简单实例代码.数据集使用的是开源人脸图像数据集img_align_celeba,共1.34G.生成器与判 ...

  8. Antlr4入门(安装、配置、简单实例)

    Antlr4入门(安装.配置.简单实例) 2020.5.28 仅本人初次使用Antlr4的经历分享 目前所知有3种使用Antlr4的方式: 通过命令行使用: 在Eclipse中安装Antlr4插件:( ...

  9. WPF MvvmLight简单实例(1) 页面导航

    原文:WPF MvvmLight简单实例(1) 页面导航 实现了那些功能,先看看截图: 操作描述: 在程序运行后,点击"Load"按钮,页面会加载PageOne,点击PageOne ...

最新文章

  1. sql server 2008建域时提示admin密码不符合要求解决方法
  2. Stuts的Web.xml 详解
  3. oracle数据库exp命令导入导出dmp文件演示,oracle数据库备份还原功能
  4. 2.数据中心网络演进
  5. python交互式shell_交互式 shell 玩转 Python
  6. 【VB.NET】VB.NET字符串数组排序
  7. mysql 集中join的区别
  8. java常用方法名_Java语言常见名称有哪些
  9. CentOS下安装JDK6u30
  10. CSDN VIP 常见问题解答
  11. 《JavaScript权威指南第7版》第4章 表达式和运算符
  12. matlabRC电路实验仿真
  13. office文档管理服务器编辑,office在线编辑方案
  14. ActiveMQ笔记(一)
  15. Git使用小技巧【git reset和git revert, 你真的知道怎么用吗, 详细图解】
  16. 洛谷 P1192 台阶问题
  17. IO模型(阻塞,非阻塞,多路复用......)
  18. 如何消除USB共享网络导致的Windows系统中自动增加的网络设备序列号?
  19. buuctf [WUSTCTF2020]dp_leaking_1s_very_d@angerous
  20. Python之xlrd读Excel文件问题解决 (python xlrd unsupported format, or corrupt file.)

热门文章

  1. web端微信二维码自定义样式
  2. python自动化测试面试题None is ==详解
  3. js赋值改变后,原数据也发生改变
  4. 雷神领域(并查集真是个好东西)并查集+流氓dp
  5. 微信小程序+SpringBoot+mybatis+MySQL实现简单的登录
  6. Windows平台精选软件工具列表-Windows绝赞应用
  7. 女生从猫猫身上学到的.........||精品||
  8. 模拟计算 |“五重解读”带你玩转CO2RR描述符-科学指南针
  9. 大数据必学Java基础(三十一):IDEA模板的使用
  10. 撸猫游戏千千万,他们凭什么被推荐?