python - serial communication(串口通信)

python - serial communication(串口通信),第1张

由于测试工作的需要,在C端产品上经常使用串口进行通信,而测试脚本大部分时候又采用python编写,于是就不得不了解并熟悉python下的串口通信实现方法了,整理如下以备随时使用:

一、说明

pyserial封装了python环境下对串口的访问,其兼容各种平台,并有统一的 *** 作接口。通过python属性访问串口设置,并可对串口的各种配置参数(如串口名,波特率、停止校验位、流控、超时等等)做修改,再进行串口通信的类与接口封装后,非常方便地被调用和移植。

二、模块安装

pip insatll pyserial

三、初始化与参数说明

import serial

ser = serial.Serial('COM3', 115200, timeout=0.5, ....................)

下面看看 serial.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口连接串行口

五、串口属性

ser.name #串口名称

ser.port #端口号

ser.baudrate #波特率

ser.bytesize #字节大小

ser.parity #校验位N-无校验,E-偶校验,O-奇校验

ser.stopbits #停止位

ser.timeout #读超时设置

ser.writeTimeout #写超时

ser.xonxoff #软件流控

ser.rtscts #硬件流控

ser.dsrdtr #硬件流控

ser.interCharTimeout #字符间隔超时 

六、串口常用方法

isOpen():查看端口是否被打开。

open() :打开端口‘。

close():关闭端口。

read(size=1):从端口读字节数据。默认1个字节。

read_all():从端口接收全部数据。

write(data):向端口写数据。

readline():读一行数据。

readlines():读多行数据。

in_waiting():返回输入缓存中的字节数。

out_waiting():返回输出缓存中的字节数。

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

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

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

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

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

setRTS(level=True):设置请求发送(RTS)的控制信号

setDTR(level=True):设置数据终端准备就绪的控制信号

七、类与接口封装

import time

import serial

import serial.tools.list_ports

# 串口 *** 作类

class serialCommunication(object):

    def __init__(self, port, bps, timeout):# 可配置更多参数

        port_list =self.show_usable_com()

        if len(port_list) >0:

            if portnot in port_list:

                self.port = port_list[0]

            else:

                self.port = port

        else:

            print("no usable serial, please plugin your serial board")

            return

        self.bps = bps

        self.timeout = timeout

        try:

            # 初始化串口,并得到串口对象,根据需要可拓展更多参数

            self.ser = serial.Serial(self.port, self.bps, 8, 'N', 1, timeout=self.timeout, write_timeout=self.timeout)

        except Exception as e:# 抛出异常

            print("Exception={}".format(e))

    # 显示可用串口列表

    @staticmethod

    def show_usable_com():

        serialport_list = []

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

        if len(portInfo_list) <=0:

            print("can not find any serial port!")

        else:

            print(portInfo_list)

            for i in range(len(portInfo_list)):

                plist =list(portInfo_list[i])

                print(plist)

                serialport_list.append(plist[0])

            print(serialport_list)

            return serialport_list

# 输出串口基本信息

    def serial_infor(self):

        print(self.ser.name)# 设备名字

        print(self.ser.port)# 读或者写端口

        print(self.ser.baudrate)# 波特率

        print(self.ser.bytesize)# 字节大小

        print(self.ser.parity)# 校验位

        print(self.ser.stopbits)# 停止位

        print(self.ser.timeout)# 读超时设置

        print(self.ser.writeTimeout)# 写超时

        print(self.ser.xonxoff)# 软件流控

        print(self.ser.rtscts)# 软件流控

        print(self.ser.dsrdtr)# 硬件流控

        print(self.ser.interCharTimeout)# 字符间隔超时

    # 打开串口

    def serial_open(self):

        try:

            if not self.ser.isOpen():

                self.ser.open()

        except Exception as e:# 抛出异常

            print("serial_open Exception={}".format(e))

            self.ser.close()

    # 读取指定大小的数据

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

    def serial_read_with_size(self, size):

        try:

            self.serial_open()

            return self.ser.read(size).decode("utf-8")

        except Exception as e:

            print("serial_read_all Exception={}".format(e))

            self.ser.close()

    # 读取当前串口缓存中的所有数据

    def serial_read_data(self):

        try:

            self.serial_open()

            datalen =self.ser.inWaiting()

            if datalen ==0:

                return None

            return self.ser.read(datalen).decode("utf-8")

        except Exception as e:

            print("serial_read_data Exception={}".format(e))

            self.ser.close()

    # 读串口全部数据,注意timeout的设置

    # 在设定的timeout时间范围内,如果读取的字节数据是有效的(就是非空)那就直接返回,

    # 否则一直会等到设定的timeout时间并返回这段时间所读的全部字节数据。

    def serial_read_all(self):

        try:

            self.serial_open()

            return self.ser.read_all().decode("utf-8")

        except Exception as e:

            print("serial_read_all Exception={}".format(e))

            self.ser.close()

    # 读一行数据

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

    # 如果没有超时,readline会报异常。

    def serial_read_line(self):

        try:

            self.serial_open()

            return self.ser.readline().decode("utf-8")

        except Exception as e:

            print("serial_read_line Exception={}".format(e))

            self.ser.close()

    # 读多行数据,返回行列表

    def serial_read_lines(self):

        try:

            self.serial_open()

            return self.ser.readlines().decode("utf-8")

        except Exception as e:

            print("serial_read_lines Exception={}".format(e))

            self.ser.close()

    # 写数据

    def serial_write_data(self, data):

        try:

            self.serial_open()

            self.ser.flushOutput()

            data_len =self.ser.write(data.encode('utf-8'))

            return data_len

        except Exception as e:

            print("serial_write_data Exception={}".format(e))

            return 0

    # 写行数据,注意参数差异

    def serial_write_lines(self, lines):

        self.ser.writelines(lines)

    # 清除串口缓存

    def serial_clean(self):

        try:

            if self.ser.isOpen():

                self.ser.flush()

        except Exception as e:

            print("serial_clean Exception={}".format(e))

    # 关闭串口

    def serial_close(self):

        try:

            if self.ser.isOpen():

                self.ser.close()

        except Exception as e:

            print("serial_clean Exception={}".format(e))

