【发布时间】:2019-04-18 07:00:15
【问题描述】:
我有一个用于获取数据的串行端口外部设备。我设置了两个定时器。其中一个必须用于绘图(0.5sn),另一个用于写入文本文件(15sn)。计时器不应通过列表或数组相互获取数据。因为有时我需要关闭绘图按钮。
所以我必须从同一个资源(即将到来的连续数据)中获取数据,对吗?但是当我尝试这个时,它被阻止了。
以及如何在不阻塞的情况下获取数据? 例如,下面的代码运行时没有阻塞:
# -*- coding: utf-8 -*-
#!/usr/bin/python
import time
import numpy as np
import sys
import wx
def next_data():
t0 = time.time()
return t0
class MyFrame1 ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 223,183 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )
bSizer1 = wx.BoxSizer( wx.VERTICAL )
self.toggleBtn1 = wx.ToggleButton( self, wx.ID_ANY, u"Btn 1(enabled)", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer1.Add( self.toggleBtn1, 1, wx.ALL|wx.EXPAND, 5 )
self.toggleBtn2 = wx.ToggleButton( self, wx.ID_ANY, u"Btn 2(enabled)", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer1.Add( self.toggleBtn2, 1, wx.ALL|wx.EXPAND, 5 )
self.SetSizer( bSizer1 )
self.Layout()
self.timer1 = wx.Timer()
self.timer1.SetOwner( self, 1 )
self.timer1.Start( 1000 )
self.timer2 = wx.Timer()
self.timer2.SetOwner( self, 2 )
self.timer2.Start( 1000 )
self.Centre( wx.BOTH )
# Connect Events
self.toggleBtn1.Bind( wx.EVT_TOGGLEBUTTON, self.btn1_f )
self.toggleBtn2.Bind( wx.EVT_TOGGLEBUTTON, self.btn2_f )
self.Bind( wx.EVT_TIMER, self.timer1_f, id=1 )
self.Bind( wx.EVT_TIMER, self.timer2_f, id=2 )
def btn1_f( self, event ):
event.Skip()
def btn2_f( self, event ):
event.Skip()
def timer1_f( self, event ):
t1 = next_data()
print("t1 : ",t1)
def timer2_f( self, event ):
t2 = next_data()
print("t2*****: ",t2)
app = wx.App()
f = MyFrame1(None)
f.Show(True)
app.MainLoop()
它会打印(如预期的那样):
t2*****: 1555568620.1363716
t1 : 1555568620.1363716
t2*****: 1555568621.1300163
t1 : 1555568621.1300163
但是我的串口不能像上面那样正常工作:
# -*- coding: utf-8 -*-
#!/usr/bin/python
import time
import numpy as np
import sys
import wx
import serial
ser = serial.Serial('COM9',9600)
def next_data():
#===========================================================================
# for line in ser:
# return line
#===========================================================================
data_str = ser.read(ser.inWaiting())
return data_str
## also the commented above 2 lines gave same output.
class MyFrame1 ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 223,183 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )
bSizer1 = wx.BoxSizer( wx.VERTICAL )
self.toggleBtn1 = wx.ToggleButton( self, wx.ID_ANY, u"Btn 1(enabled)", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer1.Add( self.toggleBtn1, 1, wx.ALL|wx.EXPAND, 5 )
self.toggleBtn2 = wx.ToggleButton( self, wx.ID_ANY, u"Btn 2(enabled)", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer1.Add( self.toggleBtn2, 1, wx.ALL|wx.EXPAND, 5 )
self.SetSizer( bSizer1 )
self.Layout()
self.timer1 = wx.Timer()
self.timer1.SetOwner( self, 1 )
self.timer1.Start( 1000 )
self.timer2 = wx.Timer()
self.timer2.SetOwner( self, 2 )
self.timer2.Start( 1000 )
self.Centre( wx.BOTH )
# Connect Events
self.toggleBtn1.Bind( wx.EVT_TOGGLEBUTTON, self.btn1_f )
self.toggleBtn2.Bind( wx.EVT_TOGGLEBUTTON, self.btn2_f )
self.Bind( wx.EVT_TIMER, self.timer1_f, id=1 )
self.Bind( wx.EVT_TIMER, self.timer2_f, id=2 )
def btn1_f( self, event ):
event.Skip()
def btn2_f( self, event ):
event.Skip()
def timer1_f( self, event ):
t1 = next_data()
print("t1 : ",t1)
def timer2_f( self, event ):
t2 = next_data()
print("t2*****: ",t2)
app = wx.App()
f = MyFrame1(None)
f.Show(True)
app.MainLoop()
它的输出如下:
t2*****: b'\xb5b\x010\x04\x018\>$GNRMC,063337.00.....$GNGGA...
t1 : b''
t2*****: b'\xb5b\x010\x04\x01\x18\>$GNRMC,063338.00.....$GNGGA...
t1 : b''
和(用于注释的两行):
t2*****: b'$GPGSV,3,1,11,05,43,248,30,07,31,068,12,08,15,048,23,09,16,128,30*7B\r\n'
t1 : b'$GPGSV,3,2,11,13,42,311,27,15,10,310,18,17,04,157,09,28,70,161,27*72\r\n'
正如所见,无论t1 没有获取数据还是t1 都只获取下一个。我还设置了计时器(100 毫秒),但输出相同。有人可以指导我吗,我错过了什么?
【问题讨论】:
-
如果你执行“ser.read(ser.inWaiting())”你会得到缓冲区中的字符。之后缓冲区为空。数据现在仅在“data_str”中。你不能用 ser.read 再读一遍...!?
-
@dede,我该如何克服,有什么建议吗?
-
我不太明白您要实现的目标.....您可以将 t1 声明为 self.t1(即 timer1_f 中的 self.t1=next_data())并设置 t2= timer2_f 中的 self.t1。
标签: python multithreading timer serial-port nonblocking