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制作自动推送微信消息提醒的备忘录功能
Sep 06 Python
使用Python处理BAM的方法
Sep 28 Python
pandas每次多Sheet写入文件的方法
Dec 10 Python
Python使用lambda表达式对字典排序操作示例
Jul 25 Python
使用Python串口实时显示数据并绘图的例子
Dec 26 Python
浅析python表达式4+0.5值的数据类型
Feb 26 Python
python爬虫实现POST request payload形式的请求
Apr 30 Python
解决python执行较大excel文件openpyxl慢问题
May 15 Python
在Keras中利用np.random.shuffle()打乱数据集实例
Jun 15 Python
Python调用jar包方法实现过程解析
Aug 11 Python
vscode+PyQt5安装详解步骤
Aug 12 Python
5道关于python基础 while循环练习题
Nov 27 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源码之 ext/mysql扩展部分
2009/07/17 PHP
php 文件上传代码(限制jpg文件)
2010/01/05 PHP
判断是否为指定长度内字符串的php函数
2010/02/16 PHP
php发送邮件的问题详解
2015/06/22 PHP
基于PHP实现用户注册登录功能
2016/10/14 PHP
从JavaScript的函数重名看其初始化方式
2007/03/08 Javascript
jQuery获得内容和属性方法及示例
2013/12/02 Javascript
javascript中不等于的代码是什么怎么写
2013/12/29 Javascript
js实现简单锁屏功能实例
2015/05/27 Javascript
js实现按钮颜色渐变动画效果
2015/08/20 Javascript
Nodejs实战心得之eventproxy模块控制并发
2015/10/27 NodeJs
Javascript实现的SHA-256加密算法完整实例
2016/02/02 Javascript
如何让一个json文件显示在表格里【实现代码】
2016/05/09 Javascript
JS实现将Asp.Net的DateTime Json类型转换为标准时间的方法
2016/08/02 Javascript
javascript 判断当前浏览器版本并判断ie版本
2017/02/17 Javascript
Node.js五大应用性能技巧小结(必须收藏)
2017/08/09 Javascript
JavaScript实现兼容IE6的收起折叠与展开效果实例
2017/09/20 Javascript
原生js实现密码强度验证功能
2020/03/18 Javascript
[01:56]林书豪DOTA2上海特级锦标赛励志短片
2016/03/05 DOTA
python通过imaplib模块读取gmail里邮件的方法
2015/05/08 Python
python求解数组中两个字符串的最小距离
2018/09/27 Python
详解Python requests 超时和重试的方法
2018/12/18 Python
详解Python_shutil模块
2019/03/15 Python
jupyternotebook 撤销删除的操作方式
2020/04/17 Python
学生励志演讲稿
2014/01/06 职场文书
社区消防工作实施方案
2014/03/21 职场文书
大学课外活动总结
2014/07/09 职场文书
介绍信格式
2015/01/30 职场文书
出纳试用期自我评价
2015/03/10 职场文书
餐厅保洁员岗位职责
2015/04/10 职场文书
2015年生活老师工作总结
2015/05/27 职场文书
大学校园招聘会感想
2015/08/10 职场文书
vue中三级导航的菜单权限控制
2021/03/31 Vue.js
详细总结Python常见的安全问题
2021/05/21 Python
一篇文章看懂MySQL主从复制与读写分离
2021/11/07 MySQL
Java完整实现记事本代码
2022/06/16 Java/Android