STM32传感器外设集 -- 蓝牙(HC-05)+超声波(hc-sr04)

2023-10-28

前言

前言:蓝牙外设还没有给大家安排上,今天我就给大家安排上使用蓝牙传输超声波距离的例程,会给大家附带蓝牙的上位机的测试APP


 一、模块介绍

1.连接图

蓝牙模块 引脚 超声波传感器 引脚
GND GND GND GND
VCC 3.3 VCC 5V
EN PA7 TG PB13
RST PA5 EG PB12
TX PB11    
RX PB10    

2 蓝牙(HC-05)

介绍

蓝牙通讯技术是-f0短距离通讯方式,主机和从机使用相同的通讯协议,不同的应用中,可以使用不同的通讯协议,协议规范遵循开放系统互联参考模型。HC05模块是一款高性能主从一体蓝牙串口模块。支持 SPP 蓝牙串口协议,具有成本低、体积小、功耗低、收发灵敏性高等优点,它可以充当三种角色,分别是Slave(从角色)、Master(主角色)和Slave-Loop(回环角色)。

连线图

3.超声波(hc-sr04)

介绍

HC-SR04超声波距离传感器的核心是两个超声波传感器。一个用作发射器,将电信号转换为40 KHz超声波脉冲。接收器监听发射的脉冲。如果接收到它们,它将产生一个输出脉冲,其宽度可用于确定脉冲传播的距离。就是如此简单!

该传感器体积小,易于在任何机器人项目中使用,并提供2厘米至400厘米(约1英寸至13英尺)之间出色的非接触范围检测,精度为3mm。由于它的工作电压为5伏

连线图

三、 代码编写

使用到了串口三和两个定时器

usart3.c

#include "delay.h"
#include "usart3.h"
#include "stdarg.h"	 	 
#include "stdio.h"	 	 
#include "string.h"	 
#include "timer.h"

//串口接收缓存区 	
u8 USART3_RX_BUF[USART3_MAX_RECV_LEN]; 				//接收缓冲,最大USART3_MAX_RECV_LEN个字节.
u8  USART3_TX_BUF[USART3_MAX_SEND_LEN]; 			//发送缓冲,最大USART3_MAX_SEND_LEN字节

//通过判断接收连续2个字符之间的时间差不大于10ms来决定是不是一次连续的数据.
//如果2个字符接收间隔超过10ms,则认为不是1次连续数据.也就是超过10ms没有接收到
//任何数据,则表示此次接收完毕.
//接收到的数据状态
//[15]:0,没有接收到数据;1,接收到了一批数据.
//[14:0]:接收到的数据长度
vu16 USART3_RX_STA=0;   	


void USART3_IRQHandler(void)
{
	u8 res;	      
	if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)//接收到数据
	{	 
		res =USART_ReceiveData(USART3);		 
		if((USART3_RX_STA&(1<<15))==0)//接收完的一批数据,还没有被处理,则不再接收其他数据
		{ 
			if(USART3_RX_STA<USART3_MAX_RECV_LEN)	//还可以接收数据
			{
				TIM_SetCounter(TIM3,0);//计数器清空          				//计数器清空
				if(USART3_RX_STA==0) 				//使能定时器7的中断 
				{
					TIM_Cmd(TIM3,ENABLE);//使能定时器7
				}
				USART3_RX_BUF[USART3_RX_STA++]=res;	//记录接收到的值	 
			}else 
			{
				USART3_RX_STA|=1<<15;				//强制标记接收完成
			} 
		}
	}  				 											 
}   


//初始化IO 串口3
//pclk1:PCLK1时钟频率(Mhz)
//bound:波特率	  
void usart3_init(u32 bound)
{  

	NVIC_InitTypeDef NVIC_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	// GPIOB时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //串口3时钟使能

 	USART_DeInit(USART3);  //复位串口3
		 //USART3_TX   PB10
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
  GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB10
   
    //USART3_RX	  PB11
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOB, &GPIO_InitStructure);  //初始化PB11
	
	USART_InitStructure.USART_BaudRate = bound;//波特率一般设置为9600;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
  
	USART_Init(USART3, &USART_InitStructure); //初始化串口	3
  

	USART_Cmd(USART3, ENABLE);                    //使能串口 
	
	//使能接收中断
  USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启中断   
	
	//设置中断优先级
	NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
	
	
	TIM3_Init(99,7199);		//10ms中断
	USART3_RX_STA=0;		//清零
	TIM_Cmd(TIM3,DISABLE);			//关闭定时器7

}

