基于STM32中两蓝牙模块(HC-05)间的通信

一、引脚连接:

        TX - RX

        RX - TX

        GND - GND(接地)

        VCC - VCC(5V)

        EN、STATE不用连接

二、使用的串口工具:

        链接:https://pan.baidu.com/s/1zmHCT-tslNEL-3D1EEWuJQ 
        提取码:z786

CH340驱动:

链接:https://pan.baidu.com/s/1E-2djqB7WT3zi04l3wg45Q 
提取码:ryx5

三、进入AT命令模式:

        1、进入AT命令模式

        HC05 进入AT命令模式需要手一直按住按键然后上电,此时模块红灯慢闪(大概2秒闪一次),模块进入AT模式,电脑串口助手波特率需要调至38400,AT命令后面要加回车换行符(电脑上直接按回车键即可)

        2、需要的AT命令

        测试命令(AT

                

        恢复默认指令(AT+ORGL

            输入命令后,蓝牙会退出AT命令模式,所以需要重新进入。

        设置配对密码(AT+PSWD="0000"

        配置模式(主模式或从模式  AT+ROLE

AT+ROLE=1 (主模式)

AT+ROLE=0 (从模式)

        查询地址(AT+ADDR?

        绑定地址(AT+BIND)

获取到的地址记得把:改为,

        设置波特率(AT+UART=115200,0,0)

此波特率为两个蓝牙通信时的波特率,AT命令模式的波特率还是38400

3、AT命令

1, AT+ROLE设置主从模式:
AT+ROLE=1是设成主,AT+ROLE=0是设成从,AT+ROLE=2设成回环模式Slave-Loop:被动连接,接收远程蓝 牙主设备数据并将数据原样返回给远程蓝牙
AT+ROLE?:查询主从状态
2, AT+RESET:HC-05复位

3, AT+VERSION?:获取HC-05的软件版本号,只能获取,不能修改。

4, AT+ORGL:恢复出厂默认设置,当把模块设置乱了,使用此命令进行恢复默认值。

5, AT+ADDR?:获取HC-05的蓝牙地址码,只能获取,不能修改。

6, AT+NAME?:获取HC-05的名字,AT+NAME=xlg,修改模块的名字为xlg,具体名字自行修改。

7, AT+CLASS?:设置查询设备的类型,尽量不要去修改此参数。默认是1F00。

8, AT+IAC?:查询设置查询访问码,默认是9E8B33,尽量不要去修改此参数。

9, AT+PSWD?:查询设置配对密码,AT+PSWD=”0000”,密码要有双引号,密码是四位数字.

10, AT+UART:AT+UART?是查询当前模块的波特率,AT+UART=波特率,0,0。

11, AT+CMODE:AT+CMODE?是查询当前连接模式。AT+CMODE=0,1,2(0——指定蓝牙地址连接模式(指定蓝牙地址由绑定指令设置)1——任意蓝牙地址连接模式(不受绑定指令设置地址的约束)2——回环角色(Slave-Loop)默认连接模式:0)。

12, AT+BIND:AT+BIND?查询当前绑定地址,AT+BIND=NAP,UAP,LAP(用逗号隔开)。

13, AT+RMADD:从蓝牙配对列表中删除所有认证设备.

14, AT+STATE?:获取蓝牙模块工作状态.

15, AT+LINK=NAP,UAP,LAP:与远程设备建立连接。

16, AT+DISC:断开连接.

17, AT+RNAME?NAP,UAP,LAP:获取远程蓝牙设备名称.

18, AT+ADCN?:获取蓝牙配对列表中认证设备数。

19, AT+MRAD?获取最近使用过的蓝牙认证设备地址。

20, AT+INQM:设置查询模式,AT+INQM=1,9,48(1-带RSSI信号强度指示,9-超过9个蓝牙设备响应则终止查询,48-设定超时为48*1.28=61.44秒)

四、两蓝牙通信配置:

  1、测试

2、复位

3、设置波特率

4、设置配对码

5、设置主从模式

6、绑定地址

从模块绑定主模块地址或主模块绑定主地址都有可以

7、测试通信

先把主从模块断电再上电(不用按按钮),两个模块会自动匹配,匹配成功两模块会按一定频率同时亮灯和灭灯。

此时选择波特率为AT命令设置时的波特率。

五、在STM32中两设备通信

接线:STM32中PTA9接RX,PTA10接TX,PTB1、PTB11为两个按钮,分别为按钮1和按钮2,PTA1、PTA2接两个LED,分别为LED1,LED2

功能:按钮1控制LED2的亮灭,按钮2控制LED1的亮灭

现象:当按钮1按下时,两STM32中LED2同时亮灭,按钮2按下时,两LED1同时亮灭

代码:

串口.c

#include "stm32f10x.h"                  // Device header
#include <stdio.h>
#include <stdarg.h>
#include <String.h>
#include "OLED.h"

char BUF[256];
unsigned short cnt = 0;

/**
  * 函    数:串口初始化
  * 参    数:无
  * 返 回 值:无
  */
void Serial_Init(void)
{
	/*开启时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);	//开启USART1的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//开启GPIOA的时钟
	
	/*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);					//将PA9引脚初始化为复用推挽输出
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);					//将PA10引脚初始化为上拉输入
	
	/*USART初始化*/
	USART_InitTypeDef USART_InitStructure;					//定义结构体变量
	USART_InitStructure.USART_BaudRate = 115200;				//波特率
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	//硬件流控制,不需要
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;	//模式,发送模式和接收模式均选择
	USART_InitStructure.USART_Parity = USART_Parity_No;		//奇偶校验,不需要
	USART_InitStructure.USART_StopBits = USART_StopBits_1;	//停止位,选择1位
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;		//字长,选择8位
	USART_Init(USART1, &USART_InitStructure);				//将结构体变量交给USART_Init,配置USART1
	
	/*中断输出配置*/
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);			//开启串口接收数据的中断
	
	/*NVIC中断分组*/
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);			//配置NVIC为分组2
	
	/*NVIC配置*/
	NVIC_InitTypeDef NVIC_InitStructure;					//定义结构体变量
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;		//选择配置NVIC的USART1线
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//指定NVIC线路使能
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;		//指定NVIC线路的抢占优先级为1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;		//指定NVIC线路的响应优先级为1
	NVIC_Init(&NVIC_InitStructure);							//将结构体变量交给NVIC_Init,配置NVIC外设
	
	/*USART使能*/
	USART_Cmd(USART1, ENABLE);								//使能USART1,串口开始运行
}


/**
  * 函    数:自己封装的prinf函数
  * 参    数:format 格式化字符串
  * 参    数:... 可变的参数列表
  * 返 回 值:无
  */
void Serial_Printf(char *format, ...)
{
	char String[100];				//定义字符数组
	va_list arg;					//定义可变参数列表数据类型的变量arg
	va_start(arg, format);			//从format开始,接收参数列表到arg变量
	vsprintf(String, format, arg);	//使用vsprintf打印格式化字符串和参数列表到字符数组中
	va_end(arg);					//结束变量arg
	uint8_t i =0;
	//串口发送字符数组(字符串)
	for (i = 0; String[i] != '\0'; i ++)//遍历字符数组(字符串),遇到字符串结束标志位后停止
	{
		USART_SendData(USART1, String[i]);		//将字节数据写入数据寄存器,写入后USART自动生成时序波形
		while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);	//等待发送完成
	/*下次写入数据寄存器会自动清除发送完成标志位,故此循环后,无需清除标志位*/
	}
}

/**
  * 函    数:获取串口接收的数据
  * 参    数:无
  * 返 回 值:接收的数据,范围:0~255
  */
uint8_t Serial_GetRxData(void)
{
	return Serial_RxData;			//返回接收的数据变量
}

void Serial_ClearFlag(void)
{
	cnt = 0;
	memset(BUF, 0, sizeof(BUF));
	
}

/**
  * 函    数:USART1中断函数
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数为中断函数,无需调用,中断触发后自动执行
  *           函数名为预留的指定名称,可以从启动文件复制
  *           请确保函数名正确,不能有任何差异,否则中断函数将不能进入
  */
void USART1_IRQHandler(void)
{
	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)		//判断是否是USART1的接收事件触发的中断
	{
		if(cnt >= sizeof(BUF))cnt =0;
		BUF[cnt++] = USART_ReceiveData(USART1);
//		OLED_ShowNum(2,1,cnt,2);
//		OLED_ShowString(3, 1, (char*)BUF);
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);			//清除USART1的RXNE标志位
																//读取数据寄存器会自动清除此标志位														//如果已经读取了数据寄存器,也可以不执行此代码
	}
}

