Python 之 Serial串口通信_python serial-程序员宅基地

技术标签: PYTHON  

0 Serial方法

1、导入pyserial模块

import serial

2、打开串行口

// 打开串口0, 9600,8N1,连接超时0.5秒
import serial
ser=serial.Serial("/dev/ttyUSB0",9600,timeout=0.5) #使用USB连接串行口
ser=serial.Serial("/dev/ttyAMA0",9600,timeout=0.5) #使用树莓派的GPIO口连接串行口
ser=serial.Serial(1,9600,timeout=0.5)#winsows系统使用com1口连接串行口
ser=serial.Serial(“com1”,9600,timeout=0.5)#winsows系统使用com1口连接串行口
ser=serial.Serial("/dev/ttyS1",9600,timeout=0.5)#Linux系统使用com1口连接串行口
print ser.name#打印设备名称
print ser.port#打印设备名
ser.open() #打开端口
s = ser.read(10)#从端口读10个字节
ser.write(“hello”)#向端口些数据
ser.close()#关闭端口
data = ser.read(20) #是读20个字符
data = ser.readline() #是读一行,以/n结束,要是没有/n就一直读,阻塞。
data = ser.readlines()和ser.xreadlines()#都需要设置超时时间
ser.baudrate = 9600 #设置波特率
ser.isOpen() #看看这个串口是否已经被打开

3、获得串行口状态

串行口的属性:
name:设备名字
portstr:已废弃,用name代替
port:读或者写端口
baudrate:波特率
bytesize:字节大小
parity:校验位
stopbits:停止位
timeout:读超时设置
writeTimeout:写超时
xonxoff:软件流控
rtscts:硬件流控
dsrdtr:硬件流控
interCharTimeout:字符间隔超时

属性的使用方法:
ser=serial.Serial("/dev/ttyAMA0",9600,timeout=0.5)
ser.open()

print ser.name
print ser.port
print ser.baudrate#波特率
print ser.bytesize#字节大小
print ser.parity#校验位N-无校验,E-偶校验,O-奇校验
print ser.stopbits#停止位
print ser.timeout#读超时设置
print ser.writeTimeout#写超时
print ser.xonxoff#软件流控
print ser.rtscts#硬件流控
print ser.dsrdtr#硬件流控
print ser.interCharTimeout#字符间隔超时

ser.close()

4、设置串行口状态

需要用的常量

bytesize:FIVE BITS、SIXBITS、SEVENBITS、EIGHTBITS
parity: PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE
stopbits: STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO
异常:
ValueError:参数错误
SerialException:找不到设备或不能配置

ser.baudrate=9600#设置波特率

ser.bytesize=8#字节大小
ser.bytesize=serial.EiGHTBITS#8位数据位

ser.parity=serial.PARITY_EVEN#偶校验
ser.parity=serial.PARITY_NONE#无校验
ser.parity=serial.PARITY_ODD#奇校验

ser.stopbits=1#停止位
ser.timeout=0.5#读超时设置
ser.writeTimeout=0.5#写超时
ser.xonxoff#软件流控
ser.rtscts#硬件流控
ser.dsrdtr#硬件流控
ser.interCharTimeout#字符间隔超时

5、Readline方法的使用

是读一行,以/n结束,要是没有/n就一直读,阻塞。

使用readline()时应该注意:打开串口时应该指定超时,否则如果串口没有收到新行,则会一直等待。如果没有超时,readline会报异常。

6、serial.Serial类——原生端口

