【功能实现总结】【STM32HAL库】【2021A】 蓝牙显示采样波形
序言
由于电赛2021年的A题中要求在手机上显示波形、THD、归一化幅值等,在这篇文章里记录我们使用蓝牙显示采样波形的过程,侧重记录蓝牙部分,且只有蓝牙接受单片机数据,没有蓝牙发送的部分。仅供参考。
准备:
- 主控采用stm32(我们用的是h743),蓝牙使用了HC06,也可以准备usb to ttl模块方便调试
- 在手机端下载蓝牙调试器app
HC06部分:
HC06默认波特率为9600,可以通过AT指令改变,具体方法如下:
- 通过usb to ttl模块连接hc06,打开串口助手,发送AT,若收到OK,则表明成功进入到设置状态;
- 这里我们想将其波特率设置为115200,发送AT+BAUD8,收到OK115200表明设置成功。
还有其他的一些指令,可以参考文档。
注意:在这里要将数据引擎设置为RawData,我开始使用FireWater一直收不到数据。
手机app部分
https://www.jianshu.com/p/1a8262492619#google_vignette
这是原作者发布的地方,可以了解该app的基本功能和通信协议,支持原作者。
在这里我们采用的是大佬开发的一款功能十分强大的app,使用其专业调试功能进行编辑。具体操作如下:
- 添加数据包:我们因为只需要用到接受数据包,所以只配置了7个float类型的接受数据包;
- 编辑界面:添加波形、文本框等控件,并链接到数据包。
STM32部分
https://blog.csdn.net/XLazyDog/article/details/99680628?spm=1001.2014.3001.5502
代码最初来自于这里。
ADC采样部分的设置和代码在此不做赘述,这里最重要的部分就是对数据包的发送的处理。
我在网上只找到了使用标准库进行发送的源码,将其移植成了使用HAL库。(代码展示)
点击查看代码
#include "valuepack.h"
unsigned char *valuepack_tx_buffer;
unsigned short valuepack_tx_index;
unsigned char valuepack_tx_bit_index;
unsigned char valuepack_stage;
// 1. 开始将数据打包,需传入定义好的数组(需保证数组长度足以存放要发送的数据)
void startValuePack(unsigned char *buffer)
{
valuepack_tx_buffer = buffer;
valuepack_tx_index = 1;
valuepack_tx_bit_index = 0;
valuepack_tx_buffer[0] = PACK_HEAD;
valuepack_stage = 0;
}
// 2. 向数据包中放入各类数据,由于数据包的顺序结构是固定的,因此注意严格以如下的顺序进行存放,否则会出现错误
void putBool(unsigned char b)
{
if(valuepack_stage<=1)
{
if(b)
valuepack_tx_buffer[valuepack_tx_index] |= 0x01<<valuepack_tx_bit_index;
else
valuepack_tx_buffer[valuepack_tx_index] &= ~(0x01<<valuepack_tx_bit_index);
valuepack_tx_bit_index++;
if(valuepack_tx_bit_index>=8)
{
valuepack_tx_bit_index = 0;
valuepack_tx_index++;
}
valuepack_stage = 1;
}
}
void putByte(char b)
{
if(valuepack_stage<=2)
{
if(valuepack_tx_bit_index!=0)
{
valuepack_tx_index++;
valuepack_tx_bit_index = 0;
}
valuepack_tx_buffer[valuepack_tx_index] = b;
valuepack_tx_index++;
valuepack_stage = 2;
}
}
void putShort(short s)
{
if(valuepack_stage<=3)
{
if(valuepack_tx_bit_index!=0)
{
valuepack_tx_index++;
valuepack_tx_bit_index = 0;
}
valuepack_tx_buffer[valuepack_tx_index] = s&0xff;
valuepack_tx_buffer[valuepack_tx_index+1] = s>>8;
valuepack_tx_index +=2;
valuepack_stage = 3;
}
}
void putInt(int i)
{
if(valuepack_stage<=4)
{
if(valuepack_tx_bit_index!=0)
{
valuepack_tx_index++;
valuepack_tx_bit_index = 0;
}
valuepack_tx_buffer[valuepack_tx_index] = i&0xff;
valuepack_tx_buffer[valuepack_tx_index+1] = (i>>8)&0xff;
valuepack_tx_buffer[valuepack_tx_index+2] = (i>>16)&0xff;
valuepack_tx_buffer[valuepack_tx_index+3] = (i>>24)&0xff;
valuepack_tx_index +=4;
valuepack_stage = 4;
}
}
int fi;
void putFloat(float f)
{
if(valuepack_stage<=5)
{
if(valuepack_tx_bit_index!=0)
{
valuepack_tx_index++;
valuepack_tx_bit_index = 0;
}
fi = *(int*)(&f);
valuepack_tx_buffer[valuepack_tx_index] = fi&0xff;
valuepack_tx_buffer[valuepack_tx_index+1] = (fi>>8)&0xff;
valuepack_tx_buffer[valuepack_tx_index+2] = (fi>>16)&0xff;
valuepack_tx_buffer[valuepack_tx_index+3] = (fi>>24)&0xff;
valuepack_tx_index +=4;
valuepack_stage = 5;
}
}
// 3. 结束打包,函数将返回 数据包的总长度
unsigned short endValuePack()
{
unsigned char sum=0;
for(int i=1;i<valuepack_tx_index;i++)
{
sum+=valuepack_tx_buffer[i];
}
valuepack_tx_buffer[valuepack_tx_index] = sum;
valuepack_tx_buffer[valuepack_tx_index+1] = PACK_TAIL;
return valuepack_tx_index+2;
}
// 4. 发送数据
void sendBuffer(unsigned char *p,unsigned short length)
{
for(int i=0;i<length;i++)
{
// USART_SendData(USART1, *p++);
// while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
// {}
HAL_UART_Transmit(&huart2,p++,1,100);
}
}
点击查看代码
#include "stm32h7xx_hal.h"
#include "main.h"
// 本程序通过 USART 将数据包发送到手机上,不支持接收的功能
// 初始化 valuepack 一些必要的硬件外设配置
void initValuePack(int baudrate);
////////////////////////////////////////////////////////////////////////////////////////////
// 以下函数是按顺序调用的,先开始打包,然后依次存放数据,最后结束打包。结束打包后,使用串口将数组发送出去。
// 1. 开始将数据打包,需传入定义好的数组(需保证数组长度足以存放要发送的数据)
void startValuePack(unsigned char *buffer);
// 2. 向数据包中放入各类数据,由于数据包的结构是固定的,因此注意严格以如下的顺序进行存放,否则会出现错误
void putBool(unsigned char b);
void putByte(char b);
void putShort(short s);
void putInt(int i);
void putFloat(float f);
// 3. 结束打包,函数将返回 数据包的总长度
unsigned short endValuePack(void);
// 4. 发送数据
void sendBuffer(unsigned char *buffer,unsigned short length);
#define PACK_HEAD 0xa5
#define PACK_TAIL 0x5a
具体使用方法如下:
- 将.h文件中的头文件改为自己相应单片机的库;
- 将两个文件加入到工程中;
- 有putBool、putByte、putShort、putInt、putFloat五个函数,使用时一定要按照数据包中数据的顺序逐个使用函数发送数据。
- main.c使用如下,添加buffer然后使用startValuePack(buffer)开始打包数据,之后按照自己在app端配置的数据包顺序使用相应类型的put函数,注意一定要按照顺序且不能漏,最后使用sendBuffer(buffer,endValuePack())结束输出。
点击查看代码
unsigned char buffer[50];
startValuePack(buffer);
putFloat(temp/100);//THD
putFloat(adc1_data[i]);//wave
putFloat(U[0]);//V1
putFloat(U[1]);//V2
putFloat(U[2]);//V3
putFloat(U[3]);//V4
putFloat(U[4]);//V5
sendBuffer(buffer,endValuePack());
整体搭建
- 编写好代码烧写到单片机,完成usart电路连接HC-06,这里使用3.3V、5V供电均可;
- 手机连接蓝牙,进行配对,默认密码是1234,再在app中连接蓝牙,注意一定要开定位,不然搜索不到;配对好后就是这样:

- 然后就可以由单片机发送数据了 ( ゚ ▽ ゚)つ□乾杯。成品如图:


浙公网安备 33010602011771号