//串口3,printf 函数
//确保一次发送数据不超过USART3_MAX_SEND_LEN字节
void u3_printf(char* fmt,...)  
{  
	u16 i,j; 
	va_list ap; 
	va_start(ap,fmt);
	vsprintf((char*)USART3_TX_BUF,fmt,ap);
	va_end(ap);
	i=strlen((const char*)USART3_TX_BUF);		//此次发送数据的长度
	for(j=0;j<i;j++)							//循环发送数据
	{
	  while(USART_GetFlagStatus(USART3,USART_FLAG_TC)==RESET); //循环发送,直到发送完毕   
		USART_SendData(USART3,USART3_TX_BUF[j]); 
	} 
}

 

usart3.h

#ifndef __USART3_H
#define __USART3_H	 
#include "sys.h"  
#define USART3_MAX_RECV_LEN		600					//最大接收缓存字节数
#define USART3_MAX_SEND_LEN		600					//最大发送缓存字节数
#define USART3_RX_EN 			1					//0,不接收;1,接收.

extern u8  USART3_RX_BUF[USART3_MAX_RECV_LEN]; 		//接收缓冲,最大USART3_MAX_RECV_LEN字节
extern u8  USART3_TX_BUF[USART3_MAX_SEND_LEN]; 		//发送缓冲,最大USART3_MAX_SEND_LEN字节
extern vu16 USART3_RX_STA;   						//接收数据状态

void usart3_init(u32 bound);				//串口2初始化 
void u3_printf(char* fmt,...);
#endif


hc05.c

#include "delay.h" 			 
#include "usart.h" 			 
#include "usart3.h" 			 
#include "hc05.h" 

