2014-09-25 297 views
1

我已經開始使用PySerial編寫一些代碼來發送和接收數據到串行設備。Python串行端口監聽器

到目前爲止,我一直致力於從終端啓動事務並接收來自串行設備的響應。

僞:

main: 
    loop: 
     message = get_message() 
     send_to_serial(message) 
     time_delay(1 second) 
     read_response() 

現在我想實現在串行設備是一個發起通信的情況下該端口上的監聽器。還要刪除time_delay,這可能會導致系統設備響應時間過長或不夠長。

state = idle 
register_interrupt(serial_device, read_response()) 

main: 
    loop: 
     message = get_message() 
     state = sending 
     send_to_serial(message) 

到目前爲止,我還沒有找到任何使用中斷進行通信的PySerial代碼。

我只是不知道如何設置在python任何形式的中斷,怎麼會

回答

4

它可以使用select模塊上serial連接選擇:

import serial 
import select 

timeout = 10 
conn = serial.Serial(serial_name, baud_rate, timeout=0) 
read,_,_ = select.select([conn], [], [], timeout) 
read_data = conn.read(0x100) 

以下是一個在主線程中創建僞tty的完整示例。主線程以5秒爲間隔將數據寫入pty。創建一個子線程試圖使用select.select等待讀取數據,以及使用正常serial.Serial.read方法來讀取數據PTY:

#!/bin/bash 

import os 
import pty 
import select 
import serial 
import sys 
import threading 
import time 

def out(msg): 
    print(msg) 
    sys.stdout.flush() 

# child process 
def serial_select(): 
    time.sleep(1) 

    out("CHILD THREAD: connecting to serial {}".format(serial_name)) 
    conn = serial.Serial(serial_name, timeout=0) 
    conn.nonblocking() 

    out("CHILD THREAD: selecting on serial connection") 
    avail_read, avail_write, avail_error = select.select([conn],[],[], 7) 
    out("CHILD THREAD: selected!") 

    output = conn.read(0x100) 
    out("CHILD THREAD: output was {!r}".format(output)) 

    out("CHILD THREAD: normal read serial connection, set timeout to 7") 
    conn.timeout = 7 

    # len("GOODBYE FROM MAIN THREAD") == 24 
    # serial.Serial.read will attempt to read NUM bytes for entire 
    # duration of the timeout. It will only return once either NUM 
    # bytes have been read, OR the timeout has been reached 
    output = conn.read(len("GOODBYE FROM MAIN THREAD")) 
    out("CHILD THREAD: read data! output was {!r}".format(output)) 

master, slave = pty.openpty() 
serial_name = os.ttyname(slave) 

child_thread = threading.Thread(target=serial_select) 
child_thread.start() 

out("MAIN THREAD: sleeping for 5") 
time.sleep(5) 

out("MAIN THREAD: writing to serial") 
os.write(master, "HELLO FROM MAIN THREAD") 

out("MAIN THREAD: sleeping for 5") 
time.sleep(5) 

out("MAIN THREAD: writing to serial") 
os.write(master, "GOODBYE FROM MAIN THREAD") 

child_thread.join() 

PySerial內部使用的讀取方法選擇(如果你是在posix系統上),使用提供的超時。但是,它會嘗試讀取NUM個字節,直到NUM字節的總數被讀取,或者直到達到超時。這就是爲什麼示例顯式讀取pty中的len("GOODBYE FROM MAIN THREAD")(24個字節),以便conn.read調用將立即返回,而不是等待整個超時。

TL; DR它可以使用與select.select,這是什麼,我相信serial.Serial連接,你正在尋找。

+0

根據我的經驗,在'serial.Serial'實例上設置一個很小的超時值是很好的,比如1ms。根據傳輸設備的不同,數據可能會稍微慢一點,如果超時時間爲0,您可能會逐字節地讀取數據,因此循環/選擇的CPU數量會明顯增加。 – xzoert 2017-02-24 11:47:53