当前位置:网站首页>Stm32+hc05 serial port Bluetooth design simple Bluetooth speaker
Stm32+hc05 serial port Bluetooth design simple Bluetooth speaker
2022-07-06 18:34:00 【Hua Weiyun】
One 、 Introduction to the environment
MCU: STM32F103C8T6
Bluetooth module : HC05 ( Serial Bluetooth )
Audio decoding module : VS1053B
OLED display : 0.96 " SPI Interface OLED
Development software : Keil5
Upper computer : Use QT Design Android End APP
Two 、 Function is introduced
Android Mobile phone open APP, After setting the parameters , Select the music file and send it to the Bluetooth speaker device ,HC05 After Bluetooth receives the data , And pass it on to VS1053 Play it . Ring buffer is used in the program , receive HC05 Data transmitted by Bluetooth , After setting the passed parameters , Basically playing music is very smooth .
3、 ... and 、 Hardware object
VS1053 You can connect headphones or speakers to listen to music .
Four 、 Set up HC05 Bluetooth baud rate
HC05 The default baud rate of Bluetooth serial port is 38400, In order to improve the transmission rate of Bluetooth , The baud rate needs to be modified to : 921600.
5、 ... and 、APP End interface
6、 ... and 、 Device end : Core code
6.1 vs1053.c
#include "vs1053b.h" /* The functionality : Porting interfaces --SPI Sequential reading and writing a byte function parameter :data: The data to be written is returned return value : Data read */u8 VS1053_SPI_ReadWriteByte(u8 tx_data){ u8 rx_data=0; u8 i; for(i=0;i<8;i++) { VS1053_SCLK=0; if(tx_data&0x80){VS1053_OUTPUT=1;} else {VS1053_OUTPUT=0;} tx_data<<=1; VS1053_SCLK=1; rx_data<<=1; if(VS1053_INPUT)rx_data|=0x01; } return rx_data; }/* The functionality : initialization VS1053 Of IO mouth */void VS1053_Init(void){ RCC->APB2ENR|=1<<0; AFIO->MAPR&=~(0x7<<24); // Release PA13/14/15 AFIO->MAPR|=0x4<<24; RCC->APB2ENR|=1<<2; RCC->APB2ENR|=1<<3; GPIOA->CRH&=0x00000FFF; GPIOA->CRH|=0x33338000; GPIOB->CRL&=0xFFF00FFF; GPIOB->CRL|=0x00083000; VS1053_SCLK=1; VS1053_XCS=1;} /* The functionality : Soft reset VS10XX*/void VS1053_SoftReset(void){ u8 retry=0; while(VS1053_DREQ==0); // Wait for the software reset to end VS1053_SPI_ReadWriteByte(0Xff); // Start transmission retry=0; while(VS1053_ReadReg(SPI_MODE)!=0x0800) // Software reset , A new model { VS1053_WriteCmd(SPI_MODE,0x0804); // Software reset , A new model DelayMs(2);// Wait for at least 1.35ms if(retry++>100)break; } while(VS1053_DREQ==0);// Wait for the software reset to end retry=0; while(VS1053_ReadReg(SPI_CLOCKF)!=0X9800)// Set up VS10XX The clock of ,3 frequency doubling ,1.5xADD { VS1053_WriteCmd(SPI_CLOCKF,0X9800); // Set up VS10XX The clock of ,3 frequency doubling ,1.5xADD if(retry++>100)break; } DelayMs(20);} /* function work can : Hard reset MP3 Function return value :1: Reset failed ;0: Reset successfully */u8 VS1053_Reset(void){ u8 retry=0; VS1053_RESET=0; DelayMs(20); VS1053_XDCS=1;// Cancel data transfer VS1053_XCS=1; // Cancel data transfer VS1053_RESET=1; while(VS1053_DREQ==0&&retry<200)// wait for DREQ For the high { retry++; DelayUs(50); }; DelayMs(20); if(retry>=200)return 1; else return 0; }/* The functionality : towards VS10XX Write command function parameters : address: Order address data : Command data */void VS1053_WriteCmd(u8 address,u16 data){ while(VS1053_DREQ==0); // Waiting for leisure VS1053_XDCS=1; VS1053_XCS=0; VS1053_SPI_ReadWriteByte(VS_WRITE_COMMAND);// send out VS10XX Write the command of VS1053_SPI_ReadWriteByte(address); // Address VS1053_SPI_ReadWriteByte(data>>8); // Send the upper eight digits VS1053_SPI_ReadWriteByte(data); // Number eight VS1053_XCS=1; } /* Function parameter : towards VS1053 Write data function parameters :data: The data to be written */void VS1053_WriteData(u8 data){ VS1053_XDCS=0; VS1053_SPI_ReadWriteByte(data); VS1053_XDCS=1; }/* The functionality : read VS1053 The register of Function parameter :address: Register address return value : The value read */u16 VS1053_ReadReg(u8 address){ u16 temp=0; while(VS1053_DREQ==0);// Non waiting idle state VS1053_XDCS=1; VS1053_XCS=0; VS1053_SPI_ReadWriteByte(VS_READ_COMMAND);// send out VS10XX Read command for VS1053_SPI_ReadWriteByte(address); // Address temp=VS1053_SPI_ReadWriteByte(0xff); // Read high byte temp=temp<<8; temp+=VS1053_SPI_ReadWriteByte(0xff); // Read low byte VS1053_XCS=1; return temp; } /* The functionality : Read VS1053 Of RAM Function parameter :addr:RAM Address return return value : The value read */u16 VS1053_ReadRAM(u16 addr) { u16 res; VS1053_WriteCmd(SPI_WRAMADDR, addr); res=VS1053_ReadReg(SPI_WRAM); return res;} /* The functionality : Write VS1053 Of RAM Function parameter : addr:RAM Address val: Value to write */void VS1053_WriteRAM(u16 addr,u16 val) { VS1053_WriteCmd(SPI_WRAMADDR,addr); // Write RAM Address while(VS1053_DREQ==0); // Waiting for leisure VS1053_WriteCmd(SPI_WRAM,val); // Write RAM value } /* Function parameter : Send audio data once , Fixed for 32 Byte return return value :0, Send successfully 1, The data was not sent successfully */ u8 VS1053_SendMusicData(u8* buf){ u8 n; if(VS1053_DREQ!=0) // Send data to VS10XX { VS1053_XDCS=0; for(n=0;n<32;n++) { VS1053_SPI_ReadWriteByte(buf[n]); } VS1053_XDCS=1; }else return 1; return 0;// Successfully sent }/* Function parameter : Send audio data once , Fixed for 32 Byte return return value :0, Send successfully 1, The data was not sent successfully */ void VS1053_SendMusicByte(u8 data){ u8 n; while(VS1053_DREQ==0){} VS1053_XDCS=0; VS1053_SPI_ReadWriteByte(data); VS1053_XDCS=1; }/* The functionality : Set up VS1053 Playback volume function parameters :volx: Volume size (0~254)*/void VS1053_SetVol(u8 volx){ u16 volt=0; // Temporary volume value volt=254-volx; // Take it backwards , Get the maximum , Represents the largest representation of volt<<=8; volt+=254-volx; // Get the volume setting size VS1053_WriteCmd(SPI_VOL,volt);// Set volume }
7、 ... and 、Android mobile phone APP Core source code
7.1 Code page
7.2 mainwindow.cpp Code
#include "mainwindow.h"#include "ui_mainwindow.h"/* * Set up QT The style of the interface */void MainWindow::SetStyle(const QString &qssFile) { QFile file(qssFile); if (file.open(QFile::ReadOnly)) { QString qss = QLatin1String(file.readAll()); qApp->setStyleSheet(qss); QString PaletteColor = qss.mid(20,7); qApp->setPalette(QPalette(QColor(PaletteColor))); file.close(); } else { qApp->setStyleSheet(""); }}static const QLatin1String serviceUuid("00001101-0000-1000-8000-00805F9B34FB");// The contents of this string are in serial port mode UuidMainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow){ ui->setupUi(this); this->SetStyle(":/qss/blue.css"); // Set up a style sheet this->setWindowTitle("HC05 Bluetooth speakers "); // Set title this->setWindowIcon(QIcon(":/wbyq.ico")); // Set icon /*1. Instantiate Bluetooth related objects */ discoveryAgent = new QBluetoothDeviceDiscoveryAgent(); localDevice = new QBluetoothLocalDevice(); socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol); //RfcommProtocol Indicates that the service uses RFCOMM Socket protocol .RfcommProtocol Belongs to simulation RS232 Pattern , It is called serial port mode /*2. Associate signals related to Bluetooth devices */ /*2.1 The slot function of the associated discovery device , When scanning finds Bluetooth devices around , Will be issued deviceDiscovered The signal */ connect(discoveryAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)), this, SLOT(addBlueToothDevicesToList(QBluetoothDeviceInfo)) ); // Bluetooth has data readable connect(socket, SIGNAL(readyRead()), this, SLOT(readBluetoothDataEvent()) ); // Bluetooth connection established successfully connect(socket, SIGNAL(connected()), this, SLOT(bluetoothConnectedEvent()) ); // Bluetooth disconnect connect(socket, SIGNAL(disconnected()), this, SLOT(bluetoothDisconnectedEvent()) ); // Bluetooth writes successful data connect(socket, SIGNAL(bytesWritten(qint64)), this, SLOT(bluetoothbytesWritten(qint64)) ); /*3.2 Set the label to display the name of the local Bluetooth */ QString name_info(" Native Bluetooth :"); name_info+=localDevice->name(); ui->label_BluetoothName->setText(name_info); ui->plainTextEdit->setEnabled(false); // It can't be edited /* Timer is used to send files regularly */ timer = new QTimer(this); // Create timer connect(timer, SIGNAL(timeout()), this, SLOT(update())); // Correlation slot function ConnectStat=0; // Connection status SendStat=0; // File open status FileSendTime=100; // The default time of each sending Company ms ui->lineEdit_Timer->setText(QString::number(FileSendTime)); FileSendCnt=32; // Default data value per packet 32 byte ui->lineEdit_SendFileCnt->setText(QString::number(FileSendCnt)); // Create a directory for storing music files QDir dir; if(dir.mkpath("/sdcard/WBYQ_MP3")) { ui->plainTextEdit->insertPlainText("/WBYQ_MP3 Directory created successfully !\n"); } else { ui->plainTextEdit->insertPlainText("/WBYQ_MP3 Directory creation failed !\n"); } MusicFileDir="assets:/nansannan.mp3"; // Path to directory Def_MusicName="assets:/nansannan.mp3"; file.setFileName(Def_MusicName); // Set file name ui->lineEdit_MusicName->setText(Def_MusicName); // Default file name }int count=0;// to update void MainWindow::update(){ if(SendStat) { int len; if(file.atEnd()==false) // File not closed { len=file.read(FileBuff,FileSendCnt); len=socket->write(FileBuff,len); // send data } else { file.close(); timer->stop(); // Stop timer SendStat=0; ui->plainTextEdit->setPlainText(" File read and write completed !\n"); } }}MainWindow::~MainWindow(){ delete ui; delete discoveryAgent; delete localDevice; delete socket; timer->stop(); delete timer;}void MainWindow::on_pushButton_CloseBluetooth_clicked(){ /* Turn off Bluetooth devices */ localDevice->setHostMode(QBluetoothLocalDevice::HostPoweredOff);}void MainWindow::on_pushButton_BluetoothScan_clicked(){ /*3.1 Check whether Bluetooth is on */ if(localDevice->hostMode() == QBluetoothLocalDevice::HostPoweredOff) { /* Request to turn on the Bluetooth device */ localDevice->powerOn(); } /* Start scanning the surrounding Bluetooth devices */ discoveryAgent->start(); ui->comboBox_BluetoothDevice->clear(); // Clear entries }void MainWindow::on_pushButton_DeviceVisible_clicked(){ /* Set Bluetooth visible , Can be searched by surrounding devices , stay Android On , This mode can only run at most 5 minute .*/ // localDevice->setHostMode( QBluetoothLocalDevice::HostDiscoverable); static bool cnt=1; cnt=!cnt; if(cnt) { MusicFileDir="assets:/nansannan.mp3"; // Path to directory QMessageBox::information(this," Tips "," Switch the path to the internal path !\n Please select a file !",QMessageBox::Ok,QMessageBox::Ok); } else { MusicFileDir="/mnt/sdcard"; // Path to directory QMessageBox::information(this," Tips "," Switch the path to SD route !\n Please select a file !",QMessageBox::Ok,QMessageBox::Ok); }}void MainWindow::on_pushButton_StopScan_clicked(){ /* Stop scanning the surrounding Bluetooth devices */ discoveryAgent->stop();}/* When scanning to the surrounding devices, the current slot function will be called */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); // Add a string to comboBox On }// Data readable void MainWindow::readBluetoothDataEvent(){ QByteArray all = socket->readAll(); ui->plainTextEdit->insertPlainText(all);}// Establishing a connection void MainWindow::bluetoothConnectedEvent(){ QMessageBox::information(this,tr(" Connection tips ")," Bluetooth connection successful !"); ConnectStat=1; /* Stop scanning the surrounding Bluetooth devices */ discoveryAgent->stop();}// disconnect void MainWindow::bluetoothDisconnectedEvent(){ ConnectStat=0; QMessageBox::information(this,tr(" Connection tips ")," Bluetooth disconnect !");}/* Before talking about Bluetooth device connection , I have to mention a very important concept , It's Bluetooth Uuid, Quote Baidu : In Bluetooth , Each service and service attribute is uniquely determined by " Globally unique identifier " (UUID) To verify . As its name implies , Each such identifier must be unique in time and space .UUID Class can be represented as short shaping (16 or 32 position ) And long plastic surgery (128 position )UUID. He provides separate use String and 16 Bit or 32 Bit value to create the constructor of the class , Provides a way to compare two UUID( If both are 128 position ) Methods , There is another one that can convert one UUID For a string method .UUID Instances are immutable (immutable), Only by UUID Marked services can be found . stay Linux Next you use an order uuidgen -t Can generate a UUID value ; stay Windows Then execute the command uuidgen .UUID It looks like the following form :2d266186-01fb-47c2-8d9f-10b8ec891363. When using generated UUID To create a UUID object , You can remove hyphens .*/// Send music files void MainWindow::on_pushButton_SendData_clicked(){ if(ConnectStat) { if(file.open(QIODevice::ReadOnly)) { SendStat=1; count=0; ui->plainTextEdit->insertPlainText(" System prompt : Start sending files !\n"); ui->lineEdit_fileSizef->setText(QString::number(file.size())); ui->lineEdit_fileCount->setText(""); ui->progressBar_SendCount->setMaximum(file.size()); // Set the maximum display value of the progress bar ui->progressBar_SendCount->setValue(0); // Set the value of the progress bar timer->start(FileSendTime); // Start timer } }}// Connect Bluetooth 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=" Start connecting Bluetooth devices :\n"; connect_device+=ui->comboBox_BluetoothDevice->currentText(); QMessageBox::information(this,tr(" Connection tips "),connect_device); // Start connecting Bluetooth devices socket->connectToService(address, QBluetoothUuid(serviceUuid) ,QIODevice::ReadWrite);}// Help tips void MainWindow::on_pushButton_help_clicked(){ QMessageBox::information(this,tr(" Help tips ")," This software is used for HC-05/06 Series serial port Bluetooth connection !\n" " Temporarily not supported BLE4.0 Version Bluetooth !\n" " Used to send music file data , Send each time 32 byte , Default 100ms Sending interval \n" " Software author :DS Little dragon brother \n" "BUG feedback :[email protected]");}// Select a music file void MainWindow::on_pushButton_select_clicked(){ QString filename=QFileDialog::getOpenFileName(this," Select the music file to send ",MusicFileDir,tr("*.mp3 *.MP3 *.WAV")); //filename== Select the absolute path of the file file.setFileName(filename); ui->lineEdit_MusicName->setText(filename); Def_MusicName=filename; // Save the file name }// eliminate void MainWindow::on_pushButton_clear_clicked(){ ui->plainTextEdit->setPlainText("");}void MainWindow::on_pushButton_StopSend_clicked(){ timer->stop(); // Stop timer }// Set the sending interval void MainWindow::on_pushButton_SendTime_clicked(){ QString str=ui->lineEdit_Timer->text(); int time=str.toInt(); FileSendTime=time; // Storage time if(time<=0) { QMessageBox::warning(this," Warning tips "," Setting error : The interval between sending is the smallest 1ms\n",QMessageBox::Ok,QMessageBox::Ok); } else ui->plainTextEdit->insertPlainText(tr(" Set the sending interval to %1ms\n").arg(time));}// Modify the number of packets sent void MainWindow::on_pushButton_SendFileCnt_clicked(){ QString str=ui->lineEdit_SendFileCnt->text(); int cnt=str.toInt(); if(cnt>4096 || cnt<=0) { QMessageBox::warning(this," Warning tips "," Setting error : The range of quantity sent per packet : 1~4096\n",QMessageBox::Ok,QMessageBox::Ok); } else { FileSendCnt=cnt; ui->plainTextEdit->insertPlainText(tr(" Send quantity is set to %1 byte .\n").arg(cnt)); }}// Write the number of successes void MainWindow::bluetoothbytesWritten(qint64 byte){ count+=byte; ui->lineEdit_fileCount->setText(QString::number(count)); ui->progressBar_SendCount->setValue(count); // Set the value of the progress bar } If you need complete code, you can download it here :https://download.csdn.net/download/xiaolong1126626497/18621270
边栏推荐
- JDBC驱动器、C3P0、Druid和JDBCTemplate相关依赖jar包
- Take you through ancient Rome, the meta universe bus is coming # Invisible Cities
- POJ 2208 已知边四面体六个长度,计算体积
- CSRF vulnerability analysis
- 图之广度优先遍历
- Shangsilicon Valley JUC high concurrency programming learning notes (3) multi thread lock
- 当保存参数使用结构体时必备的开发技巧方式
- C language college laboratory reservation registration system
- 监控界的最强王者,没有之一!
- Xu Xiang's wife Ying Ying responded to the "stock review": she wrote it!
猜你喜欢
Compilation Principle -- C language implementation of prediction table
Interesting - questions about undefined
F200 - UAV equipped with domestic open source flight control system based on Model Design
UDP protocol: simple because of good nature, it is inevitable to encounter "city can play"
Xu Xiang's wife Ying Ying responded to the "stock review": she wrote it!
Distiller les connaissances du modèle interactif! L'Université de technologie de Chine & meituan propose Virt, qui a à la fois l'efficacité du modèle à deux tours et la performance du modèle interacti
【中山大学】考研初试复试资料分享
Easy to use PDF to SVG program
Take you through ancient Rome, the meta universe bus is coming # Invisible Cities
Top command details
随机推荐
30 分钟看懂 PCA 主成分分析
Splay
Use cpolar to build a business website (1)
【LeetCode第 300 场周赛】
2022暑期项目实训(二)
Cobra 快速入门 - 专为命令行程序而生
递归的方式
2019 Alibaba cluster dataset Usage Summary
JDBC驱动器、C3P0、Druid和JDBCTemplate相关依赖jar包
测试123
模板于泛型编程之declval
STM32+ESP8266+MQTT协议连接OneNet物联网平台
287. 寻找重复数
1700C - Helping the Nature
HMS core machine learning service creates a new "sound" state of simultaneous interpreting translation, and AI makes international exchanges smoother
Virtual machine VirtualBox and vagrant installation
Blue Bridge Cup real question: one question with clear code, master three codes
使用cpolar建立一个商业网站(1)
C语言高校实验室预约登记系统
CRMEB 商城系统如何助力营销?