文章目录

  • 前言 注意看 !
  • 一、蓝牙通信流程
  • 二、怎么实现蓝牙通信
    • 1.了解蓝牙模块功能
    • 2.了解蓝牙通信本质
    • 3.进行AT命令调试
    • 4.调试完成,连接通信
  • 三、结尾

前言 注意看 !

如果朋友们遇到了如下问题,可以仔细借鉴本文章和另一篇专门讲解蓝牙通信问题的文章,一定能够解决你在蓝牙通信时遇到的诸多困难

1.在调试蓝牙模块AT指令时无返回值

2.身边无USB转TTL模块可以直接调试蓝牙模块(本人就是由于无模块花了了整整一天才调试成功)

3.在调试蓝牙模块AT指令时存在诸多异常
(1)上位机接收数据时乱码
(2)卡死在数据接受中断当中,导致接受不了数据或者一直发送数据等异常情况。
(3)拨动,或者拔掉数据线,会出现大量的数据发送情况等异常。

如果朋友们只是想了解蓝牙通信过程或者应用思路那这篇文章基本可以满足入门的朋友。(本文章采用蓝牙模块为HC-06模块)


提示:以下是本篇文章正文内容,下面案例可供参考

一、蓝牙通信流程

最简单实际的的蓝牙通信过程就是
单片机——蓝牙——手机蓝牙app
蓝牙作为桥梁进行单片机与手机数据的交换
蓝牙就如同一个无线的USART一样,将两者连接。

二、怎么实现蓝牙通信

1.了解蓝牙模块功能

1.引脚功能:

HC-06共有4个外接引脚分别为RXD(接收数据),TXD(发送数据)
工作电源3.6-6v,我采用STM32F103C8t6的5V电源口供电。(其余两个引脚功能可以自查,如果图效率也可以不用管)

2.传输数据格式:数据位8位,停止位1位,无校验,无流控制,除了波特率以外,和基础USART串口通信设置基本一致。

2.了解蓝牙通信本质

**就是将蓝牙当做一个无线的额外的串口模块进行单片机与其他通信源的连接。
而要正确的使用串口,一定要知道的三要素是:
1.波特率 2.串口号 3.数据格式

3.进行AT命令调试

之前说过,蓝牙通信的本质就是串口通信,那么我们在AT命令调试时,也相当于串口通信,**电脑发送调试命令给单片机,单片机再发送给蓝牙,蓝牙再返还命令处理结果给单片机,单片机再上传给电脑。所以需要两个USART串口,分别连接电脑与蓝牙。
(有额外的USB转TTL模块则不需要这么麻烦)

所以,我们需要先编写串口通信的代码。

以下是usart.c文件 在其中编写串口初始化与NVIC中断管理设置
(一般都为数据接受中断,当某个串口接收到数据时,执行中断服务函数)

#include "usart.h"
//设置NVIC中断管理器
void NVIC_config(USART_TypeDef* USARTx,uint8_t USARTx_IRQn,uint8_t Sub)
{NVIC_InitTypeDef NVIC_InitStruct;  //构建NVIC结构体NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);         //中断优先级分组NVIC_InitStruct.NVIC_IRQChannel=USARTx_IRQn;       //设置中断源NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1; //主优先级NVIC_InitStruct.NVIC_IRQChannelSubPriority=Sub;       //子优先级NVIC_Init(&NVIC_InitStruct);
}//可以多次调用,从而初始化多个USART串口//利用续行符来声明变量
void usart_config(GPIO_TypeDef* GPIOx, \
uint16_t USART_Pin_RX,uint16_t USART_Pin_TX, \
uint32_t USART_IO_Clock,uint32_t USART_Clock, \
USART_TypeDef* USARTx,uint8_t USARTx_IRQn,uint8_t Sub,uint32_t BaudRate)     //对应的GPIO时钟与USART的时钟
{GPIO_InitTypeDef GPIO_RXInitStruct;                                //两个Pin 两个结构体GPIO_InitTypeDef GPIO_TXInitStruct;USART_InitTypeDef USART_InitStruct;                 //声明USART初始化结构体RCC_APB2PeriphClockCmd(USART_IO_Clock , ENABLE);      //开IO时钟GPIO_RXInitStruct.GPIO_Pin=USART_Pin_RX;   GPIO_RXInitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;     //设置为浮空输入,不需要设置速度GPIO_TXInitStruct.GPIO_Pin=USART_Pin_TX;GPIO_TXInitStruct.GPIO_Mode=GPIO_Mode_AF_PP;           //要使用复用推挽输出GPIO_TXInitStruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOx, &GPIO_RXInitStruct);       //加&指明结构体位置GPIO_Init(GPIOx, &GPIO_TXInitStruct);       //初始化USART 所用的 GPIO if(USARTx_IRQn==USART1_IRQn){RCC_APB2PeriphClockCmd(USART_Clock , ENABLE);         //开串口外设时钟}if(USARTx_IRQn==USART2_IRQn){RCC_APB1PeriphClockCmd(USART_Clock , ENABLE); //!!!!!!时钟线不一样}USART_InitStruct.USART_BaudRate=BaudRate;                     //B RateUSART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None; //No controlFlowUSART_InitStruct.USART_Mode=USART_Mode_Rx|USART_Mode_Tx; //双向USART_InitStruct.USART_Parity=USART_Parity_No;           //No Parity 无校验USART_InitStruct.USART_StopBits=USART_StopBits_1;       //1stop BitUSART_InitStruct.USART_WordLength=USART_WordLength_8b;   //8bit dataUSART_Init(USARTx,&USART_InitStruct);   //初始化串口结构体NVIC_config(USARTx,USARTx_IRQn,Sub);USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE);   //使能串口接收中断USART_Cmd(USARTx,ENABLE); //使能串口
}

