当前位置: 首页 > news >正文

STM32F103C8T6蓝牙3.0模块 SPP透传 兼容HC-05/06从机 JDY-31的使用方法和代码驱动

STM32F103C8T6蓝牙3.0模块 SPP透传 兼容HC-05/06从机 JDY-31的使用方法和代码驱动

文档结尾有代码下载链接

🎯 实现效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

🌟 传感器用途

基于 “SPP 透传 + HC-05/06 兼容” 的特性,JDY-31 广泛应用于需要 “串口无线化” 的场景。

1.工业控制

  • 传感器无线组网:将温湿度传感器、压力传感器、电流传感器的串口数据,通过 JDY-31 传输到 PLC 或上位机,替代传统的有线布线(尤其适合车间、仓库等大面积场景,减少布线成本和维护难度)。
  • 备无线控制:通过手机 APP 或电脑,向连接 JDY-31 的 PLC、变频器发送控制指令(如启停、调速),实现 “远程操控”(如流水线设备的无线调试、无人车间的简易控制)。

2. 智能家居

  • 家电控制:在 Arduino 或 51 单片机上连接 JDY-31,通过手机蓝牙 APP 发送指令(如 “开灯”“关窗帘”),控制继电器、电机等执行器,实现 “蓝牙智能家居”(无需 WiFi,适合小范围场景,如卧室、书房)。
  • 数据反馈:将智能插座、加湿器的运行数据(如功率、湿度)通过 JDY-31 传输到手机,实时查看设备状态(如 “插座当前功率是否超标”“室内湿度是否达标”)。

3. 消费电子与 DIY 项目

  • 蓝牙串口调试:替代传统的 USB-TTL 模块,用 JDY-31 连接单片机(如 STM32),通过手机或电脑的蓝牙串口助手查看调试信息(无需接线,适合移动场景调试,如机器人、无人机)。
  • DIY 智能设备:在创客项目中(如蓝牙小车、蓝牙电子秤),用 JDY-31 作为从机,接收手机发送的控制指令(如 “前进”“后退”)或传输数据(如电子秤的重量数据),开发门槛低且成本可控。

4. 医疗与健康设备

  • 便携医疗设备:在血压计、血糖仪等设备中集成 JDY-31,将测量数据(如血压值、血糖值)无线传输到手机 APP,方便用户记录历史数据(无需手动输入,适合老年人或医护人员使用)。
  • 健康监测:在心率手环、睡眠监测仪中,用 JDY-31 传输低速率的生理数据(如心率、睡眠时长),无需复杂的 WiFi 模块,降低设备功耗和成本(适合民用级健康产品)。

🌟 传感器的介绍

蓝牙 3.0 是由蓝牙技术联盟(SIG)于 2009 年发布的经典蓝牙版本,核心定位是 “平衡传输速率与功耗”,为中低速数据交互场景提供稳定支持,其关键特性如下:

  • 高速传输能力:支持EDR技术,理论最高传输速率可达 24Mbps,相比蓝牙 2.0 速率提升 3 倍以上,能快速传输串口设备的批量数据。
  • 适中功耗表现:虽不具备蓝牙 4.0+BLE(低功耗蓝牙)的 “超低功耗” 特性,但蓝牙 3.0 的 “间歇通信” 机制(无数据时进入休眠),可满足多数民用 / 工业设备的续航需求(如电池供电的传感器,续航可达数天至数月,视通信频率而定)。
  • 广泛兼容性:向下兼容蓝牙 2.0/2.1 版本,可与手机、平板、电脑(Windows/macOS)等主流设备的蓝牙功能直接配对,无需额外驱动。

1.关键技术

  • SPP(Serial Port Profile,串行端口协议)是经典蓝牙的核心协议之一,其本质是 “在蓝牙链路中模拟一个物理串口(如 RS232/TTL)”。对用户而言,无需理解复杂的蓝牙底层协议(如 L2CAP、HCI),只需像操作传统有线串口一样,通过 “发送 / 接收串口数据” 实现无线通信。
  • “透传” 即 “透明传输”——JDY-31 接收串口端(如单片机、传感器)发来的数据后,不进行任何解析或修改,直接通过蓝牙链路转发给配对设备(如手机、电脑);反之,蓝牙端接收的数据也会原封不动地通过串口发送给终端设备。

