python 实现串口通信USB转232自闭环、USB转485测试

原理 

USB转232自闭环:将模块拔好对应的拔码开关,向usb口发送信号,然后通过一个usb转232杜邦线将信号转为rs232的。

USB转485测试:半双工数据通讯模式连接,只用一对简单的杜邦线将各个接口的”A””B“两端连接起来,可以实现AB之间互相传输数据。

模块效果图

 

调拔码开关和杜邦线连接效果图 

 

准备工作

        1、下载串口驱动程序,并安装,这里我已放在网盘中,可以自行下载安装

                链接:https://pan.baidu.com/s/1G3nWvtRCJTBkVx5X6cTyEg 
                提取码:linv

        2、串口模块三到四个

开发工具

        Python3、Windows10、VSCdoe

        需安装模块:pip install pyserial 、pip install Pyside2

开始写代码

1、导入所有模块

from PySide2.QtWidgets import QApplication,QMessageBox,QPlainTextEdit
from PySide2.QtGui import  QIcon
from PySide2.QtCore import QFile
from PySide2.QtUiTools import QUiLoader
import serial
import serial.tools.list_ports
from threading import Thread
import time
from PySide2.QtCore import Signal,QObject,QTimer,QDateTime
from serial.tools.list_ports_windows import *
import wmi  
import chardet

 2、加载动态UI文件

 # 动态加载UI文件
 qfile = QFile('UI/Ser_485.ui')
 qfile.open(QFile.ReadOnly)
 qfile.close()
 self.ui = QUiLoader().load(qfile)
# 动态加载UI文件
qfile = QFile('UI/Ser_232.ui')
qfile.open(QFile.ReadOnly)
qfile.close()
self.ui = QUiLoader().load(qfile)

3、 获取所有串口设备实例

# 如果没找到串口设备,则输出:“无串口设备。”
# 如果找到串口设备,则依次输出每个设备对应的串口号和描述信息。
self.com = list(serial.tools.list_ports.comports())

4、打开串口

# 点击启动按钮
    def Slot_bp_start_btn(self):
        self.ui.bp_recv_msg.setEnabled(True)
        global bp_ser
        try:
            for num,com in enumerate(self.com):
                if self.ui.bp_com.currentIndex() == num:
                    self.Slot_bp_com_clear()
                    # 打开当前选中的下拉框某个串口
                    bp_ser = serial.Serial(com[0],timeout=0.5)
                    # 判断串口是否成功打开
                    if bp_ser.isOpen():
                        self.ui.bp_baud_rate.addItem(str(bp_ser.baudrate))
                        self.ui.bp_data_bit.addItem(str(bp_ser.bytesize))
                        self.ui.bp_check_bit.addItem(str(bp_ser.parity))
                        self.ui.bp_stop_bit.addItem(str(bp_ser.stopbits))
                        self.Solt_TimeUpdate()
                        self.ui.bp_log_msg.appendPlainText('{0}\n串口已开启.'.format(localTime))
                    # 串口未打开
                    else:
                        self.Solt_TimeUpdate()
                        self.ui.bp_log_msg.appendPlainText('{0}\n发生意外错误!'.format(localTime))
            for bp_bol_tru in self.dict_['bp_bool_true']:
                bp_bol = False
            if not bp_bol:
                for bp_con in self.dict_['bp_controls']:
                    bp_run_data = ''.join(['self.ui.',bp_con,'.setEnabled(',bp_bol_tru,')'])
                    eval(bp_run_data)
            self.ui.bp_com.setEnabled(False)
            self.ui.bp_start_btn.setEnabled(False)
        # 处理异常
        except serial.SerialException as err:
            self.Solt_TimeUpdate()
            self.ui.bp_log_msg.appendPlainText('{0}\n{1}'.format(localTime,err))
            # 警告提示
            QMessageBox.critical(self.ui,'War',str(err)[49:53])
            return

 5、检测是否有可用的串口