可以看出来函数体中的参数较多,是为了减少编写的数次,之后调用函数体,输入对应的参数即可,注意除了USART1挂载在APB2时钟上其他都挂载在APB1上!

代码执行功能如下

NVIC_Init(&NVIC_InitStruct);//初始化NVIC中断管理器
RCC_APB2PeriphClockCmd(USART_IO_Clock , ENABLE); //开GPIO时钟
if(USARTx_IRQn==USART1_IRQn)RCC_APB2PeriphClockCmd(USART_Clock , ENABLE);//开串口时钟
if(USARTx_IRQn==USART2_IRQn)RCC_APB1PeriphClockCmd(USART_Clock , ENABLE);
USART_Init(USARTx,&USART_InitStruct);   //初始化串口结构体
USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE);  //使能串口接收中断
USART_Cmd(USARTx,ENABLE);   //使能串口

此时已经配置好了串口,还需要编写中断服务函数,编写中断服务函数时要在stm32f10x.it.c文件下编写(其他问题如函数名,中断号可自查)

uint8_t temp1;
uint8_t temp2;
void USART1_IRQHandler(void)
{if(USART_GetITStatus(USART1,USART_IT_RXNE) !=  RESET)//判断中断位{USART_ClearITPendingBit(USART1, USART_IT_RXNE);temp1 = USART_ReceiveData(USART1); //接收数据 usart_sendByte(USART2,temp1);LED1_TOOGLE;  //作为可视信号,亮灯  }
}void USART2_IRQHandler(void)
{if(USART_GetITStatus(USART2,USART_IT_RXNE) !=  RESET)//判断中断位{USART_ClearITPendingBit(USART2, USART_IT_RXNE);temp2 = USART_ReceiveData(USART2); //接收数据 usart_sendByte(USART1,temp2);LED1_TOOGLE;      }
}

中断函数的功能与完整调试过程如下:
当上PC端发送调试命令给USART1时,接受的命令再通过USART2发送给蓝牙。
当蓝牙接收到调试命令,反馈出调试结果发送到USART2,接收到的结果再通过USART1发送到PC端。

接线方式:
STM32连接电脑任意端口

蓝牙上电后与STM32连接
蓝牙 RXD: PA2(USART2 TXD)
蓝牙 TXD: PA3(USART2 RXD)

开始调试
打开串口调试软件 设置波特率,数据格式与编写时的格式一致,开始调试
可以看到我们发送出AT后,回得到一个OK返还信息,说明调试成功,如果没有得到返还需要去找出错误原因。如果需要执行其他命令操作,比如修改密码,蓝牙名称,可以查找对应的命令表。

4.调试完成,连接通信

在进行正式通信前我们还需要下载一个蓝牙串口助手这样才能更简单的进行数据发送与接受。(要设置好接收到的数据编码,与发送出去的数据编码)
通信效果如下。

三、结尾

蓝牙通信的过程十分简单,可以说就是一个串口通信的过程,不过需要一个调试命令和连接的阶段,不过蓝牙通信可以说是我们入门STM32的一个很重要的时刻,因为无线操作永远比按键或者有线操作来得骚,可以给我们极大的发挥空间,比如可以远程控制LLED亮灭,或者蓝牙小车,远程监控等等更加高级的思路就应运而生。

但是调试的过程中遇到困难是不可避免的,打击和bug层出不穷,希望不是很富裕又想学STM32的同志们看到这篇文章时,坚持的走下去,就像在实现调试过程中,绝大部分人 包括我去询问的B站UP主,和众多帖吧老哥,都是用了额外的USB转TTL模块进行调试,不过我没有米,所以才不得不采另辟蹊径。

谢谢同志们阅读!