#include "string.h"	 
#include "math.h"
//初始化ATK-HC05模块
//返回值:0,成功;1,失败.
u8 HC05_Init(void)
{
	u8 retry=10,t;	  		 
	u8 temp=1;
	
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);	//使能PORTA
 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;				 // 端口配置
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 		 //上拉输入
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
	GPIO_Init(GPIOA, &GPIO_InitStructure);					 //根据设定参数初始化A15
	 
 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;				 // 端口配置
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
	GPIO_Init(GPIOA, &GPIO_InitStructure);					 //根据设定参数初始化GPIOA4

	GPIO_SetBits(GPIOA,GPIO_Pin_7);
 	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
	HC05_KEY=1;
	HC05_LED=1; 
	
	usart3_init(9600);	//初始化串口2为:9600,波特率.
	
	while(retry--)
	{
		HC05_KEY=1;					//KEY置高,进入AT模式
		delay_ms(10);
		u3_printf("AT\r\n");		//发送AT测试指令
		HC05_KEY=0;					//KEY拉低,退出AT模式
		for(t=0;t<10;t++) 			//最长等待50ms,来接收HC05模块的回应
		{
			if(USART3_RX_STA&0X8000)break;
			delay_ms(5);
		}		
		if(USART3_RX_STA&0X8000)	//接收到一次数据了
		{
			temp=USART3_RX_STA&0X7FFF;	//得到数据长度
			USART3_RX_STA=0;			 
			if(temp==4&&USART3_RX_BUF[0]=='O'&&USART3_RX_BUF[1]=='K')
			{
				temp=0;//接收到OK响应
				break;
			}
		}			    		
	}		    
	if(retry==0)temp=1;	//检测失败
	return temp;	  
}	 
//获取ATK-HC05模块的角色
//返回值:0,从机;1,主机;0XFF,获取失败.							  
u8 HC05_Get_Role(void)
{	 		    
	u8 retry=0X0F;
	u8 temp,t;
	while(retry--)
	{
		HC05_KEY=1;					//KEY置高,进入AT模式
		delay_ms(10);
		u3_printf("AT+ROLE?\r\n");	//查询角色
		for(t=0;t<20;t++) 			//最长等待200ms,来接收HC05模块的回应
		{
			delay_ms(10);
			if(USART3_RX_STA&0X8000)break;
		}		
		HC05_KEY=0;					//KEY拉低,退出AT模式
		if(USART3_RX_STA&0X8000)	//接收到一次数据了
		{
			temp=USART3_RX_STA&0X7FFF;	//得到数据长度
			USART3_RX_STA=0;			 
			if(temp==13&&USART3_RX_BUF[0]=='+')//接收到正确的应答了
			{
				temp=USART3_RX_BUF[6]-'0';//得到主从模式值
				break;
			}
		}		
	}
	if(retry==0)temp=0XFF;//查询失败.
	return temp;
} 							   
//ATK-HC05设置命令
//此函数用于设置ATK-HC05,适用于仅返回OK应答的AT指令
//atstr:AT指令串.比如:"AT+RESET"/"AT+UART=9600,0,0"/"AT+ROLE=0"等字符串
//返回值:0,设置成功;其他,设置失败.							  
u8 HC05_Set_Cmd(u8* atstr)
{	 		    
	u8 retry=0X0F;
	u8 temp,t;
	while(retry--)
	{
		HC05_KEY=1;					//KEY置高,进入AT模式
		delay_ms(10);
		u3_printf("%s\r\n",atstr);	//发送AT字符串
		HC05_KEY=0;					//KEY拉低,退出AT模式
		for(t=0;t<20;t++) 			//最长等待100ms,来接收HC05模块的回应
		{
			if(USART3_RX_STA&0X8000)break;
			delay_ms(5);
		}		
		if(USART3_RX_STA&0X8000)	//接收到一次数据了
		{
			temp=USART3_RX_STA&0X7FFF;	//得到数据长度
			USART3_RX_STA=0;			 
			if(temp==4&&USART3_RX_BUF[0]=='O')//接收到正确的应答了
			{			
				temp=0;
				break;			 
			}
		}		
	}
	if(retry==0)temp=0XFF;//设置失败.
	return temp;
} 
///
//通过该函数,可以利用USMART,调试接在串口3上的ATK-HC05模块
//str:命令串.(这里注意不再需要再输入回车符)
void HC05_CFG_CMD(u8 *str)
{					  
	u8 temp;
	u8 t;		  
	HC05_KEY=1;						//KEY置高,进入AT模式
	delay_ms(10);
	u3_printf("%s\r\n",(char*)str); //发送指令
	for(t=0;t<50;t++) 				//最长等待500ms,来接收HC05模块的回应
	{
		if(USART3_RX_STA&0X8000)break;
		delay_ms(10);
	}									    
	HC05_KEY=0;						//KEY拉低,退出AT模式
	if(USART3_RX_STA&0X8000)		//接收到一次数据了
	{
		temp=USART3_RX_STA&0X7FFF;	//得到数据长度
		USART3_RX_STA=0;
		USART3_RX_BUF[temp]=0;		//加结束符		 
		printf("\r\n%s",USART3_RX_BUF);//发送回应数据到串口1
	} 				 
}

hc05.h

#ifndef __HC05_H
#define __HC05_H	 
#include "sys.h" 

#define HC05_KEY  	PAout(7) 		//蓝牙控制KEY信号
#define HC05_LED  	PAin(5)		//蓝牙连接状态信号
  
u8 HC05_Init(void);
void HC05_CFG_CMD(u8 *str);
u8 HC05_Get_Role(void);
u8 HC05_Set_Cmd(u8* atstr);	     
#endif  




HC_SR04.c

#include "HC_SR04.h"
#include "timer.h"
#include "delay.h"

//	 

void HC_SR04_IO_Init(void)
{
 
 GPIO_InitTypeDef  GPIO_InitStructure;
 	
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	 //使能PB端口时钟
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;				 // 端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 		 //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
 GPIO_Init(GPIOB, &GPIO_InitStructure);					 //根据设定参数初始化GPIOB.12
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;				 // 端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
 GPIO_Init(GPIOB, &GPIO_InitStructure);					 //根据设定参数初始化GPIOB.13
	
}

u16 TIM2_UPDATA = 0;
u32 temp = 0;
u16  Get_SR04_Distance(void)
{

   SR04_Trlg=1;       //触发信号是高电平脉冲,宽度大于10us
   delay_us(20);
   SR04_Trlg=0;
   while(!SR04_Echo); //等待高电平
	 TIM_SetCounter(TIM2,0);  //重填计数器值
	 TIM2_UPDATA = 0;         //溢出次数清零
   while(SR04_Echo);  //等待低电平
	 TIM_Cmd(TIM2,DISABLE);  //暂时关闭定时器,保证数据正确性
   temp = (int)(((double)(TIM_GetCounter(TIM2) + (7200* TIM2_UPDATA)))/72/2);  //得到高电平总时间,单位us(定时器的计数值加上溢出的值才是高电平的时间),除以2是计算单程的时间
	 //(7200* TIM2_UPDATA这里为溢出的时间us,可以转换为100* TIM2_UPDATA,因为在公式后面除以了72。可最终理解为TIM2_UPDATA个100us)
	 TIM_Cmd(TIM2,ENABLE);
	 return temp;
}
 