def Get_com(self):
        # 当串口列表长度大于1且不等0时,添加串口到下拉框,在主窗口所有控件禁用状态解除
        if len(self.com) != 0 and len(self.com) >= 1:
            for index in self.com:
                self.ui.com.addItem(index[0])
            self.Solt_TimeUpdate()
            self.ui.log_msg.appendPlainText('{0}\n当前串口:{1}'.format(localTime, self.ui.com.currentText()))
            for bol_fal in self.dict_['bol_false']:
                bol = False
            if not bol:
                for con in self.dict_['controls']:
                    run_data = ''.join(['self.ui.',con,'.setEnabled(',bol_fal,')'])
                    eval(run_data)

6、 发送数据(Rs485)

 def Slot_dp_send_msg_1(self):
        try:
            if dp_ser.isOpen():
                try:
                    msg = self.ui.dp_send_msg_1.text()
                    if str(msg) == '':
                        QMessageBox.warning(self.ui,'War','发送数据不能为空!')
                        return
                    if self.ui.dp_check_hex_1.isChecked() == False:
                        if self.ui.bp_recv_msg.isChecked() == True:
                            result_1=dp_ser.write(str(msg).encode('utf-8'))
                            self.Solt_TimeUpdate()
                            self.ui.dp_log_msg.appendPlainText('{2}\nsend:->{0}\tbyte_size:{1}'.format(msg,result_1,localTime))
                        else:
                            QMessageBox.critical(self.ui,'Err','发送失败!')
                            self.Solt_TimeUpdate()
                            self.ui.dp_log_msg.appendPlainText('{0}\n发送失败,检查另一端串口是否开启接收功能!'.format(localTime))
                            return
                    if self.ui.dp_check_hex_1.isChecked() == True:
                        if self.ui.bp_recv_msg.isChecked() == True:
                            result_2=dp_ser.write(str(msg).encode('UTF-16'))
                            hex_ = str(msg).encode("UTF-8")
                            adchar=chardet.detect(hex_)
                            try:
                                if adchar['encoding'] == 'ascii':
                                    str_1 = hex(int(str(msg).encode('utf-8')))[2:]
                                    self.Solt_TimeUpdate()
                                    pattern=r'(\w+)(\w{4})((,\w{4})*)'
                                    while True:
                                        str_1,count=re.subn(pattern,r'\1 \2\3',str_1)
                                        if count==0:
                                            break
                                    self.ui.dp_log_msg.appendPlainText('{2}\nsend:->{0}\tbyte_size:{1}'.format(str_1,result_2,localTime))
                                else:
                                    str_2 = str(msg).encode('utf-8').hex()[2:]
                                    self.Solt_TimeUpdate()
                                    pattern=r'(\w+)(\w{4})((,\w{4})*)'
                                    while True:
                                        str_2,count=re.subn(pattern,r'\1 \2\3',str_2)
                                        if count==0:
                                            break
                                    self.ui.dp_log_msg.appendPlainText('{2}\nsend:->{0}\tbyte_size:{1}'.format(str_2,result_2,localTime))
                            except:
                                str_9 = str(msg).encode('utf-8').hex()[2:]
                                self.Solt_TimeUpdate()
                                pattern=r'(\w+)(\w{4})((,\w{4})*)'
                                while True:
                                    str_9,count=re.subn(pattern,r'\1 \2\3',str_9)
                                    if count==0:
                                        break
                                self.ui.dp_log_msg.appendPlainText('{2}\nsend:->{0}\tbyte_size:{1}'.format(str_9,result_2,localTime))
                        else:
                            QMessageBox.critical(self.ui,'Err','发送失败!')
                            self.Solt_TimeUpdate()
                            self.ui.dp_log_msg.appendPlainText('{0}\n发送失败,检查另一端串口是否开启接收功能!'.format(localTime))
                            return
                except Exception as err:
                    self.Solt_TimeUpdate()
                    self.ui.dp_log_msg.appendPlainText('{0}\nWar:{1}'.format(localTime,err))
        except:
                self.Solt_TimeUpdate()
                self.ui.dp_log_msg.appendPlainText('{1}\nErr:{0}'.format('串口未开启,无法发送数据!',localTime))
                QMessageBox.critical(self.ui,'Err','串口未开启,无法发送数据!')
                return

7、接收数据(Rs485)

