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 相关文章推荐
kNN算法python实现和简单数字识别的方法
Nov 18 Python
在Python程序中操作文件之isatty()方法的使用教程
May 24 Python
Python实现将文本生成二维码的方法示例
Jul 18 Python
django1.11.1 models 数据库同步方法
May 30 Python
python实现键盘控制鼠标移动
Nov 27 Python
linux查找当前python解释器的位置方法
Feb 20 Python
详解django中url路由配置及渲染方式
Feb 25 Python
Django错误:TypeError at / 'bool' object is not callable解决
Aug 16 Python
使用 Python 遍历目录树的方法
Feb 29 Python
Python读取二进制文件代码方法解析
Jun 22 Python
python sleep和wait对比总结
Feb 03 Python
python 闭包函数详细介绍
Apr 19 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设计模式 Interpreter(解释器模式)
2011/06/26 PHP
解析php如何将日志写进syslog
2013/06/28 PHP
简要剖析PHP的Yii框架的组件化机制的基本知识
2016/03/17 PHP
jQuery-serialize()输出序列化form表单值的方法
2012/12/26 Javascript
Ajax请求在数据量大的时候出现超时的解决方法
2014/02/27 Javascript
用js代码和插件实现wordpress雪花飘落效果的四种方法
2014/12/15 Javascript
AngularJS自定义插件实现网站用户引导功能示例
2016/11/07 Javascript
jquery二级目录选中当前页的css样式
2016/12/08 Javascript
BootStrap Fileinput的使用教程
2016/12/30 Javascript
原生js实现选项卡功能
2017/03/08 Javascript
探究react-native 源码的图片缓存问题
2017/08/24 Javascript
Vue 源码分析之 Observer实现过程
2018/03/29 Javascript
JSONP原理及应用实例详解
2018/09/13 Javascript
vue+elementUI实现表格关键字筛选高亮
2020/10/26 Javascript
Webpack中SplitChunksPlugin 配置参数详解
2020/03/24 Javascript
js中!和!!的区别与用法
2020/05/09 Javascript
Vue组件生命周期运行原理解析
2020/11/25 Vue.js
在python中对变量判断是否为None的三种方法总结
2019/01/23 Python
Python的高阶函数用法实例分析
2019/04/11 Python
Flask框架 CSRF 保护实现方法详解
2019/10/30 Python
linux环境下安装python虚拟环境及注意事项
2020/01/07 Python
TensorFlow内存管理bfc算法实例
2020/02/03 Python
Python生成六万个随机,唯一的8位数字和数字组成的随机字符串实例
2020/03/03 Python
Python importlib模块重载使用方法详解
2020/10/13 Python
HTML5是否真的可以取代Flash
2010/02/10 HTML / CSS
德国药房apodiscounter中文官网:德国排名前三的网上药店
2019/06/03 全球购物
FragranceNet中文网:北美健康美容线上零售商
2020/08/26 全球购物
配件采购员岗位职责
2013/12/03 职场文书
大学生演讲稿范文
2014/01/11 职场文书
政工例会汇报材料
2014/08/26 职场文书
2014年质量管理工作总结
2014/12/01 职场文书
尼克胡哲观后感
2015/06/08 职场文书
2016春季幼儿园小班开学寄语
2015/12/03 职场文书
廉洁自律准则学习心得体会
2016/01/13 职场文书
Python 快速验证代理IP是否有效的方法实现
2021/07/15 Python
Netty分布式客户端处理接入事件handle源码解析
2022/03/25 Java/Android