HC_SR04.h

#ifndef __HC_SR04_H
#define __HC_SR04_H	 
#include "sys.h"


#define SR04_Trlg PBout(12)// PB12
#define SR04_Echo PBin(13)// PB13	

void HC_SR04_IO_Init(void);
u16  Get_SR04_Distance(void);



	 				    
#endif

timer.c

#include "timer.h"
#include "delay.h"
#include "sys.h"

//通用定时器中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器2

void TIM2_Init(u16 arr,u16 psc)
{	 
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);	//使能TIM2时钟
	
	//初始化定时器2	 
	TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值 
	TIM_TimeBaseStructure.TIM_Prescaler =psc; 	//预分频器   
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
  

	
	//中断分组初始化
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;  //先占优先级2级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级0级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 
	
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//允许更新中断 ,
	
  TIM_Cmd(TIM2,ENABLE ); 	//使能定时器2

}
//定时器2中断服务程序	               主要记录溢出次数

extern u16 TIM2_UPDATA;
extern u8 state_machine;
void TIM2_IRQHandler(void)
{ 
				if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
				{
					  TIM2_UPDATA++;//当回响信号很长时,记录溢出次数,每加一次代表加100us
						TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除中断标志位
			  }
}

void TIM3_Init(u16 arr,u16 psc)
{	 
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);	//使能TIM2时钟
	
	//初始化定时器3	 
	TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值 
	TIM_TimeBaseStructure.TIM_Prescaler =psc; 	//预分频器   
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
  

	
	//中断分组初始化
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;  //先占优先级2级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级0级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 
	
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);//允许更新中断 ,
	
  TIM_Cmd(TIM3,ENABLE ); 	//使能定时器2
   


}

extern vu16 USART3_RX_STA;
//定时器3中断服务程序		    
void TIM3_IRQHandler(void)
{ 	
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)//是更新中断
	{	 			   
		USART3_RX_STA|=1<<15;	//标记接收完成
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIM7更新中断标志    
		TIM_Cmd(TIM3, DISABLE);  //关闭TIM7 
	}	    
}

timer.h

#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"


void TIM2_Init(u16 arr,u16 psc);
void TIM3_Init(u16 arr,u16 psc);

#endif

main.c

