Qt实现安卓手机蓝牙通信并控制stm32f103c8t6驱动VFD屏

2023-10-28 06:20

本文主要是介绍Qt实现安卓手机蓝牙通信并控制stm32f103c8t6驱动VFD屏,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、Qt建立蓝牙通信

Qt具有跨平台的特性所以非常适合写通信的demo,但是在这个例程中Qt蓝牙部分不支持Windows平台,安卓平台使用没问题。
Qt蓝牙主要涉及到三个类的使用:
QBluetoothDeviceDiscoveryAgent //扫描周围蓝牙设备
QBluetoothLocalDevice //扫描本地蓝牙
QBluetoothSocket //建立蓝牙的socket读写

安卓不支持低功耗蓝牙,但是socket既可以使用经典蓝牙也可以使用低功耗蓝牙,本例程使用经典蓝牙socket收发数据

1、在.pro工程文件添加

Qt                   +=bluetooth

2、主要代码Widget.h和Widget.c

#ifndef WIDGET_H
#define WIDGET_H
#pragma execution_character_set("utf-8")   //解决中文乱码#include <QWidget>
#include <QObject>
#include <QtBluetooth/qbluetoothlocaldevice.h>
#include <qbluetoothaddress.h>
#include <qbluetoothdevicediscoveryagent.h>
#include <qbluetoothlocaldevice.h>
#include <qbluetoothsocket.h>
#include <QMap>
#include <QTimer>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();void model2_Init();
public slots:void addBlueToothDevicesToList(const QBluetoothDeviceInfo&);void readBluetoothDataEvent();void bluetoothConnectedEvent();void bluetoothDisconnectedEvent();void onError(QBluetoothSocket::SocketError error);void open_BLE();void close_BLE();void scanFinished();
private:QBluetoothDeviceDiscoveryAgent *discoveryAgent;QBluetoothLocalDevice *localDevice;QBluetoothSocket *socket;QByteArray blueArray;QMap<QString,QBluetoothAddress>m;QBluetoothDeviceInfo remoteDeviceInfo;float ff;//随机数缓存float div;//每次下降数float sx;//上限float t;//时间QString ss;//字符判断是模式1还是模式2QTimer *time;private slots:void on_pushButton_clicked();void on_pushButton_2_clicked();void on_pushButton_4_clicked();void on_pushButton_5_clicked();void on_pushButton_3_clicked();void on_pushButton_7_clicked();void on_pushButton_8_clicked();void on_pushButton_9_clicked();void on_pushButton_6_clicked();void timeProcess();void on_pushButton_10_clicked();void on_label_7_linkActivated(const QString &link);private:Ui::Widget *ui;
};
#endif // WIDGET_H
## Widget.c
#include "widget.h"
#include "ui_widget.h"
#include <QRandomGenerator>
#include <QLowEnergyController>//这个UUID要根据自己的使用情况来确定,我使用的是串口类的UUID,具体可https://www.jianshu.com/p/eb85cb690e86
static const QLatin1String serviceUuid("00001101-0000-1000-8000-00805F9B34FB");
//static const QLatin1String serviceUuid("FDA50693A4E24FB1AFCFC6EB07647825");
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);ui->plainTextEdit->setDisabled(1);discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);localDevice = new QBluetoothLocalDevice(this);socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);time = new QTimer(this);connect(time,SIGNAL(timeout()),this,SLOT(timeProcess()));discoveryAgent->start();ui->pushButton_4->setDisabled(1);connect(discoveryAgent, SIGNAL(finished()), this, SLOT(scanFinished()));//搜索结束connect(discoveryAgent,SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),this,SLOT(addBlueToothDevicesToList(QBluetoothDeviceInfo)));connect(socket,SIGNAL(readyRead()),this,SLOT(readBluetoothDataEvent()));connect(socket,SIGNAL(connected()),this,SLOT(bluetoothConnectedEvent()));connect(socket,SIGNAL(disconnected()),this,SLOT(bluetoothDisconnectedEvent()));connect(socket,SIGNAL(error(QBluetoothSocket::SocketError)),this,SLOT(onError(QBluetoothSocket::SocketError)));}Widget::~Widget()
{delete ui;delete discoveryAgent;delete localDevice;delete socket;delete time;
}void Widget::onError(QBluetoothSocket::SocketError error)
{QString str;if(QBluetoothSocket::UnknownSocketError == error){str = "UnknownSocketError";}else if(QBluetoothSocket::NoSocketError == error){str = "NoSocketError";}else if(QBluetoothSocket::HostNotFoundError == error){str = "HostNotFoundError";}else if(QBluetoothSocket::ServiceNotFoundError == error){str = "ServiceNotFoundError";}else if(QBluetoothSocket::NetworkError == error){str = "NetworkError";}else if(QBluetoothSocket::UnsupportedProtocolError == error){str = "UnsupportedProtocolError";}else if(QBluetoothSocket::OperationError == error){str = "OperationError";}else if(QBluetoothSocket::RemoteHostClosedError == error){str = "RemoteHostClosedError";}qDebug()<<error;//emit backendRunMesgPost(str);//emit backendRunMesgPost("SocketError");
}void Widget::addBlueToothDevicesToList( const QBluetoothDeviceInfo &info )
{remoteDeviceInfo = info;qDebug()<<"进入addBlueToothDevicesToList函数!";QString label = QString("%1 %2").arg(info.address().toString()).arg(info.name());qDebug()<<label;ui->comboBox->addItem(info.name());if(label.contains("BT04-A")){//找到需要连接的蓝牙名字int index = label.indexOf(' ');if(index == -1){qDebug()<<"index";return;}QBluetoothAddress address(label.left(index));m[info.name()] = address;//关联蓝牙名字和addressQString name(label.mid(index + 1));qDebug() << "You has choice the bluetooth address is " << address<<name<<endl;//qDebug() << "The device is connneting.... ";//ui->plainTextEdit_2->setPlainText("You has choice the bluetooth address is "+name);//ui->plainTextEdit_2->setPlainText("The device is connneting.... ");//emit backendRunMesgPost("The device is connneting");//socket->connectToService(address, QBluetoothUuid(serviceUuid) ,QIODevice::ReadWrite);}
}void Widget::readBluetoothDataEvent()
{static int cnt = 0;QByteArray line = socket->readAll();if(line.startsWith("y") || line.startsWith("r"))ss = line;if(ss.startsWith("y")){//ss = "d";if(!line.startsWith('y')){blueArray.append(line);}if(cnt < 4){ui->plainTextEdit->appendPlainText(QString(blueArray));cnt++;}else{cnt = 0;ui->plainTextEdit->clear();}//ui->plainTextEdit->setPlainText(QString(blueArray));ui->plainTextEdit_2->setPlainText("模式1");emit ui->pushButton_3->clicked(1);}else if(ss.startsWith("r")){ss = "d";ui->plainTextEdit_2->setPlainText("模式2");model2_Init();emit ui->pushButton_10->clicked(1);emit ui->pushButton_7->clicked(1);ss = "d";}else if(line.startsWith("Flash")){ui->plainTextEdit_2->setPlainText(QString(line));ss = "d";}
}void Widget::bluetoothConnectedEvent()
{qDebug() << "The android device has been connected successfully!";ui->plainTextEdit_2->setPlainText("The android device has been connected successfully!");
}void Widget::bluetoothDisconnectedEvent()
{qDebug() << "The android device has been disconnected successfully!";
}void Widget::open_BLE()
{if( localDevice->hostMode() == QBluetoothLocalDevice::HostPoweredOff)//开机没有打开蓝牙{localDevice->powerOn();//调用打开本地的蓝牙设备discoveryAgent->start();//开始扫描蓝牙connect(discoveryAgent,SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),this,SLOT(addBlueToothDevicesToList(QBluetoothDeviceInfo)));ui->plainTextEdit_2->setPlainText("手机蓝牙已成功打开!");}else{qDebug() << "手机蓝牙已成功打开!";ui->plainTextEdit_2->setPlainText("手机蓝牙已成功打开!");}
}void Widget::close_BLE()
{socket->close();ui->plainTextEdit_2->setPlainText("蓝牙已断开!");
}void Widget::on_pushButton_clicked()//模式一
{//ui->plainTextEdit->clear();ui->pushButton_2->setDisabled(1);ui->pushButton_7->setDisabled(1);socket->write("y");
}void Widget::on_pushButton_2_clicked()//模式二
{model2_Init();ui->pushButton->setDisabled(1);ui->pushButton_3->setDisabled(1);if(socket->state() == QAbstractSocket::ConnectedState){socket->write("r");}
}void Widget::on_pushButton_4_clicked()//连接蓝牙
{discoveryAgent->stop();if(ui->comboBox->currentText().startsWith("BT04-A")){//低功耗蓝牙连接方式/*QLowEnergyController *lowBtControl = QLowEnergyController::createCentral(remoteDeviceInfo);lowBtControl->connectToDevice();*///经典蓝牙连接方式qDebug() << "连接到的蓝牙是" << m[ui->comboBox->currentText()]<<ui->comboBox->currentText();socket->connectToService(m[ui->comboBox->currentText()],QBluetoothUuid(serviceUuid) ,QIODevice::ReadWrite);ui->plainTextEdit_2->setPlainText("The device is connneting.... ");if(socket->state() == QAbstractSocket::ConnectedState)ui->plainTextEdit_2->setPlainText("蓝牙连接成功!");}else{ui->plainTextEdit_2->setPlainText("没有找到目标蓝牙!");}
}void Widget::on_pushButton_5_clicked()//断开连接
{close_BLE();
}void Widget::on_pushButton_3_clicked()//模式一修改数字
{if(socket->write("v")){QString str;str = ui->lineEdit_6->text();str.append('z');socket->write(str.toUtf8());ui->plainTextEdit_2->setPlainText("成功发送一条数据!v");}
}void Widget::on_pushButton_7_clicked()
{if(socket->write("s"))//发送随机数{QString str = QString("%1").arg(sx);if(str.length() > 4)str = str.left(4);str.append('x');socket->write(str.toUtf8());}
}void Widget::on_pushButton_8_clicked()//切换模式
{ui->pushButton->setEnabled(1);ui->pushButton_2->setEnabled(1);ui->pushButton_7->setEnabled(1);ui->pushButton_3->setEnabled(1);ui->plainTextEdit->setEnabled(1);ui->plainTextEdit->clear();ui->plainTextEdit->setDisabled(1);time->stop();
}void Widget::on_pushButton_9_clicked()
{open_BLE();
}void Widget::on_pushButton_6_clicked()
{this->close();
}void Widget::scanFinished()
{ui->pushButton_4->setEnabled(1);
}void Widget::timeProcess()
{sx = sx - div;QString str;str = QString("%1").arg(sx);qDebug()<<"sx is " + str<<endl;if(sx <= ff){sx = ff;time->stop();}ui->plainTextEdit_2->setPlainText("成功发送一条数据!s"+str);str = QString("%1").arg(div);qDebug()<<"div is " + str<<endl;emit ui->pushButton_7->clicked(1);
}void Widget::model2_Init()
{sx = ui->lineEdit_3->text().toUInt();t = ui->lineEdit_4->text().toUInt();div = (sx - ff)/(t*10);
}void Widget::on_pushButton_10_clicked()
{if(ui->lineEdit->text().isEmpty() == false && ui->lineEdit_2->text().isEmpty() == false ){std::uniform_real_distribution<float> dist(ui->lineEdit->text().toUInt(), ui->lineEdit_2->text().toUInt());ff = dist(*QRandomGenerator::global());ui->lineEdit_5->setText(QString::number(ff));QString str = ui->lineEdit_5->text();if(str.length() > 4)str = str.left(4);ff = str.toFloat();ui->lineEdit_5->setText(QString::number(ff));if(ui->lineEdit_3->text().isEmpty() == false && ui->lineEdit_4->text().isEmpty() == false){time->start(6000);}}}

在这里插入图片描述

二、通过蓝牙模块控制stm32f103c8t6驱动VFD

蓝牙模块选择BT08B蓝牙串口模块兼容HC-06,只需连接四个引脚 VCC 、GND、TX、RX即可

下面为VFD模块驱动程序,采用带驱动芯片的模块,直流5V供电即可,stm32可直接驱动模块引出引脚

1、VFD_Drive.h

#ifndef _VFD_DRIVE_H
#define _VFD_DRIVE_H#include "stm32f10x.h"void VFD_GPIOInit(void);//GPIO初始化void WriteCMD(u8 cmd);//写命令
void WriteDATA(u8 data);//写数据void Clear(void);//清屏
void Cursor_home(void);//光标归位
/*
该指令选择在每次DDRAM或CGRAM访问后AC(游标位置)是递增还是递减,并确定在每次DDRAM写入后显示信息的移动方向。
该指令还在每次DDRAM写入后启用或禁用显示移位。
*/
void IncCursor(void);//光标递增(向右)
void DecCursor(void);//光标递减(向左)void DisplayOFForON(u8 i,u8 j,u8 n);//光标显示还是不显示,i = 1显示i = 0不显示,并指定是否闪烁j = 1闪烁,j = 0闪烁,n=1开光标,n=0关光标
/*
该指令增加或减少AC(光标位置),并将显示信息向左或向右移动一个字符的位置
*/
void CharLeft(void);//字符和光标左移
void CharRight(void);//字符和光标右移
void CursorLeft(void);//光标左移
void CursorRight(void);//光标右移/*
设置并行口模式DL = 0为4位模式,DL = 1为8位模式
设置单行显示还是两行显示,N = 0,单行显示,N = 1两行显示
设置亮度BR = 0  100%亮度,BR = 1   75%亮度,BR = 2   50%亮度,BR = 3    25%亮度
*/
void FunSet(u8 DL,u8 N,u8 BR);//这里固定为两行显示,亮度100%,如需更改请查看手册重写函数/*该指令将DB5-DB0指定的6位CGRAM地址放入AC(光标位置)。后续的数据写入(读取)将会指向(从)CGRAM。*/
u8 CGRAM_addrSet(u8 addr);//返回传入addr后的命令/*该指令将DB6-DB0指定的7位DDRAM地址放入AC(光标位置)。后续的数据写入(读取)将从DDRAM写入(从DDRAM读取)。*/
u8 DDRAM_addrSet(u8 addr);//返回传入addr后的命令/*该指令将DB7-DB0上的8位数据字节写入AC寻址的DDRAM或CGRAM位置。
最近的DDRAM或CGRAM地址集指令决定是写入DDRAM还是CGRAM。
该指令还根据输入模式设置(Entry 

这篇关于Qt实现安卓手机蓝牙通信并控制stm32f103c8t6驱动VFD屏的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/291287

相关文章

AJAX请求上传下载进度监控实现方式

《AJAX请求上传下载进度监控实现方式》在日常Web开发中,AJAX(AsynchronousJavaScriptandXML)被广泛用于异步请求数据,而无需刷新整个页面,:本文主要介绍AJAX请... 目录1. 前言2. 基于XMLHttpRequest的进度监控2.1 基础版文件上传监控2.2 增强版多

Redis分片集群的实现

《Redis分片集群的实现》Redis分片集群是一种将Redis数据库分散到多个节点上的方式,以提供更高的性能和可伸缩性,本文主要介绍了Redis分片集群的实现,具有一定的参考价值,感兴趣的可以了解一... 目录1. Redis Cluster的核心概念哈希槽(Hash Slots)主从复制与故障转移2.

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

使用Python实现一键隐藏屏幕并锁定输入

《使用Python实现一键隐藏屏幕并锁定输入》本文主要介绍了使用Python编写一个一键隐藏屏幕并锁定输入的黑科技程序,能够在指定热键触发后立即遮挡屏幕,并禁止一切键盘鼠标输入,这样就再也不用担心自己... 目录1. 概述2. 功能亮点3.代码实现4.使用方法5. 展示效果6. 代码优化与拓展7. 总结1.

Mybatis 传参与排序模糊查询功能实现

《Mybatis传参与排序模糊查询功能实现》:本文主要介绍Mybatis传参与排序模糊查询功能实现,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、#{ }和${ }传参的区别二、排序三、like查询四、数据库连接池五、mysql 开发企业规范一、#{ }和${ }传参的

Docker镜像修改hosts及dockerfile修改hosts文件的实现方式

《Docker镜像修改hosts及dockerfile修改hosts文件的实现方式》:本文主要介绍Docker镜像修改hosts及dockerfile修改hosts文件的实现方式,具有很好的参考价... 目录docker镜像修改hosts及dockerfile修改hosts文件准备 dockerfile 文

基于SpringBoot+Mybatis实现Mysql分表

《基于SpringBoot+Mybatis实现Mysql分表》这篇文章主要为大家详细介绍了基于SpringBoot+Mybatis实现Mysql分表的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录基本思路定义注解创建ThreadLocal创建拦截器业务处理基本思路1.根据创建时间字段按年进

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整