新闻详情

说说WINCC与串口通讯

发布时间: 2024-04-10

二、串口的事件触发

串口的触发分为周期触发和事件触发。周期触发就是在全局脚本中定义某一周期,周期性获取缓冲区数据。事件触发就是事件触发oncomm事件,具体参考串口属性。因为条形码的长度不一,刚开始的获取数据,通过周期性触发,判断缓冲区字符长度来判定,但该方式有很多bug,比如,再下一触发周期没到之前(缓冲区数据没有提取),扫了两次条码,那么缓冲区将是两次的数据,长度判断就不靠谱了。这次客户提出要求,就顺势改为事件触发。

在串口使用前,首先要打开串口,我的方法是,当主画面一打开,就执行以下脚本:


dim objmscomm3, tagconnection3

         set objmscomm3 = hmiruntime.screens("main").screenitems("op30com1")

         set tagconnection3 = hmiruntime.tags("op30_connection1")

        

         if objmscomm3.portopen = false then

                 

                  ' assign com port number

                  objmscomm3.commport = 9

                 

                  ' values: 9600 baud, n - no parity, 8 - databit, 1 - stopbit

                  objmscomm3.settings = "9600,n,8,1"

'                 objmscomm3.rthreshold = 1

'                 objmscomm3.sthreshold = 1

                  objmscomm3.inbuffercount = 0

                  objmscomm3.inputlen = 0

                  objmscomm3.portopen = true

                 

 

                  tagconnection3.write (true)

                  hmiruntime.trace("9# port open." & vbcrlf)

         else

                  hmiruntime.trace("9# port is already opened." & vbcrlf)

         end if

其他串口类似,请注意区分串口号。

三、串口的属性

请参与附件,如果不行,请网上下载相关资料《串口通信-mscomm控件使用详解》,因为是获取条码,故只列举rthreshold属性。

rthreshold属性: 通过该属性设置产生oncomm 事件(接收时产生)的阀值,若mscomm1.rthreshold:=0,不产生oncomm 事件,若mscomm1.rthreshold:=5,接收缓冲区每收到5字节时,则产生oncomm 事件

在实际的使用中,设定rthreshold属性的值为1,即1个字符触发一次oncomm事件,通过判断字符是否接收到末尾字符(案例中,条码的末尾字符是eot(char(4))。扫描枪识别条码后会自动加上回车符char(13)),把没有检测到末尾字符就接收到数据放在一个wincc的内部变量中,不断的累加。心想,50个字符应该会进行50次的oncomm事件吧?

四、模拟测试与实际调试

测试的环境如下:win7 32位,安装了commtone6.0串口调试和configure virtual serial port driver软件,用于发送数据和虚拟串口。

在模拟测试中发现,50个字符并没有产生50次的oncomm事件,在画面刚开始打开,也就是第一次打开串口,执行了2次,后面继续发送,每发送一次,产生3次时间,其中50个字符都是一次接受完成,其余均为空字符。(至于第一次是2,后面是3次,还是第一次是3,后面2次不记得了,重要的信息是,无论多少个字符都是一次完成)

在虚拟测试中发现,把数据写入内部变量,比如buffer1.write,在该代码后面出现buffer1.read,发现仍然为空值,但是如果中间有msgbox弹出别的对话框,人工确定,那么后面弹出的buffer1.read有值,说明buffer1.write(内部变量的写入)也是有时间要求。(原先以为是整个代码执行完成后再写入,类似于plc的io寄存器一样,执行程序时先扫描,执行完成后再更新)。

虽然是一次完成,但我初步认为,虚拟的串口数据在内存或硬盘上,几乎是不用传送时间,所以实际中不见得也是一次接收到这么多字符,我还是按我的设想迎接实际调试。

以下是数据接收代码:

获取手持扫描枪的信息

      dim objmscomm,buffer1,processlabel,process_run,sgw

      dim strtemptag,strtemp,t1,t2

      dim mm,nn,jj,kk,tt

      dim pp,qq,bz

      dim messagecode,messagetype,messagetext,r1,r2,r3,r4,r5

      dim m,n,p,q

      dim xx,zz,outmsgtext

 

      set objmscomm = hmiruntime.screens("main").screenitems("op30com1")

      set buffer1 = hmiruntime.tags("op30_buffer1")

      set processlabel = hmiruntime.tags("op30_processlabel")