#include "delay.h"
#include "sys.h"
#include "timer.h"
#include "HC_SR04.h"
#include <stdio.h>
#include <math.h>
#include "usart.h"	
#include "hc05.h"
#include "usart3.h"
//STM32超声波测距
int  SAFET_Distance  = 300;         //安全距离
float  Distance = 0;  //距离
//显示ATK-HC05模块的主从状态
void HC05_Role_Show(void)
{
	
	if(HC05_Get_Role()==1)printf("ROLE:Master \n");	//主机
	else printf("ROLE:Slave \n");			 		//从机
//	/*4. 设置蓝牙的名称*/
//	if(HC05_Set_Cmd("AT+NAME=HEATR"))printf("4 蓝牙名称设置失败!\r\n");
//	else printf("4 蓝牙名称设置为 HEATR \r\n");
//	/*5. 设置蓝牙配对密码*/
//	if(HC05_Set_Cmd("AT+PSWD=1234"))printf("5 蓝牙配对密码设置失败!\r\n"); //密码必须是4位
//	else printf("5 蓝牙配对密码设置为 1234 \r\n");
}
//显示ATK-HC05模块的连接状态
void HC05_Sta_Show(void)
{												 
	if(HC05_LED)printf("STA:Connected \n");			//连接成功
	else printf("STA:Disconnect \n");	 			//未连接				 
}	
int main(void)
{
    char displaytemp[16];       //开启字符串空间
	int bobao_delay;
	u16 time=0;
	u16 count = 0;
	u8 reclen=0;
	u8 key = 0;
	delay_init();	    //延时函数初始化
 uart_init(115200);
	HC_SR04_IO_Init();  //超声波模块GPIO初始化
	delay_ms(500);       //上电瞬间加入一定延时在初始化
	TIM2_Init(7199,0);    //以10KHz计数,定时100us
	delay_ms(1000);			//等待蓝牙模块上电稳定
	while(HC05_Init()) 		//初始化ATK-HC05模块  
	{
		printf("ATK-HC05 Error!\n"); 
		delay_ms(500);
		printf("Please Check!!!\n"); 
		delay_ms(100);
	}
	HC05_Role_Show();
	delay_ms(100);
	USART3_RX_STA=0;		
    while(1)
    {
			time++ ;

				Distance = (Get_SR04_Distance() * 331) * 1.0/1000;   //Get_SR04_Distance()返回单程声波传输时间 us,转换为秒=时间*10^(-6);331m/s等于331000mm/s,
			 //最终换算为Distance =Get_SR04_Distance()*10^(-6)*331000=(Get_SR04_Distance() * 331) * 1.0/1000;
			
			 delay_ms(10);
			
			 if(time==300)
			 {
				 u3_printf(" %.1f",Distance);		//发送到蓝牙模块
				 printf("%.1f\n",Distance);
				 HC05_Sta_Show();
				 time=0;
			 }	
			 
			 if(USART3_RX_STA&0X8000)			//接收到一次数据了
			 {
			
				reclen=USART3_RX_STA&0X7FFF;	//得到数据长度
					USART3_RX_BUF[reclen]=0;	 	//加入结束符
				printf("%s\n",USART3_RX_BUF);//显示接收到的数据
				USART3_RX_STA=0;	 
			  }	

    }
    
}

四、 蓝牙APP测试工具

 链接:

APP连接https://pan.baidu.com/s/1LOWmq_fsPrx7TskBymwxlQ?pwd=heru%C2%A0
提取码:heru 


总结

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32传感器外设集 -- 蓝牙(HC-05)+超声波(hc-sr04) 的相关文章

  • vs2010中引入boost库

    引言 在vs2010中无法使用C 11中的大多数特性 像mutex互斥锁 要想使用需要引入boost库 下面记录一下boost库引入到vs2010中 实现 分为以下几步 下载boost压缩包 可以采用下面的地址下载适合自己的版本 下载地址
  • List转Map的三种方法

    for循环 import com google common base Function import com google common collect Maps import java util ArrayList import jav