# 接收数据
    def Slot_bp_recv_data(self):
        if self.ui.bp_recv_msg.isChecked() == True:
            try:
                self.Solt_TimeUpdate()
                self.ui.bp_log_msg.appendPlainText('{0}\n开始接收数据...'.format(localTime))
                bp_ser.close()
                def bp_recv():
                    bp_ser.open()
                    # 一直循环操作
                    while True:
                        try:
                            # 监测接收的字符串长度
                            if bp_ser.in_waiting:
                                # 读取全部字符(阻塞)
                                recv_data = bp_ser.readall()
                                # 编码检测
                                bp_codeing = chardet.detect(recv_data)
                                # 判断编码格式是否为UTF-16
                                if bp_codeing['encoding'] == 'UTF-16':
                                    recv_hex = recv_data.decode('UTF-16')
                                    global_ms.bp_text_print.emit(self.ui.bp_log_msg,recv_hex)
                                # 判断编码格式是否为utf-8
                                elif bp_codeing['encoding'] == 'utf-8':
                                    recv_8 = recv_data.decode('utf-8')
                                    global_ms.bp_text_print.emit(self.ui.bp_log_msg,recv_8)
                                else:
                                    recv_8 = recv_data.decode('ascii')
                                    global_ms.bp_text_print.emit(self.ui.bp_log_msg,recv_8)
                            # 判断勾选中接收数据复选框
                            if self.ui.bp_recv_msg.isChecked() == False:
                                self.Solt_TimeUpdate()
                                self.ui.bp_log_msg.appendPlainText('{0}\n已关闭接收操作!'.format(localTime))
                                break
                        # 处理异常
                        except serial.SerialException:
                            break
                bp_thread = Thread(target=bp_recv)
                bp_thread.start()
            except:
                 QMessageBox.critical(self.ui,'Err','意外错误警报,请您检查下串口是否开启!')
                 self.ui.bp_recv_msg.setChecked(False)
                 self.Solt_TimeUpdate()
                 self.ui.bp_log_msg.appendPlainText('{0}\n意外中断!'.format(localTime))
                 return
        else:
            self.Solt_TimeUpdate()
            self.ui.bp_log_msg.appendPlainText('{0}\n已关闭接收数据!'.format(localTime))

 8、关闭窗口

# 点击关闭按钮
    def Slot_bp_stop_com(self):
        self.Solt_TimeUpdate()
        self.ui.bp_log_msg.appendPlainText('{0}\n正在关闭串口中...'.format(localTime))
        # 串口关闭
        bp_ser.close()
        def bp_time():
            # 设定10s关闭
            time.sleep(10)
            self.Solt_TimeUpdate()
            # 通过Signal 的 emit 触发执行 主线程里面的处理函数
            # emit参数和定义Signal的数量、类型必须一致
            global_ms.bp_time_text_print.emit(self.ui.bp_log_msg,localTime)
            self.Slot_bp_com_clear()
            for bp_bol_fal in self.dict_['bp_bool_false']:
                bp_bol = False
            if not bp_bol:
                for bp_con in self.dict_['bp_controls']:
                    bp_run_data = ''.join(['self.ui.',bp_con,'.setEnabled(',bp_bol_fal,')'])
                    eval(bp_run_data)
            self.ui.bp_com.setEnabled(True)
            self.ui.bp_start_btn.setEnabled(True)
            self.ui.bp_stop_btn.setEnabled(False)
            self.ui.bp_recv_msg.setEnabled(False)
            self.ui.bp_recv_msg.setChecked(False)
        bp_thread = Thread(target=bp_time)
        bp_thread.start()

以上的步骤我只能Rs485部分代码作讲解,详细的可以到网盘中下载,链接在下方

最终效果图

Rs485

 Rs232

需要全部的代码,可以点击下面连接下载直接拿来用,我已经打包成exe,直接运行就可以了 

链接:https://pan.baidu.com/s/1IcAIwAHTTVEyNpEXAG0SBQ 
提取码:linv

如果觉得这篇文章对你有帮助就点个赞吧!哈哈哈,项目有问题可以私聊。 

 

 

 

 

  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值