今日学习配置HC-05蓝牙模块 与 STM32 F103C8T6 单片机的通信:
文章提供测试代码讲解、完整工程下载、测试效果图
主要需要用到的知识: 串口通信
目标是配置单片机串口1 与 HC-05蓝牙模块的通信,并借此传送数据打印数据给手机APP
目录
HC-05蓝牙模块:
基本特性:
默认波特率 9600
引脚功能介绍:
模块STA指示灯:
模块自带了一个状态指示灯:STA。该灯有3种状态:
①在模块上电的同时(也可以是之前),将KEY设置为高电平(接
VCC),此时STA慢闪(1秒亮1次),模块进入AT状态,且此时波
特率固定为38400。
②在模块上电的时候,将KEY悬空或接GND,此时STA快闪(1秒2
次),表示模块进入可配对状态。如果此时将KEY再拉高,模块也
会进入AT状态,但是STA依旧保持快闪。
③模块配对成功,此时STA双闪(一次闪2下,2秒闪一次)。
有了STA指示灯,我们就可以很方便的判断模块的当前状态,方便
大家使用。
HC-05 AT指令集:
模块是通过一个串口TTL接口,既实现AT指令来设置和查询相关参数,同时实现串口数据透传。所以,模块必定有两种模式:
1)AT指令模式
2)串口透传通信模块
两种模式通信波特率可能不一样
HC-05蓝牙模块AT预设:
我们首先要使用USB 转TTL模块与HC-05蓝牙模块 进行连接,通过PC上位机的串口助手来对它的一些参数进行预设:
有 2 种方法使模块进入 AT 指令状态:1 ,上电同时 / 上电之前将 KEY 设置为 VCC , 上电后,模块即进入 AT 指令状态。2 ,模块上电后,通过将 KEY 接 VCC ,使模块进 入 AT 状态。方法 1 ( 推荐 )进入 AT 状态后, 模块的波特率为:38400 ( 8 位数据位, 1 位停止 位)。方法 2 进入 AT 状态后,模块波特率和通信波特率一致。
1、连线提示:
HC-05蓝牙模块 USB 转TTL模块 RXD TXD TXD RXD GND GND VCC VCC KEY(进入AT模式用) VCC
2、上位机发送AT指令对模块进行预设:
发送版本查询指令:
AT+VERSION?\r\n
正确反馈如下图所示:
查询模块目前的串口配置:
AT+UART?\r\n
AT指令对蓝牙模块进行串口波特率、停止位、校验的配置:
AT+UART=115200,0,0\r\n
这段指令表示设置波特率为115200,1位停止位,无校验:
AT配置蓝牙模块名称:
AT+NAME=Violet\r\n
配置蓝牙名称为Violet:
AT配置蓝牙PSWD配对密码:
AT+PSWD=1234\r\n
这个配对密码只能4位字节长度
HC-05蓝牙模块与单片机的连接:
经过上文的上位机串口AT指令配置后,我们就不需要让单片机对蓝牙模块进行额外配置了:
因此KEY就不需要连接高电平,可以悬空了:
HC-05蓝牙模块 STM32F103 C8T6 RXD PA9 TXD PA10 GND GND VCC 5V / VCC 这里蓝牙模块是与STM32的串口1的TXD RXD引脚通信连接的......
测试程序设计:
根据之前的AT指令配置:
蓝牙模块的通信波特率被改为了 115200,1停止位,0校验
并且蓝牙的名称被改为了Violet 蓝牙PSWD配对密码 为1234
这里就尝试设计一个程序:STM32初始化串口1,和一个1s周期定时器,每隔1s发送一次数据给蓝牙模块,然后使用手机连接蓝牙进行测试效果检验:
单片机与蓝牙测试代码:
串口1初始化:
void Usart1_Init(unsigned int baud)
{
GPIO_InitTypeDef gpio_initstruct;
USART_InitTypeDef usart_initstruct;
NVIC_InitTypeDef nvic_initstruct;
// 打开串口GPIO的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 打开串口外设的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
//PA9 TXD // 将USART Tx的GPIO配置为推挽复用模式
gpio_initstruct.GPIO_Mode = GPIO_Mode_AF_PP;
gpio_initstruct.GPIO_Pin = GPIO_Pin_9;
gpio_initstruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpio_initstruct);
//PA10 RXD // 将USART Rx的GPIO配置为浮空输入模式
gpio_initstruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
gpio_initstruct.GPIO_Pin = GPIO_Pin_10;
gpio_initstruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpio_initstruct);
usart_initstruct.USART_BaudRate = baud; //配置波特率
usart_initstruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件流控
usart_initstruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //接收和发送
usart_initstruct.USART_Parity = USART_Parity_No; //无校验
usart_initstruct.USART_StopBits = USART_StopBits_1; //配置停止位 1位停止位
usart_initstruct.USART_WordLength = USART_WordLength_8b; //配置 针数据字长 8位数据位
// 完成串口的初始化配置
USART_Init(USART1, &usart_initstruct);
USART_Cmd(USART1, ENABLE); //使能串口
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //使能接收中断
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /* 嵌套向量中断控制器组选择 */
nvic_initstruct.NVIC_IRQChannel = USART1_IRQn; /* 配置USART为中断源 */
nvic_initstruct.NVIC_IRQChannelCmd = ENABLE; /* 使能中断 */
nvic_initstruct.NVIC_IRQChannelPreemptionPriority = 0; /* 抢断优先级*/
nvic_initstruct.NVIC_IRQChannelSubPriority = 2; /* 子优先级 */
NVIC_Init(&nvic_initstruct); /* 初始化配置NVIC */
}
定时器2初始化:
//初始化定时器2用作计时中断定时器:
void Timer2_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_InternalClockConfig(TIM2);//选择哪个中断就写哪个
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //修改分频,对实际情况影响不大,可以不修改,这里是不分频(可选1~72)
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上对齐模式,同时还有向下对齐,中央对齐模式
TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1; //计数器周期。该参数决定了计数器计数溢出前的最大值。
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //分频器预分频系数。该参数决定了计数器时钟频率的变化程度。
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //高级计数器需要,不需要用到的直接给0就好
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
TIM_ClearFlag(TIM2, TIM_FLAG_Update); //用于解决一复位时就先进一次中断的情况
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //响应优先级
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2, ENABLE);
}
定时器中断服务函数:
//定时器2中断服务函数
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
if(++TimeDisplay_cnt==100) //定时器刷新时间
{
TimeDisplay_cnt=0;T++;printf("%d seconds passed.....",T);
}
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//清出中断寄存器标志位,用于退出中断
}
}
主函数情况:
测试效果图:
发现串口成功发送了蓝牙的数据到手机APP上(蓝牙调试宝):