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指令集来配置蓝牙模块的参数,如名称、配对码等。也可以使用串口发送和接收数据来实现与其他蓝牙设备的通信。
- 主程序:在主程序中添加代码来处理蓝牙连接和数据传输。可以使用中断或轮询方式来接收蓝牙模块发送的数据,然后进行相应的处理。
需要注意的是,连接蓝牙模块之前,需要确保蓝牙模块处于可配对和可连接状态。也要注意蓝牙模块的供电电压和电流要求,以及串口引脚的电平适配和电气特性匹配。另外,还要注意蓝牙模块的串口通信协议和数据格式,以便正确解析和处理蓝牙模块发送的数据。
热门推荐
2025减肥药赛道展望:两大巨头激战中国市场,口服药群雄逐鹿
周易研究——尚秉和之易学研究与贡献
缓解视疲劳训练(缓解视疲劳最好的最有效的方法)
珍惜时间的名言警句:莫让“一日难再晨”成为遗憾
负袋鼠让人更清醒认识国青队的形势:下仗更艰巨!
一文搞懂“职业院校如何打造高效工业互联网课程体系”
科技之美:传统科技的积累与进步
电线颜色代表什么线?电线颜色详细介绍
如何预防传导性耳聋
三国演义中,蜀国这5人被严重低估,前2名接近五虎,鄂焕廖化上榜
芥末的种子——开启辛辣味觉的奇妙之旅
什么是聚酰胺树脂(尼龙树脂)?
西安恒大悦龙台供暖第一年多户暖气漏水 地产拒绝回答记者提问
揭秘特大走私冻品案:涉案金额超10亿元,警方全链条打击黑色产业链
枕大池蛛网膜囊肿是什么意思
室内常用灯具的分类及用途
轻舟校园AI防霸凌系统:守护校园的隐形盾牌
糍粑:传统美味与多样吃法
如何录入规范的数据库表
自主豪华SUV之争:实拍对比魏派VV7和红旗HS5
成都发布“熊猫家园·大熊猫主题游线”:从成都出发,穿越城市与自然探索熊猫家园
八字纳音全是火 八字纳音都是火
2025春节怎么玩?团圆、度假两不误
细雨盖不住的热辣滚烫!五一小长假天心区热力出圈
十款跟《空洞骑士》一样的类银河恶魔城游戏推荐
心学问心理教育,学习也要灵活应变,适应不同环境
《鸣潮》角色深度分析:今汐的辅助价值与培养建议
迈向科学发现的生成式人工智能:进展、机遇与挑战
猪肉嘌呤含量全解析:美味与健康如何兼得?
如何训练宝宝自己坐起来:宝宝学坐与婴儿发展全指南