一浇衬、介紹
??串口通信是指外設(shè)和計(jì)算機(jī)間懒构,通過數(shù)據(jù)信號(hào)線 、地線耘擂、控制線等胆剧,按位進(jìn)行傳輸數(shù)據(jù)的一種通訊方式。這種通信方式使用的數(shù)據(jù)線少醉冤,在遠(yuǎn)距離通信中可以節(jié)約通信成本秩霍,但其傳輸速度比并行傳輸?shù)汀4谑怯?jì)算機(jī)上一種非常通用的設(shè)備通信協(xié)議蚁阳,pyserial模塊封裝了python對(duì)串口的訪問铃绒,為多平臺(tái)的使用提供了統(tǒng)一的接口。
??在樹莓派基礎(chǔ)實(shí)驗(yàn)35:USB TO TTL模塊實(shí)驗(yàn)中學(xué)習(xí)了通過串口對(duì)樹莓派進(jìn)行控制臺(tái)控制韵吨,讓串口作為控制終端調(diào)試口即 serial console匿垄。
??在樹莓派基礎(chǔ)實(shí)驗(yàn)36:通用串口通信實(shí)驗(yàn)中學(xué)習(xí)了設(shè)置樹莓派的串口為通用串口與PC電腦的串口調(diào)試工具進(jìn)行通信移宅。
??本實(shí)驗(yàn)中學(xué)習(xí)樹莓派中使用Python的pyserial模塊,通過串口與PC電腦的串口調(diào)試工具進(jìn)行通信椿疗。
二漏峰、組件
★Raspberry Pi 3 B+主板*1
★樹莓派電源*1
★USB TO TTL模塊*1
★面包板*1(可選)
★40P軟排線*1
★跳線若干
三、實(shí)驗(yàn)原理
(一)pyserial概述
該模塊封裝了對(duì)串行端口的訪問届榄。它為Windows浅乔,OSX,Linux铝条,BSD(可能是任何POSIX兼容系統(tǒng))和IronPython上運(yùn)行的Python提供了后端靖苇。名為“串行”的模塊會(huì)自動(dòng)選擇適當(dāng)?shù)暮蠖恕?/p>
功能:
- 在所有支持的平臺(tái)上基于相同類的接口。
- 通過Python屬性訪問端口設(shè)置班缰。
- 通過RTS / CTS和/或Xon / Xoff支持不同的字節(jié)大小贤壁,停止位,奇偶校驗(yàn)和流控制埠忘。
- 有無超時(shí)都可以使用脾拆。
- 帶有“讀”和“寫”的API之類的文件(也支持“ readline”等)。
- 該軟件包中的文件是100%純Python莹妒。
- 該端口已設(shè)置為二進(jìn)制傳輸名船。沒有NULL字節(jié)剝離,CR-LF轉(zhuǎn)換等(對(duì)于POSIX啟用了很多次)旨怠。這使該模塊具有通用性渠驼。
- 與io庫兼容
- 示例中提供的RFC 2217客戶端(實(shí)驗(yàn))。
(二)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:設(shè)備名稱或None鉴腻。如COM1,COM2,COM3,COM4......如果port設(shè)置為0對(duì)應(yīng)的為COM1迷扇。
baudrate(int):設(shè)置波特率,如9600或115200等拘哨。
bytesize:數(shù)據(jù)位谋梭,可能的值:FIVEBITS信峻、SIXBITS倦青、SEVENBITS、EIGHTBITS盹舞。
parity:奇偶校驗(yàn)产镐, 啟用奇偶校驗(yàn)。PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE踢步。
stopbits:停止位癣亚,可能的值:STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO。
timeout(float):設(shè)置讀取超時(shí)值获印,timeout = None: 長(zhǎng)時(shí)間等待述雾;timeout = 0: 不阻塞形式 (讀完之后就返回);timeout = x: x秒后超時(shí) (float allowed)。
xonxoff(bool):?jiǎn)⒂密浖骺刂啤?br>
rtscts(bool):?jiǎn)⒂糜布≧TS / CTS)流量控制玻孟。
dsrdtr(bool):?jiǎn)⒂糜布―SR / DTR)流控制唆缴。
write_timeout(float):設(shè)置寫超時(shí)值。
inter_byte_timeout(float):字符間超時(shí)黍翎,None禁用(默認(rèn))面徽。
2.打開串口
在給出端口時(shí),在創(chuàng)建對(duì)象時(shí)立即打開端口匣掸。當(dāng)端口是None
并且需要連續(xù)調(diào)用時(shí)它不會(huì)打開open()
趟紊。
port是設(shè)備名稱:取決于操作系統(tǒng)。
打開串口0碰酝, 9600霎匈,8N1,連接超時(shí)0.5秒:
import serial #導(dǎo)入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系統(tǒng)使用com1口連接串行口
ser=serial.Serial("com1",9600,timeout=0.5)#winsows系統(tǒng)使用com1口連接串行口
ser=serial.Serial("/dev/ttyS1",9600,timeout=0.5)#Linux系統(tǒng)使用com1口連接串行口
print ser.name#打印設(shè)備名稱
print ser.port#打印設(shè)備名
ser.open() #打開端口
s = ser.read(10)#從端口讀10個(gè)字節(jié)
ser.write("hello")#向端口些數(shù)據(jù)
ser.close()#關(guān)閉端口
3.獲得串行口狀態(tài)
串行口的屬性:
name:設(shè)備名字
portstr:已廢棄送爸,用name代替
port:讀或者寫端口
baudrate:波特率
bytesize:字節(jié)大小
parity:校驗(yàn)位
stopbits:停止位
timeout:讀超時(shí)設(shè)置
writeTimeout:寫超時(shí)
xonxoff:軟件流控
rtscts:硬件流控
dsrdtr:硬件流控
interCharTimeout:字符間隔超時(shí)
屬性的使用方法:
ser=serial.Serial("/dev/ttyAMA0",9600,timeout=0.5)
ser.open()
print ser.name#設(shè)備名字
print ser.port#讀或者寫端口
print ser.baudrate#波特率
print ser.bytesize#字節(jié)大小
print ser.parity#校驗(yàn)位N-無校驗(yàn)唧躲,E-偶校驗(yàn),O-奇校驗(yàn)
print ser.stopbits#停止位
print ser.timeout#讀超時(shí)設(shè)置
print ser.writeTimeout#寫超時(shí)
print ser.xonxoff#軟件流控
print ser.rtscts#硬件流控
print ser.dsrdtr#硬件流控
print ser.interCharTimeout#字符間隔超時(shí)
ser.close()
4.設(shè)置串行口狀態(tài)
ser=serial.Serial("/dev/ttyAMA0",9600,timeout=0.5)
ser.baudrate=9600#設(shè)置波特率
ser.bytesize=8#字節(jié)大小
ser.bytesize=serial.EiGHTBITS#8位數(shù)據(jù)位
ser.parity=serial.PARITY_EVEN#偶校驗(yàn)
ser.parity=serial.PARITY_NONE#無校驗(yàn)
ser.parity=serial.PARITY_ODD#奇校驗(yàn)
ser.stopbits=1#停止位
ser.timeout=0.5#讀超時(shí)設(shè)置
ser.writeTimeout=0.5#寫超時(shí)
ser.xonxoff=False#軟件流控
ser.rtscts=False#硬件流控
ser.dsrdtr=False#硬件流控
ser.interCharTimeout=0.5#字符間隔超時(shí)
5.serial方法:
open() # 打開串口
close() # 立即關(guān)閉串口
isOpen() #看看這個(gè)串口是否已經(jīng)被打開
setBaudrate(baudrate) # change baud rate on an open port
inWaiting() # 返回接收緩存中的字節(jié)數(shù)
read(size=1) # 從串口讀size個(gè)字節(jié)碱璃。如果指定超時(shí)弄痹,
#則可能在超時(shí)后返回較少的字節(jié);
#如果沒有指定超時(shí)嵌器,則會(huì)一直等到收完指定的字節(jié)數(shù)肛真。
write(s) # 發(fā)送s,并返回發(fā)送字節(jié)數(shù)爽航。如果bytes和bytearray可用蚓让,
#則接受其作為參數(shù);否則接受str作為參數(shù)讥珍。
flushInput() # 丟棄接收緩存中的所有數(shù)據(jù)
flushOutput() # 終止當(dāng)前寫操作历极,并丟棄發(fā)送緩存中的數(shù)據(jù)。
sendBreak(duration=0.25)# 發(fā)送BREAK條件衷佃,并于duration時(shí)間之后返回IDLE
setRTS(level=1) # 將RTS行設(shè)置為指定的邏輯級(jí)別
setDTR(level=1) # 將DTR行設(shè)置為指定邏輯級(jí)別
getCTS() # 返回CTS行的狀態(tài)
getDSR() # 返回DSR行的狀態(tài)
getRI() # 返回RI行的狀態(tài)
getCD() # 返回CD行的狀態(tài)
6.Readline庫
data = ser.readline() #是讀一行趟卸,以/n結(jié)束,要是沒有/n就一直讀氏义,阻塞锄列。
data = ser.readlines()和ser.xreadlines()#都需要設(shè)置超時(shí)時(shí)間
使用readline()時(shí)要小心。在打開串行端口時(shí)惯悠,請(qǐng)務(wù)必指定一個(gè)超時(shí)時(shí)間邻邮,否則如果沒有收到換行符,它將永遠(yuǎn)阻塞克婶。另請(qǐng)注意筒严,readlines()僅適用于超時(shí)丹泉。 readlines()取決于是否存在超時(shí),并將其解釋為EOF(文件末尾)鸭蛙。如果未正確打開端口嘀掸,則會(huì)引發(fā)異常。
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"))
四睬塌、實(shí)驗(yàn)步驟
??第1步: 連接電路。與樹莓派基礎(chǔ)實(shí)驗(yàn)36:通用串口通信實(shí)驗(yàn)一樣設(shè)置樹莓派的串口為通用串口歇万,與PC上的串口調(diào)試工具通信揩晴。
樹莓派(name) | T型轉(zhuǎn)接板(BCM) | USB TO TTL模塊 |
---|---|---|
TXD | TXO | RXD |
RXD | RXI | TXD |
GND | GND | GND |
下圖中的USB要插到筆記本電腦上哈,為方便拍照就沒插上贪磺。連線很簡(jiǎn)單硫兰,電路圖就沒畫了。
??第2步: 向串口發(fā)送簡(jiǎn)單數(shù)據(jù)程序寒锚。PC串口調(diào)試工具上將收到字符串“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串口調(diào)試工具發(fā)送的字符,打印出來刹前,再發(fā)送回PC串口調(diào)試工具泳赋。手動(dòng)設(shè)置讀取字符的數(shù)量。
#!/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) #手動(dòng)設(shè)置讀取字符的數(shù)量為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串口調(diào)試工具發(fā)送的字符喇喉,打印出來祖今,再發(fā)送回PC串口調(diào)試工具。通過inWaiting()函數(shù)自動(dòng)獲得接收緩沖區(qū)字符數(shù)拣技。
# -*- coding: utf-8 -*
import serial
import time
ser = serial.Serial('/dev/ttyAMA0', 9600, timeout=0.5)
def rec_tra():
while True:
count = ser.inWaiting() # 獲得接收緩沖區(qū)字符
if count != 0:
recv = ser.read(count) # 讀取內(nèi)容
ser.write(recv) # 發(fā)送回PC
print recv
ser.flushInput() # 清空接收緩沖區(qū)
time.sleep(0.1) # 必要的軟件延時(shí)
if __name__ == '__main__':
try:
rec_tra()
except KeyboardInterrupt:
if ser != None:
ser.close()