基于STM32F103C8T6的HC-06蓝牙通信相关推荐

  1. C51编程23-应用篇(HC 06蓝牙模块)

    现在的手机,平板,笔记本电脑都会自带蓝牙.本文将会介绍51单片机使用HC 06 蓝牙模块实现手机与笔记本电脑的通讯.   HC 06 模块 购买HC 06模块后需要检测蓝牙模块是否是好的,使用串口线与 ...

  2. 基于STM32F103C8T6与ESP8266的物联网智能温度采集与蓝牙OLED数字钟的设计与实现

    基于STM32F103C8T6与ESP8266的物联网智能温度采集与蓝牙OLED数字钟的设计与实现 作者: 颜孙炜 文章目录 基于STM32F103C8T6与ESP8266的物联网智能温度采集与蓝牙O ...

  3. python 蓝牙开发_基于python实现蓝牙通信代码实例

    这篇文章主要介绍了基于python实现蓝牙通信代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 安装和示例 linux下安装 sudo apt ...

  4. 基于Android Studio的蓝牙通信的简单应用与开发

    实现基于Android Studio的蓝牙通信的简单应用与开发 实现蓝牙通信 界面展示 核心文件 部分代码展示 总结 实现蓝牙通信 通过权限申请与代码实现,完成蓝牙通信的简单应用与开发. 界面展示 核 ...

  5. python写安卓app控制蓝牙_基于python实现蓝牙通信代码实例

    这篇文章主要介绍了基于python实现蓝牙通信代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 安装和示例 linux下安装 sudo apt ...

  6. android蓝牙传输脉冲,一种基于Android操作系统的激光测距仪蓝牙通信方法与流程...

    本发明属于无线通信技术领域,涉及Android操作系统的应用,具体涉及一种基于Android操作系统的激光测距仪蓝牙通信方法. 背景技术: 目前,随着智能设备的普及,智能操作系统得到了极大的发展,An ...

  7. 基于intel芯片的安卓蓝牙4.0 BLE通信总结

    基于intel芯片的安卓蓝牙4.0 BLE通信问题总结 使用设备: 台电 x98 air 3G 系统:安卓4.4.4 系统搭建: 1.安装ADT驱动,可以搜索intel_mobile_usb_driv ...

  8. 基于STM32F103C8T6的充电桩计费系统(程序+原理图+PCB+论文)

    本设计: 基于STM32F103C8T6的充电桩计费系统(程序+原理图+PCB+论文) 原理图:Altium Designer 程序编译器:keil 5 编程语言:C语言 编号C0019 下载链接 [ ...

  9. 基于BlueZ的C语言蓝牙编程

    hci_inquiry()   //查询周围蓝牙设备并获取其地址 sdp_connect()   //链接到蓝牙设备的sdp服务器 sdp_list_append()  //添加sdp查询列表项 sd ...

最新文章

  1. sql xml 入门
  2. 解决firefox不能安装Flash插件
  3. DDD:一个朋友对领域驱动的小结
  4. 设备管理 USB ID
  5. ftp 服务器文件夹创建命令,ftp 服务器文件夹创建命令
  6. wps序号打乱重新排序_wps表格序号自动排列
  7. 相机视场角和焦距_完全解析视场角度
  8. 牛客网——B 遥远的记忆
  9. 【JavaSE】Java9Java10Java11新特性(687~717)
  10. 计算机B和D的转换,模数转换
  11. 【编程游戏】贺岁霓虹灯。(参观366楼xiuyouxu的霓虹灯)
  12. 每天3分钟知晓天下事,一句话新闻资讯简报的公众号推荐
  13. notifyDataSetChanged使用总结
  14. gRPC和gRPC-Gateway的使用以及遇到的坑
  15. 我的世界服务器显示伤害指令,我的世界怎么关闭队友伤害命令_我的世界怎么关闭队伤...
  16. ESXI 迁移至KVM (V2V迁移)
  17. 多道程序设计、多线程和多处理
  18. C语言做的接鸡蛋小游戏(附源码注释)【原创】
  19. 深度学习面试总结-1
  20. 设计模式之美-11| 实战一(下):如何利用基于充血模型的DDD开发一个虚拟钱包系统?

热门文章

  1. CQ的包打开进行修改
  2. tree命令生成目录树
  3. 面向对象程序设计课程设计——MFC实现同学通讯录管理系统
  4. lucene实现分组统计的方法
  5. 《Python之禅》——原文和翻译
  6. F2FS文件系统工具编译及使用方法
  7. 用C++编写一个人事管理系统
  8. ZJ_slider兼容Firefox,IE,Opera,Safari的滑动条,拖动条
  9. 百度导航SDK APP Mcode码校验失败解决方案
  10. FTP,SFTP,HTTP,HTTPS网络传输协议