按钮.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

/**
  * 函    数:按键初始化
  * 参    数:无
  * 返 回 值:无
  */
void Key_Init(void)
{
	/*开启时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);		//开启GPIOB的时钟
	
	/*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);						//将PB1和PB11引脚初始化为上拉输入
}

/**
  * 函    数:按键获取键码
  * 参    数:无
  * 返 回 值:按下按键的键码值,范围:0~2,返回0代表没有按键按下
  * 注意事项:此函数是阻塞式操作,当按键按住不放时,函数会卡住,直到按键松手
  */
uint8_t Key_GetNum(void)
{
	uint8_t KeyNum = 0;		//定义变量,默认键码值为0
	
	if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)			//读PB1输入寄存器的状态,如果为0,则代表按键1按下
	{
		Delay_ms(20);											//延时消抖
		while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0);	//等待按键松手
		Delay_ms(20);											//延时消抖
		KeyNum = 1;												//置键码为1
	}
	
	if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0)			//读PB11输入寄存器的状态,如果为0,则代表按键2按下
	{
		Delay_ms(20);											//延时消抖
		while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0);	//等待按键松手
		Delay_ms(20);											//延时消抖
		KeyNum = 2;												//置键码为2
	}
	
	return KeyNum;			//返回键码值,如果没有按键按下,所有if都不成立,则键码为默认值0
}

