Python 利用PyQt5寫一個簡易的串口助手

       學習單片機,STM32好長時間了,也做了一些項目,一直想利用上位機實現電腦與單片機之間的傳輸數據,利用串口助手是最直接的通信方式,但串口助手不適合做上位機,如果會寫串口助手的軟件,基本能寫自己寫一個上位機,歷時一個月,終於寫出一個簡易的串口助手,筆者自己寫的軟件,有些Bug,分享出來,僅供參考,歡迎大家一起學習與討論。

       目標:利用Python語言寫一個簡易的串口助手

       環境:Win10,  python語言, PyQt5, Pycharm

       思路:先做出主體,慢慢優化與添加其他的功能,在串口助手設計中主體是獲取串口ID號,設置波特率,發送數據,接收數據,添加界面佈局,信號觸發等操作。

       一、設置串口ID號

        建議製作第一版串口助手,可以先選定固定串口和波特率進行設計,在筆者設計時,固定一個串口爲COM4,波特率爲9600設計,設置參考代碼如下:

 self.t = serial.Serial('com4', 9600)
 port = self.t.portstr
 print(port)

這樣就簡單將串口設置爲打開串口時爲COM4,波特率爲9600,COM4是筆者所用的電腦端口。後續將端口和波特率變爲可選擇

        二、發送數據和接收數據

       發送數據類型簡單可分爲字符串發送和十六進制發送,發送數據方式是輸入發送,在本文中先實現字符串發送,後續再實現十六進制發送。同理,接收數據也可先實現字符串接收,後續再實現十六進制發送。參考代碼如下:

import serial
import time
import threading
class SerialPort:
    message = ''
    def __init__(self, port, buand):
        super(SerialPort, self).__init__()
        self.port = serial.Serial(port, buand)
        self.port.close()
        if not self.port.isOpen():
            self.port.open()
    def port_open(self):
        if not self.port.isOpen():
            self.port.open()    #打開串口
    def port_close(self):
        self.port.close()
    def send_data(self):
        data = input("請輸入要發送的數據(非中文)並同時接收數據: ")
        n = self.port.write(data.encode())    #發送數據
        print(n)
    def read_data(self):          #接收數據
        while True:    
            self.message = self.port.readline()  #接收數據
            print(self.message)

serialPort = "COM4"  # 串口
baudRate = 9600  # 波特率

if __name__ == '__main__':
    mSerial = SerialPort(serialPort, baudRate)
    t1 = threading.Thread(target=mSerial.read_data)
    t1.start()
    while True:
        time.sleep(1)
        mSerial.send_data()

 三、加入界面佈局

       利用PyQt5庫搭建界面,在界面佈局中使用網格佈局管理QGridLayout,代碼如下:

 def initUI(self):
        grid = QGridLayout()

        self.portname = QLabel("端口號")   #添加控件
        self.datanumber = QLabel("發送數據位數:")
        self.datasender = QLabel("發送數據:")
        self.datareview = QLabel("接收數據:")
        self.button = QPushButton("發送")
        self.open_button = QPushButton("打開")
        self.portnameEdit = QLineEdit()
        self.datanumberEdit = QLineEdit()
        self.datasenderEdit = QLineEdit()
        self.datareviewEdit = QLineEdit()

        grid.addWidget(self.portname, 1, 0)  #添加控件的位置
        grid.addWidget(self.portnameEdit, 1, 1)
        grid.addWidget(self.datanumber, 2, 0)
        grid.addWidget(self.datanumberEdit, 2, 1)
        grid.addWidget(self.datasender, 3, 0,)
        grid.addWidget(self.datasenderEdit, 3, 1, 1, 6)
        grid.addWidget(self.datareview, 4, 0)
        grid.addWidget(self.datareviewEdit, 4, 1, 1, 6)
        grid.addWidget(self.button, 5, 3)
        grid.addWidget(self.open_button, 5, 1)
        self.setLayout(grid)    #佈局

        self.button.clicked.connect(self.Cosender)    #關聯"發送"按鈕與信號槽
        self.open_button.clicked.connect(self.Check_serial)    #關聯“打開”按鈕與信號槽
        self.setGeometry(300,300,200,200)  #設置窗體大小
        self.setWindowTitle("串口助手")    

四、加入觸發信號

       在上面的佈局管理中,加入了“打開”和“發送”兩個按鈕。需要給兩個按鈕加入信號槽。編寫好信號槽代碼後再關聯按鈕與信號槽。信號槽代碼如下:

    def messageUI(self):
        '''提示串口打開狀況信息'''
        QMessageBox.critical(self, "錯誤", "串口打開失敗,請選擇正確的串口")  #彈出提示信息
    def Check_serial(self):
        '''檢測串口是否被打開'''
        try:
            self.t = serial.Serial('com4', 9600)   #打開串口COM4
            port = self.t.portstr     #返回但端口號
            self.portnameEdit.setText(port)   #顯示在界面上
            self.flag_open=1
        except serial.serialutil.SerialException:   #打開失敗,輸出提示信息
            self.messageUI()      #提示信息
    def Cosender(self):
        '''“發送”按鈕,信號槽'''
        if self.flag_open==1:    #串口被打開
            self.str_input = self.datasenderEdit.text()   #返回上面的發送文字
            n = self.t.write((self.str_input+'\n').encode())
            self.datanumberEdit.setText(str(n-1))     #寫入數據位數框
            self.datasenderEdit.setText(str(self.str_input))    #寫入發送框
            time.sleep(1)  # sleep() 與 inWaiting() 最好配對使用
            num = self.t.inWaiting()  #獲取接收到的數據長度
            if num:
                self.receivemessage = self.t.read(num) #讀取接收數據
                print(self.receivemessage)
                self.datareviewEdit.setText(str(self.receivemessage)[2:-1])  #寫入接收框

        else:    #串口打開失敗
            self.messageUI()

     關聯按鈕與信號槽的代碼如下:

 self.button.clicked.connect(self.Cosender)    #關聯"發送"按鈕與信號槽
 self.open_button.clicked.connect(self.Check_serial)    #關聯“打開”按鈕與信號槽

   這樣製作一個基本的簡易串口助手完成。如有不足之處請多多指教。效果如圖1所示。後面在開發加入了串口,波特率可供選擇性,發送和接收數據有字符串和十六進制等設計,效果如圖2所示,有興趣的讀者可以自行下載源代。源代碼鏈接:

https://download.csdn.net/download/scx2006114/11579725

                                              

                                         圖1                                                                                                  圖2                

參考資料鏈接:

   1.發送和接收數據:https://blog.csdn.net/xiaoeleis/article/details/81484872

   2.頁面佈局:https://blog.csdn.net/zhulove86/article/details/52563298

完整代碼如下:

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLineEdit, \
                            QGridLayout, QLabel, QMessageBox, QComboBox, \
                            QCheckBox
import serial
import time
import serial.tools.list_ports

class CO2UI(QWidget):

    def __init__(self):
        super(CO2UI, self).__init__()
        self.initUI()
        global flag_open     #標誌位,判斷串口是否打開
        self.flag_open = 0
    def initUI(self):
        grid = QGridLayout()

        self.portname = QLabel("端口號")
        self.datanumber = QLabel("發送數據位數:")
        self.datasender = QLabel("發送數據:")
        self.datareview = QLabel("接收數據:")
        self.button = QPushButton("發送")
        self.open_button = QPushButton("打開")
        self.portnameEdit = QLineEdit()
        self.datanumberEdit = QLineEdit()
        self.datasenderEdit = QLineEdit()
        self.datareviewEdit = QLineEdit()

        grid.addWidget(self.portname, 1, 0)
        grid.addWidget(self.portnameEdit, 1, 1)
        grid.addWidget(self.datanumber, 2, 0)
        grid.addWidget(self.datanumberEdit, 2, 1)
        grid.addWidget(self.datasender, 3, 0,)
        grid.addWidget(self.datasenderEdit, 3, 1, 1, 6)
        grid.addWidget(self.datareview, 4, 0)
        grid.addWidget(self.datareviewEdit, 4, 1, 1, 6)
        grid.addWidget(self.button, 5, 3)
        grid.addWidget(self.open_button, 5, 1)
        self.setLayout(grid)

        self.button.clicked.connect(self.Cosender)
        self.open_button.clicked.connect(self.Check_serial)
        self.setGeometry(300,300,200,200)
        self.setWindowTitle("C02上位機")
    def messageUI(self):
        '''提示信息'''
        QMessageBox.critical(self, " ", "串口打開失敗,請選擇正確的串口")
    def Check_serial(self):
        '''檢測串口是否被打開'''
        try:
            self.t = serial.Serial('com4', 9600)   #打開串口COM4
            port = self.t.portstr     #返回但端口號
            self.portnameEdit.setText(port)   #顯示在界面上
            self.flag_open=1
        except serial.serialutil.SerialException:   #打開失敗,輸出提示信息
            self.messageUI()      #提示信息

    def Cosender(self):
        if self.flag_open==1:
            if self.flag_open == 1:  # 串口被打開
                self.str_input = self.datasenderEdit.text()  # 返回上面的發送文字
                n = self.t.write((self.str_input + '\n').encode())
                self.datanumberEdit.setText(str(n - 1))  # 寫入數據位數框
                self.datasenderEdit.setText(str(self.str_input))  # 寫入發送框
                time.sleep(1)  # sleep() 與 inWaiting() 最好配對使用
                num = self.t.inWaiting()  # 獲取接收到的數據長度
                if num:
                    self.receivemessage = self.t.read(num)  # 讀取接收數據
                    print(self.receivemessage)
                    self.datareviewEdit.setText(str(self.receivemessage)[2:-3])  # 寫入接收框
        else:
            self.messageUI()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    test = CO2UI()
    test.show()
    sys.exit(app.exec_())

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章