多位二进制输入记录常用于从硬件读取连续,多位输入。二进制值代表最多16种状态中一种。多位二进制记录与使用多个比特位的设备连接。
大部分设备支持从硬件获取值并且在RVAL中放置这个值。对于这些记录支持模块,记录运行使用RVAL来确定当前状态(传给VAL的一个值介于0和15之间)。设备支持模块可以可选地直接读取值到VAL。
提供了软设备支持模块通过数据库或者通道访问链接或者dbPutField或dbPutLink请求获取输入。提供了两个软设备支持模块:Soft Channel允许VAL是一个任意无符号短整数。Raw Soft Channel就像正常地设备支持模块把值读取到RVAL。
参数字段
以下描述了记录特定的字段,按功能分组。
用于扫描的参数
多位二进制输入记录有用于指定在何种情况下运行它的标准字段。这些字段在Scan Fields中列出。
用于读取和转换的参数
设备支持模块从在INP字段中指定的设备或链接获取本记录的输入。对于从设备获取它们输入的记录,INP字段必须包含I/O板卡的地址,并且DTYP字段必须指定合适的设备支持模块。注意地址格式根据使用I/O总线而不同。
在DTYP中可以指定两个设备支持模块Soft Channel和Raw Soft Channel。
Raw Soft Channel读取值到RVAL,对其进行正常的转换过程。Soft Channel直接读取任何无符号整数到VAL。对于一个软mbbi记录,INP字段可以是常数,数据库或通道访问链接。如果INP是一个常数,则VAL被初始化乘这个常数值,但在运行时可以通过dbPutField或dbPutLink被更改。
raw soft取读例程,和一般设备支持读取例程在读取硬件寄存器时使用MASK来选择只需的比特位。记录初始化将它初始化位((1<<NOBT)-1)。用户可以配置NOBT字段,但设置支持可以设置它,在这种情况下,由用户传递给它的值就被重写了。设备支持例程也可以重写MASK或者监将其左移SHTF位。如果MASK是非0,仅由MASK指定的位将出现在RVAL中。
除非设备支持例程不指定转换,RVAL用于按以下确定VAL:
1) RVAL被分配一个临时变量--rval=RVAL
2) ravl被右移SHFT比特位
3) 在rval和状态值字段ZRVL-FFVL之一之间搜索匹配
ZRVL-FFVL每个字段代表可能的16个状态之一(不是必须使用全部16个字段)。
另外,可以以一个字符串读取输入值,在此情况下,在ZRST-FFST字段指定字符串中查找一个匹配。接着RVAL被设置成对应那个字符串的值,并且转换过程发生。
操作显示参数
这些参数用于向操作者显示有意义数据。它们以文本或图形显示mbbi的值和其它参数。ZRST-FFST字段包含了用于描述这个记录可能状态之一的字符串。get_enum_str和get_enum_strs记录例程为操作者获取这些字符串。get_enum_str获取对应设置在VAL中值的字符串,而get_enum_strs获取所有字符串。
有关记录名称(NAME)和描述(DESC)字段的更多信息见Fields Common to All Record Types。
警报参数
对应多位二进制输入记录的可能的警报条件是SCAN,READ和状态警报。在以下严重性字段中配置状态警报。这些字段有用于严重性字段的通常可能指:NO_ALARM,MINOR和MAJOR。
未知状态严重性(UNSV)字段,如果设置为NINOR或MAJOR,当记录支持例程不能再状态值字段中为rval找到一个匹配值时触发一个警报。
记录警报和标准字段的完整解释见Alarm Specification。Alarm Fields列出了与所有记录类型警报状态相关联的其它字段。
运行时参数
这些参数由运行时代码用于处理多位二进制输入。
ORAW被记录运行使用来保存前一个RVAL,为了在确定何时发送一个RVAL字段的monitor事件中使用。
LALM字段通过保存前一次被发送状态警报变化时的VAL值实现了状态警报严重性变化。
MLST保存在触发上次值变化的monitor时的值。
如果没有状态被定义,SDEF被记录支持使用来节省时间。
仿真模式参数
以下字段用于在仿真模式中操作这个记录。
如果SIMM(通过SIML获取)是YES或RAW,记录被置入SIMS严重性,并且通过SIOL获取值(在SVAL中缓存)。如果SIMM是YES, SVAL不经过转换地写入VAL,如果SIMM是RAW,SVAL被传入RVAL并且转换。SSCN设置要在仿真模式中使用的不同SCAN机制。SDLY设置一个延时(以sec为单位),其用于异步模仿运行。
有关仿真模式和其字段的信息见Input Simulation Fiels。
记录支持
记录支持例程
1) init_record
如果SIML类型是CONSTANT链接,用SIML的值初始化SIMM或者如果SIML类型是PV_LINK,创建一个通道访问链接。根据SIOL是CONSTANT或PV_LINK,对SVAL进行类似的初始化。
这个例程接着检查设备支持是否可用以及是否定义了一个设备支持读取例程。如果二者中有一个不存在,则发布一条错误消息并且终止运行。
清除MASK并且接着设置NOBT低位比特。
如果设备支持包含了init_record(),调用它。
接着调用init_common来确定是否定义了任何状态。如果状态被定义了,SDEF被设置成TRUE。
2) process:见下一部分。
3) special:当字段ZRVL...FFVL中有任何字段变化值时,调用init_compute计算SDEF。
4) get_enum_str:获取对应VAL的ASCII字符串
5) get_enum_strs:获取对应ZRST,...,FFST的ASCII字符串。
6) put_enum_str:检查字符串是否匹配ZRST, FFST并且如果匹配,设置VAL。
记录运行
例程process实现了以下算法:
1) 检查合适的设备支持模块是否存在。如果不存在,发布一条错误消息并且用PACT字段仍然设置为TRUE,终结运行。这确保了不再为这个记录调用processes。因而错误风暴将不发生。
2) 调用readValue。更多信息见"Input Records"。
3) 如果PACT已经变为TRUE,设备支持例程已经启动但还未完成读取一个新输入值。在这种情况下,运行例程仅返回,保留PACT为TRUE。
4) 转换:
- status=read_mbbi
- PACT=TRUE
- 调用recGblGetTimeStamp()
- 如果status是0,则确定VAL :a) 设置rval=RVAL b) 右移rval SHFT位
- 如果定义了至少一个状态值,设置UDF位TRUE
- 如果RVAL是ZRVL,... ,FFVL,则设置VAL等于状态的索引,UDF设置位False
- 否则,设置VAL=undefined,否则设置VAL=RVAL
- 设置UDF为FALSE a) 如果status是1,返回0,b) 如果status是2,设置status=0
5) 检查警报。这个例程检查新的VAL是否使得警报状态和严重性变化。如果变化了,设置NSEV,NSTA和LALM。
6) 检查是否应该调用monitors。
- 如果警报状态或严重性发生变化,调用警报monitors。
- 如果MLST不等于VAL,调用存档和值变化monitors。
- NSEV和NSTA被重置为0
7) 如果需要,扫描forward链接,设置PACT为FALSE,并且返回。
设备支持
设备支持相关字段
每个输入记录必须有一个相关联的设备支持例程集合。
设备支持例程的主要作用是在调用read_mbbi时获取一个新的raw输入值。设备支持例程主要使用以下字段:
设备支持例程
设备支持由以下例程组成:
1) long report(int level)
这个例程被IOC命令dbior调用并且被传递用户请求的报告级别。它应该打印这个设备支持状态到标准输出。level参数可用于以更高级别增强输入更详细信息,或者选取不同级别不同类型的信息。级别0应该输出不多于一小段概述。
2) long init(after)
此可选的例程在IOC初始化时被调用两次。第一次调用用after参数设置为0发生在进行任何init_record()调用前。第二次调用用after设置为1发生在所有init_record()调用后。
3) init_record(precord)
这个例程是可选的。如果提供了,它被记录支持init_record()例程调用。如果它使用了MASK,它应该按需要位移它并且也给SHFT赋一个值。
4) get_ioinit_info(int cmd, struct dbCommon * precord, IOSCANPVT * ppvt)
在这个记录被添加到一个I/O事件扫描列表或者从一个I/O事件扫描列表删除时,这个例程被ioEventScan调用。根据记录被添加到一个I/O事件列表或者从一个I/O事件列表被删除,cmd有值0或1。必须为能够使用I/O事件Scanner的任何设备类型提供它。
5) read_mbbi(precord)
例程必须提供一个新输入值。他返回以下值:
- 0:成功。一个新值被放入RVAL。记录支持模块从RVAL,SHFT和ZEVL,...,FFVL确动VAL。
- 2:成功,单不更改VAL。
- 其它,错误。
软记录的设备支持
为不与实际硬件设备相关联的多位二进制输入记录提供了两个软设备支持模块Soft Channel和Raw Soft Channel。INP链接类型必须是CONSTANT, DB_LINK或CA_LINK。
Soft Channel
read_mbbi总是返回一个2值,其表示不执行转换。如果INP链接是一个常数,则init_record()把这个常数值存入VAL,并且UDF被设置成False。通过dbPut请求可以更改VAL。如果INP链接类型是PV_LINK,则dbCaAddInlink被init_record()调用。
read_mbbi调用recGblGetLinkValue读取VAL的当前值。
如果recGblGetLinkValue的返回值为0,则read_mbbi设置UDF为FALSE。recGblGetLinkValue的状态被返回。
raw Soft Channel
这个模块除了值被读取到RVAL外像先前的模块,从RVAL计算VAL,并且read_mbbi返回一个0值。因而这个记录运行例程将用正常方式确定VAL。
举例:
用以下文件作为测试数据库:
这个数据库文件中有4个记录实例组成:一个类型为longin的记录实例,一个类型为fanout的记录实例和两个类型为mbbi的记录实例;其中两个mbbi记录实例中一个采用Soft Channel软设备支持,另一个采用Raw Soft Channel软设备支持。
这四个记录运行过程如下所述:
由于longin记录是被动的,通过通道访问写,向其写入一个整数值,会使得这个记录运行,并且在运行结束前使得被动记录fanout运行;fanout记录运行中会依次使得mbb1和mbb2运行,mbbi1和mbb2运行中INP字段会通过数据库访问获取longin记录的值。
record(longin, "$(USER):longin")
{
field(INP, "0")
field(SCAN, "Passive")
field(DTYP,"Soft Channel")
field(FLNK, "$(USER):fanout.PROC")
}
record(fanout, "$(USER):fanout")
{
field(SELM,"Mask")
field(SELN,"3")
field(SHFT,"0")
field(SCAN,"Passive")
field(LNK0, "$(USER):mbbi1.PROC")
field(LNK1, "$(USER):mbbi2.PROC")
}
record(mbbi, "$(USER):mbbi1")
{
field(INP, "$(USER):longin.VAL")
field(SCAN,"Passive")
field(DTYP, "Soft Channel")
field(ZRVL,"0")
field(ONVL,"2")
field(TWVL,"4")
field(THVL,"6")
field(FRVL,"8")
field(FVVL,"10")
field(SXVL,"12")
field(ZRST,"Red")
field(ONST,"Yellow")
field(TWST,"Blue")
field(THST,"White")
field(FRST,"Pink")
field(FVST,"Orange")
field(SXST,"Green")
field(SHFT,"0")
field(NOBT, "2")
}
record(mbbi, "$(USER):mbbi2")
{
field(INP, "$(USER):longin.VAL")
field(SCAN,"Passive")
field(DTYP, "Raw Soft Channel")
field(ZRVL,"0")
field(ONVL,"2")
field(TWVL,"4")
field(THVL,"6")
field(FRVL,"8")
field(FVVL,"10")
field(SXVL,"12")
field(ZRST,"Red")
field(ONST,"Yellow")
field(TWST,"Blue")
field(THST,"White")
field(FRST,"Pink")
field(FVST,"Orange")
field(SXST,"Green")
field(SHFT,"0")
field(NOBT, "2")
}
把上述数据库文件加载到IOC程序后,检查当前加载的记录:
epics> dbl
blctrl:mbbi1
blctrl:mbbi2
blctrl:fanout
blctrl:longin
通过通道访问写blctrl:longin记录写入整数数值,并且观察mbb1和mbb2的输出:
1) 向blctrl:longin写0
[root@bjAli ~]# caput blctrl:longin 0
Old : blctrl:longin 0
New : blctrl:longin 0
[root@bjAli ~]# caget blctrl:mbbi1.VAL blctrl:mbbi2.VAL
blctrl:mbbi1.VAL Red
blctrl:mbbi2.VAL Red
[root@bjAli ~]# caget -d 1 blctrl:mbbi1.VAL blctrl:mbbi2.VAL
blctrl:mbbi1.VAL
Native data type: DBF_ENUM
Request type: DBR_SHORT
Element count: 1
Value: 0
blctrl:mbbi2.VAL
Native data type: DBF_ENUM
Request type: DBR_SHORT
Element count: 1
Value: 0
2) 向blctrl:longin写1
[root@bjAli ~]# caput blctrl:longin 1
Old : blctrl:longin 0
New : blctrl:longin 1
[root@bjAli ~]# caget -d 1 blctrl:mbbi1.VAL blctrl:mbbi2.VAL
blctrl:mbbi1.VAL
Native data type: DBF_ENUM
Request type: DBR_SHORT
Element count: 1
Value: 1
blctrl:mbbi2.VAL
Native data type: DBF_ENUM
Request type: DBR_SHORT
Element count: 1
Value: -1
[root@bjAli ~]# caget blctrl:mbbi1.VAL blctrl:mbbi2.VAL
blctrl:mbbi1.VAL Yellow
blctrl:mbbi2.VAL Illegal Value
3) 向blctrl:longin写2
[root@bjAli ~]# caput blctrl:longin 2
Old : blctrl:longin 1
New : blctrl:longin 2
[root@bjAli ~]# caget -d 1 blctrl:mbbi1.VAL blctrl:mbbi2.VAL
blctrl:mbbi1.VAL
Native data type: DBF_ENUM
Request type: DBR_SHORT
Element count: 1
Value: 2
blctrl:mbbi2.VAL
Native data type: DBF_ENUM
Request type: DBR_SHORT
Element count: 1
Value: 1
[root@bjAli ~]# caget blctrl:mbbi1.VAL blctrl:mbbi2.VAL
blctrl:mbbi1.VAL Blue
blctrl:mbbi2.VAL Yellow
4) 向blctrl:longin写3
[root@bjAli ~]# caput blctrl:longin 3
Old : blctrl:longin 2
New : blctrl:longin 3
[root@bjAli ~]# caget -d 1 blctrl:mbbi1.VAL blctrl:mbbi2.VAL
blctrl:mbbi1.VAL
Native data type: DBF_ENUM
Request type: DBR_SHORT
Element count: 1
Value: 3
blctrl:mbbi2.VAL
Native data type: DBF_ENUM
Request type: DBR_SHORT
Element count: 1
Value: -1
[root@bjAli ~]# caget blctrl:mbbi1.VAL blctrl:mbbi2.VAL
blctrl:mbbi1.VAL White
blctrl:mbbi2.VAL Illegal Value
5) 向blctrl:longin写4
[root@bjAli ~]# caput blctrl:longin 4
Old : blctrl:longin 3
New : blctrl:longin 4
[root@bjAli ~]# caget -d 1 blctrl:mbbi1.VAL blctrl:mbbi2.VAL
blctrl:mbbi1.VAL
Native data type: DBF_ENUM
Request type: DBR_SHORT
Element count: 1
Value: 4
blctrl:mbbi2.VAL
Native data type: DBF_ENUM
Request type: DBR_SHORT
Element count: 1
Value: 0
[root@bjAli ~]# caget blctrl:mbbi1.VAL blctrl:mbbi2.VAL
blctrl:mbbi1.VAL Pink
blctrl:mbbi2.VAL Red
6) 向blctrl:longin写5
[root@bjAli ~]# caput blctrl:longin 5
Old : blctrl:longin 4
New : blctrl:longin 5
[root@bjAli ~]# caget -d 1 blctrl:mbbi1.VAL blctrl:mbbi2.VAL
blctrl:mbbi1.VAL
Native data type: DBF_ENUM
Request type: DBR_SHORT
Element count: 1
Value: 5
blctrl:mbbi2.VAL
Native data type: DBF_ENUM
Request type: DBR_SHORT
Element count: 1
Value: -1
[root@bjAli ~]# caget blctrl:mbbi1.VAL blctrl:mbbi2.VAL
blctrl:mbbi1.VAL Orange
blctrl:mbbi2.VAL Illegal Value
5) 向blctrl:longin写6
[root@bjAli ~]# caput blctrl:longin 6
Old : blctrl:longin 5
New : blctrl:longin 6
[root@bjAli ~]# caget -d 1 blctrl:mbbi1.VAL blctrl:mbbi2.VAL
blctrl:mbbi1.VAL
Native data type: DBF_ENUM
Request type: DBR_SHORT
Element count: 1
Value: 6
blctrl:mbbi2.VAL
Native data type: DBF_ENUM
Request type: DBR_SHORT
Element count: 1
Value: 1
[root@bjAli ~]# caget blctrl:mbbi1.VAL blctrl:mbbi2.VAL
blctrl:mbbi1.VAL Green
blctrl:mbbi2.VAL Yellow
从以上运行结果我们可以得出以下结论:
1) 使用Soft Channel软设备支持的mbbi,通过INP获取的值,直接放入VAL字段,并且根据这个获取的值(0-15),从ZRST ~ FFST获取一个字符串作为枚举请求返回的字符串。
2)使用Raw Soft Channel软设备支持的mbbi,通过INP获取的值,放入到RVAL字段,经过移位和掩码处理后的值,与ZRVL~FFVL中的值进行比较,如果匹配上了,就设置为与之匹配的<XX>VL的索引号,并且根据这个索引号从ZRST~FFST中取出对应字符串作为枚举请求的返回值。