简体   繁体   English

如何使用 pyserial 将文件逐行写入 com0com?

[英]How can I write file line-by-line with pyserial to com0com?

I cannot write more than one line of data from a file to a virtual com port (com0com) using pyserial.我不能使用 pyserial 将文件中的多行数据写入虚拟 com 端口(com0com)。 I am attempting to write the file line-by-line so I can simultaneously update a progress bar in Tkinter.我正在尝试逐行编写文件,以便同时更新 Tkinter 中的进度条。 I am running on Windows and have attempted to put the write operation in its own thread (per UART Controller with Tkinter and Python GUI ). I am running on Windows and have attempted to put the write operation in its own thread (per UART Controller with Tkinter and Python GUI ). My program hangs after writing one line.我的程序在写一行后挂起。

Relevant Code:相关代码:

import os
import sys
from functools import partial
import re
import time
import threading

import serial
import serial.tools.list_ports

import tkinter as tk
from tkinter import ttk, filedialog

class MainApp(tk.Tk):

    def __init__(self,
                 parent,
                 title = 'Main Application',
                 *args,
                 **kwargs):

        self.parent = parent

        #Set window title and size
        self.parent.title(title)

        #Create widget container
        container = tk.Frame(self.parent)

        #Add widgets

        # --> Create load program widgets
        load_frame = tk.LabelFrame(container,
                                   text = 'Load Program',
                                   width = 400,
                                   height = 100)

        port_dropdown = DropDown(load_frame,
                                 label = 'Port:',
                                 row = 0)

        file_browser = Browser(load_frame,
                               path_type = 'file',
                               label = 'File:',
                               row = 1)

        program_downloader = Downloader(load_frame,
                                        port_dropdown,
                                        file_browser,
                                        row = 2)

        # --> Layout load program widgets
        load_frame.grid(row = 0,
                        column= 0,
                        padx = (5,5),
                        pady = (5,5))

        #Layout widget container
        container.pack(fill = tk.BOTH,
                       padx = 10,
                       pady = 5,
                       expand = True)         
.
.
.

class Downloader(tk.Frame):

    def __init__(self,
                 parent,
                 port_dropdown,
                 file_browser,
                 row = 0):

        self.port_dropdown = port_dropdown
        self.file_browser = file_browser

        #Instantiate serial port object
        self.serial_port = None

        self.progress_bar = ttk.Progressbar(parent,
                                            orient = 'horizontal',
                                            mode = 'determinate')

        self.progress_bar.grid(row = row,
                               column = 0,
                               columnspan = 2,
                               padx = (5,5),
                               pady = (5,5),
                               sticky = 'WE')

        self.button = tk.Button(parent,
                                text = 'Download',
                                command = self.download_program)

        self.button.grid(row = row,
                         column = 2,
                         padx = (5,5),
                         pady = (5,5),
                         sticky = 'W')

    def download_program(self):

        port_full_name = self.port_dropdown.combobox.get()
        port_name = re.match('([^\s]+)', port_full_name).group(0)

        baud_rate = 9600

        program_path = self.file_browser.text.get()

        self.connect(port_name,
                     baud_rate,
                     program_path)

    def connect(self,
                port_name,
                baud_rate,
                program_path):

        self.serial_port = serial.Serial(port_name,
                                         baud_rate,
                                         timeout=1)

        t1 = threading.Thread(target = self.transfer_data,
                              args = (program_path,))
        t1.daemon = True
        t1.start()

    def transfer_data(self,
                      program_path):

        line = 1
        self.progress_bar['value'] = line

        with open(program_path, 'r') as program:

            max_lines = len(program.readlines())
            self.progress_bar['maximum'] = max_lines

        with open(program_path, 'r') as program:

            while line < max_lines:

                command = program.readline().replace('\n','\r\n')

                print(str(line) + ': ' + repr(command))

                self.serial_port.write(command.encode('ascii'))

                line += 1

                self.progress_bar['value'] = line

                self.serial_port.flush()

        print('done')
        self.disconnect()

    def disconnect(self):
        self.serial_port.close()

if __name__ == '__main__':

    #Initialize Tkinter
    root = tk.Tk()

    #Create GUI
    gui = MainApp(root,
                  'Main Application')

    #Run program
    root.mainloop()

GUI Hangs: GUI挂起:

图形用户界面输出

Terminal Output:端子 Output:

1: '@01\r\n'
2: '@02\r\n'

The fact that I'm able to read from program.txt the second time around in the loop tells me the program might be hanging because the port is still stuck on the first write.我能够在循环中第二次从program.txt读取的事实告诉我,程序可能会挂起,因为端口仍然停留在第一次写入上。

Any help would be appreciated.任何帮助,将不胜感激。

Set timeout and write_timeout to 0 prevents blocking, which seems to fix the problem.timeoutwrite_timeout设置为0可以防止阻塞,这似乎可以解决问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM