4.2 运行策略 |
|
运行策略类似于窗口中的构件,区别在于构件看得见,有视觉效果,而策略在执行过程中是看不到的,相当于人的灵魂一样,在后台指挥程序运行。策略一般是通过点击按钮触发或者通过条件触发,例如,每隔一定时间定时触发、某个变量或表达式达到某个值触发。策略的命名与变量类似,包括三个部分,即名字、类型和注释,如图4-4所示。启动策略、退出策略与循环策略都是系统固有的,用户仅能进行简单的修改,如改变循环执行的时间周期。用户策略由用户根据需要通过点击按钮或菜单来完成,用户策略的名字、执行条件和功能注释都可以自行开发和拓展,非常方便。可参考二维码视频讲解。
图4-4 程序中各运行策略设计图
本例中设置了“定时接收数据”“发送命令策略”和“设置串口参数策略”。
“定时接收数据”策略相当于在一个定时器的作用下不断触发,定时器会自动复原,每隔一定时间触发一次,程序便可执行一次。
“发送命令策略”和“设置串口参数策略”为用户自行定义的策略,双击图4-3中的“设置串口参数”按钮,弹出图4-5所示“标准按钮构件属性设置”界面,在“执行运行策略块”前面打“√”,说明点击按钮后执行后面的策略,用户可以在下拉列表中从已经设置的所有策略中选择需要的策略。
图4-5 按钮动作与策略关联窗口
双击图4-4中的“设置串口参数策略”,弹出如图4-6所示的界面组态窗口,策略组态包括如下三个步骤。
图4-6 设置串口参数策略
第一步,策略定义,点击 图标,出现如图4-7所示界面,这个界面可以定义策略的名字,如本例中为“设置串口参数策略”,后面可以通过引用这个名字实现对策略的执行,窗口下方可以加入策略的注释,完成对策略的基本描述。
图4-7 策略执行条件窗口
第二步,策略条件,点击 图标,出现如图4-8所示界面,该界面用于输入条件表达式,表达式由变量及函数构成,条件表达式的结果为真(非0)或假(0),根据条件表达式的值进行逻辑判断,例如,当条件为真时执行或当条件为假时执行,前面是表达式的计算,后面是表达式的逻辑。
图4-8 策略执行条件窗口
第三步,脚本编写,点击 图标,出现如图4-9所示界面,此处可以输入脚本语句,类似于VB的脚本语言,语法简单,而且可以通过快捷按钮输入,具有纠错功能,当出现语法或变量未定义时,系统提示错误,并可以弹出自动增加变量对话框,减轻了用户的编程负担。
图4-9 策略执行脚本窗口
脚本为用户提供了很大的灵活性,一些无法用变量及动作链接完成的任务,可以通过编写脚本指令实现,本例中运用系统提供的串口操作函数,完成了串口的设置、打开、发送和接收,不需要任何硬件驱动即可解决对串口的操作。
“设置串口参数策略”这段代码中,关键是了解串口操作函数的使用,这里,可以看到有4个对串口参数进行设置的基本函数,即:
①!SetSerialBaud(CommNo,BaudRate) 设置串口波特率;
②!SetSerialDataBit(CommNo,DataBit) 设置串口数据位;
③!SetSerialStopBit(CommNo,StopBit) 设置串口停止位;
④!SetSerialParityBit(CommNo,ParityBit) 设置串口奇偶校验位。
由于BaudRate、DataBit、StopBit、ParityBit这4个变量与组态窗口的标签构件相关联,用户在界面中输入相应的值时,根据串口实际通信参数进行设置。
程序初始化时,需要先将已经设置好的参数保存,每次设定一个参数,都要执行相应函数,函数执行结果会出现成功与失败两种情况,此处为了监测设置是否成功,定义了跟踪变量CommError1、CommError2、CommError3和CommError4。如果成功,对应变量值为真;如果失败,变量值为假。这4条设置参数指令只要有一条为假,则退出串口参数设置过程,说明操作失败。在MCGSE中对串口的操作不同于其他高级语言(VB、VC++等),其功能简单,可以使用的操作函数非常少,例如,只有设置串口参数函数,却没有串口打开与关闭函数,用户只有利用现有的几个函数实现串口的自由通信。下面是对应“设置串口参数策略”的执行脚本程序。可参考二维码视频讲解。
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
'保存串口参数 CommNo.SaveDataInitValue( ) BaudRate.SaveDataInitValue( ) DataBit.SaveDataInitValue( ) StopBit.SaveDataInitValue( ) ParityBit.SaveDataInitValue( ) '刷新到磁盘上 !FlushDataInitValueToDisk( ) '设定波特率 CommError1=!SetSerialBaud(CommNo,BaudRate) IF CommError1<>0 THEN EXIT ENDIF '设定数据位 CommError2=!SetSerialDataBit(CommNo,DataBit) IF CommError2<>0 THEN EXIT ENDIF '设定停止位 CommError3=!SetSerialStopBit(CommNo,StopBit) IF CommError3<>0 THEN EXIT ENDIF '设定校验位 CommError4=!SetSerialParityBit(CommNo,ParityBit) IF CommError4<>0 THEN EXIT ENDIF
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
“发送命令策略”是直接向串口输出一字符串,采用的命令是:
!WriteSerialStr(参数1,参数2)
函数意义:向串口写一个字符串。
返 回 值:开关型。返回值=0:调用正常;返回值<>0:调用不正常。
参 数 1:开关型,串口号,从1开始,串口1对应1;
参 数 2:字符型,写入的字符串。
实 例:!WriteSerialStr(1, "ABCDEFG")。
实例说明:向串口1写入字符串"ABCDEFG",括号必须为英文括号。
与这个函数功能相似的函数为:
!WriteSerial(参数1,参数2)
函数意义:向串口写入一个字节。
返 回 值:开关型。返回值=0:调用正常;返回值<>0:调用不正常。
参 数 1:开关型,串口号,从1开始,串口1对应1;
参 数 2:开关型,写入的字节。
实 例:!WriteSerial(1,255)。
实例说明:向串口1写入255。
!WriteSerialStr(参数1,参数2)与!WriteSerial(参数1,参数2)的不同之处在于参数2,前者为字符串型,后者为开关型。因此,向串口写字符串时必须采用!WriteSerialStr(参数1,参数2)函数,脚本程序如下所示。
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
'发送一串字符串 SendError=!WriteSerialStr(CommNo,!StrFormat("%s%s%s",SendStr,!I2Ascii(13),!I2Ascii(10))) IF SendError<>0 THEN EXIT ENDIF !beep()
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
定时接收数据就是每隔一定时间便从串口读入数据,实际上是从串口输入缓冲区取出数据放在MCGSE定义的变量中,由于计算机通信时间快,这里的时间间隔可以设为500ms或200ms等,本案例将其设为100ms,时间设得过短,串口会在没有收到数据之前就进入下一次循环,浪费CPU的工作效率,所以时间间隔的设置尤为重要。
从串口接收数据采用循环策略,如图4-10~图4-12所示,每隔100ms脚本程序执行一次。首先判断串口缓冲区内是否有字符,如果有则继续从串口读;如果没有,则退出本次循环。此处用到一个技巧,将每次读上来的字符串进行累加,读串口函数采用的是!ReadSerialStr(串口号),读上来的数据存在ReceiveStr中,可以理解为寄存,就是暂时存储的意思,后面读上来的数据会覆盖以前的字符串。因此,需要另外一个变量AllRecStr保存旧的数据,然后与新的数据进行累加,这样,新旧两种字符串就会实时地显示在标签构件中,使用户体会到数据在不断地从串口读进来,下面是完整的从串口接收数据的脚本代码。
图4-10 定时接收数据策略
图4-11 定时接收数据策略时间设定窗口
图4-12 定时接收数据策略表达式条件设定窗口
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
'串口未正确打开则退出 IF CommError1<>0 OR CommError2<>0 OR CommError3<>0 OR CommError4<>0 THEN EXIT ENDIF '串口中无可读数据则退出 IF !GetSerialReadBufferSize(CommNo)<=0 THEN EXIT ENDIF '从串口读数据 ReceiveStr=!ReadSerialStr(CommNo) '将读入的数据加入到总字符串中 AllRecStr=!StrFormat("%s%s",AllRecStr,ReceiveStr) EXIT
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *