[其他ST产品] HC-05蓝牙模块与STM32控制led灯亮详解

[复制链接]
2361|15
 楼主| 为你转身 发表于 2023-6-29 12:29 | 显示全部楼层 |阅读模式
HC-05蓝牙模块解析
1.简介
HC-05模块是一种基于蓝牙协议的简单无线通信设备,共有6个引脚,其中两个引脚通过stm32的两个含TX和RX的接口与之进行通信,一般用于无线控制,智能家居等。

2.HC-05原理
VCC:用于供电
GND:用于供电
TX(发送):与单片机某一RX口进行通信
RX(接收):与单片机某一TX口进行通信
一句话,TX->RX,RX->TX.
//这里的TX与RX直接选某STM32一个USART的一对。
如下图
21645649d089356ead.png

EN:使能,若置低电平,则模块被禁用
STATE:通过该引脚输出的高低电平可以知道蓝牙模块的状态,连接时输出高电平,断开时输出低电平。

在配置后使用蓝牙时,我一般不用EN和STATE这两个引脚

 楼主| 为你转身 发表于 2023-6-29 12:29 | 显示全部楼层
 楼主| 为你转身 发表于 2023-6-29 12:30 | 显示全部楼层
HC-05实物图

9946649d08c615cfd.png
46530649d08d04b6aa.png
 楼主| 为你转身 发表于 2023-6-29 12:30 | 显示全部楼层
使用AT指令进行配置
1.进入命令响应工作模式
我使用PWLINK2和串口助手进行对其的配置,接线时,也采用TX->RX,RX->TX.

长按蓝牙模块的同时,给HC-05模块进行上电,与此同时,模块上的指示灯大概每隔1s闪烁一次,如视频所示,此时则说明已经进入了命令响应模式。
 楼主| 为你转身 发表于 2023-6-29 12:30 | 显示全部楼层
配置串口
我使用VOFA+来进行串口调试.

打开VOFA+,
设置接口为串口
设置数据引擎为RawData
设置波特率 38400
设置数据位 8 位
设置停止位 1 位
设置无校验位
 楼主| 为你转身 发表于 2023-6-29 12:31 | 显示全部楼层
 楼主| 为你转身 发表于 2023-6-29 12:31 | 显示全部楼层
进行指令
1.测试指令:发送AT,得到回应OK
2.获取软件版本号:发送AT+VERSON,得到版本号
3.获取蓝牙地址:AT+ADDR,获得蓝牙地址
4.配置蓝牙模块名称:AT+NAME=“(名称)”
5.配置密码:AT+PSWD=(密码)(4位)
6.配置主从模式:AT+ROLE=0或1(0为从模式,1为主模式)

以上指令对初学者已经足够使用,多余的指令可以查找参考手册
 楼主| 为你转身 发表于 2023-6-29 12:32 | 显示全部楼层
状况如下图
55559649d0952a78f3.png
 楼主| 为你转身 发表于 2023-6-29 12:32 | 显示全部楼层
和手机连接(使用手机软件蓝牙调试器)
19207649d0964e63a7.png
 楼主| 为你转身 发表于 2023-6-29 12:32 | 显示全部楼层
使用stm32f103c8t6实现
1.思路
配置好串口后,当单片机接收到数据后,执行LED点亮的操作
 楼主| 为你转身 发表于 2023-6-29 12:33 | 显示全部楼层