if __name__ =='__main__':

    testSerial = serialCommunication("COM10", 1500000, 0.5)

    testSerial.serial_open()

    testSerial.serial_infor()

    testSerial.serial_write_data("ifconfig eth0\n")

    time.sleep(0.1)

    data = testSerial.serial_read_all()

    print(data)

    testSerial.serial_close()

八、其他

1)ser.VERSION表示pyserial版本 另外,ser.name表示设备名称

2)端口设置可以被读入字典,也可从字典加载设置:

    getSettingDict():返回当前串口设置的字典

    applySettingDict(d):应用字典到串口设置

3) Readline()是读一行,以/n结束,要是没有/n就一直读,阻塞。注意:打开串口时应该指定超时,否则如果串口没有收到新行,则会一直等待。

4)serial.read_all 与 serial.read_all()区别

    serial.read_all:读取串口所有的参数信息

    serial.read_all():超时时间内从串口读取的所有数据

5) 异常信息

    exception serial.SerialException

    exception serial.SerialTimeoutException

可以,使用comm,jar

class SerialExample {

public static void main(String[] args) {

//TO DO: Add your JAVA codes here

long curTime = System.currentTimeMillis()

long serialtime = 8000

boolean state = true

SerialBean SB = new SerialBean(2)//设置端口号2

String Msg = "AD 01 0D"//发送命令

SB.Initialize(9600)//设置波率

SB.WritePort(Msg)//发送命令

/*for (int i = 5i <10i++) {

System.out.println( SB.ReadPort(3))//设置读取个数

}

*/

String readdata = SB.ReadPort("0D",4000)//读取以OD结束的数据,4000ms没有数据就返回空

if (readdata.length() >0) { //System.out.println(readdata.length())//如果有读到数据

System.out.println(readdata)//如果有读到数据

}

while (readdata.length() <1 &&state) {//如果没有读到数据

readdata = SB.ReadPort("0D",4000)

System.out.println(readdata)

if (System.currentTimeMillis() - curTime >serialtime) {

state = false//设置读取错误超时

}

System.out.println("readdaa:" + state)

System.out.println(System.currentTimeMillis() - curTime)

}

if (!state) {

System.out.println("数据读取超时")

}

SB.ClosePort()//关闭连接

}

}

