STM32嵌入式开发蓝牙模块使用指南
创作时间:
作者:
@小白创作中心
STM32嵌入式开发蓝牙模块使用指南
引用
CSDN
1.
https://blog.csdn.net/m0_63037616/article/details/144778714
本文将重点介绍如何在STM32微控制器上实现与蓝牙模块的连接。STM32是一款常用的嵌入式微控制器,具有强大的处理能力和丰富的外设接口,非常适合用于开发各种智能设备。通过与蓝牙模块的连接,STM32可以实现与其他蓝牙设备之间的数据传输和通信,从而拓展了其应用场景和功能。
一、蓝牙是什么?
这里我们以JDY-31蓝牙为例,其他蓝牙基本相似。
JDY31蓝牙模块是一种蓝牙通信模块,它可以实现无线数据传输和通信功能。该模块采用了JDY系列芯片,具有低功耗、稳定性好、传输距离远等特点。JDY31蓝牙模块可以广泛应用于无线通信、智能家居、医疗器械、智能穿戴等领域。该模块可以与其他蓝牙设备进行配对,实现数据传输和远程控制。
JDY-31蓝牙
引脚标识
PCB原理图
二、使用步骤
1.JDY31.c
#include "stm32f10x.h" // 设备头文件
#include <stdio.h>
#include <stdarg.h>
uint8_t JDY31_RxData; // 存储接收到的数据
uint8_t JDY31_RxFlag; // 接收标志位
// 初始化JDY31蓝牙模块
void JDY31_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0}; // GPIO初始化结构体
USART_InitTypeDef USART_InitStruct = {0}; // USART初始化结构体
NVIC_InitTypeDef NVIC_InitStruct = {0}; // 中断向量表初始化结构体
// 使能GPIOB和USART3的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
// 配置USART3的TX引脚(PB10)为复用推挽输出模式
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
// 配置USART3的RX引脚(PB11)为浮空输入模式
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStruct);
// 配置USART3的基本参数
USART_InitStruct.USART_BaudRate = 9600; // 波特率设置为9600
USART_InitStruct.USART_WordLength = USART_WordLength_8b; // 数据位长度为8位
USART_InitStruct.USART_Parity = USART_Parity_No; // 无校验位
USART_InitStruct.USART_StopBits = USART_StopBits_1; // 停止位为1位
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 同时开启接收和发送功能
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 不使用硬件流控
USART_Init(USART3, &USART_InitStruct);
// 使能USART3的接收中断
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
// 配置USART3中断优先级
NVIC_InitStruct.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStruct);
// 使能USART3
USART_Cmd(USART3, ENABLE);
}
// 发送一个字节的数据到JDY31蓝牙模块
void JDY31_SendByte(uint8_t Byte)
{
USART_SendData(USART3, Byte); // 将数据放入发送缓冲区
while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET); // 等待发送完成
}
// 发送一个数组的数据到JDY31蓝牙模块
void JDY31_SendArray(uint8_t *Array, uint16_t Length)
{
uint16_t i;
for (i = 0; i < Length; i ++)
{
JDY31_SendByte(Array[i]); // 循环发送数组中的每一个字节
}
}
// 发送字符串到JDY31蓝牙模块
void JDY31_SendString(char *String)
{
uint8_t i;
for (i = 0; String[i] != '\0'; i ++)
{
JDY31_SendByte(String[i]); // 循环发送字符串中的每一个字符
}
}
// 计算X的Y次方
uint32_t JDY31_Pow(uint32_t X, uint32_t Y)
{
uint32_t Result = 1;
while (Y --)
{
Result *= X; // 循环乘法计算X的Y次方
}
return Result;
}
// 发送数字到JDY31蓝牙模块
void JDY31_SendNumber(uint32_t Number, uint8_t Length)
{
uint8_t i;
for (i = 0; i < Length; i ++)
{
JDY31_SendByte(Number / JDY31_Pow(10, Length - i - 1) % 10 + '0'); // 提取每一位数字并发送
}
}
// 使用printf格式化输出数据到JDY31蓝牙模块
void JDY31_Printf(char *format, ...)
{
char String[100];
va_list arg;
va_start(arg, format);
vsprintf(String, format, arg); // 格式化字符串
va_end(arg);
JDY31_SendString(String); // 发送格式化后的字符串
}
2.JDY31.h
#ifndef __JDY31_H
#define __JDY31_H
#include <stdio.h>
// 声明外部变量JDY31_RxData,用于存储接收到的数据
extern uint8_t JDY31_RxData;
// 声明外部变量JDY31_RxFlag,用于表示接收标志位
extern uint8_t JDY31_RxFlag;
// 初始化JDY31蓝牙模块
void JDY31_Init(void);
// 发送一个字节的数据到JDY31蓝牙模块
void JDY31_SendByte(uint8_t Byte);
// 发送一个数组的数据到JDY31蓝牙模块
void JDY31_SendArray(uint8_t *Array, uint16_t Length);
// 发送字符串到JDY31蓝牙模块
void JDY31_SendString(char *String);
// 发送数字到JDY31蓝牙模块
void JDY31_SendNumber(uint32_t Number, uint8_t Length);
// 使用printf格式化输出数据到JDY31蓝牙模块
void JDY31_Printf(char *format, ...);
#endif
3.main.c
#include "stm32f10x.h" // Device header
#include "OLED.h"
#include "JDY31.h"
/*
串口3(USART3)
TX PB10
RX PB11
*/
int main()
{
OLED_Init(); // 初始化OLED显示屏
JDY31_Init(); // 初始化JDY31蓝牙模块
while(1)
{
OLED_ShowString(0, 0, "RX:", OLED_8X16); // 在OLED上显示“RX:”
OLED_ShowChar(24, 0, JDY31_RxData, OLED_8X16); // 显示接收到的数据
if(JDY31_RxFlag == 1) // 检查是否接收到数据
{
// 处理接收到的数据
JDY31_SendString("RX_OK"); // 发送确认信息到蓝牙模块
JDY31_RxFlag = 0; // 清除接收标志位
// 示例:根据接收到的数据执行不同的操作
switch (JDY31_RxData)
{
case 'A':
OLED_ShowString(0, 2, "Received A", OLED_8X16); // 显示接收到'A'
break;
case 'B':
OLED_ShowString(0, 2, "Received B", OLED_8X16); // 显示接收到'B'
break;
default:
OLED_ShowString(0, 2, "Unknown", OLED_8X16); // 显示未知字符
break;
}
}
OLED_Update(); // 更新OLED显示
}
}
// 数据接收中断服务程序
void USART3_IRQHandler(void)
{
if (USART_GetITStatus(USART3, USART_IT_RXNE) == SET) // 检查接收缓冲区非空中断标志
{
JDY31_RxData = USART_ReceiveData(USART3); // 读取接收到的数据
JDY31_RxFlag = 1; // 设置接收标志位
USART_ClearITPendingBit(USART3, USART_IT_RXNE); // 清除接收中断标志
}
}
总结
- 硬件准备:获取一个STM32F103C8T6开发板和一个蓝牙模块(如HC-05或HC-06)。将蓝牙模块连接到开发板的串口引脚(TX和RX),并将模块的电源引脚连接到3.3V电源引脚。
- 软件准备:安装STM32CubeIDE开发环境,并创建一个新的STM32Cube工程。选择正确的MCU型号(STM32F103C8T6),并选择合适的时钟配置和外设配置。
- 串口初始化:在工程代码中添加串口初始化代码。配置串口的波特率、数据位、停止位和校验位等参数。
- 蓝牙通信:使用串口的发送和接收函数来与蓝牙模块进行通信。可以使用AT指令集来配置蓝牙模块的参数,如名称、配对码等。也可以使用串口发送和接收数据来实现与其他蓝牙设备的通信。
- 主程序:在主程序中添加代码来处理蓝牙连接和数据传输。可以使用中断或轮询方式来接收蓝牙模块发送的数据,然后进行相应的处理。
需要注意的是,连接蓝牙模块之前,需要确保蓝牙模块处于可配对和可连接状态。也要注意蓝牙模块的供电电压和电流要求,以及串口引脚的电平适配和电气特性匹配。另外,还要注意蓝牙模块的串口通信协议和数据格式,以便正确解析和处理蓝牙模块发送的数据。
热门推荐
春天多喝这汤,少油少盐,鲜嫩营养,一周喝5次真鲜美
关于FFmpeg基础知识入门
如何在研发团队中建立学习机制
企业管理法则:法约尔原则
浅析李清照的人生经历对词风的影响
(图解)JPEG 图像压缩原理技术
路沿石施工工艺详解:从准备到养护的完整流程
增肌饮食全解析:蛋白质、碳水化合物与脂肪的科学配比
竞业协议纠纷如何解决?一文详解法律依据与应对方案
用人单位如何依法缴纳基本养老保险费
头痛一阵一阵的痛怎么快速解决
自书遗嘱的效力:解读我国法律规定的遗嘱继承问题
如何解决物业费拖欠问题?这种行为可能带来哪些后果?
儿童肺炎:原因、症状、治疗和预防
泪囊炎和睑腺炎区别在哪
除尘骨架怎么清洁最有效?技巧揭秘
皮肌炎怎样区分早期中期晚期
专家解读:每天只吃两顿饭是否可行?
如何验证电子发票的真伪?
六堡茶的传统工艺与现代工艺:千年名茶的演变之路
断桥铝门窗的优点有哪些?
足球小将被诊断为脑死亡,还有救治的必要吗?重症医生讲清楚
科创板连续竞价阶段的限价申报规则
Netperf网络测试工具使用指南
眼部黑色素代谢不出来怎么办
王者荣耀段位系统详解:从青铜到荣耀王者,职业选手选拔标准全解析
PS5必玩佳作推荐:十大不可错过的顶级游戏
私募基金的运作方式是什么?其投资策略有哪些特点?
酸性体质调理指南:从情绪到饮食全方位调适
如何打造独特的苏州别墅家装设计风格与氛围?