set process_run = hmiruntime.tags("op30_process_run")

      set sgw = hmiruntime.tags("op30_status_sgw")

      set bz = hmiruntime.tags("op30_barread_bz")

      set messagecode = hmiruntime.tags("op30_messagecode")

      set messagetype = hmiruntime.tags("op30_messagetype")

      set messagetext = hmiruntime.tags("op30_messagetext")

      set outmsgtext = hmiruntime.tags("op30_text")

strtemp = ""

         if objmscomm.portopen = true then

                   strtemp = cstr(objmscomm.input)

                   if strtemp<> "" then

                   if instr(strtemp,chr(4)) then '如果判断已经接收到停止符号,则判断条码接受完成

         strtemptag = mid(strtemp,1,len(strtemp)-1)

                t1 = len(buffer1.read)

                t2 = len(strtemptag)

         tt = t1 + t2

                buffer1.read

                buffer1.value = buffer1.value &strtemptag

                buffer1.write

                'msgbox t30

                            if tt> 50 then    '判断为物料标签,超出45位,截取其中的字符

                                     mm = instr(buffer1.read, "p")

                                     jj = instr(buffer1.read, "2p")

                                     xx = instr(buffer1.read, "q")

                                     nn = instr(buffer1.read, "3s")

                                     kk = instr(buffer1.read, "1t")

                                     pp = mid(buffer1.read, mm + 1, jj - mm - 1)

                                     zz = mid(buffer1.read, xx + 1, 5)

                                     qq = mid(buffer1.read, nn + 2, kk - nn - 2)

                                     processlabel.value = pp&qq&zz '将数据写入buffer

                                     processlabel.write

                                     objmscomm.inbuffercount = 0

                                     bz.write 1

 

                            end if

        

                            if tt

                                buffer1.read

                            processlabel.value = buffer1.value  '将数据写入processlabel

                                     processlabel.write

                                     objmscomm.inbuffercount = 0

                                     bz.write 1

                            end if

……

实际测试中,字符的获取在9600波特率的情况下,即使是远的距离下,在该项目需求的60个字符都是一次全部接收,并没有分段接收,说明mscomm1.rthreshold:=1的情况下,接收数据产生的oncomm事件也只执行了一次(准确的说是多次,只是其他的都是空字符,只有一次非空字符,该字符数据长度就是接收的数据)。

五、经验总结

1、  注册mscomm32.ocx请用管理员身份运行。

2、  zuihao使用事件触发,通过判断某个特殊字符来确定是否数据接收完成。

3、  在接收阀值属性mscomm1.rthreshold:=1的设定下,9600的波特率,13米的距离(事实上距离对传输时间的影响几乎可以忽略),可以一起传送并接收。首先需要判断为非空字符,然后再判断是否有特殊字符,再执行其他语法。

4、  可以使用msgbox来诊断程序执行到哪一步,也可以用inputbox来输入程序需要的数值。

 

后记:项目还没有进行完成,但关于串口的使用已经ok。从刚开始接触wincc到如今,越来越感受到wincc的开放性,利用脚本可以实现很多功能。从初的“小白”到如今的“小白”是从形式到内涵的改变,这个旅途也是学习一点应用一点不断进步,项目做完不是终结,而是下一个项目的开始,能不能承接下一个项目,就需要在这个过程中有没有积累,不然即使机会来了也抓不住。工控行业博大精深,需要有不断学习的心,没有一招鲜或大杀器,只有不断积累不断学习,深刻掌握原理,才能举一反三。


展开全文

供应商
广东湘恒智能科技有限公司
联系电话
15903418770
手机号
15915421161
联系人
张经理
所在地
惠州大亚湾澳头石化大道中480号太东天地花园2栋二单元9层01号房
我们的新闻
咨询 在线询价 拨打电话