前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >树莓派基础实验37:pyserial模块通信实验

树莓派基础实验37:pyserial模块通信实验

作者头像
张国平
发布2020-09-27 10:45:02
2.7K0
发布2020-09-27 10:45:02
举报

一、介绍

  串口通信是指外设和计算机间,通过数据信号线 、地线、控制线等,按位进行传输数据的一种通讯方式。这种通信方式使用的数据线少,在远距离通信中可以节约通信成本,但其传输速度比并行传输低。串口是计算机上一种非常通用的设备通信协议,pyserial模块封装了python对串口的访问,为多平台的使用提供了统一的接口。

  在树莓派基础实验35:USB TO TTL模块实验中学习了通过串口对树莓派进行控制台控制,让串口作为控制终端调试口即 serial console。

  在树莓派基础实验36:通用串口通信实验中学习了设置树莓派的串口为通用串口与PC电脑的串口调试工具进行通信。

  本实验中学习树莓派中使用Python的pyserial模块,通过串口与PC电脑的串口调试工具进行通信。

二、组件

★Raspberry Pi 3 B+主板*1

★树莓派电源*1

★USB TO TTL模块*1

★面包板*1(可选)

★40P软排线*1

★跳线若干

三、实验原理

(一)pyserial概述

该模块封装了对串行端口的访问。它为Windows,OSX,Linux,BSD(可能是任何POSIX兼容系统)和IronPython上运行的Python提供了后端。名为“串行”的模块会自动选择适当的后端。

功能:

  • 在所有支持的平台上基于相同类的接口。
  • 通过Python属性访问端口设置。
  • 通过RTS / CTS和/或Xon / Xoff支持不同的字节大小,停止位,奇偶校验和流控制。
  • 有无超时都可以使用。
  • 带有“读”和“写”的API之类的文件(也支持“ readline”等)。
  • 该软件包中的文件是100%纯Python。
  • 该端口已设置为二进制传输。没有NULL字节剥离,CR-LF转换等(对于POSIX启用了很多次)。这使该模块具有通用性。
  • 与io库兼容
  • 示例中提供的RFC 2217客户端(实验)。
(二)pyserial介绍
1.本地端口
代码语言:javascript
复制
class serial.Serial
    __init__(port=None, baudrate=9600, bytesize=EIGHTBITS, 
    parity=PARITY_NONE, stopbits=STOPBITS_ONE, timeout=None, 
    xonxoff=False, rtscts=False, write_timeout=None, 
    dsrdtr=False, inter_byte_timeout=None)

其中:

port:设备名称或None。如COM1,COM2,COM3,COM4......如果port设置为0对应的为COM1。

baudrate(int):设置波特率,如9600或115200等。

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。

timeout(float):设置读取超时值,timeout = None: 长时间等待;timeout = 0: 不阻塞形式 (读完之后就返回);timeout = x: x秒后超时 (float allowed)。

xonxoff(bool):启用软件流控制。

rtscts(bool):启用硬件(RTS / CTS)流量控制。

dsrdtr(bool):启用硬件(DSR / DTR)流控制。

write_timeout(float):设置写超时值。

inter_byte_timeout(float):字符间超时,None禁用(默认)。

2.打开串口

在给出端口时,在创建对象时立即打开端口。当端口None并且需要连续调用时它不会打开open()

port是设备名称:取决于操作系统。

打开串口0, 9600,8N1,连接超时0.5秒:

代码语言:javascript
复制
import serial #导入pyserial模块
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()#关闭端口
3.获得串行口状态

串行口的属性:

name:设备名字

portstr:已废弃,用name代替

port:读或者写端口

baudrate:波特率

bytesize:字节大小

parity:校验位

stopbits:停止位

timeout:读超时设置

writeTimeout:写超时

xonxoff:软件流控

rtscts:硬件流控

dsrdtr:硬件流控

interCharTimeout:字符间隔超时

属性的使用方法:

代码语言:javascript
复制
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.设置串行口状态
代码语言:javascript
复制
ser=serial.Serial("/dev/ttyAMA0",9600,timeout=0.5)

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=False#软件流控
ser.rtscts=False#硬件流控
ser.dsrdtr=False#硬件流控
ser.interCharTimeout=0.5#字符间隔超时
5.serial方法:
代码语言:javascript
复制
open()                  # 打开串口
close()                 # 立即关闭串口
isOpen()                #看看这个串口是否已经被打开
setBaudrate(baudrate)   # change baud rate on an open port
inWaiting()             # 返回接收缓存中的字节数
read(size=1)            # 从串口读size个字节。如果指定超时,
                        #则可能在超时后返回较少的字节;
                        #如果没有指定超时,则会一直等到收完指定的字节数。

