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中使用print输出中文的方法
Jul 16 Python
Python中的Numpy矩阵操作
Aug 12 Python
python实现控制台打印的方法
Jan 12 Python
Python实现查找二叉搜索树第k大的节点功能示例
Jan 24 Python
详解爬虫被封的问题
Apr 23 Python
python递归下载文件夹下所有文件
Aug 31 Python
python实现根据文件格式分类
Oct 31 Python
Python Print实现在输出中插入变量的例子
Dec 25 Python
windows下的pycharm安装及其设置中文菜单
Apr 23 Python
python urllib和urllib3知识点总结
Feb 08 Python
Python中OpenCV实现简单车牌字符切割
Jun 11 Python
python中tkinter复选框使用操作
Nov 11 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 显示客户端IP与服务器IP的代码
2010/10/12 PHP
几种有用的变型 PHP中循环语句的用法介绍
2012/01/30 PHP
PHP number_format() 函数定义和用法
2012/06/01 PHP
深入理解PHP之数组(遍历顺序)  Laruence原创
2012/06/13 PHP
PHP常用函数总结(180多个)
2016/12/25 PHP
CL vs ForZe BO5 第三场 2.13
2021/03/10 DOTA
jQuery学习笔记 操作jQuery对象 文档处理
2012/09/19 Javascript
JavaScript调试工具汇总
2014/12/23 Javascript
JS实现一个按钮的方法
2015/02/05 Javascript
JavaScript创建一个object对象并操作对象属性的用法
2015/03/23 Javascript
基于javascript实现简单计算器功能
2016/01/03 Javascript
jquery对dom节点的操作【推荐】
2016/04/15 Javascript
node.js入门教程之querystring模块的使用方法
2017/02/27 Javascript
JS按钮闪烁功能的实现代码
2017/07/21 Javascript
Vue中的验证登录状态的实现方法
2019/03/09 Javascript
深入理解Node内建模块和对象
2019/03/12 Javascript
微信小程序 button样式设置为图片的方法
2020/06/19 Javascript
[20:21]《一刀刀一天》第十六期:TI国际邀请赛正式打响,总奖金超过550万
2014/05/23 DOTA
python使用calendar输出指定年份全年日历的方法
2015/04/04 Python
python 连接sqlite及简单操作
2017/06/30 Python
Python3实现爬取简书首页文章标题和文章链接的方法【测试可用】
2018/12/11 Python
Django 接收Post请求数据,并保存到数据库的实现方法
2019/07/12 Python
python+logging+yaml实现日志分割
2019/07/22 Python
通过Python实现一个简单的html页面
2020/05/16 Python
Python中的xlrd模块使用原理解析
2020/05/21 Python
python语言是免费还是收费的?
2020/06/15 Python
Tensorflow--取tensorf指定列的操作方式
2020/06/30 Python
Europcar英国:英国汽车和货车租赁
2017/01/21 全球购物
阿里云:Aliyun.com
2017/02/15 全球购物
什么是触发器(trigger)? 触发器有什么作用?
2013/09/18 面试题
新闻专业个人自我评价
2013/09/21 职场文书
毕业生多媒体设计求职信
2013/10/12 职场文书
女大学生自我鉴定
2013/12/09 职场文书
文明美德伴我成长演讲稿
2014/05/12 职场文书
乡镇领导班子四风对照检查材料
2014/09/27 职场文书
SQL语句中EXISTS的详细用法大全
2022/06/25 MySQL