一、蓝牙模块参数简介
- 蓝牙模块:汇承HC05蓝牙串口通信模块。
- 蓝牙协议:Bluetooth Specification V2.0带EDR蓝牙协议。
- 无线工作频段为2.4GHz ISM。
- 调制方式是GFSK。
- 模块最大发射功率为4dBm。
- 接收灵敏度-85dBm。
- 板载PCB天线,可以实现10米距离通信。
- 自带LED灯,可直观判断蓝牙的连接状态。
- 模块采用CSR的BC417芯片,支持AT 指令。
- 用户可根据需要更改角色(主、从模式)以及串口波特率、设备名称等参数,使用灵活。
二、系列产品
三、工作原理简介
1、工作原理
如上图所示,HC-05 模块用于代替全双工通信时的物理连线。左边的设备向模块发送串口数据,模块的 RXD 端口收到串口数据后,自动将数据以无线电波的方式发送到空中。右边的模块能自动接收到,并从 TXD 还原最初左边设备所发的串口数据。从右到左也是一样的。
2、模块与单片机 MCU 等设备的连接
①:模块与供电系统为 3.3V 的 MCU 连接时,串口交叉连接即可(模块的 RX 接 MCU 的 TX、模块的 TX 接 MCU
的 RX)
②:模块与供电系统为 5V 的 MCU 连接时,可在模块的 RX 端串接一个 220R~1K 电阻再接 MCU 的 TX,模块的
TX 直接接 MCU 的 RX,无需串接电阻。(注:请先确认所使用的 MCU 把 3.0V 或以上电压认定为高电平,否则需
加上 3.3V/5V 电平转换电路)
注:模块的电源为 3.3V,不能接 5V, 5V 的电源必须通过 LDO 降压到 3.3V 后再给模块供电。
四、蓝牙模式及AT指令
1、AT指令模式
用于设置蓝牙的相关信息(名字,配对密码,波特率(9600))按下模块上的按键,上电,即可进行AT指令模式,led灯慢闪表示进入AT模式,双闪表示蓝牙已连接并打开了端口。
2、数据透传模式
上电后就进入了数据透传模式,此时蓝牙模块led灯快闪,连接后led灯双闪。在此模式下连接后可以传输数据。
3、常用的AT指令
①测试:AT 返回:OK (即通信成功)
②设置蓝牙名称:AT+NAME=PDD 返回:OK
③查询蓝牙名称:AT+NAME? 返回:+NAME=PDD OK
④设置配对密码:AT+PSWD=1234 返回:OK
⑤查询配对密码:AT+PSWD? 返回:+PSWD=1234 OK
⑥查询设备mac地址:AT+ADDR? 返回:+ADDR:21:13:52b9b OK
五、蓝牙调试
手机可以下载蓝牙调试器或者关注蓝牙调试公众号,蓝牙模块在数据透传模式可以用来连接蓝牙模块,并且给蓝牙模块发送数据,也可以通过编辑按钮,按按钮发送数据给蓝牙模块,蓝牙模块收到数据后通过串口发给MCU,从而控制MCU的一些外设
六、STM32F407ZET6与蓝牙模块连接
如上图U转UART1的RXD和TXD通过CH340芯片连接USB,可以通过USB连接电脑,用串口工具给MCU发数据和接收数据,USART1_TX和UASRT1_RX是和主芯片连着,调帽跳到1-3、2-4。如果蓝牙要和MCU通信,则调帽3-5、4-6相连,此时连到P4,将蓝牙模块的RXD和P4的TXD1连接,TXD和P4的RXD1连接,此时蓝牙模块就可以就可以和MCU通信.
实验一:通过手机连接蓝牙控制蜂鸣器的响灭。
//uart.c文件 #include "uart.h" void Uart_Init(uint32_t band) { GPIO_InitTypeDef GPIO_InitStruct; USART_InitTypeDef USART_InitStruct; NVIC_InitTypeDef NVIC_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //1、初始化硬件 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_25MHz; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_Init(GPIOA, &GPIO_InitStruct); //复用为串口1 GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); USART_InitStruct.USART_BaudRate = band; USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件控制流 USART_InitStruct.USART_Mode = USART_Mode_Tx|USART_Mode_Rx ; USART_InitStruct.USART_Parity= USART_Parity_No; //无奇偶校验 USART_InitStruct.USART_StopBits = USART_StopBits_1; USART_InitStruct.USART_WordLength = USART_WordLength_8b; USART_Init(USART1, &USART_InitStruct); //初始化NVIC NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x1;//抢占优先级 0-3 NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x1;//响应占优先级 0-3 NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;//中断向量号 TIM3 中断向量号位tim3 NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//使能 NVIC_Init(&NVIC_InitStruct); //串口中断 USART_ITConfig(USART1, USART_IT_RXNE,ENABLE); USART_Cmd(USART1,ENABLE); } //main函数 #include "stdio.h" uint16_t uart1_recv_data; //重定向fputc fputs fgetc fgets int fputc(int ch,FILE *f) { USART_SendData(USART1, ch); while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET); return ch; } //串口进入中断接收蓝牙发过来的数据 void USART1_IRQHandler() { if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { //清楚中断标志位 往里面写1 记住一定要清空 USART_ClearITPendingBit(USART1,USART_IT_RXNE); uart1_recv_data = USART_ReceiveData(USART1); } } //给蓝牙模块发数据 void USART_SendString(const uint8_t* str) { u8 i = 0; while(*(str+i)!=' ') { USART_SendData(USART1, *(str+i)); while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET); i++; } } int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //给中断优先级分组 LED_Init(); Key_Init(); Beep_Init(); Uart_Init(9600); //和蓝牙模块的波特率一致 printf("hello"); while(1) { if(uart1_recv_data == '1') { PFout(8) =1; } if(uart1_recv_data == '0') { PFout(8) =0; } delay_s(1); } return 0; }//uart.c文件 #include "uart.h" void Uart_Init(uint32_t band) { GPIO_InitTypeDef GPIO_InitStruct; USART_InitTypeDef USART_InitStruct; NVIC_InitTypeDef NVIC_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //1、初始化硬件 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_25MHz; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_Init(GPIOA, &GPIO_InitStruct); //复用为串口1 GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); USART_InitStruct.USART_BaudRate = band; USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件控制流 USART_InitStruct.USART_Mode = USART_Mode_Tx|USART_Mode_Rx ; USART_InitStruct.USART_Parity= USART_Parity_No; //无奇偶校验 USART_InitStruct.USART_StopBits = USART_StopBits_1; USART_InitStruct.USART_WordLength = USART_WordLength_8b; USART_Init(USART1, &USART_InitStruct); //初始化NVIC NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x1;//抢占优先级 0-3 NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x1;//响应占优先级 0-3 NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;//中断向量号 TIM3 中断向量号位tim3 NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//使能 NVIC_Init(&NVIC_InitStruct); //串口中断 USART_ITConfig(USART1, USART_IT_RXNE,ENABLE); USART_Cmd(USART1,ENABLE); }
//main函数 ------通过手机连接蓝牙控制蜂鸣器的响灭。 #include "stdio.h" uint16_t uart1_recv_data; //重定向fputc fputs fgetc fgets int fputc(int ch,FILE *f) { USART_SendData(USART1, ch); while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET); return ch; } //串口进入中断接收蓝牙发过来的数据 void USART1_IRQHandler() { if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { //清楚中断标志位 往里面写1 记住一定要清空 USART_ClearITPendingBit(USART1,USART_IT_RXNE); uart1_recv_data = USART_ReceiveData(USART1); } } //给蓝牙模块发数据 void USART_SendString(const uint8_t* str) { u8 i = 0; while(*(str+i)!=' ') { USART_SendData(USART1, *(str+i)); while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET); i++; } } int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //给中断优先级分组 LED_Init(); Key_Init(); Beep_Init(); Uart_Init(9600); //和蓝牙模块的波特率一致 printf("hello"); while(1) { if(uart1_recv_data == '1') { PFout(8) =1; } if(uart1_recv_data == '0') { PFout(8) =0; } delay_s(1); } return 0; }
实验二、usart1连接电脑串口,usart3连接蓝牙模块,串口调试工具和蓝牙模块通信,串口工具发命令给usart1,usart1发给usart3到蓝牙模块。(注意stm32Fxx.h修改晶振频率为8M)
#include "stm32f4xx.h" #include "stm32f4xx_gpio.h" #include "stm32f4xx_rcc.h" #include "stm32f4xx_usart.h" #include "stdio.h" static GPIO_InitTypeDef GPIO_InitStructure; static USART_InitTypeDef USART_InitStructure; static NVIC_InitTypeDef NVIC_InitStructure; static uint8_t g_usart1_recv_buf[128]={0}; static uint8_t g_usart1_recv_cnt = 0; //重定义fputc函数 int fputc(int ch, FILE *f) { USART_SendData(USART1,ch); while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET); return ch; } void delay_us(int nus) //微秒 { //SystemCoreClock SysTick->LOAD = (SystemCoreClock/8/1000000) * nus; //定时时间 SysTick->CTRL |= 1; //开启定时器,开始计数 while((SysTick->CTRL & (1<<16)) == 0); //等待定时时间到 SysTick->CTRL &=~1; //关闭定时器 } void delay_ms(int nms) //毫秒 { uint32_t m,n; m = nms/500; n = nms%500; while(m--) { SysTick->LOAD = (SystemCoreClock/8/1000) * 500; //定时时间 SysTick->CTRL |= 1; //开启定时器,开始计数 while((SysTick->CTRL & (1<<16)) == 0); //等待定时时间到 SysTick->CTRL &=~1; //关闭定时器 } if(n) { SysTick->LOAD = (SystemCoreClock/8/1000) * n; //定时时间 SysTick->CTRL |= 1; //开启定时器,开始计数 while((SysTick->CTRL & (1<<16)) == 0); //等待定时时间到 SysTick->CTRL &=~1; //关闭定时器 } } void LED_Init(void) { //使能GPIOE,GPIOF时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOF, ENABLE); //GPIOF9,F10初始化设置 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //LED0和LED1对应IO口 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //普通输出模式, GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出,驱动LED需要电流驱动 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉 GPIO_Init(GPIOF, &GPIO_InitStructure); //初始化GPIOF,把配置的数据写入寄存器 //GPIOE13,PE14初始化设置 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14; //LED2和LED3对应IO口 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //普通输出模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉 GPIO_Init(GPIOE, &GPIO_InitStructure); //初始化GPIOE,把配置的数据写入寄存器 GPIO_SetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10); //GPIOF9,PF10设置高,灯灭 GPIO_SetBits(GPIOE,GPIO_Pin_13 | GPIO_Pin_14); } void USART1_Init(uint32_t baud) { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //使能USART1时钟 //串口1对应引脚复用映射 GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为USART1 GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1 //USART1端口配置 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉 GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10 //USART1 初始化设置 USART_InitStructure.USART_BaudRate = baud; //波特率设置 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(USART1, &USART_InitStructure); //初始化串口1 USART_Cmd(USART1, ENABLE); //使能串口1 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启相关中断 //Usart1 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //串口1中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3; //抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 } void USART3_Init(uint32_t baud) { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); /* GPIOB Configuration: PB10 PB11 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ; GPIO_Init(GPIOB, &GPIO_InitStructure); /* Connect USART3_TX pins to PB10 */ GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3); /* Connect USART3_RX pins to PB11 */ GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3); /* Enable USART3 clock */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); USART_InitStructure.USART_BaudRate = baud; USART_InitStructure.USART_WordLength = USART_WordLength_8b; 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); /* Enable the USARTx Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* Enable USART3 */ USART_Cmd(USART3, ENABLE); /* Enable the Rx buffer empty interrupt */ USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); } void USART1_SendBytes(uint8_t *pbuf,uint32_t len) { while(len--) { USART_SendData(USART1,*pbuf++); while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET); } } void USART1_SendString(uint8_t *pstr) { while(pstr && *pstr) { USART_SendData(USART1,*pstr++); while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET); } } void USART3_SendBytes(uint8_t *pbuf,uint32_t len) { while(len--) { USART_SendData(USART3,*pbuf++); while(USART_GetFlagStatus(USART3,USART_FLAG_TXE)==RESET); } } void USART3_SendString(uint8_t *pstr) { while(pstr && *pstr) { USART_SendData(USART3,*pstr++); while(USART_GetFlagStatus(USART3,USART_FLAG_TXE)==RESET); } } int main(void) { LED_Init(); //系统定时器初始化,时钟源来自HCLK,且进行8分频, //系统定时器时钟频率=168MHz/8=21MHz SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //设置中断优先级分组2 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //串口1,波特率115200bps,开启接收中断 USART1_Init(115200); //串口3,波特率9600bps,开启接收中断 USART3_Init(38400); while(1) { } } void USART1_IRQHandler(void) //串口1中断服务程序 { if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断 { //从串口1接收数据 g_usart1_recv_buf[g_usart1_recv_cnt]=USART_ReceiveData(USART1); USART_SendData(USART1, g_usart1_recv_buf[g_usart1_recv_cnt]); //记录多少个数据 g_usart1_recv_cnt++; //检测到换行符或接收的数据满的时候则发送数据 if(g_usart1_recv_buf[g_usart1_recv_cnt-1]==' ' || g_usart1_recv_cnt>=(sizeof g_usart1_recv_buf)-1) { USART3_SendBytes(g_usart1_recv_buf,g_usart1_recv_cnt); USART1_SendBytes(g_usart1_recv_buf,g_usart1_recv_cnt); g_usart1_recv_cnt = 0; } } } void USART3_IRQHandler(void) { uint8_t d; /* USART in Receiver mode */ if (USART_GetITStatus(USART3, USART_IT_RXNE) == SET) { d=USART_ReceiveData(USART3); USART1_SendBytes(&d,1); } }