write(s)                # 发送s,并返回发送字节数。如果bytes和bytearray可用,
                        #则接受其作为参数;否则接受str作为参数。

flushInput()            # 丢弃接收缓存中的所有数据
flushOutput()           # 终止当前写操作,并丢弃发送缓存中的数据。
sendBreak(duration=0.25)# 发送BREAK条件,并于duration时间之后返回IDLE
setRTS(level=1)         # 将RTS行设置为指定的逻辑级别
setDTR(level=1)         # 将DTR行设置为指定逻辑级别
getCTS()                # 返回CTS行的状态
getDSR()                # 返回DSR行的状态
getRI()                 # 返回RI行的状态
getCD()                 # 返回CD行的状态
6.Readline库
代码语言:javascript
复制
data = ser.readline() #是读一行,以/n结束,要是没有/n就一直读,阻塞。
data = ser.readlines()和ser.xreadlines()#都需要设置超时时间

使用readline()时要小心。在打开串行端口时,请务必指定一个超时时间,否则如果没有收到换行符,它将永远阻塞。另请注意,readlines()仅适用于超时。 readlines()取决于是否存在超时,并将其解释为EOF(文件末尾)。如果未正确打开端口,则会引发异常。

7.EOL

要为指定EOL字符或使用通用换行模式,建议使用io.TextIOWrapper

代码语言:javascript
复制
import serial
import io
ser = serial.serial_for_url('loop://', timeout=1)
sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser))

sio.write(unicode("hello\n"))
sio.flush() # it is buffering. required to get the data out *now*
hello = sio.readline()
print(hello == unicode("hello\n"))

四、实验步骤

第1步: 连接电路。与树莓派基础实验36:通用串口通信实验一样设置树莓派的串口为通用串口,与PC上的串口调试工具通信。

树莓派(name)

T型转接板(BCM)

USB TO TTL模块

TXD

TXO

RXD

RXD

RXI

TXD

GND

GND

GND

下图中的USB要插到笔记本电脑上哈,为方便拍照就没插上。连线很简单,电路图就没画了。

USB TO TTL模块实物接线图

第2步: 向串口发送简单数据程序。PC串口调试工具上将收到字符串“Send string by serial”。

代码语言:javascript
复制
import serial

ser = serial.Serial('/dev/ttyAMA0', 9600, timeout=0.5)
ser.write('Send string by serial'.encode("gbk"))

第3步: 树莓派接收PC串口调试工具发送的字符,打印出来,再发送回PC串口调试工具。手动设置读取字符的数量。

代码语言:javascript
复制
#!/usr/bin/python
import serial
from time import sleep
 
ser = serial.Serial('/dev/ttyAMA0', 9600, timeout=0.5) 
 
print ser.port
print ser.baudrate
 
def recv(serial):  
  while True:  
    data =serial.read(10)  #手动设置读取字符的数量为10
    if data == '':  
      continue
    else:
      break
    sleep(0.02) 
  return data 
 
while True:  
  data =recv(ser) 
  if data != '': 
    print data
    ser.write(data)

第4步: 树莓派接收PC串口调试工具发送的字符,打印出来,再发送回PC串口调试工具。通过inWaiting()函数自动获得接收缓冲区字符数。

代码语言:javascript
复制
# -*- coding: utf-8 -*
import serial
import time

ser = serial.Serial('/dev/ttyAMA0', 9600, timeout=0.5)

def rec_tra():
    while True:
        count = ser.inWaiting() # 获得接收缓冲区字符
        if count != 0:
            recv = ser.read(count) # 读取内容
            ser.write(recv)        # 发送回PC
            print recv
        ser.flushInput()  # 清空接收缓冲区
        time.sleep(0.1)   # 必要的软件延时

if __name__ == '__main__':
    try:
        rec_tra()
    except KeyboardInterrupt:
        if ser != None:
            ser.close()
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、介绍
  • 二、组件
  • 三、实验原理
    • (一)pyserial概述
      • (二)pyserial介绍
      • 四、实验步骤
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档