Python串口编程初探

2016/8/13 Python

今天在网上购买了一套环境监测板,功能十分强大,支持PM2.5,PM10,TVOC,甲醛以及温湿度测量。模块使用串口TTL向上位机传输数据,协议结构简单,每秒上传一次数据。以下记录一下用PYTHON读取和计算数据的过程,以免下次忘了。

# 安装模块

强大的Python拥有强大的库,几乎可以解决所有问题,而我需要的就是端杯茶,敲几行代码,耶!请出强大的pip工具,在windows命令行下键入以下代码:
pip install pyserial 
坐下来喝杯茶,等待模块安装完成,继续下一步。

# 操作串口

先上代码
import serial
ser=serial.Serial(port='COM4',baudrate=9600,bytesize=8,parity=serial.PARITY_NONE,stopbits=1,timeout=5) 

两行代码,引入模块,打开串口,下面说一下参数:

  • port:不需多做解释,去设备管理器查看
  • baudrate:波特率,根据实际情况设定,这里设置为9600
  • bytesize:位数,根据实际情况可以设置为5、6、7、8,也可以用模块的常量(FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS)
  • parity:校验位,根据实际情况可以设置为PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE
  • stopbist:停止位,根据实际情况可以设置为STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO
  • timeout:超时,此参数设计同步和异步编程
    • timeout=None, # set a timeout value, None for waiting forever 上面timeout的意思是,如果是none,那么程序永远会死在这里.一直等待
    • timeout=0 # non-blocking mode (return immediately on read) timeout = 0: 非阻塞形式 (读完之后就返回,费时的io操作,就直接交给后台处理了)
    • timeout=x # set timeout to x seconds (float allowed) 超时时间一到,程序就是继续执行

还有如下一些参数:

  • xonxoff=0, # enable software flow control
  • rtscts=0, # enable RTS/CTS flow control
  • interCharTimeout=None # Inter-character timeout, None to disable

以下代码为读取数据:

print("PM2.5    PM10    TVOC    湿度  温度  甲醛 ")
while ser.isOpen():
    n = ser.inWaiting()
    if n == 16:
        x=ser.readline(n) 
        z = struct.unpack_from('>3B6HB', x)
        if z[0] == 0xAA:
            print("{0}      {1}     {2}     {3}    {4}   {5}".format(z[3],z[4],z[5]/100,z[6]/10,z[7]/10,z[8]/100))
ser.close() 
  • isOpen():判断串口有没有成功打开
  • inWaiting():返回接收缓冲区的数据长度

其他一些方法

  • open() # open port
  • close() # close port immediately
  • setBaudrate(baudrate) # change baud rate on an open port
  • inWaiting() # return the number of chars in the receive buffer
  • read(size=1) # read "size" characters
  • write(s) # write the string s to the port
  • flushInput() # flush input buffer, discarding all it's contents
  • flushOutput() # flush output buffer, abort output
  • sendBreak() # send break condition
  • setRTS(level=1) # set RTS line to specified logic level
  • setDTR(level=1) # set DTR line to specified logic level
  • getCTS() # return the state of the CTS line
  • getDSR() # return the state of the DSR line
  • getRI() # return the state of the RI line
  • getCD() # return the state of the CD line

# 数据处理

以上代码涉及数据处理的方法就一行,使用struct模块,充分体现了python的简洁高效,下面介绍一下Python struct模块的使用。

struct模块为python处理字节流的库,可以很方便的把python数据编辑为字节流,提供给网络或其他通讯模块使用,该库为python默认库,无需安装。

先看一下使用方法:

>>> from struct import *
>>> pack('hhl', 1, 2, 3)
b'\x00\x01\x00\x02\x00\x00\x00\x03'
>>> unpack('hhl', b'\x00\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)
>>> calcsize('hhl')
8
>>> record = b'raymond   \x32\x12\x08\x01\x08'
>>> name, serialnum, school, gradelevel = unpack('<10sHHb', record)
>>> name, serialnum, school, gradelevel
(b'raymond   ', 4658, 264, 8)
  • pack():将字符编码
  • ‘hhl’:编码规则,具体规则如下,这里前两个为short,后一个为int。连续的类型可以用数字代替,比如“2hi”
Format C Type Python type Standard size Notes
x pad byte no value
c char bytes of length 1 1
b signed char integer 1 (1),(3)
B unsigned char integer 1 (3)
? _Bool bool 1 (1)
h short integer 2 (3)
H unsigned short integer 2 (3)
i int integer 4 (3)
I unsigned int integer 4 (3)
l long integer 4 (3)
L unsigned long integer 4 (3)
q long long integer 8 (2), (3)
Q unsigned long long integer 8 (2), (3)
n ssize_t integer (4)
N size_t integer (4)
f float float 4 (5)
d double float 8 (5)
s char[] bytes
p char[] bytes
P void * integer (6)
  • 1,2,3:待编码的数据
  • calcsize():计算按此规则编码需要的字节数,‘hhi’需要8个字节,根据上表short为2字节,int为4字节,2*2+4=8。
  • unpack():解码数据,第一个参数为编码规则,参考上表,第二个参数为字节数据。

关于编码规则需要注意字节序,熟悉C编程的都知道,计算机有大端序和小端序之分,网络数据统一为大端序。字节序如果不设置为本机序列,此次的传感器模块传输的为大端序,需要在规则前加上“>”,具体规则如下表:

Character Byte order Size Alignment
@ native native native
= native standard none
< little-endian standard none
> big-endian standard none
! network (= big-endian) standard none

另外,还要注意字节对齐的问题,如:

>>> calcsize("3ch")
6
>>> calcsize("4ch")
6
>>> calcsize("=4ch")
6
>>> calcsize("=3ch")
5

‘3ch’:如果使用默认设置需要6个字节,这是由于字节对齐造成的,系统是按照4字节对齐,所以多出一个字符。使用‘=’可以设置系统不按字节对齐,所以需要5个字节。

# 茶未凉!喝杯茶去!