当前位置:   article > 正文

使用STM32F103C8T6与蓝牙模块HC-05连接实现手机蓝牙控制LED灯_hc05蓝牙模块怎么与stm32c8t6连接

hc05蓝牙模块怎么与stm32c8t6连接

Gitee工程地址:https://gitee.com/WYW3541/Mobile-phone-Bluetooth-control-based-on-STM32-and-HC-05icon-default.png?t=N7T8https://gitee.com/WYW3541/Mobile-phone-Bluetooth-control-based-on-STM32-and-HC-05

导言:

在现代智能家居系统中,远程控制设备变得越来越普遍和重要。本文将介绍如何利用STM32F103C8T6单片机和蓝牙模块HC-05实现远程控制LED灯的功能。通过这个简单的项目,可以学会如何将嵌入式系统与蓝牙通信技术相结合,实现远程控制的应用。

目录

导言:

准备工作:

硬件设计:

HC-05蓝牙串口模块介绍:

引脚:

手机蓝牙APP:

物理连接:

通信协议:

AT指令:

蓝牙测试软件:

​编辑

推荐资料: 

软件设计:

手机APP和蓝牙通过串口接发通信:

使用HC-05控制mcu

代码实现:

最终实现:


准备工作:

在开始之前,确保已经准备好以下材料:

  • STM32F103C8T6开发板
  • HC-05蓝牙模块
  • LED灯
  • 杜邦线等连接线
  • USB转串口模块(用于调试)

硬件设计:

本次设计使用HC-05(JDY-31)无线蓝牙模块实现单片机和手机的无线通信,将其正常工作的频段2.4 GHz ISM,GFSK作为它的调制方式。主控芯片STM32F103 C8T6单片机通过串口连接HC-05,安卓手机端自带蓝牙,通过手机App与单片机蓝牙设备建立配对,蓝牙模块将接收的数据传送给单片机,单片机处理后控制电机的运转和桶盖的开关。工作原理如图3所示。

图3蓝牙工作原理

HC-05蓝牙串口模块介绍:

HC-05是一款常用的蓝牙串口模块,用于在微控制器和其他设备之间建立蓝牙串口通信连接。下面我将详细介绍HC-05蓝牙模块的接口设计,以便将其与STM32F103C8T6微控制器进行通信。

HC-05蓝牙串口模块

引脚:

标号PIN引脚说明
1STATE状态引出引脚(未连接时输出低电平,连接时输出高电平)
2RXD接收端
3TXD发送端
4GND模块供电负极
5VCC模块供电正极
6EN使能端,需要进入命令模式时接3.3V

注:或者也可以直接去优信买JDY-31模块,相比HC05更加便宜,使用也没什么区别并且资料全套。

手机蓝牙APP:

这几个都可以,手机应用商店直接搜索就行。

物理连接:

电源供应:HC-05通常需要3.3V电源供应。你可以使用STM32F103C8T6的一块3.3V输出引脚连接到HC-05的VCC引脚,或者使用一个3.3V的稳压芯片。

串口通信:HC-05通过串口与STM32通信。它包含了TX(发送)和RX(接收)引脚,分别用于发送和接收数据。你可以将HC-05的TX引脚连接到STM32的一个USART接收引脚(比如USART1的RX(PA10)引脚),并将HC-05的RX引脚连接到STM32的一个USART发送引脚(比如USART1的TX(PA9)引脚)。

接地:HC-05的GND与STM32的GND相连接

通信协议:

波特率设置:HC-05支持多种波特率,通常默认波特率为9600bps。你可以通过AT指令将其更改为其他波特率,以便与STM32的USART通信波特率匹配。

数据格式:通常情况下,HC-05使用8位数据位、无校验位和1位停止位的数据格式。

AT指令:

HC-05也可以使用AT指令进行配置。在配置之前,首先需要让模块进入配置模式。一般HC-05有一个小按钮。按住小按钮再给蓝牙模块上电,蓝牙模块进入配置模式,此时模块上自带的LED会慢速闪烁。进入配置模式后,就可以用AT指令来配置我们的HC-05了。配置时,用USB转TTL连接HC-05,用串口调试助手发送AT指令进行配置。需要注意的是,HC-05配置模式的波特率固定为38400,如果你给HC-05发送指令,没有收到回复,记得检查一下串口调试助手的波特率是否正确。下面列举一些配置时常用的AT指令

