您当前的位置: 首页 >  stm32

DS小龙哥

暂无认证

  • 3浏览

    0关注

    679博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

STM32+HC05串口蓝牙设计简易的蓝牙音箱

DS小龙哥 发布时间:2021-05-12 15:35:54 ,浏览量:3

一、环境介绍

MCU:  STM32F103C8T6

蓝牙模块:  HC05 (串口蓝牙)

音频解码模块:  VS1053B 

OLED显示屏:  0.96寸SPI接口OLED

开发软件: Keil5

上位机: 使用QT设计Android端APP

二、功能介绍

Android手机打开APP,设置好参数之后,选择音乐文件发送给蓝牙音箱设备端,HC05蓝牙收到数据之后,再传递给VS1053进行播放。程序里采用环形缓冲区,接收HC05蓝牙传递的数据,设置好传递的参数之后,基本播放音乐是很流畅的。

完整项目源码下载地址:  https://download.csdn.net/download/xiaolong1126626497/18621270

三、硬件实物

VS1053可以接耳机或者接音箱设备即可听音乐。

四、设置HC05蓝牙波特率

HC05蓝牙串口默认波特率是38400,为了提高蓝牙传输速率,需要修改波特率为: 921600。

五、APP端界面

 

六、设备端:核心代码  6.1  mian.cpp

 

#include "stm32f10x.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include 
#include "sdcard.h"
#include "ff.h"
#include "vs1053b.h"	
#include "timer.h"
#include "hc05_Bluetooth.h" 

//文件系统工作区注册
FATFS FatFs;

//函数声明
u8 VS1053_PlayOneMusic(u8 *pname);
u8 VS1053_ScanDirPlayMusic(const char *path);

//存放OLED显示屏滚动显示的提示语句
u8 oled_show_buff[50];
u8 *oled_data_p; 

//蓝牙音乐的缓冲区
#define MUSIC_BUFF_LEN 1024*5	//音乐数据缓冲区大小
u32 rev_len=0;
u32 play_len=0;
u8 musicbuff[MUSIC_BUFF_LEN];
u8 flagbuff[MUSIC_BUFF_LEN];
u8 music_byte;
	

/*
                       使用STM32F103C8T6最小系统板编写的代码----买的那种
*/

