STM32--HC08的使用

开发板用的是正点原子的精英板 STM32F103ZET6 蓝牙模块 用的是HC08

蓝牙模块HC08的简单测试

刚拿到模块的时候,一定要先确定模块是否能正常工作,这能为后续减少很多不必要的麻烦。因为我购买的模块是汇承的,他有一个初学者套餐,也不贵就8,9块钱,对初学者还是很友好的。如果购买了那个的兄弟们,直接按照上面的字母对应接上就行了
初学者套餐
如果没有这个支架也没有关系,这个支架就相当于一个USB转TTL模块,如果你手头上有USB转TTL也是可以直接拿来测试的。
VCC–>3.3V,GND–>GND.TX–>RX,RX–>TX 如下图所示,把线接好就可以插入电脑开始测试了。
在这里插入图片描述
什么!你告诉我你什么都没有,没关系,板子总有吧(前提是板子上有CH340)例如正点原子的精英板,你可以把PA9,PA10的跳线帽拔了,然后把蓝牙用杜邦线接上,TX–>RX,RX–>TX。测试好后记得把跳线帽插回去。接线如下图所示
在这里插入图片描述
把线接好后就可以测试了。打开串口调试助手,波特率选择为9600,把发送新行的勾取消掉然后发送AT 就能收到OK了。
在这里插入图片描述

AT指令

1. 测试指令

指令 说明 响应
AT 检测串口是否正常工作 OK

2. 查看当前基本参数

指令 说明 响应
AT+RX 查询模块的基本参数 Name:HC-08 >>(蓝牙名称)
Role:Slave >>>>(模块角色 主 M / 从 S)
Baud:9600,NONE (串口波特率, 校验位)
Addr:48,70,1E,24,16,27>>(蓝牙地址)
PIN :000000>>>>[ 蓝牙密码 (密码无效) ]

3. 查看当前基本参数

指令 响应 说明 说明
AT+DEFAULT OK 恢复出厂设置) 不会清除主机已记录的从机地址!若要清除请在 未连线状态下使用 AT+CLEAR 指令进行清除。模块会自动重启,重启 200ms 后可进行新的操作!

4.模块重启指令

指令 响应 说明 详情
AT+RESET OK 重启模块 模块会自动重启,重启 200ms 后 可进行新的操作!

5.查看软件版本指令

指令 响应 说明
AT+VERSION HC-08 V3.3,2020-10-16 获取软件版本和发布日期

6.修改模块角色指令

指令 响应 说明 详情
AT+ROLE=x Master/Slave 设置主机/从机 默认从机,设置后模块将自动重启, 重启 200ms 后可进行新的操作!

7.修改蓝牙名称指令

在这里插入图片描述

8.修改蓝牙地址指令

在这里插入图片描述

9.修改射频功率指令

在这里插入图片描述

10.修改串口波特率指令

在这里插入图片描述
在这里插入图片描述

11.设置模块是否可连接指令

在这里插入图片描述

12.更新广播数据指令(仅从机可以设置)

在这里插入图片描述

手机与板子进行通信

蓝牙模块主要的功能就是拿来通信,目前我只是用手机和板子之间进行通信,因为手头资源有限,所以就没有用蓝牙进行两块板子之间的通信

板子,电脑,模块之间的关系

在这里插入图片描述
为了更方便,更直观的观察到接收的数据。这里将串口3接收到的数据通过串口1发给电脑,以至于能在电脑上显示蓝牙模块接收的数据

实验效果

手机发送特定的指令来控制板子上的LED亮灭,并且在电脑上显示手机发送的内容,电脑可以通过串口调试助手将数据发到手机上。

部分代码

串口3的配置

//串口接收缓存区 	
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(TIM7,0);//计数器清空          				//计数器清空
				if(USART3_RX_STA==0) 				//使能定时器7的中断 
				{
					TIM_Cmd(TIM7,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寄存器
	
	
	TIM7_Int_Init(99,7199);		//10ms中断
	USART3_RX_STA=0;		//清零
	TIM_Cmd(TIM7,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]); 
	} 
}

串口三中是通过判断接收连续2个字符之间的时间差不大于10ms来决定是不是一次连续的数据,因此还需要开启定时器

extern vu16 USART3_RX_STA;

//定时器7中断服务程序		    
void TIM7_IRQHandler(void)
{ 	
	if (TIM_GetITStatus(TIM7, TIM_IT_Update) != RESET)//是更新中断
	{	 			   
		USART3_RX_STA|=1<<15;	//标记接收完成
		TIM_ClearITPendingBit(TIM7, TIM_IT_Update  );  //清除TIM7更新中断标志    
		TIM_Cmd(TIM7, DISABLE);  //关闭TIM7 
	}	    
}
 
//通用定时器7中断初始化
//这里时钟选择为APB1的2倍,而APB1为42M
//arr:自动重装值。
//psc:时钟预分频数
//定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=定时器工作频率,单位:Mhz 
//通用定时器中断初始化
//这里始终选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数		 
void TIM7_Int_Init(u16 arr,u16 psc)
{	
	NVIC_InitTypeDef NVIC_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);//TIM7时钟使能    
	
	//定时器TIM7初始化
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM7, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
 
	TIM_ITConfig(TIM7,TIM_IT_Update,ENABLE ); //使能指定的TIM7中断,允许更新中断
	
	TIM_Cmd(TIM7,ENABLE);//开启定时器7
	
	NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//抢占优先级0
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;		//子优先级2
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
	
}
	 

主函数部分就很简单了,就像上图那样,将串口3接收到的数据,用串口1发出去,将电脑发的信息通过串口3发给模块,进而在手机上显示。

如果想做一个手机蓝牙控制开关灯的东西,那么只需要再加上一个pwm控制舵机的部分,就可以实现了
最后,第一次写,主要是记录自己的学习过程,如果那里有错的地方,还请大家指出,互相学习,共同进步

版权声明:本文为CSDN博主「释怀。。」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_52422778/article/details/122123388

生成海报
点赞 0

释怀。。

我还没有学会写个人说明!

暂无评论

相关推荐

RT-Thread Studio移植LAN8720A驱动

RTT网络协议栈驱动移植(霸天虎) 1、新建工程 ​ 工程路径不含中文路径名,工程名用纯英文不含任何符号。 2、用CubeMx配置板子外设 2.1、配置时钟 ​ 按照自己板子配置相应时钟。

Lin总线通信在STM32作为主机代码以及从机程序

距离上次做资料准备已经过去六天了。最近在学车,上周末就没有开电脑。这周开始进行了Lin通信的代码整理,目前是可以正常通信的了,采用的是增强型校验方式。后期再进一步跟进研究。。。更新一博,留

4路红外循迹模块使用教程

4路红外循迹模块使用教程 个人原创博客:点击浏览模块详细信息: 工作电压:DC 3.3V~5V 工作电流:尽量选择1A以上电源供电 工作温度:-10℃~50℃ 安装孔

【STM32Cube笔记】12-配置外部中断

【STM32Cube笔记】系列文章目录 1-基于STM32的VSCode入门级教程前言 2-STM32Cube安装教程 3-STM32CubeIDE汉化 4-STM32Cube配置时钟设置 5-跑马灯引脚配置 6-Cortex-M7内核基本配