AT
检查HC-05模块连接是否正常,HC-05收到后会回复“OK”


AT+NAME=名字
配置HC-05的名字,配置成功后会返回“OK”


AT+NAME?
询问HC-05的名字。发送后会收到“+NAME:“名字””,换行加“OK”


AT+PSWD=密码
配置HC-05密码,配对时需要用到。配置成功后,会收到“OK”


AT+PSWD?
询问HC-05配对密码。发送后会收到“+PSWD:991102”,换行加“OK”


AT+UART=波特率,停止位,校验
设置HC-05的波特率,其中停止位0表示一位停止位,为1表示两位停止位。校验位为0表示无校验,为1表示奇校验,为2表示偶校验。比如设置115200的波特率,一位停止位,无校验。发送“AT+UART=115200,0,0”即可。配置成功后会返回“OK”


AT+UART?
询问HC-05波特率。发送后会收到“+UART:波特率,停止位,校验”,换行加“OK”
配置完成功后,断电重新上电,HC-05按照配置好的名字,配对密码和波特率开始工作。此时LED快闪。

蓝牙测试软件:

推荐一个特别好用的蓝牙测试软件,将蓝牙模块与HC05连接好后,插上电脑可以一键直接获得当前这个蓝牙模块的信息,需要的可以直接去我的资源里自取。

资源链接:

蓝牙测试软件-HC-05AT测试版

推荐资料: 

蓝牙模块(HC-05/HC-06)详解

两个蓝牙模块HC-05的主从机匹配

蓝牙模块HC-05使用指南

软件设计:

手机APP和蓝牙通过串口接发通信:

  1. 机寻找蓝牙,并填写配对码
  2. SPP蓝牙串口连接对应蓝牙
  3. 发送数据,串口接收,串口发送,手机接收

使用HC-05控制mcu

stm32f103c8t6自带一个led灯,使用PC13引脚就行了,

切记尽量避免使用PB3、PB4,因为PB3和PB4在默认情况下是做JTAG调试用的。如果需要将其当普通GPIO使用,需要关闭JTAG调试功能,否则会发现普通的GPIO初始化程序无法正常使用PB3和PB4

代码实现:

led.c

  1. #include "stm32f10x.h" // Device header
  2. #include "LED.h" // Device header
  3. void LED_Init(void)
  4. {
  5. GPIO_InitTypeDef GPIO_InitStructure;
  6. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE); //使能PA,PD端口时钟
  7. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //LED0-->PA.8 端口配置
  8. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
  9. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
  10. GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA.8
  11. GPIO_ResetBits(GPIOA,GPIO_Pin_8); //PA.8 输出高
  12. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //LED1-->PD.2 端口配置, 推挽输出
  13. GPIO_Init(GPIOB, &GPIO_InitStructure); //推挽输出 ,IO口速度为50MHz
  14. GPIO_SetBits(GPIOB,GPIO_Pin_8); //PD.2 输出高
  15. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //LED1-->PD.2 端口配置, 推挽输出
  16. GPIO_Init(GPIOB, &GPIO_InitStructure); //推挽输出 ,IO口速度为50MHz
  17. GPIO_SetBits(GPIOB,GPIO_Pin_9); //PD.2 输出高
  18. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //LED1-->PD.2 端口配置, 推挽输出
  19. GPIO_Init(GPIOC, &GPIO_InitStructure); //推挽输出 ,IO口速度为50MHz
  20. GPIO_SetBits(GPIOC,GPIO_Pin_13); //PD.2 输出高
  21. }

led.h

  1. #ifndef __LED_H
  2. #define __LED_H
  3. #include "sys.h" // Device header
  4. #define LED0 PCout(13) // PA8
  5. #define LED1 PBout(8) // PB8
  6. #define LED2 PBout(9) // PB9
  7. #define BUZ PAout(8) // PA8
  8. void LED_Init(void);//初始化
  9. #endif

