基础:
HC-05是一个主从机一体的蓝牙模块,也可以称之为无线串口透传模块。它可以让不懂蓝牙通信协议的零基础小白也能够使用蓝牙进行设备通讯。
我使用的这款是有6个引脚的,但是只要使用其中4个引脚就可以完成串口通信的功能了,这四个引脚分别是RXD、TXD、GND、VCC,剩下的两个引脚是配置蓝牙模块用的,在进行简单通信时并不需要。
思路:
我的思路很简单,模块使用串口通信,STM32的HAL库已经为我们封装好了串口通信的函数。
所以我们直接使用STM32CubeMx配置两个用于串口收发的引脚RX和TX即可。
波特率要与蓝牙模块保持一致,这里我们设置为9600。
代码:
#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
#include "oled.h"
//一个枚举,包含灯的状态,方便等会儿状态机编程
typedef enum
{
normal,
shut,
shine,
run,
water,
breath
} LED_MODE;
LED_MODE mode = normal;//初始化为正常开灯
char receive[2];//用于存储串口接受的数据
void ShowCharacter(void);//用于控制OLED屏显示内容的函数
void main_loop(void);//用于控制灯
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM3_Init();
MX_USART3_UART_Init();
OLED_Init();
ShowCharacter();
HAL_UART_Receive_IT(&huart3,(uint8_t *)receive,2);//打开串口接收中断
while (1)
{
main_loop();//灯
}
}
void ShowCharacter()
{
OLED_ShowChinese(16,0,32,2,3);//我
OLED_ShowChinese(32,0,48,2,4);//的
OLED_ShowChinese(48,0,64,2,5);//智
OLED_ShowChinese(64,0,80,2,6);//能
OLED_ShowChinese(80,0,96,2,7);//家
OLED_ShowChinese(96,0,112,2,8);//居
OLED_ShowString(3,1,"LED");
OLED_ShowChar(3,4,58);
OLED_ShowString(3,5,"open");//LED:open(默认灯是打开状态)
}
/*
串口接收中断回调函数
因为中断回调函数长时间占用会阻塞程序执行
所以这里用的是状态机编程
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
//主掌灯
if(receive[0]== 'L')
{
if(receive[1] == '1')//L1开灯
{
mode = normal;
HAL_UART_Transmit(&huart3,(uint8_t *)receive,sizeof(receive),1000);
OLED_ShowString(3,5,"opened ");
}
else if(receive[1] == '0')//L0关灯
{
mode = shut;
HAL_UART_Transmit(&huart3,(uint8_t *)receive,sizeof(receive),1000);
OLED_ShowString(3,5,"closed ");
}
else if(receive[1] == 'S')//LS闪灯
{
mode = shine;
HAL_UART_Transmit(&huart3,(uint8_t *)receive,sizeof(receive),1000);
OLED_ShowString(3,5,"shine ");
}
else if(receive[1] == 'R')//LR跑马灯
{
mode = run;
HAL_UART_Transmit(&huart3,(uint8_t *)receive,sizeof(receive),1000);
OLED_ShowString(3,5,"running");
}
else if(receive[1] == 'W')//LW流水灯
{
mode = water;
HAL_UART_Transmit(&huart3,(uint8_t *)receive,sizeof(receive),1000);
OLED_ShowString(3,5,"water ");
}
}
//主掌蜂鸣器,蜂鸣器就一行代码的事儿,不进行状态机编程
else if(receive[0]== 'B')
{
if(receive[1] == '1')//B1蜂鸣器开
{
HAL_UART_Transmit(&huart3,(uint8_t *)receive,sizeof(receive),1000);
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_14,GPIO_PIN_SET);
OLED_ShowString(4,6,"opened");
}
else if(receive[1] == '0')//B0蜂鸣器关
{
HAL_UART_Transmit(&huart3,(uint8_t *)receive,sizeof(receive),1000);
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_14,GPIO_PIN_RESET);
OLED_ShowString(4,6,"closed");
}
else if(receive[1] == 'L')//BL呼吸灯(本来该写灯那儿的,懒得改了反正效果一样)
{
mode = breath;
OLED_ShowString(3,5,"breath ");
HAL_UART_Transmit(&huart3,(uint8_t *)receive,sizeof(receive),1000);
}
}
//重新打开接收中断
HAL_UART_Receive_IT(&huart3, (uint8_t *)receive, sizeof(receive));
}
//种灯的操作
void main_loop()
{
//呼吸灯
if (mode == breath)
{
int num=0;
for(num=0;num<1500;num++)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,GPIO_PIN_RESET);
delay_us(num);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,GPIO_PIN_SET);
delay_us(1500-num);
}
for(num=1500;num>0;num--)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,GPIO_PIN_RESET);
delay_us(num);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,GPIO_PIN_SET);
delay_us(1500-num);
}
}
//正常开灯
else if(mode == normal)
{
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED4_GPIO_Port,LED4_Pin,GPIO_PIN_RESET);
}
//正常关灯
else if(mode == shut)
{
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED4_GPIO_Port,LED4_Pin,GPIO_PIN_SET);
}
//闪灯
else if(mode == shine)
{
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED4_GPIO_Port,LED4_Pin,GPIO_PIN_RESET);
HAL_Delay(300);
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED4_GPIO_Port,LED4_Pin,GPIO_PIN_SET);
HAL_Delay(300);
}
//跑马灯
else if(mode==run)
{
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED4_GPIO_Port,LED4_Pin,GPIO_PIN_SET);
HAL_Delay(200);
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED4_GPIO_Port,LED4_Pin,GPIO_PIN_SET);
HAL_Delay(200);
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED4_GPIO_Port,LED4_Pin,GPIO_PIN_SET);
HAL_Delay(200);
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED4_GPIO_Port,LED4_Pin,GPIO_PIN_RESET);
HAL_Delay(200);
}
//流水灯
else if(mode==water)
{
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED4_GPIO_Port,LED4_Pin,GPIO_PIN_SET);
HAL_Delay(100);
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED4_GPIO_Port,LED4_Pin,GPIO_PIN_SET);
HAL_Delay(100);
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED4_GPIO_Port,LED4_Pin,GPIO_PIN_SET);
HAL_Delay(100);
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED4_GPIO_Port,LED4_Pin,GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED4_GPIO_Port,LED4_Pin,GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED4_GPIO_Port,LED4_Pin,GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED4_GPIO_Port,LED4_Pin,GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED4_GPIO_Port,LED4_Pin,GPIO_PIN_SET);
HAL_Delay(100);
}
}
关于蓝牙连接:
一开始我以为要先把蓝牙模块接到串口转USB模块 并且连上电脑给它配置好才可以使用,后来发现原厂默认已经把它配置好了从机模式和9600的波特率,要做的只是用手机或者电脑连接蓝牙就好。但是我的电脑不管怎么样都搜索不到HC-05,所以我还是用手机下载了一个蓝牙调试助手(直接在应用商店下载的),还挺好用的也没有广告。
OK,就这样^v^!