【功能实现总结】【STM32HAL库】【2021A】 蓝牙显示采样波形

序言

由于电赛2021年的A题中要求在手机上显示波形、THD、归一化幅值等,在这篇文章里记录我们使用蓝牙显示采样波形的过程,侧重记录蓝牙部分,且只有蓝牙接受单片机数据,没有蓝牙发送的部分。仅供参考。

准备:

  1. 主控采用stm32(我们用的是h743),蓝牙使用了HC06,也可以准备usb to ttl模块方便调试
  2. 在手机端下载蓝牙调试器app

HC06部分:

HC06默认波特率为9600,可以通过AT指令改变,具体方法如下:

  1. 通过usb to ttl模块连接hc06,打开串口助手,发送AT,若收到OK,则表明成功进入到设置状态;
  2. 这里我们想将其波特率设置为115200,发送AT+BAUD8,收到OK115200表明设置成功。
    还有其他的一些指令,可以参考文档。
    注意:在这里要将数据引擎设置为RawData,我开始使用FireWater一直收不到数据。

手机app部分

https://www.jianshu.com/p/1a8262492619#google_vignette
这是原作者发布的地方,可以了解该app的基本功能和通信协议,支持原作者。
在这里我们采用的是大佬开发的一款功能十分强大的app,使用其专业调试功能进行编辑。具体操作如下:

  1. 添加数据包:我们因为只需要用到接受数据包,所以只配置了7个float类型的接受数据包;
  2. 编辑界面:添加波形、文本框等控件,并链接到数据包。

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

具体使用方法如下:

  1. 将.h文件中的头文件改为自己相应单片机的库;
  2. 将两个文件加入到工程中;
  3. 有putBool、putByte、putShort、putInt、putFloat五个函数,使用时一定要按照数据包中数据的顺序逐个使用函数发送数据。
  4. 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());

整体搭建

  1. 编写好代码烧写到单片机,完成usart电路连接HC-06,这里使用3.3V、5V供电均可;
  2. 手机连接蓝牙,进行配对,默认密码是1234,再在app中连接蓝牙,注意一定要开定位,不然搜索不到;配对好后就是这样:

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

posted @ 2024-07-21 12:29  极光幔  阅读(232)  评论(1)    收藏  举报