class serial.Serial
{
init(port=None, baudrate=9600, bytesize=EIGHTBITS,parity=PARITY_NONE, stopbits=STOPBITS_ONE, timeout=None, xonxoff=False, rtscts=False, writeTimeout=None, dsrdtr=False, interCharTimeout=None)

#其中:
# bytesize:FIVEBITS、SIXBITS、SEVENBITS、EIGHTBITS
# parity: PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE
# stopbits: STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO
#异常:
#ValueError:参数错误
#SerialException:找不到设备或不能配置

open():打开串口

close():立即关闭串口

del():析构函数

read(size=1):从串口读size个字节。如果指定超时,则可能在超时后返回较少的字节;如果没有指定超时,则会一直等到收完指定的字节数。

write(data):发送data,并返回发送字节数。如果bytes和bytearray可用(python 2.6以上),则接受其作为参数;否则接受str作为参数。
#异常:SerialTimeoutException——配置了写超时并发生超时时发生此异常。

inWaiting():返回接收缓存中的字节数

flush():等待所有数据写出。

flushInput():丢弃接收缓存中的所有数据

flushOutput():终止当前写操作,并丢弃发送缓存中的数据。

sendBreadk(duration=0.25):发送BREAK条件,并于duration时间之后返回IDLE

setBreak(level=True):根据level设置break条件。

setRTS(level=True)

setDTR(level=True)

getCTS()

getDSR()

getRI()

getCD()

#只读属性:
name:设备名字
portstr:已废弃,用name代替
port:读或者写端口
baudrate:波特率
bytesize:字节大小
parity:校验位
stopbits:停止位
timeout:读超时设置
writeTimeout:写超时
xonxoff:软件流控
rtscts:硬件流控
dsrdtr:硬件流控
interCharTimeout:字符间隔超时

#端口设置可以被读入字典,也可从字典加载设置:
getSettingDict():返回当前串口设置的字典
applySettingDict(d):应用字典到串口设置

#对提供io库的系统(python 2.6或以上),Serial从io.RawIOBase派生。对其它系统,从FileLike派生。

#异常:
exception serial.SerialException
exception serial.SerialTimeoutException

#常量:
serial.VERSION:pyserial版本

#模块函数和属性:
serial.device(number)

serial.serial_for_url(url, *args, **kwargs)

serial.protocol_handler_packages()

serial.to_bytes(sequence):接收一个字符串或整数列表sequence,返回bytes实例

1 确定串口名称

1.1 WINDOWS

获取可用串口列表

#!/usr/bin/env python
#-*- coding: utf-8 -*
import serial
import serial.tools.list_ports

plist = list(serial.tools.list_ports.comports())

if len(plist) <= 0:
    print ("The Serial port can't find!")
else:
    plist_0 =list(plist[0])
    serialName = plist_0[0]
    serialFd = serial.Serial(serialName,9600,timeout = 60)
    print ("check which port was really used >",serialFd.name)

在这里插入图片描述

import serial #导入模块

import serial.tools.list_ports
port_list = list(serial.tools.list_ports.comports())
print(port_list)
if len(port_list) == 0:
   print('无可用串口')
else:
    for i in range(0,len(port_list)):
        print(port_list[i])
1.2 LINUX

查询从系统启动到现在串口插拔的信息,显示串口Ubuntu连接的端口号:

在终端输入:

dmesg | grep ttyS*

在这里插入图片描述
在这里插入图片描述

在Ubuntu下装了CuteCom,但当打开 /dev/ttyUSB0 时,总提示错误,打开失败时:

用 Minicom 可以正常读取 ttyUSB0。

sudo chmod 666 /dev/ttyUSB0

这样修改后, CuteCom 就可以正常打开 USB 串口了

1,pycharm程序端代码。


#usr/bin/python3
# -*- coding: utf-8 -*-
import serial
from time import sleep
 
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=0.5)
 
 
def recv(serial):
        global data
        while True:
                data = serial.read(30)
                if data == '':
                        continue
                else:
                        break
                sleep(0.02)
        return data
 
 
while True:
        data = recv(ser)
        ser.write(data)
 

在pycharm上的程序:

在这里插入图片描述

程序效果为: 运行后,在CuteCom发生的代码, 程序这边会原文返回发给CuteCom。

1.3 Python(Linux下)获取串口的idv和idp以及serial序列号

串口端口的获取脚本

# coding=utf-8
#

__author__ = 'Haleydu'
__editTime__ = '2018.12.7'

import serial.tools.list_ports
import serial
import os
import re

