最近在学STM32.基础学完了,想学几个模块巩固知识,就想到了蓝牙模块。玩什么好难过?有很多博客教你怎么连接,但是你看起来还是有点迷茫。我就不解释模块的原理和知识点了。我主要在这里手把手记录我是如何学习和使用蓝牙模块的。
我会把使用的信息和工具放在最后的链接里,需要的话可以自己下载。
模块名称:HC-05蓝牙串口通信模块
其他模块:USB转TTL模块、杜邦线、蓝牙串口助手app
初步调试蓝牙模块
因为我们只使用蓝牙模块的传输功能,只需要四个引脚(RXT、TXD、GND、VCC)
先用杜邦线将USB转TTL模块和HC-蓝牙模块连接05
共电、共地、两个模块TX和RX交换相接(USB转TTL的TX(RX)接蓝牙的RX(TX))
如图所示:
然后将USB转TTL将模块插入计算机,并通过串口助手进行调试。
蓝牙模块通信模式有两种工作模式:命令响应工作模式和自动连接工作模式(可分为三个角色:自动连接工作模式、从和回环)
给模块上电即插USB按住蓝牙HC-当模块进入05模块的小按钮时AT模式
蓝牙模块上有一盏小灯。当灯闪烁时,它是自动连接模式。慢闪时,命令响应工作模式
命令响应模式的波特率固定在38400,可直接用串口助手发送AT指令。
AT命令
AT指令不区分大小写,但应以回车符结束
以下是常用的AT指令
注意:AT NAME?也许没有返回数据,我们可以直接设置蓝牙名称
接下来,我们的主要配置是
蓝牙名称及串口参数(波特率、停止位、验证位)
如图:
设置好后把手usb拔下并重新上电时,默认为自动连接模式。此时,使用手机的蓝牙助手连接蓝牙模块并进行通信。我也会把蓝牙助手放在后面的数据链接中。
将串口助手波特率设置为115200,在手机蓝牙中发送信息,并在串口助手中显示。
最后,我们将在这里STM32开发板连接蓝牙进行信息传输控制LED灯
我会把源码放在后面的数据里一起打包。
在这里,我们使用串口1,因为串口1是我开发板的下载串口,所以在连接蓝牙模块之前,我们需要下载代码TX和RX,若使用其它串口进行通信改为其它串口,则连接方式如图所示:
蓝牙模块的RX连PA9,TX连PA10,VCC接板载的5V,GND接板子的GND即可
因为我用的是野火开发板,用的LED灯是个RGB灯,你只需要初始化串口,然后看看main函数中的逻辑实现了自己的板LED灯也可以在中断函数中操作灯。
接下来可以举一反三,用蓝牙返回信息等操作。
需要自行提取数据:链接:https://pan.baidu.com/s/1iGrbTiivAsTwzd9wDLYFaQ 提取码:3sp6
还有一个数据HC蓝牙助手可以自定义按钮发送信息。
串口控制LED灯的代码如下:
usart.c:
#include "bsp_usart.h" //static void NVIC_Configuration(void) //配置中断优先级,这里不使用中断,所以屏蔽 //{ // NVIC_InitTypeDef NVIC_InitStructure; // // /* 选择嵌套向量中断控制器组 */ // NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // // /* 配置USART为中断源 */ // NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ; // /* 抢断优先级*/ // NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // /* 子优先级 */ // NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // /* 使能中断 */ // NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // /* 初始化配置NVIC */ // NVIC_Init(&NVIC_InitStructure); //} void USART_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; // 打开串口GPIO的时钟 #include "stm32f10x.h" // Device header DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE); // 打开串口外设的时钟 DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE); // 将USART Tx的GPIO配置为推挽复用模式 #include "stm32f10x.h" // Device header GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure); // 将USART Rx的GPIO配置为浮空输入模式 GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure); // 配置串口工作参数 // 配置波特率 USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE; // 配置 针数据字长 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(DEBUG_USARTx, &USART_InitStructure); // // 优先配置串口中断 // NVIC_Configuration(); // // // 使串口接收中断 // USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE); // 使能串口 USART_Cmd(DEBUG_USARTx, ENABLE); } /* 发送字节 */ void Usart_SendByte(USART_TypeDef* pUSARTx, uint8_t data) { USART_SendData(pUSARTx, data); while( USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET ); } /* 发送两个字节的数据 */ void Usart_SendHalfWord(USART_TypeDef* pUSARTx, uint16_t data) { uint8_t temp_h,temp_l; temp_h = (data&0xff00) >> 8 ; temp_l = data&0xff; USART_SendData(pUSARTx, temp_h); while( USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET ); USART_SendData(pUSARTx, temp_l); while( USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET ); } /* 数组发送8位数据 */ void Usart_SendArray(USART_TypeDef* pUSARTx, uint8_t *array,uint8_t num) { uint8_t i; for(i=0; i<num; i++ )
{
Usart_SendByte(pUSARTx, array[i]);
}
while( USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET );
}
/* 发送字符串 */
void Usart_SendStr(USART_TypeDef* pUSARTx, uint8_t *str)
{
uint8_t i=0;
do
{
Usart_SendByte(pUSARTx, *(str+i));
i++;
}while(*(str+i) != '\0');
while( USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET );
}
///重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
/* 发送一个字节数据到串口 */
USART_SendData(DEBUG_USARTx, (uint8_t) ch);
/* 等待发送完毕 */
while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);
return (ch);
}
///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{
/* 等待串口输入数据 */
while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);
return (int)USART_ReceiveData(DEBUG_USARTx);
}
main.c
int main(void)
{
uint8_t ch;
USART_Config();
LED_GPIO_Config();
printf( "这是一个串口控制RGB灯的程序\n" );
while (1)
{
ch = getchar();
printf( "ch=%c\n",ch );
switch(ch)
{
case '1': LED_RED;
break;
case '2': LED_GREEN;
break;
case '3': LED_BLUE;
break;
default: LED_RGBOFF;
break;
}
}
}
led.c
#include "bsp_led.h"
/**
* @brief 初始化控制LED的IO
* @param 无
* @retval 无
*/
void LED_GPIO_Config(void)
{
/*定义一个GPIO_InitTypeDef类型的结构体*/
GPIO_InitTypeDef GPIO_InitStructure;
/*开启LED相关的GPIO外设时钟*/
RCC_APB2PeriphClockCmd( LED1_GPIO_CLK | LED2_GPIO_CLK | LED3_GPIO_CLK, ENABLE);
/*选择要控制的GPIO引脚*/
GPIO_InitStructure.GPIO_Pin = LED1_GPIO_PIN;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*调用库函数,初始化GPIO*/
GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure);
/*选择要控制的GPIO引脚*/
GPIO_InitStructure.GPIO_Pin = LED2_GPIO_PIN;
/*调用库函数,初始化GPIO*/
GPIO_Init(LED2_GPIO_PORT, &GPIO_InitStructure);
/*选择要控制的GPIO引脚*/
GPIO_InitStructure.GPIO_Pin = LED3_GPIO_PIN;
/*调用库函数,初始化GPIOF*/
GPIO_Init(LED3_GPIO_PORT, &GPIO_InitStructure);
/* 关闭所有led灯 */
GPIO_SetBits(LED1_GPIO_PORT, LED1_GPIO_PIN);
/* 关闭所有led灯 */
GPIO_SetBits(LED2_GPIO_PORT, LED2_GPIO_PIN);
/* 关闭所有led灯 */
GPIO_SetBits(LED3_GPIO_PORT, LED3_GPIO_PIN);
}
/*********************************************END OF FILE**********************/