2.优势

  • 开发门槛低:无需学习蓝牙协议栈,仅需掌握串口通信(如波特率、数据位、停止位配置)即可。
  • 兼容性强:支持所有具备串口的设备(如 51 单片机、Arduino、PLC、传感器),且与主流操作系统(Windows、Android、iOS)的串口工具(如 SSCOM、蓝牙串口助手)无缝适配。
  • 数据可靠:内置 CRC 校验、重传机制,确保数据在短距离(10-20 米空旷环境)传输中无丢失、无错码。

🎯 单片机连接硬件图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

🌟 驱动思路

步骤 1:硬件初始化

  • 配置串口:波特率为 9600bps,数据位设为 8 位,停止位 1 位,无校验位。

步骤 2:数据透传交互

  • 完成初始化配置后,蓝牙模块进入透传模式(无需额外指令,直接透明转发串口数据),此时 STM32 需构建完整的双向数据交互机制:
  • 发送数据:STM32 将需传输的信息(如传感器数据、设备状态)通过串口发送给蓝牙模块,模块自动无线转发给已配对的外部设备(如手机 APP);
  • 接收与解析:外部设备(如手机)发送的指令(如控制命令)经蓝牙模块转发至 STM32,STM32 接收后解析指令(如识别 “开灯”“启动电机”),并执行对应操作(如控制 GPIO、驱动外设)。

🎯 单片机程序代码

main.c

#include "stm32f10x.h"  
#include "string.h"  
#include "stdio.h" 
#include "delay.h"   
#include "bsp_usart.h"
#include "oled.h"int cnt=0;
char OledBuff[52];
int flag=0;
int main(void)
{NVIC_PriorityGroupConfig (NVIC_PriorityGroup_2);SysTick_Init(72);  //系统时钟初始化 usart1_init(115200);//串口1初始化printf("USART1 OK!\r\n");usart2_init(9600);//串口1初始化usart3_init(115200);//串口3初始化	OLED_Init();OLED_ShowString(36,0,"JDY-31");//:+CONNECTINGwhile(1){if(strstr(buf_uart2.buf,"CONNECTED")!=NULL){flag=1;OLED_ShowString(0,2,"        ");OLED_ShowString(0,2,"设备连接");printf("BLE设备连接\r\n");delay_ms(100);OLED_ShowString(0,2,"        ");Clear_Buffer_UART2();}if(strstr(buf_uart2.buf,"+DISC:SUCCESS")!=NULL){flag=0;OLED_ShowString(0,2,"             "); OLED_ShowString(0,2,"设备断开");printf("BLE设备断开\r\n");delay_ms(100);Clear_Buffer_UART2();}cnt++;if(cnt%100==1&&flag==1){USART2_Send("Send Data:123",sizeof("Send Data:123"));printf("Send Data:123\r\n");OLED_ShowString(0,2,"Send Data:123");}if(buf_uart2.rx_flag==1&&flag==1){			printf("Receive Message:%s\r\n",buf_uart2.buf);OLED_ShowString(0,4,"             ");sprintf(OledBuff,"Rec Data:%s",buf_uart2.buf);OLED_ShowString(0,4,OledBuff);Clear_Buffer_UART2();}delay_ms(10);}
}

uart.c

