当前位置:网站首页>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

image.png

VS1053 You can connect headphones or speakers to listen to music .

Four 、 Set up HC05 Bluetooth baud rate

image.png
image.png

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

image.png
image.png
image.png

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

image.png

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
原网站

版权声明
本文为[Hua Weiyun]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/187/202207061017417193.html