usart1.c

  1. #include "stm32f10x.h" // 包含 STM32F10x 系列芯片的头文件
  2. #include <stdio.h> // 包含标准输入输出头文件
  3. #include <stdarg.h> // 包含可变参数列表的头文件
  4. #include "serial.h" // 包含串口相关的头文件
  5. uint8_t Serial_RxData; // 定义一个无符号8位整型变量 `Serial_RxData`,用于存储串口接收到的数据
  6. uint8_t Serial_RxFlag; // 定义一个无符号8位整型变量 `Serial_RxFlag`,用于表示串口接收标志位
  7. // 串口初始化函数
  8. void Serial_Init(void)
  9. {
  10. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); // 使能 USART1 时钟
  11. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能 GPIOA 时钟
  12. GPIO_InitTypeDef GPIO_InitStructure; // 定义一个 GPIO 初始化结构体变量
  13. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // GPIO 模式为复用推挽输出
  14. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // GPIO 引脚为 PA9
  15. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // GPIO 速度为 50MHz
  16. GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化 GPIOA
  17. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // GPIO 模式为上拉输入
  18. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // GPIO 引脚为 PA10
  19. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // GPIO 速度为 50MHz
  20. GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化 GPIOA
  21. USART_InitTypeDef USART_InitStructure; // 定义一个 USART 初始化结构体变量
  22. USART_InitStructure.USART_BaudRate = 9600; // 波特率为 9600
  23. USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无硬件流控制
  24. USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // 收发模式
  25. USART_InitStructure.USART_Parity = USART_Parity_No; // 无奇偶校验
  26. USART_InitStructure.USART_StopBits = USART_StopBits_1; // 1 个停止位
  27. USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 8 位数据位
  28. USART_Init(USART1, &USART_InitStructure); // 初始化 USART1
  29. USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 使能 USART1 接收中断
  30. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 配置 NVIC 中断优先级
  31. NVIC_InitTypeDef NVIC_InitStructure; // 定义一个 NVIC 初始化结构体变量
  32. NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; // USART1 中断通道
  33. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能中断通道
  34. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 抢占优先级为 1
  35. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 子优先级为 1
  36. NVIC_Init(&NVIC_InitStructure); // 初始化 NVIC
  37. USART_Cmd(USART1, ENABLE); // 使能 USART1
  38. }
  39. // 发送一个字节数据到串口
  40. void Serial_SendByte(uint8_t Byte)
  41. {
  42. USART_SendData(USART1, Byte); // 发送数据到 USART1
  43. while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); // 等待发送完成
  44. }
  45. // 发送一串数据到串口
  46. void Serial_SendArray(uint8_t *Array, uint16_t Length)
  47. {
  48. uint16_t i;
  49. for (i = 0; i < Length; i++) // 遍历数组
  50. {
  51. Serial_SendByte(Array[i]); // 逐个发送数组中的数据
  52. }
  53. }
  54. // 发送一个字符串到串口
  55. void Serial_SendString(char *String)
  56. {
  57. uint8_t i;
  58. for (i = 0; String[i] != '\0'; i++) // 遍历字符串
  59. {
  60. Serial_SendByte(String[i]); // 逐个发送字符串中的字符
  61. }
  62. }
  63. // 计算 X 的 Y 次方
  64. uint32_t Serial_Pow(uint32_t X, uint32_t Y)
  65. {
  66. uint32_t Result = 1;
  67. while (Y--) // Y 次方计算
  68. {
  69. Result *= X;
  70. }
  71. return Result;
  72. }
  73. // 发送一个数字到串口,指定长度
  74. void Serial_SendNumber(uint32_t Number, uint8_t Length)
  75. {
  76. uint8_t i;
  77. for (i = 0; i < Length; i++) // 遍历指定长度
  78. {
  79. Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0'); // 发送数字的每一位
  80. }
  81. }
  82. // 重定向标准输出函数
  83. int fputc(int ch, FILE *f)
  84. {
  85. Serial_SendByte(ch); // 发送字符到串口
  86. return ch;
  87. }
  88. // 格式化发送字符串到串口
  89. void Serial_Printf(char *format, ...)
  90. {
  91. char String[100]; // 定义一个字符数组用于存储格式化后的字符串
  92. va_list arg;
  93. va_start(arg, format); // 初始化可变参数列表
  94. vsprintf(String, format, arg); // 格式化字符串
  95. va_end(arg); // 结束可变参数列表
  96. Serial_SendString(String); // 发送格式化后的字符串到串口
  97. }
  98. // 获取串口接收标志位
  99. uint8_t Serial_GetRxFlag(void)
  100. {
  101. if (Serial_RxFlag == 1) // 如果串口接收标志位为 1
  102. {
  103. Serial_RxFlag = 0; // 清零串口接收标志位
  104. return 1; // 返回 1
  105. }
  106. return 0; // 否则返回 0
  107. }
  108. // 获取串口接收到的数据
  109. uint8_t Serial_GetRxData(void)
  110. {
  111. return Serial_RxData; // 返回串口接收到的数据
  112. }
  113. // USART1 中断处理函数
  114. void USART1_IRQHandler(void)
  115. {
  116. if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET) // 如果 USART1 接收中断标志位为 SET
  117. {
  118. Serial_RxData = USART_ReceiveData(USART1); // 获取接收到的数据
  119. Serial_SendByte(Serial_RxData); // 发送接收到的数据到串口
  120. Serial_RxFlag = 1; // 置位串口接收标志位
  121. USART_ClearITPendingBit(USART1, USART_IT_RXNE); // 清除 USART1 接收中断标志位
  122. }
  123. }
  1. #include "stm32f10x.h":包含 STM32F10x 系列芯片的头文件。
  2. #include <stdio.h>:包含标准输入输出头文件。
  3. #include <stdarg.h>:包含可变参数列表的头文件。
  4. #include "serial.h":包含串口相关的头文件。
  5. uint8_t Serial_RxData;:定义一个无符号8位整型变量 Serial_RxData,用于存储串口接收到的数据。
  6. uint8_t Serial_RxFlag;:定义一个无符号8位整型变量 Serial_RxFlag,用于表示串口接收标志位。
  7. void Serial_Init(void):串口初始化函数。
  8. void Serial_SendByte(uint8_t Byte):发送一个字节数据到串口的函数。
  9. void Serial_SendArray(uint8_t *Array, uint16_t Length):发送一串数据到串口的函数。
  10. void Serial_SendString(char *String):发送一个字符串到串口的函数。
  11. uint32_t Serial_Pow(uint32_t X, uint32_t Y):计算 X 的 Y 次方的函数。
  12. void Serial_SendNumber(uint32_t Number, uint8_t Length):发送一个数字到串口,指定长度的函数。
  13. int fputc(int ch, FILE *f):重定向标准输出函数。
  14. void Serial_Printf(char *format, ...):格式化发送字符串到串口的函数。
  15. uint8_t Serial_GetRxFlag(void):获取串口接收标志位的函数。
  16. uint8_t Serial_GetRxData(void):获取串口接收到的数据的函数。
  17. void USART1_IRQHandler(void):USART1 中断处理函数。