class AutoMatchSerialPort:
    #一.获取串口 or 判断是否存在该串口
    def getSerial(self,needdev=''):
        needSerial=''
        port_list = list(serial.tools.list_ports.comports())
        if len(port_list) <= 0:
            print ("The Serial port can't find!")
        else:
        #1.过滤,获取需要的串口
            for i in list(port_list):
                if i.name==needdev:
                    needSerial=i.name
                print(i.name,end=',')
            print('\n')
        #2.返回获取的目的串口为了绑定
        return needSerial

   # 二.根据端口号返回ID号和硬件号
    def getSerialIDAndSer(self,dev):
        cmd = "udevadm info --attribute-walk --name=" + dev
        result = self.execCmd(cmd)
        pat1 = "ATTRS{idVendor}==.?(\d\d\d\d).?"
        pat2 = "ATTRS{idProduct}==.?(\d\d\d\d).?"
        pat3 = 'ATTRS{serial}==.([A-Za-z0-9]+).'
        ret1 = re.search(pat1,result)
        ret2 = re.search(pat2,result)
        ret3 = re.search(pat3,result)
        idv = ret1.group(1)
        idp = ret2.group(1)
        ser = ret3.group(1)
        return idv,idp,ser

    # 三.根据ID号或者序列号返回串口的端口号,也可以用别名直接调用该串口(运行后需要拔插目的串口后生效)
    def getSerialPort(self,idv='',idp='',ser='',alias='ttyUSB_test'):
        if idv==''or idp=='':
            contentID = 'ATTRS{serial}=="'+ser+', MODE:="0777", SYMLINK+="'+ alias +'" \n'
        elif ser=='':
            contentID = '", ATTRS{idVendor}=="'+idv+'", ATTRS{idProduct}=="'+idp+'", MODE:="0777", SYMLINK+="'+ alias +'" \n'
        else:
            contentID = 'ATTRS{serial}=="'+ser+'", ATTRS{idVendor}=="'+idv+'", ATTRS{idProduct}=="'+idp+'", MODE:="0777", SYMLINK+="'+ alias +'" \n'

        path='/etc/udev/rules.d/getSerialPort_'+alias+'.rules'
        if os.path.exists(path):
            #print('存在文件')
            f = open(path,"w")
            f.write(contentID)
            f.flush()
            f.close()
            #print('创建成功')
            #print('重新拔插串口后生效')
        else:
            #print('不存在文件,开始创建getSerialPort_'+alias+'.rules的udev规则文件')
            f = open(path,"w")
            f.write(contentID)
            f.flush()
            f.close()
            #print('创建成功')
            #print('重新拔插串口后生效')
        #重启udev规则
        #sudo /etc/init.d/udev restart
        #根据ID获得端口号
        cmd = "udevadm info --attribute-walk --name=" + alias
        result = self.execCmd(cmd)
        pat = '(ttyUSB.)'
        ret = re.search(pat,result)
        dev=''
        try:
            dev = ret.group(1)
        except AttributeError:
            if dev=='':
                print('重新拔插串口后生效')
        return dev


    #调用终端,获取终端输出
    def execCmd(self,cmd):  
        r = os.popen(cmd)  
        result = r.read()  
        r.close()  
        return result  

if __name__ == '__main__':
    am=AutoMatchSerialPort()
    am.getSerial()
    print('ttyUSB0:' + str(am.getSerialIDAndSer("ttyUSB0")))
    print('ttyUSB1:' + str(am.getSerialIDAndSer("ttyUSB1")))
    print('0403:6002,FT2NPXY4,ttyUSB_1:' + am.getSerialPort('0403','6002','FT2NPXY4','ttyUSB_1'))
    print('0403:6001,FTSYWCXZ,ttyUSB_2:' + am.getSerialPort('0403','6001','FTSYWCXZ','ttyUSB_2'))
    


2 SERIAL 串口操作

参考文档:
https://blog.csdn.net/qq_14997473/article/details/80875722:Python学习笔记——串口配置以及发送数据

https://blog.csdn.net/ubuntu14/article/details/75335106:python实现串口自动触发工作

(1) 安装pyserial库
pip install pyserial

serial = serial.Serial(‘COM1’, 115200) 打开COM1并设置波特率为115200,COM1只适用于Windows
serial = serial.Serial(‘/dev/ttyS0’, 115200) 打开/dev/ttyS0并设置波特率为115200, 只适用于Linux