#include "stm32f10x.h"
#include "bsp_usart.h"	  
#include "stdio.h"
#include "string.h"
#include "stm32f10x_tim.h"////////////////////////////////////////////////////////////////////////////////// 	//////////////////////////////////////////////////////////////////
//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ int handle; 
}; FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
int _sys_exit(int x) 
{ x = x; return 0;
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{ 	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   USART1->DR = (u8) ch;      return ch;
}
#endif#if EN_USART1UART_BUF buf_uart1;     //CH340
//初始化IO 串口1 
//bound:波特率
void usart1_init(u32 bound){//GPIO端口设置GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟USART_DeInit(USART1);  //复位串口1//USART1_TX   PA.9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9//USART1_RX	  PA.10GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化PA10//USART 初始化设置USART_InitStructure.USART_BaudRate = bound;//一般设置为115200;USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式USART_Init(USART1, &USART_InitStructure); //初始化串口USART_Cmd(USART1, ENABLE);                    //使能串口 #if EN_USART1_RX	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启相关中断USART_ClearFlag(USART1, USART_FLAG_TC);//Usart1 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;		//子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器、#endif}/*********************************串口1的服务函数*************************************************/
void USART1_Send_byte(char data)
{while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);USART_SendData(USART1, data);
}
/*-------------------------------------------------*/
/*函数名:串口1 发送数组                             */
/*参  数:bound:波特率                             */
/*返回值:无                                        */
/*-------------------------------------------------*/
void USART1_Send(char *Data,uint16_t Len)
{ uint16_t i;for(i=0; i<Len; i++){USART1_Send_byte(Data[i]);}
}
void USART1_SendStr(char*SendBuf)//串口1打印数据
{while(*SendBuf){while((USART1->SR&0X40)==0);//等待发送完成 USART1->DR = (u8) *SendBuf; SendBuf++;}
}/*****************************************************
清空电脑反馈的缓冲数据 串口1
*****************************************************/
void Clear_Buffer_UART1(void)//清空缓存
{buf_uart1.index=0;buf_uart1.rx_flag=0;memset(buf_uart1.buf,0,BUFLEN);
}
void UART1_receive_process_event(char ch )     //串口2给4g用
{if(buf_uart1.index >= BUFLEN){buf_uart1.index = 0 ;}else{buf_uart1.buf[buf_uart1.index++] = ch;}
}//串口1的接收中断程序
void USART1_IRQHandler(void)                                //串口1中断服务程序
{uint8_t Res;Res=Res;if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断,可以扩展来控制{Res=USART_ReceiveData(USART1);//接收模块的数据;UART1_receive_process_event(Res);//接收模块的数据} if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)  //模块空闲{Res=USART_ReceiveData(USART1);//接收模块的数据;buf_uart1.rx_flag=1;} } #endif#if EN_USART2
UART_BUF buf_uart2;     //EC200T
//初始化IO 串口2
//pclk1:PCLK1时钟频率(Mhz)
//bound:波特率 
void usart2_init(u32 bound)
{  	 GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//使能,GPIOA时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//USART2USART_DeInit(USART2);  //复位串口2//USART2_TX   PA.2GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA2//USART2_RX	  PA.3GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化PA3//USART 初始化设置USART_InitStructure.USART_BaudRate = bound;//115200USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式USART_Init(USART2, &USART_InitStructure); //初始化串口USART_Cmd(USART2, ENABLE);                    //使能串口 #if EN_USART2_RX	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启相关中断USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);//开启相关中断//Usart1 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;//串口1中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority =1;		//子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器、
#endif
}void Clear_Buffer_UART2(void)//清空缓存
{buf_uart2.index=0;buf_uart2.rx_flag=0;memset(buf_uart2.buf,0,BUFLEN);
}/*********************************串口2的服务函数*************************************************/
void USART2_Send_byte(char data)
{while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);USART_SendData(USART2, data);
}/*-------------------------------------------------*/
/*函数名:串口2 发送数组                             */
/*参  数:bound:波特率                             */
/*返回值:无                                        */
/*-------------------------------------------------*/
void USART2_Send(char *Data,uint16_t Len)
{ uint16_t i;for(i=0; i<Len; i++){USART2_Send_byte(Data[i]);}
}void USART2_SendStr(char*SendBuf)//串口1打印数据
{while(*SendBuf){while((USART2->SR&0X40)==0);//等待发送完成 USART2->DR = (u8) *SendBuf; SendBuf++;}
}void usart2_receive_process_event(unsigned char ch )     //串口2给4g用
{if(buf_uart2.index >= BUFLEN){buf_uart2.index = 0 ;}else{buf_uart2.buf[buf_uart2.index++] = ch;}
}
void USART2_IRQHandler(void)                            //串口2接收函数
{char Res;Res=Res;if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  //接收中断,可以扩展来控制{Res=USART_ReceiveData(USART2);//接收模块的数据;usart2_receive_process_event(Res);//接收模块的数据} if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET)  //模块空闲{Res=USART_ReceiveData(USART2);//接收模块的数据;buf_uart2.rx_flag=1;} 
}#endif#if EN_USART3UART_BUF buf_uart3;     //TTL
void usart3_init(u32 bound)
{//GPIO端口设置GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	//使能,GPIOA时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);//USART3USART_DeInit(USART3);  //复位串口3//USART3_TX   PB10GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PA2//USART3_RX	  PB11GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOB, &GPIO_InitStructure);  //初始化PB11//USART 初始化设置USART_InitStructure.USART_BaudRate = bound;//115200USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式USART_Init(USART3, &USART_InitStructure); //初始化串口USART_Cmd(USART3, ENABLE);                    //使能串口 #if EN_USART3_RX	USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启相关中断USART_ITConfig(USART3, USART_IT_IDLE, ENABLE);//开启相关中断USART_ClearFlag(USART3, USART_FLAG_TC);//Usart3 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;//串口3中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级1NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;		//子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器、
#endif}void USART3_Send_byte(char data)
{while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);USART_SendData(USART3, data);
}/*-------------------------------------------------*/
/*函数名:串口2 发送数组                             */
/*参  数:bound:波特率                             */
/*返回值:无                                        */
/*-------------------------------------------------*/
void USART3_Send(char *Data,uint16_t Len)
{ uint16_t i;for(i=0; i<Len; i++){USART3_Send_byte(Data[i]);}
}void USART3_SendStr(char*SendBuf)//串口3打印数据
{while(*SendBuf){while((USART3->SR&0X40)==0);//等待发送完成 USART3->DR = (u8) *SendBuf; SendBuf++;}
}/*****************************************************
清空电脑反馈的缓冲数据 串口1
*****************************************************/
void Clear_Buffer_UART3(void)//清空缓存
{buf_uart3.index=0;buf_uart3.rx_flag=0;memset(buf_uart3.buf,0,BUFLEN);
}
void USART3_receive_process_event(char ch )     //串口2给4g用
{if(buf_uart3.index >= BUFLEN){buf_uart3.index = 0 ;}else{buf_uart3.buf[buf_uart3.index++] = ch;}
} 
void USART3_IRQHandler(void)                                //串口3中断服务程序
{char Res;Res=Res;if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)  //接收中断,可以扩展来控制{Res=USART_ReceiveData(USART3);//接收模块的数据;USART3_receive_process_event(Res);} if(USART_GetITStatus(USART3, USART_IT_IDLE) != RESET)  //模块空闲{Res=USART_ReceiveData(USART3);//接收模块的数据;buf_uart3.rx_flag=1;} 
} 	#endif

🎯 代码下载链接

https://download.csdn.net/download/qq_41954594/92144370?spm=1001.2014.3001.5503

http://www.dtcms.com/a/492453.html

相关文章:

  • 湖南网站搜索排名优化电话代还软件开发
  • 冠珠瓷砖X东方的东方,专访设计大师尼克、孙云、程绍正韬,探索东方人居范式设计美学
  • 小工厂ERP系统特点与选型建议
  • wordpress站群远程管理软件wordpress 去掉版权
  • javax.el.PropertyNotFoundException: Cannot resolve identifier ‘approved‘
  • 你好南京网站店铺起名网免费取名
  • 客户案例:Clearpath Robotics—让机器人技术更易于使用
  • 用Deepseek 实现一个基于web的扣图应用
  • 如何给网站续费typecho转WordPress插件
  • 网站建设申请报告上海网站设计公司
  • Spring Boot 入门:5分钟搭建Hello World
  • 网站建设频教程网站建设小程序开发公司
  • 个人网站建站指南重庆网站搭建公司
  • 小百姓这个网站谁做的怎么进入wordpress修改界面
  • 专业网站建设推广个人互联网创业项目
  • 机关网站建设工作总结常用来做网站的首页
  • 贵阳公司做网站做网站需要哪些技能
  • 高权重网站发外链枣强网址建站
  • FPGA实现CIC抽取滤波器
  • 深圳快速网站制作哪家快wordpress自适应设置宽度
  • qq临时会话网站搜索引擎网站推广法 怎么做
  • 国内可以做的国外兼职网站高端网站建设论坛
  • 网站广告策划wordpress如何使用
  • 网站品牌推广公司最新被百度收录的网站
  • 19. Linux free命令、awk命令
  • NewStarCTF2025-Week2-Pwn
  • 网站建设5个why分销网站怎么做
  • 永州做网站的公司河南省建设厅执业资格注册中心网站
  • 3-C++中类大小影响因素
  • 广州外贸网站公司新零售网络推广方案