随机推荐

  • 补 day10算法打卡

    232 用栈实现队列 代码 class MyQueue Stack
  • BugkuWeb:game1

    进去后发现是一款游戏 思路就是直接结束游戏 然后去看信息 发现网络监视器中多了score php 发现了可疑的参数score IP sign 这个sign应该在后台代码中被控制的 去审计代码 发现了sign的算法 这个游戏的得分是25 ba
  • 梦幻模拟战手游服务器维护,梦幻模拟战手游无法登陆游戏 服务器异常登录解决方法_游侠手游...

    梦幻模拟战手游 异常登录怎么办 无法登陆游戏怎么办 还没解决的玩家 下面小编就为玩家带来 梦幻模拟战手游 服务器异常登录无法登录解决方法 一起来看看吧 服务器异常登录无法登录解决方法 各位指挥官 真的非常抱歉 服务器目前不稳定 会有部分指挥
  • oracle 创建数据库 create database,使用create database语句创建数据库的详细操作步骤...

    使用create database语句创建数据库的步骤如下 1 指定一个实例标识符SID 2 确保设置了必要的环境变量 3 选择一个数据库管理员验证方法 4 创建一个初始化参数文件 5 只用于windows平台 创建一个实例 6 连接实例
  • 2022全国大学生数学建模竞赛C题思路模型

    1 比赛报名与思路解析 持续更新750967193 2 比赛时间 2022年9月15日18点到2022年9月18日20点 如下为C题思路 C 题 古代玻璃制品的成分分析与鉴别 丝绸之路是古代中西方文化交流的通道 其中玻璃是早期贸易往来的宝贵
  • Java异常, 性能有多差

    在 Java 中 异常通常被认为是成本昂贵的 不应该用于控制控制 本文将证明这个观点的正确性 并验证导致性能问题的原因 Java微基准测试框架 在编写代码评估Java异常的性能成本之前 我们需要搭建一个基准测试环境 测量异常的成本开销 并不
  • 04C++11多线程编程之创建多个线程和数据共享问题分析

    04C 11多线程编程之创建多个线程和数据共享问题分析 1 thread循环创建多个子线程 思想就是使用容器创建多个线程 推荐 以后工作中会使用到 具有实际意义 方便统一管理线程 include
  • Staple 跟踪: Complementary Learners for Real-Time Tracking

    目标跟踪算法 Staple Complementary Learners for Real Time Tracking 小小菜鸟一只 2017 03 25 09 26 42 15110 收藏 14 分类专栏 目标跟踪 版权 文章下载链接 文
  • 辨析Java与Javascript

    首先 它们是两个公司开发的不同的两个产品 Java是SUN公司推出的新一代面向对象的程序设计语言 特别适合于Internet应用程序开发 而JavaScript是Netscape公司的产品 其目的是为了扩展Netscape Navigato
  • 人才供应链(17年12月)

    库克来中国访问时说 高质量的人才是Apple公司最需要的 而苹果商店的开发者中 中国有200万开发者在支持应用商店 其中大部分是在广州 苹果的供应链也在中国 配套的零部件 面对高要求和近似到极限的品质要求 只有在中国才能满足 IT行业的人才
  • 压缩/减小VirtualBox虚拟硬盘文件占用空间

    文章目录 网上的做法 导出虚拟电脑 再导入 网上的做法 网上有两种压缩空间的做法 1 在虚拟机中 使用 SDelete 例如 sdelete c z 经本人实测 不仅不能压缩 因为SDelete 扫描了整个c 盘 而 VirtualBox
  • 【多模态】7、DINO

    文章目录 一 背景 二 方法 2 1 Contrastive DeNoising Training 2 3 Mixed Query Selection 2 4 Look Forward Twice 三 效果 论文 DINO DETR wit
  • 联想E450c下vmware安装ubuntu " Intel VT-x 处于禁用状态"

    实验环境 lenovo E450c 报错信息 解决办法 按F12进入BIOS 选择Security下的Virtualization 在Intel R 的行 设置Enabled 按F10保存 重新打开虚拟机 参考链接 vmware安装ubun
  • linux 挂载以及初始化硬盘

    linux 挂载以及初始化硬盘 简述 过多的赘述就不说了 一般使用linux完成一些像iscsi服务存储配置啥的 都需要用到硬盘的挂载来扩充服务器的存储空间 这里就简简单单给大家讲一下linux如何挂载初始化新的硬盘 我这里使用的是linu
  • CRC编码计算方法及C语言实现

    CRC编码计算方法及C语言实现 CRC Cyclic Redundancy Check 是一种常用的错误校验码 用于检测和纠正传输过程中的错误 在数据通信和存储中 CRC编码被广泛应用 因为它能够高效地检测错误 并且实现简便 CRC编码计算
  • V神·以太坊上的分片

    译者序 本文是我应以太坊中文社区 Ethfans org 之邀做的翻译稿 原文取自以太坊社区的Github https github com ethereum sharding blob develop docs doc md 原文最后更新
  • Flamingo

    基于已有的图像模型和文本模型构建多模态模型 最终模型的输入是图像 视频和文本 输出是文本 Vision encoder来自预训练的NormalizerFree ResNet NFNet 之后经过图文对比损失进一步学习 图片经过Vision
  • antd中Tabs切换控制其他地方的标签显隐(react)

    antd中Tabs切换控制其他地方的标签的显示与隐藏 过程如下 tab的回调函数 拿到key值之后就离成功不远了 然后在右边的标签下还有内容 也需要根据tab切换去控制显隐 和上面是一个道理 可以直接给里面的每个div类名 根据key值 去
  • Java写一个excel工具类_Java操作Excel工具类(poi)

    1 importorg apache commons lang3 exception ExceptionUtils 2 importorg apache poi hssf usermodel HSSFDataFormat 3 importo
  • STM32传感器外设集 -- 蓝牙(HC-05)+超声波(hc-sr04)

    前言 前言 蓝牙外设还没有给大家安排上 今天我就给大家安排上使用蓝牙传输超声波距离的例程 会给大家附带蓝牙的上位机的测试APP 一 模块介绍 1 连接图 蓝牙模块 引脚 超声波传感器 引脚 GND GND GND GND VCC 3 3 V