(2) pyserial库常用函数介绍
serial = serial.Serial(‘COM1’, 115200) 打开COM1并设置波特率为115200,COM1只适用于Windows

serial = serial.Serial(‘/dev/ttyS0’, 115200) 打开/dev/ttyS0并设置波特率为115200, 只适用于Linux

print serial .portstr 能看到第一个串口的标识

serial .write(“hello”) 往串口里面写数据

serial .close() 关闭serial 表示的串口

serial .open() 打开串口

data = serial .read(num) 读num个字符

data = serial .readline() 读一行数据,以/n结束,要是没有/n就一直读,阻塞。

serial .baudrate = 9600 设置波特率

print serial 可查看当前串口的状态信息

serial .isOpen() 当前串口是否已经打开

serial.inWaiting() 判断当前接收的数据

serial.flushInput() 清除输入缓冲区数据

serial.flushOutput() 中止当前输出并清除输出缓冲区数据
(3) 实例: 获取从其他串口发送来的数据并回显
#!/usr/bin/python 
# coding=UTF-8 
import serial 
################################################### 
# 
# 功 能: 将接收到的数据已hex显示 
# 参 数: 串口接受到的数据 
# 返 回: 转换后的数据 
# 
################################################### 
def hexshow(data): 
  hex_data = '' hLen = len(data) 

  for i in xrange(hLen): 
    hvol = ord(data[i]) 
    hhex = '%02x' % hvol 
    hex_data += hhex+' '

  print 'hexshow:', hex_data 
################################################### 
# 
# 功 能: 将需要发送的字符串以hex形式发送 
# 参 数: 待发送的数据 
# 返 回: 转换后的数据 
# 
################################################### 
def hexsend(string_data=''): 
  hex_data = string_data.decode("hex") 
  return hex_data 

if __name__ == '__main__': 
  serial = serial.Serial('/dev/ttyS0', 115200) 
  print serial 

  if serial.isOpen(): 
    print("open success") 
  else: 
    print("open failed") 


  try: 

    while True: 
      count = serial.inWaiting() 
      if count > 0: 
        data = serial.read(count) 
        if data != b'': 
          print("receive:", data) 
          serial.write(data) 
        else: 
          serial.write(hexsend(data)) 

  except KeyboardInterrupt: 
    if serial != None: 
      serial.close()
16进制处理
import serial #导入模块
try:
  portx="COM3"
  bps=115200
  #超时设置,None:永远等待操作,0为立即返回请求结果,其他值为等待超时时间(单位为秒)
  timex=None
  ser=serial.Serial(portx,bps,timeout=timex)
  print("串口详情参数:", ser)

  #十六进制的发送
  result=ser.write(chr(0x06).encode("utf-8"))#写数据
  print("写总字节数:",result)

  #十六进制的读取
  print(ser.read().hex())#读一个字节

  print("---------------")
  ser.close()#关闭串口

except Exception as e:
    print("---异常---:",e)
其他
import serial #导入模块
try:

  #端口,GNU / Linux上的/ dev / ttyUSB0 等 或 Windows上的 COM3 等
  portx="COM3"
  #波特率,标准值之一:50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,19200,38400,57600,115200
  bps=115200
  #超时设置,None:永远等待操作,0为立即返回请求结果,其他值为等待超时时间(单位为秒)
  timex=5
  # 打开串口,并得到串口对象
  ser=serial.Serial(portx,bps,timeout=timex)
  print("串口详情参数:", ser)



  print(ser.port)#获取到当前打开的串口名
  print(ser.baudrate)#获取波特率

  result=ser.write("我是东小东".encode("gbk"))#写数据
  print("写总字节数:",result)


  #print(ser.read())#读一个字节
  # print(ser.read(10).decode("gbk"))#读十个字节
  #print(ser.readline().decode("gbk"))#读一行
  #print(ser.readlines())#读取多行,返回列表,必须匹配超时(timeout)使用
  #print(ser.in_waiting)#获取输入缓冲区的剩余字节数
  #print(ser.out_waiting)#获取输出缓冲区的字节数

  #循环接收数据,此为死循环,可用线程实现
  while True:
         if ser.in_waiting:
             str=ser.read(ser.in_waiting ).decode("gbk")
             if(str=="exit"):#退出标志
                 break
             else:
               print("收到数据:",str)

  print("---------------")
  ser.close()#关闭串口