//中文字库路径: 0:/font/gbk16.DZK
//本地是1
//蓝牙是2
int main(void)
{
	LED_Init();
	KEY_Init();
	USART_X_Init(USART1,72,115200);
	OLED_Init();
	OLED_Clear(0xFF);
	OLED_Refresh_GRAM();
	printf("SD卡初始化状态:%d\r\n",SDCardDeviceInit()); //初始化SD卡
	f_mount(&FatFs,"0:", 0);      //注册工作区
	VS1053_Init();       					//VS1053初始化
	printf("正常工作.\r\n");
    
	if(KEY_UP==0) //按键已经按下 		//播放蓝牙音乐数据
	{
		u32 hc05_rx_state=1;
		VS1053_Reset();      								//硬复位MP3
		VS1053_SoftReset(); 								//软复位VS10XX
		VS1053_SetVol(250);								  //设置音量  最大值
		VS1053_PlayOneMusic((u8*)"0:/2.mp3"); //蓝牙语音提示
		
		strncpy((char*)oled_show_buff,"   Play HCO5 Bluetooth music         ",100);
		
		/*1. 初始化HC05串口蓝牙*/
		printf("1 蓝牙正在初始化.........\r\n");
		USART2_RX_FLAG=0;
		while(HC05_Bluetooth_Init()){}
		
//		/*设置当前蓝牙为从机模式*/
		HC05_Bluetooth_SetCmd("AT+ROLE=0\r\n"); //设置为从机模式
		if(HC05_Bluetooth_GetRoleStatus()==0)printf("当前蓝牙处于从机状态!\r\n");
		else if(HC05_Bluetooth_GetRoleStatus()==1)printf("当前蓝牙处于主机状态!\r\n");
		HC05_Bluetooth_SetCmd("AT+RESET\r\n");	//复位ATK-HC05模块
		DelayMs(1000);			//等待蓝牙模块稳定
			
		/*2. 查询蓝牙主从状态*/
		if(HC05_Bluetooth_GetRoleStatus()==0)printf("2 当前蓝牙处于从机状态!\r\n");
		else if(HC05_Bluetooth_GetRoleStatus()==1)printf("2 当前蓝牙处于主机状态!\r\n");
		else printf("2 当前蓝牙主从状态查询失败!\r\n");
	
		/*3. 查看蓝牙连接状态*/
		if(HC05_LED)printf("3 当前蓝牙连接成功!\r\n");
		else printf("3 当前蓝牙未连接!\r\n");
		
		/*4. 设置蓝牙的名称*/
		if(HC05_Bluetooth_SetCmd("AT+NAME=wbyq666_HC-05\r\n"))printf("4 蓝牙名称设置失败!\r\n");
		else printf("4 蓝牙名称设置为 wbyq666_HC-05 \r\n");
		
		/*5. 设置蓝牙配对密码*/
		if(HC05_Bluetooth_SetCmd("AT+PSWD=1234\r\n"))printf("5 蓝牙配对密码设置失败!\r\n"); //密码必须是4位
		else printf("5 蓝牙配对密码设置为 1234 \r\n");
		
		
		//if(HC05_Bluetooth_SetCmd("AT+UART=921600,0,0\r\n"))printf("5 蓝牙波特率设置成功!\r\n"); //密码必须是4位
		//else printf("5 蓝牙波特率设置失败!\r\n\r\n");
		
		/*6. 等待蓝牙连接*/
		printf("等待蓝牙连接.....\r\n");
		while(!HC05_LED){}
		printf("当前蓝牙连接成功! 进入到数据透传模式\r\n");
		
		//蓝牙连接成功
		USART2->CR1&=~(1lineEdit_Timer->setText(QString::number(FileSendTime));
     FileSendCnt=32;    //默认每包数据值32字节
     ui->lineEdit_SendFileCnt->setText(QString::number(FileSendCnt));


     //创建存放音乐文件的目录
     QDir dir;
     if(dir.mkpath("/sdcard/WBYQ_MP3"))
     {
          ui->plainTextEdit->insertPlainText("/WBYQ_MP3 目录创建成功!\n");
     }
     else
     {
          ui->plainTextEdit->insertPlainText("/WBYQ_MP3 目录创建失败!\n");
     }

      MusicFileDir="assets:/nansannan.mp3";  //目录的路径
      Def_MusicName="assets:/nansannan.mp3";
      file.setFileName(Def_MusicName); //设置文件名称
      ui->lineEdit_MusicName->setText(Def_MusicName); //默认文件名称
}


int count=0;
//更新
void MainWindow::update()
{
    if(SendStat)
    {
        int len;
        if(file.atEnd()==false)  //文件未结束
        {
            len=file.read(FileBuff,FileSendCnt);
            len=socket->write(FileBuff,len); //发送数据
        }
        else
        {
           file.close();
           timer->stop(); //停止定时器
           SendStat=0;
           ui->plainTextEdit->setPlainText("文件读取写入完毕!\n");
        }
    }
}

MainWindow::~MainWindow()
{
    delete ui;
    delete discoveryAgent;
    delete localDevice;
    delete socket;
    timer->stop();
    delete timer;
}

void MainWindow::on_pushButton_CloseBluetooth_clicked()
{
    /*关闭蓝牙设备*/
    localDevice->setHostMode(QBluetoothLocalDevice::HostPoweredOff);
}


void MainWindow::on_pushButton_BluetoothScan_clicked()
{
    /*3.1 检查蓝牙是否开启*/
    if(localDevice->hostMode() == QBluetoothLocalDevice::HostPoweredOff)
    {
        /*请求打开蓝牙设备*/
        localDevice->powerOn();
    }

     /*开始扫描周围的蓝牙设备*/
    discoveryAgent->start();
    ui->comboBox_BluetoothDevice->clear(); //清除条目
}

void MainWindow::on_pushButton_DeviceVisible_clicked()
{
    /*设置蓝牙可见,可以被周围的设备搜索到,在Android上,此模式最多只能运行5分钟。*/
    //  localDevice->setHostMode( QBluetoothLocalDevice::HostDiscoverable);
    static bool cnt=1;
    cnt=!cnt;
    if(cnt)
    {
        MusicFileDir="assets:/nansannan.mp3";  //目录的路径
        QMessageBox::information(this,"提示","路径切换为内部路径!\n请选择文件!",QMessageBox::Ok,QMessageBox::Ok);
    }
    else
    {
        MusicFileDir="/mnt/sdcard";  //目录的路径
        QMessageBox::information(this,"提示","路径切换为SD路径!\n请选择文件!",QMessageBox::Ok,QMessageBox::Ok);
    }
}


void MainWindow::on_pushButton_StopScan_clicked()
{
    /*停止扫描周围的蓝牙设备*/
    discoveryAgent->stop();
}


/*当扫描到周围的设备时会调用当前的槽函数*/
void MainWindow::addBlueToothDevicesToList(const QBluetoothDeviceInfo &info)
{
   // QString label = QString("%1 %2").arg(info.name()).arg(info.address().toString());
    QString label = QString("%1 %2").arg(info.address().toString()).arg(info.name());
    ui->comboBox_BluetoothDevice->addItem(label); //添加字符串到comboBox上
}


//有数据可读
void MainWindow::readBluetoothDataEvent()
{
    QByteArray all = socket->readAll();
    ui->plainTextEdit->insertPlainText(all);
}


//建立连接
void MainWindow::bluetoothConnectedEvent()
{
    QMessageBox::information(this,tr("连接提示"),"蓝牙连接成功!");
    ConnectStat=1;
    /*停止扫描周围的蓝牙设备*/
    discoveryAgent->stop();
}


//断开连接
void MainWindow::bluetoothDisconnectedEvent()
{
    ConnectStat=0;
    QMessageBox::information(this,tr("连接提示"),"蓝牙断开连接!");
}


/*
在说蓝牙设备连接之前,不得不提一个非常重要的概念,就是蓝牙的Uuid,引用一下百度的:
在蓝牙中,每个服务和服务属性都唯一地由"全球唯一标识符" (UUID)来校验。
正如它的名字所暗示的,每一个这样的标识符都要在时空上保证唯一。
UUID类可表现为短整形(16或32位)和长整形(128位)UUID。
他提供了分别利用String和16位或32位数值来创建类的构造函数,提供了一个可以比较两个UUID(如果两个都是128位)的方法,还有一个可以转换一个UUID为一个字符串的方法。
UUID实例是不可改变的(immutable),只有被UUID标示的服务可以被发现。
在Linux下你用一个命令uuidgen -t可以生成一个UUID值;
在Windows下则执行命令uuidgen 。UUID看起来就像如下的这个形式:2d266186-01fb-47c2-8d9f-10b8ec891363。当使用生成的UUID去创建一个UUID对象,你可以去掉连字符。
*/

//发送音乐文件
void MainWindow::on_pushButton_SendData_clicked()
{
    if(ConnectStat)
    {
        if(file.open(QIODevice::ReadOnly))
        {
            SendStat=1;
            count=0;
            ui->plainTextEdit->insertPlainText("系统提示: 开始发送文件!\n");
            ui->lineEdit_fileSizef->setText(QString::number(file.size()));
            ui->lineEdit_fileCount->setText("");
            ui->progressBar_SendCount->setMaximum(file.size()); //设置进度条显示最大值
            ui->progressBar_SendCount->setValue(0); //设置进度条的值
            timer->start(FileSendTime); //启动定时器
        }
    }
}


//连接蓝牙
void MainWindow::on_pushButton_ConnectDev_clicked()
{
    QString text = ui->comboBox_BluetoothDevice->currentText();
    int index = text.indexOf(' ');
    if(index == -1) return;

    QBluetoothAddress address(text.left(index));

    QString connect_device="开始连接蓝牙设备:\n";
    connect_device+=ui->comboBox_BluetoothDevice->currentText();
    QMessageBox::information(this,tr("连接提示"),connect_device);

    //开始连接蓝牙设备
    socket->connectToService(address, QBluetoothUuid(serviceUuid) ,QIODevice::ReadWrite);
}

//帮助提示
void MainWindow::on_pushButton_help_clicked()
{
    QMessageBox::information(this,tr("帮助提示"),"本软件用于HC-05/06系列串口蓝牙连接!\n"
                                             "暂时不支持BLE4.0版本蓝牙!\n"
                                             "用于发送音乐文件数据,每次发送32字节,默认100ms发送间隔时间\n"
                                             "软件作者:DS小龙哥\n"
                                             "BUG反馈:1126626497@qq.com");
}


//选择音乐文件
void MainWindow::on_pushButton_select_clicked()
{
    QString filename=QFileDialog::getOpenFileName(this,"选择发送的音乐文件",MusicFileDir,tr("*.mp3 *.MP3 *.WAV"));
    //filename==选择文件的绝对路径
    file.setFileName(filename);
    ui->lineEdit_MusicName->setText(filename);
    Def_MusicName=filename; //保存文件名称
}


//清除
void MainWindow::on_pushButton_clear_clicked()
{
     ui->plainTextEdit->setPlainText("");
}


void MainWindow::on_pushButton_StopSend_clicked()
{
       timer->stop(); //停止定时器
}


//设置发送间隔时间
void MainWindow::on_pushButton_SendTime_clicked()
{
    QString str=ui->lineEdit_Timer->text();
    int time=str.toInt();
    FileSendTime=time; //保存时间
    if(timeplainTextEdit->insertPlainText(tr("设置发送间隔时间为%1ms\n").arg(time));
}


//修改每包发送的数量
void MainWindow::on_pushButton_SendFileCnt_clicked()
{
    QString str=ui->lineEdit_SendFileCnt->text();
    int cnt=str.toInt();
    if(cnt>4096 || cntplainTextEdit->insertPlainText(tr("发送数量设置为%1字节.\n").arg(cnt));
    }
}


//写成功的数量
void MainWindow::bluetoothbytesWritten(qint64 byte)
{
   count+=byte;
   ui->lineEdit_fileCount->setText(QString::number(count));
   ui->progressBar_SendCount->setValue(count); //设置进度条的值
}
7.3  mianwindows.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 
#include 
#include 
#include 
#include "QListWidgetItem"
#include 
#include "QFile"
#include "QFileDialog"
#include "QTimer"
#include "QInputDialog"
#include 
#include 
namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    QFile file;
    QTimer *timer;
    bool ConnectStat;
    bool SendStat;
    QBluetoothDeviceDiscoveryAgent *discoveryAgent;  //这个是指扫描周围蓝牙设备!
    QBluetoothLocalDevice *localDevice;//是指配置获取设备的蓝牙状态信息等!
    QBluetoothSocket *socket; //指进行链接蓝牙设备,读写信息!
    int FileSendTime; //文件发送时间
    char FileBuff[4096]; //每包最大的字节数
    int FileSendCnt;     //每次发送的字节数
    QString Def_MusicName;
    QString MusicFileDir;
private slots:
    void on_pushButton_CloseBluetooth_clicked();

    void on_pushButton_BluetoothScan_clicked();

    void addBlueToothDevicesToList(const QBluetoothDeviceInfo&);  //发现蓝牙设备的槽函数

    void on_pushButton_DeviceVisible_clicked();

    void on_pushButton_StopScan_clicked();

    void readBluetoothDataEvent();

    void bluetoothConnectedEvent();

    void bluetoothDisconnectedEvent();
    void on_pushButton_SendData_clicked();

    void SetStyle(const QString &qssFile); //样式表设置函数
    void on_pushButton_ConnectDev_clicked();

    void on_pushButton_help_clicked();

    void on_pushButton_select_clicked();

    void on_pushButton_clear_clicked();

    void on_pushButton_StopSend_clicked();

    void on_pushButton_SendTime_clicked();

    void on_pushButton_SendFileCnt_clicked();

    void bluetoothbytesWritten(qint64 byte);
public slots:
    void update();
private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

 

 

关注
打赏
1664009229
查看更多评论
立即登录/注册

微信扫码登录

0.0387s