gitee仓库地址:https://gitee.com/lalhan/PC_BLE_UART
一、需求提出

模块功能:
- 通过PC电脑的蓝牙实现串口透传
- 制作电脑端上位机(APP端很常见)
- 波特率可调
- 对外提供RXD/TXD/GND/5V/3.3V
应用场景:
- PC端无可用USB口调试远程设备
- 任何无线串口透传使用场景
- 私人预留(MAC绑定)串口设备调试接口
- 需要对板子供电(5V/3.3V)测试场景
二、市场调研
(1)现有市场

(2)勉强使用的
1、WCH公司BleUart

2、硬件提供的PC端

特点:
- 不直观不直接
- 过于通用,且串口界面复杂难操作
- 没有调整波特率选项
三、方案设计
(1)硬件选择
选用低成本BLE蓝牙方案

淘宝:https://eciot.taobao.com/?spm=2013.1.0.0.18972c6abNXolr
注意:需要购买带OC版本,即可二次编程版本,这个需要提前问下客服
特点:
- 成本低(甚至1.8元)
- 体积小
- 外围简单
- 可二次开发
(2)电脑端上位机(PYQT5)

优点:
缺点:
(3)电源部分
参考我上个视频,电动螺丝刀

- 自带锂电池充放电功能
- 可对外提供5V
- 使用AMS1117-33后可对外提供3.3V
- 体积小外围少使用简单
四、制作流程
(1)设备侧程序编写
这里选择提供HEX文件、程序主文件(main)以及资料的下载文档

- MDK5的开发环境
- APP可烧录(参考我之前的十元蓝牙遥控车的视频)
资料地址:
百度网盘:https://pan.baidu.com/s/1_y1TtyzgXGL5tlVsYmggig 提取码:8888
360云盘:https://yunpan.360.cn/surl_yWr6A5bSpV9 (提取码:5689)
(2)PC端程序编写

- 提供源代码
- 使用PyCharm编程
- 使用PYQT5库实现
五、整体演示
因为硬件部分很简单,我这里就不实际使用IP5306供电了,主要测试串口透传和波特率修改功能

节选部分程序:
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(510, 430)
MainWindow.setFixedSize(510, 430)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(10, 10, 111, 31))
self.label.setAlignment(QtCore.Qt.AlignCenter)
self.label.setObjectName("label")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(175, 10, 50, 31))
self.pushButton.setObjectName("pushButton")
self.pushButton_5 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_5.setGeometry(QtCore.QRect(230, 10, 50, 31))
self.pushButton_5.setObjectName("pushButton_5")
self.label_2 = QtWidgets.QLabel(self.centralwidget)
self.label_2.setGeometry(QtCore.QRect(100, 10, 60, 30))
self.label_2.setAlignment(QtCore.Qt.AlignCenter)
self.label_2.setObjectName("label_2")
self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_2.setGeometry(QtCore.QRect(400, 10, 101, 31))
self.pushButton_2.setObjectName("pushButton_2")
self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_3.setGeometry(QtCore.QRect(370, 370, 101, 31))
self.pushButton_3.setObjectName("pushButton_3")
self.pushButton_4 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_4.setGeometry(QtCore.QRect(370, 50, 101, 31))
self.pushButton_4.setObjectName("pushButton_4")
self.checkBox = QtWidgets.QCheckBox(self.centralwidget)
self.checkBox.setGeometry(QtCore.QRect(370, 90, 91, 31))
self.checkBox.setObjectName("checkBox")
self.checkBox_2 = QtWidgets.QCheckBox(self.centralwidget)
self.checkBox_2.setGeometry(QtCore.QRect(370, 330, 91, 31))
self.checkBox_2.setObjectName("checkBox_2")
self.checkBox_3 = QtWidgets.QCheckBox(self.centralwidget)
self.checkBox_3.setGeometry(QtCore.QRect(370, 300, 91, 31))
self.checkBox_3.setObjectName("checkBox_3")
self.label_3 = QtWidgets.QLabel(self.centralwidget)
self.label_3.setGeometry(QtCore.QRect(390, 150, 101, 101))
self.label_3.setText("")
self.label_3.setTextFormat(QtCore.Qt.AutoText)
self.label_3.setScaledContents(True)
self.label_3.setObjectName("label_3")
self.label_4 = QtWidgets.QLabel(self.centralwidget)
self.label_4.setGeometry(QtCore.QRect(400, 260, 71, 31))
self.label_4.setAlignment(QtCore.Qt.AlignCenter)
self.label_4.setObjectName("label_4")
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(290, 12, 100, 25))
self.textEdit.setObjectName("textEdit")
self.textEdit.setAlignment((QtCore.Qt.AlignLeft))
self.textEdit_2 = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit_2.setGeometry(QtCore.QRect(20, 230, 341, 171))
self.textEdit_2.setObjectName("textEdit_2")
self.textEdit_3 = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit_3.setGeometry(QtCore.QRect(20, 50, 341, 161))
self.textEdit_3.setObjectName("textEdit_3")
self.textEdit_3.setReadOnly(True)
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "无线串口(BLE)上位机"))
self.label.setText(_translate("MainWindow", "当前设备状态:"))
self.pushButton.setText(_translate("MainWindow", "扫描"))
self.pushButton_5.setText(_translate("MainWindow", "连接"))
self.label_2.setText(_translate("MainWindow", "未连接"))
self.pushButton_2.setText(_translate("MainWindow", "更改波特率"))
self.pushButton_3.setText(_translate("MainWindow", "发送"))
self.pushButton_4.setText(_translate("MainWindow", "清屏"))
self.checkBox.setText(_translate("MainWindow", "十六进制接收"))
self.checkBox_2.setText(_translate("MainWindow", "十六进制发送"))
self.checkBox_3.setText(_translate("MainWindow", "后置换行符"))
self.label_4.setText(_translate("MainWindow", "作者信息"))
MainWindow.setWindowIcon(QIcon("./ico.ico"))
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.