except Exception as e:
    print("---异常---:",e)

3 解决 ImportError: No module named ‘serial’ 问题

在pycharm里编写Python串口程序的时候,编译时提示 ImportError: No module named ‘serial’

解决办法:

安装 serial module
这里区分python2和 python3:

首先需要在终端输入:

sudo apt install python-pip //python2
sudo apt install python3-pip    //python3

在这里插入图片描述
安装python3的 pip3的时候,如果时国内的软件源可能安装不上,(当时用中国科学技术大学的软件源,python3-pip下载有问题),换成ubuntu官网成功下载。

如果系统已经安装过了pip,就不需要这一步了。
然后通过:

pip install pyserial    //python2
pip3 install pyserial   //python3

在这里插入图片描述

可以从pyserial下载这里去获取源码进行熟悉和学习。

4 PYCHARM 里面的no module name serial错误

在这里插入图片描述
错误原因在于:==interpreter的选择==
在这里插入图片描述

安装目录下的python,其模块只有一个setuptools,所以找不到serial
在这里插入图片描述
ANACONDA下的python.exe里面包含了多个模块,所以应该将interpreter改为该目录下的python.exe

5 TypeError: ‘bool’ object is not callable

因为 isOpen是属性所以有如下做法

 def isOpen(self):
        return True

  def is_active(self):
        return True

  def is_anonymous(self):
        return False

不是方法,将sOpen()括号去掉,完美解决!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xuzhexing/article/details/91043579

智能推荐

稀疏编码的数学基础与理论分析-程序员宅基地

文章浏览阅读290次,点赞8次,收藏10次。1.背景介绍稀疏编码是一种用于处理稀疏数据的编码技术,其主要应用于信息传输、存储和处理等领域。稀疏数据是指数据中大部分元素为零或近似于零的数据,例如文本、图像、音频、视频等。稀疏编码的核心思想是将稀疏数据表示为非零元素和它们对应的位置信息,从而减少存储空间和计算复杂度。稀疏编码的研究起源于1990年代,随着大数据时代的到来,稀疏编码技术的应用范围和影响力不断扩大。目前,稀疏编码已经成为计算...

EasyGBS国标流媒体服务器GB28181国标方案安装使用文档-程序员宅基地

文章浏览阅读217次。EasyGBS - GB28181 国标方案安装使用文档下载安装包下载,正式使用需商业授权, 功能一致在线演示在线API架构图EasySIPCMSSIP 中心信令服务, 单节点, 自带一个 Redis Server, 随 EasySIPCMS 自启动, 不需要手动运行EasySIPSMSSIP 流媒体服务, 根..._easygbs-windows-2.6.0-23042316使用文档

【Web】记录巅峰极客2023 BabyURL题目复现——Jackson原生链_原生jackson 反序列化链子-程序员宅基地

文章浏览阅读1.2k次,点赞27次,收藏7次。2023巅峰极客 BabyURL之前AliyunCTF Bypassit I这题考查了这样一条链子:其实就是Jackson的原生反序列化利用今天复现的这题也是大同小异,一起来整一下。_原生jackson 反序列化链子

一文搞懂SpringCloud,详解干货,做好笔记_spring cloud-程序员宅基地

文章浏览阅读734次,点赞9次,收藏7次。微服务架构简单的说就是将单体应用进一步拆分,拆分成更小的服务,每个服务都是一个可以独立运行的项目。这么多小服务,如何管理他们?(服务治理 注册中心[服务注册 发现 剔除])这么多小服务,他们之间如何通讯?这么多小服务,客户端怎么访问他们?(网关)这么多小服务,一旦出现问题了,应该如何自处理?(容错)这么多小服务,一旦出现问题了,应该如何排错?(链路追踪)对于上面的问题,是任何一个微服务设计者都不能绕过去的,因此大部分的微服务产品都针对每一个问题提供了相应的组件来解决它们。_spring cloud

