树莓派基础实验37:pyserial模块通信实验
一、介绍
串口通信是指外设和计算机间,通过数据信号线 、地线、控制线等,按位进行传输数据的一种通讯方式。这种通信方式使用的数据线少,在远距离通信中可以节约通信成本,但其传输速度比并行传输低。串口是计算机上一种非常通用的设备通信协议,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.本地端口
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秒:
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:字符间隔超时
属性的使用方法:
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.设置串行口状态
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方法:
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库
data = ser.readline() #是读一行,以/n结束,要是没有/n就一直读,阻塞。
data = ser.readlines()和ser.xreadlines()#都需要设置超时时间
使用readline()时要小心。在打开串行端口时,请务必指定一个超时时间,否则如果没有收到换行符,它将永远阻塞。另请注意,readlines()仅适用于超时。 readlines()取决于是否存在超时,并将其解释为EOF(文件末尾)。如果未正确打开端口,则会引发异常。
7.EOL
要为指定EOL字符或使用通用换行模式,建议使用io.TextIOWrapper:
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”。
import serial
ser = serial.Serial('/dev/ttyAMA0', 9600, timeout=0.5)
ser.write('Send string by serial'.encode("gbk"))
第3步: 树莓派接收PC串口调试工具发送的字符,打印出来,再发送回PC串口调试工具。手动设置读取字符的数量。
#!/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()函数自动获得接收缓冲区字符数。
# -*- 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()