python 自动识别并连接串口的实现


Posted in Python onJanuary 19, 2021

这个属于我项目中一个函数,跟大家分享一下我的思路及最终实现

在编写串口通信工具中,需要实现一个函数,自动找到对应com 口,并且连接该com口,保证后续通信正常
作为初始化过程的一部分。

思路

在win 设备管理器中,经常会出现多个com 口,但并不是每个com 口都是目标设备所链接的。
尝试打开每个com 口,输入enter 按键, 正确的com 口,会有ack log 返回,表明通信 正常

否则,没有任何log 返回,则判断为非目标设备所连接的com 口。

实现

python 自动识别并连接串口的实现

尝试去打开所有com 口,然后发送enter, 如果在一段时间内有返回值,检查com 口收到的字节数,如果非零,则表明找到了对应的com 口。

完整测试代码如下:

import serial
import serial.tools.list_ports
import threading
import binascii
import time
from datetime import datetime

# default value
baunRate = 115200
is_read = False
is_write = False
write_buff = []
sys_buff = []
mSerial = None
callback = None
is_opened = 0
is_registed = 0


class SerialPort:

  def __init__(self,port,buand):

    self.port = serial.Serial(port,buand)
    self.port.close()
    if not self.port.isOpen():
      self.port.open()

    #the index of data_bytes for read operation,私有属性
    #only used in read lines
    self.__read_ptr = 0
    self.__read_head = 0
    #store all read bytes
    # used in read date, read lines
    self.__data_bytes = bytearray()

  def port_open(self):
    if not self.port.isOpen():
      self.port.open()

  def port_close(self):
    self.port.close()

  def send(self):
    global is_write
    global write_buff

    while is_write:
      if len(write_buff):
        msg = write_buff.pop(0)
        msg = msg+"\n"
        cmd = msg.encode()
        try:

          self.port.write(cmd)
        except:
          write_buff.clear()
          is_write = False
    write_buff.clear()

  def read_data(self):
    global is_read
    global is_opened
    byte_cnt = 0
    while is_read:
      try:
        count = self.port.inWaiting()
        if count > 0:
          rec_str = self.port.read(count)
          self.__data_bytes = self.__data_bytes+rec_str
        #print("receive:",rec_str.decode())
          #print(rec_str)
          byte_cnt += count
          if not is_opened:
            is_opened = 1
      #print("累计收到:",byte_cnt)
      #time.sleep(0.5)
        self.read_lines()
      except:
        deinit()


  #将当前所有的数据都读出,读取位置不变,每次读取指针依次移动,不漏数据, 读取行为一直在进行
  def read_lines(self):
    #reset
    line_cnt = 0
    data_len = len(self.__data_bytes)
    #print ("")
    #print ("begin: prt=:", self.__read_ptr, " head =", self.__read_head,"current len =",data_len)
    if self.__read_ptr >=data_len:
      return
    #get all lines in current data_bytes
    while(self.__read_ptr < data_len-1):
      if(self.__data_bytes[self.__read_ptr+1] == 0x0a and self.__data_bytes[self.__read_ptr] == 0x0d):
        tmp = bytearray()
        tmp = self.__data_bytes[self.__read_head:self.__read_ptr]

        try:
          line = tmp.decode()
        except:
          self.__read_head = self.__read_ptr + 2
          self.__read_ptr = self.__read_head
          continue
        iprint(line)
        line_cnt += 1
        self.__read_head = self.__read_ptr + 2
        self.__read_ptr = self.__read_head
      else:
        self.__read_ptr = self.__read_ptr + 1

def auto_open_serial():
  global baunRate
  global mSerial
  global callback
  global is_registed
  global is_opened
  #reset
  deinit()
  # 列出所有当前的com口
  port_list = list(serial.tools.list_ports.comports())
  port_list_name = []
  #get all com
  if len(port_list) <= 0:
    iprint("the serial port can't find!")
    return False
  else:
    for itms in port_list:
      port_list_name.append(itms.device)
  #try open
  #print(port_list_name)
  for i in port_list_name:
    try:
      mSerial = SerialPort(i,baunRate)
      iprint("try open %s"%i)
      start_task()
      send("")
      #return True
      time.sleep(1)
      if is_opened:
        iprint("connect %s successfully"%i)
        return True
      else:
        deinit()
        if i == port_list_name[len(port_list_name)-1]:
          iprint("uart don't open")
          break
        continue
    except:
      iprint(" uart don't open")
  deinit()
  return False

def deinit():
  global mSerial
  global is_write
  global is_read
  global write_buff
  global is_opened

  if mSerial:
    mSerial.port_close()

  is_opened = 0
  is_read = False
  is_write = False
  write_buff = []

  mSerial = None
  time.sleep(1)

def init():
  global mSerial
  global callback
  global is_registed
  global is_opened
  global is_read
  global is_write
  #retry
  retry_time = 0
  while not auto_open_serial():
    if not is_opened:
      iprint("wait for uart connect, retry %s"%str(retry_time))
    else:
      return True
    retry_time += 1
    time.sleep(2)
    if retry_time == 10:
      iprint(" open uart fail")
      return False

def send(msg):
  global mSerial
  global is_write
  global write_buff
  if is_write:
    write_buff.append(msg)

def start_task():
  global mSerial
  global is_write
  global is_read

  if mSerial:
    is_write = True
    t1 = threading.Thread (target=mSerial.send)
    t1.setDaemon (False)
    t1.start ()

    is_read = True
    t2 = threading.Thread (target=mSerial.read_data)
    t2.setDaemon (False)
    t2.start ()