LED.c

#include "stm32f10x.h"                  // Device header

/**
  * 函    数:LED初始化
  * 参    数:无
  * 返 回 值:无
  */
void LED_Init(void)
{
	/*开启时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);		//开启GPIOA的时钟
	
	/*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);						//将PA1和PA2引脚初始化为推挽输出
	
	/*设置GPIO初始化后的默认电平*/
	GPIO_SetBits(GPIOA, GPIO_Pin_1 | GPIO_Pin_2);				//设置PA1和PA2引脚为高电平
}

/**
  * 函    数:LED1开启
  * 参    数:无
  * 返 回 值:无
  */
void LED1_ON(void)
{
	GPIO_ResetBits(GPIOA, GPIO_Pin_1);		//设置PA1引脚为低电平
}

/**
  * 函    数:LED1关闭
  * 参    数:无
  * 返 回 值:无
  */
void LED1_OFF(void)
{
	GPIO_SetBits(GPIOA, GPIO_Pin_1);		//设置PA1引脚为高电平
}

/**
  * 函    数:LED1状态翻转
  * 参    数:无
  * 返 回 值:无
  */
void LED1_Turn(void)
{
	if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1) == 0)		//获取输出寄存器的状态,如果当前引脚输出低电平
	{
		GPIO_SetBits(GPIOA, GPIO_Pin_1);					//则设置PA1引脚为高电平
	}
	else													//否则,即当前引脚输出高电平
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_1);					//则设置PA1引脚为低电平
	}
}

/**
  * 函    数:LED2开启
  * 参    数:无
  * 返 回 值:无
  */
void LED2_ON(void)
{
	GPIO_ResetBits(GPIOA, GPIO_Pin_2);		//设置PA2引脚为低电平
}

/**
  * 函    数:LED2关闭
  * 参    数:无
  * 返 回 值:无
  */
void LED2_OFF(void)
{
	GPIO_SetBits(GPIOA, GPIO_Pin_2);		//设置PA2引脚为高电平
}

/**
  * 函    数:LED2状态翻转
  * 参    数:无
  * 返 回 值:无
  */
void LED2_Turn(void)
{
	if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_2) == 0)		//获取输出寄存器的状态,如果当前引脚输出低电平
	{                                                  
		GPIO_SetBits(GPIOA, GPIO_Pin_2);               		//则设置PA2引脚为高电平
	}                                                  
	else                                               		//否则,即当前引脚输出高电平
	{                                                  
		GPIO_ResetBits(GPIOA, GPIO_Pin_2);             		//则设置PA2引脚为低电平
	}
}

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"
#include <string.h>
#include "LED.h"
#include "Key.h"

uint8_t RxData;			//定义用于接收串口数据的变量

int main(void)
{
	/*模块初始化*/
	LED_Init();
	Key_Init();
	
	/*串口初始化*/
	Serial_Init();		//串口初始化
	uint8_t Num =0;
	
	while (1)
	{
		Num = Key_GetNum();
		if(1 ==Num)
		{
			Serial_Printf("LED1");
			LED1_Turn();
		}
		if(2 ==Num)
		{
			Serial_Printf("LED2");
			LED2_Turn();
		}
		if (cnt != 0)			//检查串口接收数据的标志位
		{
			if(strstr((const char *)BUF, "LED1") != NULL)
			{
				LED2_Turn();
				Serial_ClearFlag();
			}
			
		}
	}
}

注意事项      

        波特率设置为配置蓝牙时的波特率,如果波特率不一样则通信不会成功

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值