前言:
在我没接触蓝牙之前,我觉得蓝牙模块应用起来应该挺麻烦,后来发觉这个蓝牙模块的应用本质无非就是一个串口
蓝牙模块:
这是我从某宝上买到的蓝牙模块HC-08,价格还算可以,而且可以适用于大多数蓝牙调试软件。回到刚开始说的话,蓝牙模块的应用和单片机的串口几乎是一样的,我们可以用USB转TTL模块与HC-08模块进行通信,虽说HC-08有6个引脚,但是我们只用4个,连接方式如下对应
USB转TTL | HC-08 |
3V3 | VCC |
TXD | RXD |
RXD | TXD |
GND | GND |
连接之后,蓝牙模块蓝色灯闪烁(没和手机连接)。串口助手选择波特率为9600,我们可以直接用串口助手发送AT指令,当蓝牙模块回馈OK的时候,说明我们的蓝牙模块没有问题。
接下来给大家罗列一下常用的AT指令
指令 | 响应 | 说明 |
AT | OK | 检验串口是否正常工作 |
AT+RX | Name:HC-08 >>(蓝牙名称) Role:Slave >>>>(模块角色 主 M / 从 S) Baud:9600,NONE (串口波特率, 校验位) Addr:48,70,1E,24,16,27>>(蓝牙地址) PIN :000000>>>>[ 蓝牙密码 (密码无效) ] | 查询模块的基本参数 |
AT+DEFAULT | OK | 恢复出厂设置,不会清除主机已记录的从机地址!若要清除请在 未连线状态下使用 AT+CLEAR 指令进行清除。模块会自动重启,重启 200ms 后可进行新的操作 |
AT+RESET | OK | 重启模块,模块会自动重启,重启 200ms 后 可进行新的操作 |
AT+VERSION | HC-08 V3.3,2020-10-16 | 获取软件版本和发布日期 |
AT+ROLE=x | Master/Slave | 设置主机/从机;默认从机,设置后模块将自动重启, 重启 200ms 后可进行新的操作 |
STM32驱动HC-08例程:
下面是我的部分代码,包括了初始化部分,和中断部分,看完这部分代码,我们就更能理解为啥我说蓝牙模块的应用和串口几乎一致。因为我的蓝牙模块连接的刚好是USART2,所以代码部分如下
void USART2_Init(unsigned int Baudrate)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//TX
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//RX
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = Baudrate;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //关闭硬件流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
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(USART2, &USART_InitStructure);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //允许接收中断
USART_Cmd(USART2, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = USART2_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 USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2,USART_IT_RXNE) == 1) //USART_FLAG_RXNE判断数据,== 1则有数据
{
if(Receive_sum > 49) //数组能存放50个字节的数据
{
USART_ReceiveString[49] = '\0'; //数据字节超过50位时,将最后一位设置为\0
Receive_Flag = 1; //接收标志位置1,停止接收数据
Receive_sum = 0; //数组下标置0
}
if(Receive_Flag == 0) //接收标志位等于0,开始接收数据
{
USART_ReceiveString[Receive_sum] = USART_ReceiveData(USART2); //通过USART2串口接收字符
Receive_sum++; //数组下标++
if(USART_ReceiveString[Receive_sum-1] == '%')
{
Receive_Flag = 1;
Receive_sum = 0;
printf("%s\r\n",USART_ReceiveString);
if(strcmp(USART_ReceiveString,"channel:1%") == 0)
{
FSM_led = LED_state1;
FSM_hc08 = Channel_1;
Receive_Flag = 0;
}
else if(strcmp(USART_ReceiveString,"channel:2%") == 0)
{
FSM_led = LED_state2;
FSM_hc08 = Channel_2;
Receive_Flag = 0;
}
}
}
USART_ClearITPendingBit(USART2,USART_IT_RXNE); //接收后先清空标志位
}
}