在上篇建立好microblaze以address 0x7c600000 來控制LED燈
並在SDK裡面用UART來收集連續的address與data資料
所以可以用pyserial來代替tera term,並用wxGlade來建立一個超簡單的GUI好讓使用者使用
有關pyserial的wxpython範例可以在這邊看到
http://pyserial.sourceforge.net/examples.html#wxpython-examples
我會用到wxTerminal.py與wxSerialConfigDialog.py
主程式是wxTerminal, 它其實就是一個python 版的tera term
我先用wxGlade畫一個簡單的GUI,只有一個text與button
text用來寫address的data,button按下時直接送入address 0x7c600000與使用者寫入的資料
在這個例子寫入資料0x00000001 讓LED燈開始閃爍,0x00000000則讓它停止閃爍
打開wxGlade新增一個Frame,選wxFrame
加入一個boxsizer,點了boxsizer之後再點Frame的地方就會出現對話方塊,slots改成2,讓它把畫面分成兩半,使用者就可以輸入不同的功能方塊
在左邊的boxsizer加入一個textctrl
把名子改成value,之後如果要做比較大的GUI,最好把名子改成跟所需的功能相關,這樣程式寫起來比較省力,知道自己在寫哪一塊,改完後在右邊的boxsizer再加入一個button,同樣把name改成Set
如果要改在gui上顯現的button名子要改widget裡面的label,我將它也設成Set
之後按application
可以看到產生程式的對話視窗,選python與選擇輸出位置與檔案名稱,按generate
code
產生code以後,必須要用bind函式把set與value定義它們的型態與自身的函式
在寫它們本身的函式,這邊在EvtSet中蒐集由EvtVal中輸入的資料並轉成hex,
EvtVal則是當使用者輸入超過8
個數字則出件警告訊息
在把pyserial整合進來,把需要的函式放進來
import 需要的module
import wxSerialConfigDialog import serial import threading from time import sleep
完整的test.py為
#!/usr/bin/env python # -*- coding: CP1252 -*- # # generated by wxGlade 0.6.8 (standalone edition) on Thu May 15 15:13:20 2014 # import wx import wxSerialConfigDialog import serial import threading from time import sleep # begin wxGlade: dependencies import gettext # end wxGlade # begin wxGlade: extracode # end wxGlade #---------------------------------------------------------------------- SERIALRX = wx.NewEventType() # bind to serial data receive events EVT_SERIALRX = wx.PyEventBinder(SERIALRX, 0) class SerialRxEvent(wx.PyCommandEvent): eventType = SERIALRX def __init__(self, windowID, data): wx.PyCommandEvent.__init__(self, self.eventType, windowID) self.data = data def Clone(self): self.__class__(self.GetId(), self.data) #---------------------------------------------------------------------- LED_ADDR = '7c600000' NEWLINE_CR = 0 NEWLINE_LF = 1 NEWLINE_CRLF = 2 LED = int(0x00000000) #---------------------------------------------------------------------- class TerminalSetup: """Placeholder for various terminal settings. Used to pass the options to the TerminalSettingsDialog.""" def __init__(self): self.echo = False self.unprintable = False self.newline = NEWLINE_CRLF class MyFrame(wx.Frame): def __init__(self, *args, **kwds): self.serial = serial.Serial() self.serial.timeout = 0.5 self.settings = TerminalSetup() self.thread = None self.alive = threading.Event() # begin wxGlade: MyFrame.__init__ kwds["style"] = wx.DEFAULT_FRAME_STYLE wx.Frame.__init__(self, *args, **kwds) self.Value = wx.TextCtrl(self, wx.ID_ANY, "") self.Set = wx.Button(self, wx.ID_ANY, _("Set")) self.__set_properties() self.__do_layout() # end wxGlade #------------------------------------------------- self.OnPortSettings(None) if not self.alive.isSet(): self.Close() self.Bind(wx.EVT_BUTTON, self.EvtSet, self.Set) self.Bind(wx.EVT_TEXT,self.EVTVal,self.Value) # function def Write(self, addr, data): writein = str(data) if len(writein) == 3: data7 = writein[2] data6 = '0' data5 = '0' data4 = '0' data3 = '0' data2 = '0' data1 = '0' data0 = '0' elif len(writein) == 4: data7 = writein[3] data6 = writein[2] data5 = '0' data4 = '0' data3 = '0' data2 = '0' data1 = '0' data0 = '0' elif len(writein) == 5: data7 = writein[4] data6 = writein[3] data5 = writein[2] data4 = '0' data3 = '0' data2 = '0' data1 = '0' data0 = '0' elif len(writein) == 6: data7 = writein[5] data6 = writein[4] data5 = writein[3] data4 = writein[2] data3 = '0' data2 = '0' data1 = '0' data0 = '0' elif len(writein) == 7: data7 = writein[6] data6 = writein[5] data5 = writein[4] data4 = writein[3] data3 = writein[2] data2 = '0' data1 = '0' data0 = '0' elif len(writein) == 8: data7 = writein[7] data6 = writein[6] data5 = writein[5] data4 = writein[4] data3 = writein[3] data2 = writein[2] data1 = '0' data0 = '0' elif len(writein) == 9: data7 = writein[8] data6 = writein[7] data5 = writein[6] data4 = writein[5] data3 = writein[4] data2 = writein[3] data1 = writein[2] data0 = '0' elif len(writein) == 10: data7 = writein[9] data6 = writein[8] data5 = writein[7] data4 = writein[6] data3 = writein[5] data2 = writein[4] data1 = writein[3] data0 = writein[2] else: data7 = writein[9] data6 = writein[8] data5 = writein[7] data4 = writein[6] data3 = writein[5] data2 = writein[4] data1 = writein[3] data0 = writein[2] self.serial.write(addr) self.serial.write(data0) self.serial.write(data1) self.serial.write(data2) self.serial.write(data3) self.serial.write(data4) self.serial.write(data5) self.serial.write(data6) self.serial.write(data7) def EvtSet(self,event): GetValue = hex(int(self.Value.GetValue(),16)) self.Write(LED_ADDR,GetValue) #self.Write('7c600000','00000000') def EVTVal(self,event): length = len(event.GetString()) if length > 8: alert_dialog = wx.MessageDialog(None,u"Bits Overflow",u"Error",wx.OK | wx.ICON_ERROR) if alert_dialog.ShowModal() == wx.ID_OK: alert_dialog.Destroy() def StartThread(self): """Start the receiver thread""" self.thread = threading.Thread(target=self.ComPortThread) self.thread.setDaemon(1) self.alive.set() self.thread.start() def StopThread(self): """Stop the receiver thread, wait util it's finished.""" if self.thread is not None: self.alive.clear() #clear alive event for thread self.thread.join() #wait until thread has finished self.thread = None def OnTermSettings(self, event): """Menu point Terminal Settings. Show the settings dialog with the current terminal settings""" dialog = TerminalSettingsDialog(None, -1, "", settings=self.settings) result = dialog.ShowModal() dialog.Destroy() def OnPortSettings(self, event=None): """Show the portsettings dialog. The reader thread is stopped for the settings change.""" if event is not None: #will be none when called on startup self.StopThread() self.serial.close() ok = False while not ok: dialog_serial_cfg = wxSerialConfigDialog.SerialConfigDialog(None, -1, "", show=wxSerialConfigDialog.SHOW_BAUDRATE|wxSerialConfigDialog.SHOW_FOR MAT|wxSerialConfigDialog.SHOW_FLOW, serial=self.serial ) result = dialog_serial_cfg.ShowModal() dialog_serial_cfg.Destroy() #open port if not called on startup, open it on startup and OK too if result == wx.ID_OK or event is not None: try: self.serial.open() except serial.SerialException, e: dlg = wx.MessageDialog(None, str(e), "Serial Port Error", wx. OK | wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() else: self.StartThread() self.SetTitle("Serial Terminal on %s [%s, %s%s%s%s%s]" % ( self.serial.portstr, self.serial.baudrate, self.serial.bytesize, self.serial.parity, self.serial.stopbits, self.serial.rtscts and ' RTS/CTS' or '', self.serial.xonxoff and ' Xon/Xoff' or '', ) ) ok = True else: #on startup, dialog aborted self.alive.clear() ok = True def OnKey(self, event): """Key event handler. if the key is in the ASCII range, write it to the s erial port. Newline handling and local echo is also done here.""" code = event.GetKeyCode() if code < 256: #is it printable? if code == 13: #is it a newline? (check for CR w hich is the RETURN key) if self.settings.echo: #do echo if needed self.COM_STATUS.AppendText('\n') if self.settings.newline == NEWLINE_CR: self.serial.write('\r') #send CR elif self.settings.newline == NEWLINE_LF: self.serial.write('\n') #send LF elif self.settings.newline == NEWLINE_CRLF: self.serial.write('\r\n') #send CR+LF else: char = chr(code) if self.settings.echo: #do echo if needed self.COM_STATUS.WriteText(char) self.serial.write(char) #send the charcater else: print "Extra Key:", code def OnSerialRead(self, event): """Handle input from the serial port.""" text = event.data if self.settings.unprintable: text = ''.join([(c >= ' ') and c or '<%d>' % ord(c) for c in text]) self.COM_STATUS.AppendText(text) def ComPortThread(self): """Thread that handles the incomming traffic. Does the basic input transformation (newlines) and generates an SerialRxEvent""" while self.alive.isSet(): #loop while alive event is true text = self.serial.read(1) #read one, with timout if text: #check if not timeout n = self.serial.inWaiting() #look if there is more to read if n: text = text + self.serial.read(n) #get it #newline transformation if self.settings.newline == NEWLINE_CR: text = text.replace('\r', '\n') elif self.settings.newline == NEWLINE_LF: pass elif self.settings.newline == NEWLINE_CRLF: text = text.replace('\r\n', '\n') event = SerialRxEvent(self.GetId(), text) self.GetEventHandler().AddPendingEvent(event) #~ self.OnSerialRead(text) #output text in window #---------------------------------------------------------------------- def __set_properties(self): # begin wxGlade: MyFrame.__set_properties self.SetTitle(_("Test")) # end wxGlade def __do_layout(self): # begin wxGlade: MyFrame.__do_layout sizer_1 = wx.BoxSizer(wx.VERTICAL) sizer_2 = wx.BoxSizer(wx.HORIZONTAL) sizer_2.Add(self.Value, 0, 0, 0) sizer_2.Add(self.Set, 0, 0, 0) sizer_1.Add(sizer_2, 1, wx.EXPAND, 0) self.SetSizer(sizer_1) sizer_1.Fit(self) self.Layout() # end wxGlade # end of class MyFrame if __name__ == "__main__": gettext.install("app") # replace with the appropriate catalog name app = wx.PySimpleApp(0) wx.InitAllImageHandlers() frame_1 = MyFrame(None, -1, "") app.SetTopWindow(frame_1) frame_1.Show() app.MainLoop()
紅色的程式是從wxTerminal.py整合過來,綠色的是自己加上去的
函式write是為了如果使用者沒有完整輸入8位數,則自動補零
所以在測試的時候,即使對話框只輸入1,LED燈也是會閃爍
程式測試成功以後,把它轉成exe檔
寫一個py2exesetup.py,windows=['test.py']
裡填入要轉換的py檔
from distutils.core import setup import py2exe setup( windows=['test.py'], options = { "py2exe": {"dll_excludes":["MSVCP90.dll"]} } )
把所有會引用到的py檔與py2exesetup.py複製到c下面的python26
然後打開cmd進入python26下command
python py2exesetup.py install python py2exesetup.py py2exe
就會在同一層的資料夾中產生一個新的disk資料夾
裡面的exe檔就是轉換出來的小寶貝拉XD
沒有留言:
張貼留言