usart2.h

  1. #ifndef __SERIAL_H
  2. #define __SERIAL_H
  3. #include <stdio.h>
  4. #include "LED.h" // Device header
  5. #include "sys.h" // Device header
  6. #include "HC05.h" // Device header
  7. #include "Delay.h"
  8. void Serial_Init(void);
  9. void Serial_SendByte(uint8_t Byte);
  10. void Serial_SendArray(uint8_t *Array, uint16_t Length);
  11. void Serial_SendString(char *String);
  12. void Serial_SendNumber(uint32_t Number, uint8_t Length);
  13. void Serial_Printf(char *format, ...);
  14. uint8_t Serial_GetRxFlag(void);
  15. uint8_t Serial_GetRxData(void);
  16. #endif

HC05.c

  1. #include "stm32f10x.h" // Device header
  2. #include "Serial.h"
  3. #include "HC05.h" // Device header
  4. uint8_t RxSTA = 1; // 定义串口接收状态变量,初始为1,表示准备接收数据
  5. char RxData[100] = "None"; // 定义接收数据缓冲区,初始值为"None"
  6. void HC05_GetData(char *Buf)
  7. {
  8. uint32_t count = 0, a = 0; // 定义计数器和数据索引变量
  9. while (count < 10000) // 进入循环等待接收数据
  10. {
  11. if (Serial_GetRxFlag() == 1) // 如果串口接收标志为1,表示有数据接收到
  12. {
  13. Buf[a] = Serial_GetRxData(); // 将接收到的数据存储在缓冲区Buf中
  14. a ++; // 数据索引自增
  15. count = 0; // 重置计数器
  16. RxSTA = 0; // 将接收状态置为0,表示接收到数据
  17. }
  18. count ++; // 计数器自增
  19. }
  20. }
  21. void HC05_Init()
  22. {
  23. Serial_Init(); // 初始化串口通信
  24. }
  25. void HC05_EnterAT()
  26. {
  27. GPIO_SetBits(GPIOA, GPIO_Pin_0); // 将GPIOA的第0引脚置为高电平,进入AT模式
  28. }
  29. void HC05_ExitAT()
  30. {
  31. GPIO_ResetBits(GPIOA, GPIO_Pin_0); // 将GPIOA的第0引脚置为低电平,退出AT模式
  32. }
  33. void HC05_SendString(char *Buf)
  34. {
  35. Serial_Printf(Buf); // 向HC05模块发送字符串
  36. }
  37. void HC05_proc()
  38. {
  39. HC05_GetData(RxData); // 获取HC05模块接收到的数据
  40. if (RxSTA == 0) // 如果接收状态为0,表示接收到了数据
  41. {
  42. OLED_Clear(); // 清空OLED显示屏
  43. OLED_ShowString(1, 1, "RxData:"); // 在OLED上显示"RxData:"
  44. OLED_ShowString(2, 1, RxData); // 在OLED上显示接收到的数据
  45. if(strstr((const char*)RxData, "led on") != 0) // 如果接收到的数据包含"led on"
  46. {
  47. LED0 = 0; // 控制LED0点亮
  48. LED1 = 0; // 控制LED1点亮
  49. BUZ=1; // 控制蜂鸣器响
  50. Delay_ms(100); // 延时100毫秒
  51. BUZ=0; // 关闭蜂鸣器
  52. }
  53. if(strstr((const char*)RxData, "led off") != 0) // 如果接收到的数据包含"led off"
  54. {
  55. LED0 = 1; // 控制LED0熄灭
  56. LED1 = 1; // 控制LED1熄灭
  57. BUZ=1; // 控制蜂鸣器响
  58. Delay_ms(100); // 延时100毫秒
  59. BUZ=0; // 关闭蜂鸣器
  60. }
  61. memset(RxData,0,100); // 清空接收数据缓冲区
  62. RxSTA = 1; // 将接收状态置为1,表示准备接收新的数据
  63. }
  64. }