public class SerialBuffer {

Convents cv = new Convents()

private String Content = ""

private String CurrentMsg, TempContent

private boolean available = false

private int LengthNeeded = 1

String str = ""

byte b

/**

*

* This function returns a string with a certain length from the incoming

* messages.

*

* @param Length The length of the string to be returned.

*

*/

public synchronized String GetMsg(int Length) {

LengthNeeded = Length

long timeout=2000

long curtime=System.currentTimeMillis()

notifyAll()

if (LengthNeeded >Content.length()) {

available = false

while (available == false) {

try {

if(System.currentTimeMillis()-curtime<timeout) wait()

} catch (InterruptedException e) {

}

}

}

CurrentMsg = Content.substring(0, LengthNeeded)

TempContent = Content.substring(LengthNeeded)

Content = TempContent

LengthNeeded = 1

notifyAll()

return CurrentMsg

}

public synchronized String GetMsg(String endstring,long timeout) {

LengthNeeded =Content.indexOf(endstring)

notifyAll()

if (LengthNeeded <0) {

available = false

while (available == false) {

try {

wait(timeout)

available=true

} catch (InterruptedException e) {

}

}

return ""

}

if (LengthNeeded >0) {

CurrentMsg = Content.substring(0, LengthNeeded+endstring.length())

TempContent = Content.substring(LengthNeeded+endstring.length())

Content = TempContent

}

LengthNeeded = -1

notifyAll()

return CurrentMsg

}

public synchronized void PutChar(int c) {

Content = Content.concat(cv.byteToHexString(c))

if (LengthNeeded <Content.length() &&Content.length() >0) {

available = true

}

notifyAll()

}

}

/*

* To change this template, choose Tools | Templates

* and open the template in the editor.

*/

package common.serial

/**

*

* @author Jason

*/

import java.io.*

import java.util.*

import javax.comm.*

import common.code.Convents

public class SerialBean {

Convents cv=new Convents()

String PortName = ""

CommPortIdentifier portId = null

SerialPort serialPort = null

OutputStream out

InputStream in

SerialBuffer SB

ReadSerial RT

int rate=9600

String endstring =""

long timeout=2000

public SerialBean(int PortID) {

PortName = "COM" + PortID

}

public int Initialize(int rate) {

int InitSuccess = 1

int InitFail = -1

try {

portId = CommPortIdentifier.getPortIdentifier(PortName)

try {

serialPort = (SerialPort) portId.open("Serial_Communication", 2000)

} catch (PortInUseException e) {

return InitFail

}

//Use InputStream in to read from the serial port, and OutputStream

//out to write to the serial port.

try {

in = serialPort.getInputStream()

out = serialPort.getOutputStream()

} catch (IOException e) {

return InitFail

}

//Initialize the communication parameters to 9600, 8, 1, none.

try {

serialPort.setSerialPortParams(rate,

SerialPort.DATABITS_8,

SerialPort.STOPBITS_1,

SerialPort.PARITY_NONE)

} catch (UnsupportedCommOperationException e) {

return InitFail

}

} catch (NoSuchPortException e) {

return InitFail

}

SB = new SerialBuffer()

RT = new ReadSerial(SB, in)

RT.start()

return InitSuccess

}

public String ReadPort(int Length) {

String Msg

Msg = SB.GetMsg(Length)

return Msg

}

public String ReadPort(String endstring,long timeout) {

String Msg

Msg = SB.GetMsg(endstring,timeout)

return Msg

}

public void WritePort(String Msg) {

try {

out.write(cv.hexStringToByte(Msg))

} catch (IOException e) {

}

}

public void ClosePort() {

serialPort.close()

}

}

package common.serial

import java.io.*

public class ReadSerial extends Thread {

private SerialBuffer ComBuffer

private InputStream ComPort

char[] ch

public ReadSerial(SerialBuffer SB, InputStream Port) {

ComBuffer = SB

ComPort = Port

}

@Override

public void run() {

int c

try {

while (true) {

c=ComPort.read()

ComBuffer.PutChar(c)

}

} catch (IOException e) {

}

}

}

/*

* To change this template, choose Tools | Templates

* and open the template in the editor.

*/

package common.serial

/**

*

* @author Administrator

*/