代码
1.HC05.C
  1. #include "stm32f10x.h"                  // Device header
  2. //1.开启时钟,把需要用的USART和GPIO口的时钟打开
  3. //2.GPIO初始化,把TX设为复用输出,RX设为输入
  4. //配置USART,配置参数
  5. #include <stdio.h>
  6. #include <stdarg.h>
  7. #include "HC05.h"  
  8. char HC05_RxPacket[100];                                //"@MSG\r\n"
  9. uint8_t HC05_RxData;//接收数据
  10. uint8_t HC05_RxFlag;//接收标志位
  11. void HC05_Init(void)
  12. {
  13.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  14.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  15.         //初始化TX,把TX配置成复用推挽输出
  16.         GPIO_InitTypeDef GPIO_InitStructure;
  17.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  18.         //TX是USART2控制的外设输出脚,选择复用推挽输出
  19.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  20.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  21.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  22.        
  23.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  24.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  25.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  26.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  27.         //配置USART
  28.         USART_InitTypeDef USART_InitStructure;
  29.         //定义USART结构体
  30.         USART_InitStructure.USART_BaudRate = 9600;
  31.         //波特率数值
  32.         USART_InitStructure.USART_HardwareFlowControl =  USART_HardwareFlowControl_None;
  33.         //不使用流控
  34.         USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;
  35.         //TX发送功能
  36.         USART_InitStructure.USART_Parity = USART_Parity_No;
  37.         //校验:不需要
  38.         USART_InitStructure.USART_StopBits = USART_StopBits_1;
  39.         //停止位:1位停止位
  40.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  41.         //字长:8位
  42.         USART_Init(USART1, &USART_InitStructure);
  43.         //初始化
  44.        
  45.         USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
  46.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  47.         NVIC_InitTypeDef NVIC_InitStructure;
  48.         NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  49.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  50.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  51.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  52.         NVIC_Init(&NVIC_InitStructure);
  53.         //配置中断
  54.         USART_Cmd(USART1, ENABLE);
  55.         //供能
  56. }
  57. //发送一个字节数据的函数
  58. void HC05_SendByte(uint8_t Byte)
  59. {
  60.         USART_SendData(USART1, Byte);
  61.         //函数的功能是通过外设USARTx发送单个数据。
  62.         while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
  63.         //该标志位,当下一次再次使用SendData时,会自动清0
  64. }
  65. //发送多个字节数据(传递数组)
  66. void HC05_SendArray(uint8_t *Array, uint16_t Length)
  67. {
  68.         uint16_t i;
  69.         for (i = 0; i < Length; i ++)
  70.         {
  71.                 HC05_SendByte(Array[i]);
  72.         }
  73. }
  74. //发送多个字符数据
  75. //string类型自带标志位,无需长度限制
  76. void HC05_SendString(char *String)
  77. {
  78.         uint8_t i;
  79.         for (i = 0; String[i] != '\0'; i ++)
  80.         {
  81.                 HC05_SendByte(String[i]);
  82.         }
  83. }
  84. //求x的y次方函数
  85. uint32_t HC05_Pow(uint32_t X, uint32_t Y)
  86. {
  87.         uint32_t Result = 1;
  88.         while (Y --)
  89.         {
  90.                 Result *= X;
  91.         }
  92.         return Result;
  93. }
  94. //发送数字(可显示成字符串形式)
  95. //利用先相除得到首位,后取余,发送出该一个数字
  96. void HC05_SendNumber(uint32_t Number, uint8_t Length)
  97. {
  98.         uint8_t i;
  99.         for (i = 0; i < Length; i ++)
  100.         {
  101.                 HC05_SendByte(Number / HC05_Pow(10, Length - i - 1) % 10 + '0');
  102.         }
  103. }
  104. //重定向fputc
  105. //printf的本质上是不断调用fputc()
  106. //重定向后,只能该串口使用,其余串口无法使用
  107. int fputc1(int ch, FILE *f)
  108. {
  109.         HC05_SendByte(ch);
  110.         return ch;
  111. }


  112. void HC05_Printf(char *format, ...)
  113. {
  114.         char String[100];
  115.         va_list arg;
  116.         va_start(arg, format);
  117.         vsprintf(String, format, arg);
  118.         va_end(arg);
  119.         HC05_SendString(String);
  120. }
  121. //接收标志位判断
  122. uint8_t HC05_GetRxFlag(void)
  123. {
  124.         if ( HC05_RxFlag == 1)
  125.         {
  126.                 HC05_RxFlag = 0;
  127.                 return 1;
  128.         }
  129.         return 0;
  130. }

  131. uint8_t HC05_GetRxData(void)
  132. {
  133.         return HC05_RxData;
  134. }

  135. void HC05_IRQHandler(void)
  136. {
  137.         if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
  138.         {
  139.                 HC05_RxData = USART_ReceiveData(USART1);
  140.                 HC05_RxFlag = 1;
  141.                 USART_ClearITPendingBit(USART1, USART_IT_RXNE);
  142.         }
  143. }
 楼主| 为你转身 发表于 2023-6-29 12:33 | 显示全部楼层
main.c



  1. #include "stm32f10x.h"                  // Device header
  2. #include "Delay.h"
  3. #include "LED.h"
  4. #include "HC05.h"
  5. uint8_t RxData;
  6. uint16_t AD0, AD1, AD2, AD3,AD4,AD5;
  7. int main(void)
  8. {
  9.         LED_Init();
  10.         HC05_Init();
  11.         while (1)
  12.         {
  13.                 HC05_IRQHandler();
  14.                 if (HC05_GetRxFlag() == 1)
  15.                 {
  16.                         RxData = HC05_GetRxData();
  17.                         HC05_SendByte(RxData);
  18.                         LED_ON();
  19.                        
  20.                 }
  21.                
  22.         }
  23.        
  24. }
星辰大海不退缩 发表于 2023-6-29 12:33 | 显示全部楼层
在配置后使用蓝牙时,为什么不用EN和STATE这两个引脚,不方便编程还是其他?
Clyde011 发表于 2024-1-23 15:31 | 显示全部楼层

固有的ESD钳位二极管。
万图 发表于 2024-1-23 17:27 | 显示全部楼层

不打坏仪器内部
Uriah 发表于 2024-1-23 18:30 | 显示全部楼层

具体采用灌封胶的种类的性能参数,主要看对电源模块的灌封用的胶的要求
szhman 发表于 2024-10-5 14:14 | 显示全部楼层
很厉害啊!赞
您需要登录后才可以回帖 登录 | 注册

本版积分规则

82

主题

741

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部