HC05.h

  1. #ifndef __HC05_H
  2. #define __HC05_H
  3. #include "LED.h" // Device header
  4. #include "sys.h" // Device header
  5. #include "OLED.h"
  6. #include "string.h" // Device header
  7. extern char RxData[100];
  8. extern uint8_t RxSTA;
  9. void HC05_Init();
  10. void HC05_EnterAT();
  11. void HC05_ExitAT();
  12. void HC05_SendString(char *Buf);
  13. void HC05_GetData(char *Buf);
  14. void HC05_proc(void);
  15. #endif

main.c 

  1. #include "stm32f10x.h" // Device header
  2. #include "Delay.h"
  3. #include "OLED.h"
  4. #include "HC05.h"
  5. #include "sys.h" // Device header
  6. #include "serial.h" // Device header
  7. #include "string.h" // Device header
  8. #include "ESP01.h"
  9. #include "usart2.h"
  10. int main(void)
  11. {
  12. OLED_Init(); // 初始化OLED显示屏
  13. LED_Init(); // 初始化LED指示灯
  14. HC05_Init(); // 初始化HC05蓝牙模块
  15. // uart2_init(115200); //串口初始化为115200
  16. // ESP01_Init(); // 初始化ESP01模块
  17. OLED_ShowString(1, 1, "RxData:"); // 在OLED上显示"RxData:"
  18. OLED_ShowString(2, 1, RxData); // 在OLED上显示RxData变量内容
  19. BUZ=1; // 控制蜂鸣器响
  20. Delay_ms(100); // 延时100毫秒
  21. BUZ=0; // 关闭蜂鸣器
  22. while (1)
  23. {
  24. HC05_proc(); // 处理HC05模块接收到的数据
  25. // ESP01_proc(); // 处理ESP01模块接收到的数据
  26. }
  27. }

最终实现:

在APP中发送字符串“led on”可以打开LED灯,发送字符串“led off”可以关闭LED灯

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/723343
推荐阅读
相关标签
  

闽ICP备14008679号