原理
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
如果觉得这篇文章对你有帮助就点个赞吧!哈哈哈,项目有问题可以私聊。