def iprint(msg):
  global callback
  global is_registed

  msg = "[Uart] "+str(msg)
  if is_registed:
    callback.append(msg)
  else:
    print(msg)

def start_sys_cmd():
  global is_registed
  if is_registed:
    t3 = threading.Thread (target=process_receive_sys_cmd)
    t3.setDaemon (False)
    t3.start()

def process_receive_sys_cmd():
  global sys_buff
  global is_registed
  global callback
  #print("process_receive_sys_cmd")
  while is_registed:
    #print ("wait,process_receive_sys_cmd")
    if len(sys_buff):
      #print ("receive,process_receive_sys_cmd")
      line = sys_buff.pop(0)
      if "init" in line:
        if is_opened and is_read and is_write:
          iprint("already open uart")
          break
        iprint("start init")
        init()
    if is_opened:
      break
  iprint("Eixt uart sys thread")

def register_cback(list):
  global callback
  global is_registed

  callback = list
  is_registed = 1


def unregister_cback():
  global callback
  callback.clear()

if __name__ == '__main__':

  receive = []
  register_cback(receive)
  sys_buff.append("init")
  start_sys_cmd()

  def process_receive_msg():
    global receive
    while True:
      #print("wait")
      if len(receive):
        #print("receive")
        print(receive.pop(0))

  t = threading.Thread(target=process_receive_msg)
  t.setDaemon(False)
  t.start()

到此这篇关于python 自动识别并连接串口的实现的文章就介绍到这了,更多相关python 自动识别并连接串口内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python文件操作,open读写文件,追加文本内容实例
Dec 14 Python
安装python3的时候就是输入python3死活没有反应的解决方法
Jan 24 Python
pandas数据框,统计某列数据对应的个数方法
Apr 11 Python
python调用xlsxwriter创建xlsx的方法
May 03 Python
Python基于OpenCV实现人脸检测并保存
Jul 23 Python
解决Django Static内容不能加载显示的问题
Jul 28 Python
Python在OpenCV里实现极坐标变换功能
Sep 02 Python
Tensorflow不支持AVX2指令集的解决方法
Feb 03 Python
python如何求数组连续最大和的示例代码
Feb 04 Python
Python3 hashlib密码散列算法原理详解
Mar 30 Python
Python中用xlwt制作表格实例讲解
Nov 05 Python
python中scrapy处理项目数据的实例分析
Nov 22 Python
python爬取抖音视频的实例分析
Jan 19 #Python
python中的插入排序的简单用法
Jan 19 #Python
Python实现淘宝秒杀功能的示例代码
Jan 19 #Python
Python爬虫后获取重定向url的两种方法
Jan 19 #Python
详解Python+Selenium+ChromeDriver的配置和问题解决
Jan 19 #Python
VSCODE配置Markdown及Markdown基础语法详解
Jan 19 #Python
python+selenium自动化实战携带cookies模拟登陆微博
Jan 19 #Python
You might like
有关 PHP 和 MySQL 时区的一点总结
2008/03/26 PHP
PHP获取表单textarea数据中的换行问题
2010/09/10 PHP
php中解析带中文字符的url函数分享
2015/01/20 PHP
在Windows XP下安装Apache+MySQL+PHP环境
2015/02/22 PHP
PHP模板解析类实例
2015/07/09 PHP
关于文本框的一些限制控制总结~~
2010/04/15 Javascript
javascript 仿QQ滑动菜单效果代码
2010/09/03 Javascript
Bootstrap入门书籍之(一)排版
2016/02/17 Javascript
JavaScript判断变量是否为数组的方法(Array)
2016/02/24 Javascript
轻松掌握JavaScript享元模式
2016/08/27 Javascript
JavaScript注入漏洞的原理及防范(详解)
2016/12/04 Javascript
jQuery实现表格冻结顶栏效果
2017/08/20 jQuery
vue小白入门教程
2018/04/02 Javascript
nodejs之koa2请求示例(GET,POST)
2018/08/07 NodeJs
vuex存值与取值的实例
2019/11/06 Javascript
vue + el-form 实现的多层循环表单验证
2020/11/25 Vue.js
Python标准库defaultdict模块使用示例
2015/04/28 Python
Python2.x版本中基本的中文编码问题解决
2015/10/12 Python
使用Python编写简单的画图板程序的示例教程
2015/12/08 Python
基于python yield机制的异步操作同步化编程模型
2016/03/18 Python
python调用百度REST API实现语音识别
2018/08/30 Python
Python批处理更改文件名os.rename的方法
2018/10/26 Python
使用python分析统计自己微信朋友的信息
2019/07/19 Python
numpy np.newaxis 的实用分享
2019/11/30 Python
python爬取网易云音乐热歌榜实例代码
2020/08/07 Python
python中HTMLParser模块知识点总结
2021/01/25 Python
钉钉企业内部H5微应用开发详解
2020/05/12 HTML / CSS
食堂员工工作职责
2013/12/18 职场文书
百日安全活动总结
2014/05/04 职场文书
优秀学生干部先进事迹材料
2014/05/26 职场文书
2014机关党员干部“正风肃纪”思想汇报
2014/09/15 职场文书
小学“向国旗敬礼”网上签名寄语活动总结
2014/09/27 职场文书
学校开学标语
2014/10/06 职场文书
python 经纬度求两点距离、三点面积操作
2021/06/03 Python
vue实现锚点定位功能
2021/06/29 Vue.js
mysql自增长id用完了该怎么办
2022/02/12 MySQL