Js实现图片点击切换与轮播-程序员宅基地

文章浏览阅读5.9k次,点赞6次,收藏20次。Js实现图片点击切换与轮播图片点击切换<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title></title> <script type="text/ja..._点击图片进行轮播图切换

tensorflow-gpu版本安装教程(过程详细)_tensorflow gpu版本安装-程序员宅基地

文章浏览阅读10w+次,点赞245次,收藏1.5k次。在开始安装前,如果你的电脑装过tensorflow,请先把他们卸载干净,包括依赖的包(tensorflow-estimator、tensorboard、tensorflow、keras-applications、keras-preprocessing),不然后续安装了tensorflow-gpu可能会出现找不到cuda的问题。cuda、cudnn。..._tensorflow gpu版本安装

随便推点

物联网时代 权限滥用漏洞的攻击及防御-程序员宅基地

文章浏览阅读243次。0x00 简介权限滥用漏洞一般归类于逻辑问题,是指服务端功能开放过多或权限限制不严格,导致攻击者可以通过直接或间接调用的方式达到攻击效果。随着物联网时代的到来,这种漏洞已经屡见不鲜,各种漏洞组合利用也是千奇百怪、五花八门,这里总结漏洞是为了更好地应对和预防,如有不妥之处还请业内人士多多指教。0x01 背景2014年4月,在比特币飞涨的时代某网站曾经..._使用物联网漏洞的使用者

Visual Odometry and Depth Calculation--Epipolar Geometry--Direct Method--PnP_normalized plane coordinates-程序员宅基地

文章浏览阅读786次。A. Epipolar geometry and triangulationThe epipolar geometry mainly adopts the feature point method, such as SIFT, SURF and ORB, etc. to obtain the feature points corresponding to two frames of images. As shown in Figure 1, let the first image be ​ and th_normalized plane coordinates

开放信息抽取(OIE)系统(三)-- 第二代开放信息抽取系统(人工规则, rule-based, 先抽取关系)_语义角色增强的关系抽取-程序员宅基地

文章浏览阅读708次,点赞2次,收藏3次。开放信息抽取(OIE)系统(三)-- 第二代开放信息抽取系统(人工规则, rule-based, 先关系再实体)一.第二代开放信息抽取系统背景​ 第一代开放信息抽取系统(Open Information Extraction, OIE, learning-based, 自学习, 先抽取实体)通常抽取大量冗余信息,为了消除这些冗余信息,诞生了第二代开放信息抽取系统。二.第二代开放信息抽取系统历史第二代开放信息抽取系统着眼于解决第一代系统的三大问题: 大量非信息性提取(即省略关键信息的提取)、_语义角色增强的关系抽取

10个顶尖响应式HTML5网页_html欢迎页面-程序员宅基地

文章浏览阅读1.1w次,点赞6次,收藏51次。快速完成网页设计,10个顶尖响应式HTML5网页模板助你一臂之力为了寻找一个优质的网页模板,网页设计师和开发者往往可能会花上大半天的时间。不过幸运的是,现在的网页设计师和开发人员已经开始共享HTML5,Bootstrap和CSS3中的免费网页模板资源。鉴于网站模板的灵活性和强大的功能,现在广大设计师和开发者对html5网站的实际需求日益增长。为了造福大众,Mockplus的小伙伴整理了2018年最..._html欢迎页面

计算机二级 考试科目,2018全国计算机等级考试调整,一、二级都增加了考试科目...-程序员宅基地

文章浏览阅读282次。原标题:2018全国计算机等级考试调整,一、二级都增加了考试科目全国计算机等级考试将于9月15-17日举行。在备考的最后冲刺阶段,小编为大家整理了今年新公布的全国计算机等级考试调整方案,希望对备考的小伙伴有所帮助,快随小编往下看吧!从2018年3月开始,全国计算机等级考试实施2018版考试大纲,并按新体系开考各个考试级别。具体调整内容如下:一、考试级别及科目1.一级新增“网络安全素质教育”科目(代..._计算机二级增报科目什么意思

conan简单使用_apt install conan-程序员宅基地

文章浏览阅读240次。conan简单使用。_apt install conan