python与plc进行串口通信,寄存器写数据 欧姆龙plc

项目场景:

python与plc进行串口通信,寄存器写数据,适用于需要用串口通信的plc,如欧姆龙plc

问题描述:

python语言与plc建立串口通信时,无法直接读写。
用到python的serial 模块

在创建串口对象时需要定义其属性与plc一致:

			self.main_engine.baudrate = self.bps
            self.main_engine.bytesize = 7
            self.main_engine.parity = 'E'
            self.main_engine.stopbits = 2

重点:在写入数据后,需要写16进制数"0D",结束标志位

		self.main_engine.write("@00WD1010000152*".encode())
		self.main_engine.write(binascii.a2b_hex("0D"))

解决方案:

import serial #导入模块
import serial.tools.list_ports
import time
import binascii
class myserial():
    def __init__(self, com, bps, timeout=0.5):   
        self.port = com
        self.bps = bps
        self.timeout = timeout
        global Ret
        try:
            # 打开串口,并得到串口对象
            #self.main_engine= serial.Serial(self.port,self.bps,timeout=self.timeout)
            self.main_engine= serial.Serial()
            self.main_engine.port = self.port
            self.main_engine.baudrate = self.bps
            self.main_engine.bytesize = 7
            self.main_engine.parity = 'E'
            self.main_engine.stopbits = 2
            self.Open_Engine()
            # 判断是否打开成功
            if (self.main_engine.is_open):
                Ret = True
        except Exception as e:
            print("---异常---:", e)

     # 打印设备基本信息
    def Print_Name(self):
        print(self.main_engine.name) #设备名字
        print(self.main_engine.port)#读或者写端口
        print(self.main_engine.baudrate)#波特率
        print(self.main_engine.bytesize)#字节大小
        print(self.main_engine.parity)#校验位
        print(self.main_engine.stopbits)#停止位
        print(self.main_engine.timeout)#读超时设置
        print(self.main_engine.writeTimeout)#写超时
        print(self.main_engine.xonxoff)#软件流控
        print(self.main_engine.rtscts)#软件流控
        print(self.main_engine.dsrdtr)#硬件流控
        print(self.main_engine.interCharTimeout)#字符间隔超时

    #打开串口
    def Open_Engine(self):
        self.main_engine.open()

    #关闭串口
    def Close_Engine(self):
        self.main_engine.close()
        print(self.main_engine.is_open)  # 检验串口是否打开

    # 打印可用串口列表
    @staticmethod
    def Print_Used_Com():
        port_list = list(serial.tools.list_ports.comports())
        print(port_list)
        if len(port_list) == 0:
           print('无可用串口')
        else:
            for i in range(0,len(port_list)):
                print(port_list[i])

    #接收指定大小的数据
    #从串口读size个字节。如果指定超时,则可能在超时后返回较少的字节;如果没有指定超时,则会一直等到收完指定的字节数。
    def Read_Size(self,size):
        return self.main_engine.read(size=size)

    #接收一行数据
    # 使用readline()时应该注意:打开串口时应该指定超时,否则如果串口没有收到新行,则会一直等待。
    # 如果没有超时,readline会报异常。
    def Read_Line(self):
        return self.main_engine.readline()

    #发数据
    def Send_data(self,data):
        self.main_engine.write(data)

    #更多示例
    # self.main_engine.write(chr(0x06).encode("utf-8"))  # 十六制发送一个数据
    # print(self.main_engine.read().hex())  #  # 十六进制的读取读一个字节
    # print(self.main_engine.read())#读一个字节
    # print(self.main_engine.read(10).decode("gbk"))#读十个字节
    # print(self.main_engine.readline().decode("gbk"))#读一行
    # print(self.main_engine.readlines())#读取多行,返回列表,必须匹配超时(timeout)使用
    # print(self.main_engine.in_waiting)#获取输入缓冲区的剩余字节数
    # print(self.main_engine.out_waiting)#获取输出缓冲区的字节数
    # print(self.main_engine.readall())#读取全部字符。

    #接收数据
    #一个整型数据占两个字节
    #一个字符占一个字节

    def Recive_data(self,way):
        # 循环接收数据,此为死循环,可用线程实现
        print("开始接收数据:")
        while True:
            try:
                # 一个字节一个字节的接收
                if self.main_engine.in_waiting:
                    if(way == 0):
                        for i in range(self.main_engine.in_waiting):
                            print("接收ascii数据:"+str(self.Read_Size(1)))
                            data1 = self.Read_Size(1).hex()#转为十六进制
                            data2 = int(data1,16)#转为十进制print("收到数据十六进制:"+data1+"  收到数据十进制:"+str(data2))
                    if(way == 1):
                        #整体接收
                        # data = self.main_engine.read(self.main_engine.in_waiting).decode("utf-8")#方式一
                        data = self.main_engine.read_all()#方式二print("接收ascii数据:", data)
            except Exception as e:
                print("异常报错:",e)


    def send_ccd1_OK(self):
        # self.main_engine.write("@00WD1000000153*".encode())     
        self.main_engine.write("@00WD1000000250*".encode())     
              
        self.main_engine.write(binascii.a2b_hex("0D"))
        print("CCD1_OK")

    def send_ccd1_NG(self):
        self.main_engine.write("@00WD1000000153*".encode())
        self.main_engine.write(binascii.a2b_hex("0D"))
        print("CCD1_NG")

    def send_ccd2_OK(self):
        self.main_engine.write("@00WD1010000251*".encode())
        self.main_engine.write(binascii.a2b_hex("0D"))
        print("CCD2_OK")

    def send_ccd2_NG(self):
        self.main_engine.write("@00WD1010000152*".encode())
        self.main_engine.write(binascii.a2b_hex("0D"))
        #print(self.main_engine.write("@00WD1010000151*".encode()))
        print("CCD2_NG")

    def recv(self):
        while True:
            data = self.main_engine.read_all()
            if data == b'':
                continue
            else:
                break
            time.sleep(0.02)
        return data
if __name__ == "__main__":

    myserial.Print_Used_Com()
    Ret =False #是否创建成功标志

    Engine1 = myserial("COM5",115200,0.5)
    if Engine1.main_engine.isOpen():
        print("open success")   

    if (Ret):
        Engine1.Print_Name()
        Engine1.send_ccd2_OK()
        data = Engine1.recv()
        print(data)
        data = Engine1.recv()
        print(data)

  • 7
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值