本实例演示了如何使用有限状态机创建一个计时器的完成过程:
状态机源文件为:
#define PVSYS "pvsys=ca"
program seqCmdBtns(PVSYS)
option -c; /* 不等待pv连接. */
option +r; /* 允许多个实例 */
/* 定义变量,连接通道 */
short startBtn;
assign startBtn to "{P}:Start";
monitor startBtn;
short stopBtn;
assign stopBtn to "{P}:Stop";
monitor stopBtn;
int countsEntry;
assign countsEntry to "{P}:CountSet";
string seqMsg;
assign seqMsg to "{P}:SeqMsg";
float period;
assign period to "{P}:Period";
int counter;
ss seqCmdBtns{
state init{
when (pvConnectCount() == pvChannelCount()){
printf("seqCmdBtns: All channels connected\n");
sprintf(seqMsg, "Ready for counting!");
pvPut(seqMsg);
} state idle
}
state idle{
when (pvConnectCount() < pvChannelCount()){
printf("seqCmdBtns: Lost pv connection\n");
sprintf(seqMsg, "Lost connection");
pvPut(seqMsg);
} state init
when (startBtn){
sprintf(seqMsg, "0 counts");
pvPut(seqMsg);
pvGet(countsEntry);
if (countsEntry <= 0 || countsEntry > 1000){
countsEntry = 10;
pvPut(countsEntry);
}
pvGet(period);
printf("Sleep Period: %3.1f\n", period);
} state start
when (stopBtn){
stopBtn = 0;
pvPut(stopBtn);
} state idle
}
state start{
when (startBtn){
for (counter = 1; counter <= countsEntry; counter++){
if (stopBtn){
stopBtn = 0;
pvPut(stopBtn);
break;
}
else{
epicsThreadSleep(period);
sprintf(seqMsg, "%d counts", counter);
pvPut(seqMsg);
}
}
startBtn = 0;
pvPut(startBtn);
} state idle
}
}
记录数据库源文件为:
record(bo, "$(P)Start") {
field(DESC, "Start counter")
field(ZNAM, "Ready")
field(ONAM, "Start")
}
record(bo, "$(P)Stop") {
field(DESC, "Stop counter")
field(ZNAM, "Ready")
field(ONAM, "Abort")
}
record(longout, "$(P)CountSet"){
field(DESC, "Set the Count Range")
field(DOL, "10")
}
record(mbbo, "$(P)PeriodOption")
{
field(DESC, "Set the Count Period")
field(DTYP, "Raw Soft Channel")
field(NOBT, "2")
field(ZRVL,"1")
field(ONVL,"3")
field(TWVL,"5")
field(THVL,"10")
field(ZRST,"0.1 Second")
field(ONST,"0.3 Second")
field(TWST,"0.5 Second")
field(THST,"1.0 Second")
field(FLNK, "$(P)Period")
}
record(calc, "$(P)Period")
{
field(INPA, "$(P)PeriodOption.RVAL")
field(CALC, "0.1 * A")
}
record(stringout, "$(P)SeqMsg") {
field(DESC, "Message box from seq")
}
启动脚本文件为:
#!../../bin/linux-aarch64/seqcmd
#- You may have to change seqcmd to something else
#- everywhere it appears in this file
< envPaths
cd "${TOP}"
## Register all support components
dbLoadDatabase "dbd/seqcmd.dbd"
seqcmd_registerRecordDeviceDriver pdbbase
## Load record instances
dbLoadRecords("db/seqcmd.db","P=CmdSeq:")
cd "${TOP}/iocBoot/${IOC}"
iocInit
## Start any sequence programs
seq &seqCmdBtns,"P=CmdSeq"
启动这个IOC程序,并且查看加载的记录:
root@orangepi5:/usr/local/EPICS/program/seqcmd/iocBoot/iocseqcmd# ../../bin/linux-aarch64/seqcmd st.cmd
#!../../bin/linux-aarch64/seqcmd
< envPaths
...
iocInit
Starting iocInit
############################################################################
## EPICS R7.0.7
## Rev. 2023-05-26T09:07+0000
## Rev. Date build date/time:
############################################################################
iocRun: All initialization complete
## Start any sequence programs
seq &seqCmdBtns,"P=CmdSeq"
sevr=info Sequencer release 2.2.8, compiled Mon May 29 11:45:00 2023
sevr=info Spawning sequencer program "seqCmdBtns", thread 0x558bc49fb0: "seqCmdBtns"
seqCmdBtns: All channels connected
epics> dbl
CmdSeq:Start
CmdSeq:Stop
CmdSeq:Period
CmdSeq:CountSet
CmdSeq:PeriodOption
CmdSeq:SeqMsg
CSS客户端文件:
这个IOC程序具有以下功能:
1)count set设置计数量。
2)count period可以有4个选项,可以设置计数之间的时间间隔;可以设置的间隔为0.1s, 0.3s, 0.5s和1.0s。
3)按下start按钮,开始Counter开始计数,计数直到达到count set中设置的值或者按下Stop按钮时停止。