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入门篇之正则表达式
Oct 20 Python
Python3.x版本中新的字符串格式化方法
Apr 24 Python
Python3.6正式版新特性预览
Dec 15 Python
python3中int(整型)的使用教程
Mar 23 Python
python对配置文件.ini进行增删改查操作的方法示例
Jul 28 Python
python中csv文件的若干读写方法小结
Jul 04 Python
python 读取目录下csv文件并绘制曲线v111的方法
Jul 06 Python
python django下载大的csv文件实现方法分析
Jul 19 Python
python抓取多种类型的页面方法实例
Nov 20 Python
python 实现二维列表转置
Dec 02 Python
Django通过json格式收集主机信息
May 29 Python
Python基础之Socket通信原理
Apr 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
1 Tube Radio
2021/03/02 无线电
php 获取客户端的真实ip
2009/11/30 PHP
php不用内置函数对数组排序的两个算法代码
2010/02/08 PHP
PHP 导出数据到淘宝助手CSV的方法分享
2010/02/27 PHP
php使用sql数据库 获取字段问题介绍
2013/08/12 PHP
ThinkPHP中的系统常量和预定义常量集合
2014/07/01 PHP
PHP Yii框架之表单验证规则大全
2015/11/16 PHP
php array_map使用自定义的函数处理数组中的每个值
2016/10/26 PHP
利用phpexcel对数据库数据的导入excel(excel筛选)、导出excel
2017/04/27 PHP
PHP+MySQL高并发加锁事务处理问题解决方法
2018/04/30 PHP
javascript的BOM
2016/05/03 Javascript
jQuery实现简单的tab标签页效果
2016/09/12 Javascript
KnockoutJS 3.X API 第四章之数据控制流if绑定和ifnot绑定
2016/10/10 Javascript
JS处理数据四舍五入(tofixed与round的区别详解)
2017/10/26 Javascript
详解vue-element Tree树形控件填坑路
2019/03/26 Javascript
常见的浏览器存储方式(cookie、localStorage、sessionStorage)
2019/05/07 Javascript
Vuex modules模式下mapState/mapMutations的操作实例
2019/10/17 Javascript
完美解决vue 中多个echarts图表自适应的问题
2020/07/19 Javascript
vant 自定义 van-dropdown-item的用法
2020/08/05 Javascript
用tensorflow实现弹性网络回归算法
2018/01/09 Python
Python中摘要算法MD5,SHA1简介及应用实例代码
2018/01/09 Python
python实现整数的二进制循环移位
2019/03/08 Python
python实现连连看辅助(图像识别)
2020/03/25 Python
Python高级property属性用法实例分析
2019/11/19 Python
Keras—embedding嵌入层的用法详解
2020/06/10 Python
html5之Canvas路径绘图、坐标变换应用实例
2012/12/26 HTML / CSS
世界上最大的罕见唱片、CD和音乐纪念品网上商店:991.com
2018/05/03 全球购物
英国游戏机和游戏购物网站:365games.co.uk
2018/06/18 全球购物
XD健身器材:Kevlar球、Crossfit健身球
2019/03/26 全球购物
Oracle的内存结构(Memory structures)
2015/06/10 面试题
.NET方向面试题
2014/11/20 面试题
家长给小学生的评语
2014/01/30 职场文书
五月的鲜花活动方案
2014/08/21 职场文书
北京颐和园导游词
2015/01/30 职场文书
贫民窟的百万富翁观后感
2015/06/09 职场文书
会计工作自我鉴定范文
2019/06/21 职场文书