public class PortOpreate {

private String sendtxt=""

private String recivetxt=""

private int comid = 1

private int comrate = 9600

private int timeout = 4000

private long waittime = 13000

private String endtxt = "0D"

private boolean pstate=false

private String massage=""

public void PortOpreate(boolean hasreturn) {

long curTime = System.currentTimeMillis()

long serialtime = getWaittime()

boolean state = true

int t=0

SerialBean SB = new SerialBean(getComid())//设置端口号2

t=SB.Initialize(getComrate())//设置波率

if(t>0){

SB.WritePort(getSendtxt())//发送命令

if (hasreturn) {

String readdata = SB.ReadPort(getEndtxt(), getTimeout())//读取以OD结束的数据,4000ms没有数据就返回空

if (readdata.length() >0) { //System.out.println(readdata.length())//如果有读到数据

System.out.println(readdata)//如果有读到数据

}

while (readdata.length() <1 &&state) {//如果没有读到数据

readdata = SB.ReadPort(getEndtxt(), getTimeout())

System.out.println(readdata)

if (System.currentTimeMillis() - curTime >serialtime) {

state = false//设置读取错误超时

}

System.out.println("readdaa:" + state)

System.out.println(System.currentTimeMillis() - curTime)

}

if (!state) {

System.out.println("数据读取超时")

setMassage("数据读取超时")

}

setRecivetxt(readdata)

setPstate(state)

}

SB.ClosePort()//关闭连接

}else{

System.out.println("端口号出现错误")

setMassage("端口号出现错误")

}

}

/**

* @return the sendtxt

*/

public String getSendtxt() {

return sendtxt

}

/**

* @param sendtxt the sendtxt to set

*/

public void setSendtxt(String sendtxt) {

this.sendtxt = sendtxt

}

/**

* @return the recivetxt

*/

public String getRecivetxt() {

return recivetxt

}

/**

* @param recivetxt the recivetxt to set

*/

public void setRecivetxt(String recivetxt) {

this.recivetxt = recivetxt

}

/**

* @return the comid

*/

public int getComid() {

return comid

}

public void setComid(int comid) {

this.comid = comid

}

public int getComrate() {

return comrate

}

public void setComrate(int comrate) {

this.comrate = comrate

}

public int getTimeout() {

return timeout

}

public void setTimeout(int timeout) {

this.timeout = timeout

}

public long getWaittime() {

return waittime

}

public void setWaittime(long waittime) {

this.waittime = waittime

}

public String getEndtxt() {

return endtxt

}

public void setEndtxt(String endtxt) {

this.endtxt = endtxt

}

public boolean isPstate() {

return pstate

}

public void setPstate(boolean pstate) {

this.pstate = pstate

}

public String getMassage() {

return massage

}

public void setMassage(String massage) {

this.massage = massage

}

}

package common.serial

import java.io.*

import javax.servlet.*

import javax.servlet.http.*

public class PortOperatorServlet extends HttpServlet {

protected void processRequest(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/htmlcharset=UTF-8")

PrintWriter out = response.getWriter()

try {

long curTime = System.currentTimeMillis()

long serialtime = 8000

boolean state = true

String Msg = "AD 01 0D"//发送命令

SerialBean SB = new SerialBean(10)//设置端口号2

SB.Initialize(9600)//设置波率

SB.WritePort(Msg)//发送命令

/*for (int i = 5i <10i++) {

System.out.println( SB.ReadPort(3))//设置读取个数

}

*/

String readdata = SB.ReadPort("0D",4000)//读取以OD结束的数据

if (readdata.length() >0) { //System.out.println(readdata.length())//如果有读到数据

System.out.println(readdata)//如果有读到数据

}

while (readdata.length() <1 &&state) {//如果没有读到数据

readdata = SB.ReadPort("0D",4000)

System.out.println(readdata)

out.println(readdata)

if (System.currentTimeMillis() - curTime >serialtime) {

state = false//设置读取错误超时

}

System.out.println("readdaa:" + state)

System.out.println(System.currentTimeMillis() - curTime)

}

if (!state) {

System.out.println("数据读取超时")

out.println("数据读取超时")

}

SB.ClosePort()//关闭连接

} finally {

out.close()

}

}

protected void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

processRequest(request, response)

}

protected void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

processRequest(request, response)

}

public String getServletInfo() {

return "Short description"

}

}

package common.code

public final class Convents {

public final static char[] BToA = "0123456789abcdef".toCharArray()

/**

* 把16进制字符串转换成字节数组A1 01 0D

* @param hex

* @return

*/

public byte[] hexStringToByte(String hex) {

String str[] = hex.split(" ")

int len = str.length

byte[] result = new byte[len]

char[] achar = hex.toCharArray()

for (int i = 0i <leni++) {

result[i] = (byte) (toByte(str[i].charAt(0)) * 16 + toByte(str[i].charAt(1)))

}

return result

}

private static byte toByte(char c) {

byte b = (byte) ("0123456789ABCDEF".indexOf(c))

return b

}

/**

* 把字节数组转换成16进制字符串

* @param bArray

* @return

*/

public String byteToHexString(int b){

String st=""

st=Integer.toHexString(b)

if (st.length() <2) {

st="0"+Integer.toHexString(b).toUpperCase()+" "

} else {

st=Integer.toHexString(b).toUpperCase()+" "

}

return st

}

public String bytesToHexString(byte[] bArray) {

StringBuffer sb = new StringBuffer(bArray.length)

String sTemp

for (int i = 0i <bArray.lengthi++) {

sTemp = Integer.toHexString(bArray[i]).toUpperCase()

}

return sb.toString()

}

}


欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/tougao/11271747.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-14
下一篇2023-05-14

发表评论

登录后才能评论

评论列表(0条)

    保存