基于STM32F103C8T6的HC-06蓝牙通信

news2024/9/23 11:19:33

文章目录

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


前言 注意看 !

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

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

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

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

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


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

一、蓝牙通信流程

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

二、怎么实现蓝牙通信

1.了解蓝牙模块功能

HC-06模块的引脚

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 Rate
	USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None; //No controlFlow
	USART_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 Bit
	USART_InitStruct.USART_WordLength=USART_WordLength_8b;   //8bit data
	
	USART_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模块进行调试,不过我没有米,所以才不得不采另辟蹊径。

谢谢同志们阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/936140.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[第七届蓝帽杯全国大学生网络安全技能大赛 蓝帽杯 2023]——Web方向部分题 详细Writeup

Web LovePHP 你真的熟悉PHP吗&#xff1f; 源码如下 <?php class Saferman{public $check True;public function __destruct(){if($this->check True){file($_GET[secret]);}}public function __wakeup(){$this->checkFalse;} } if(isset($_GET[my_secret.flag]…

性能测试流程? 怎么做性能测试?

一、前期准备 性能测试虽然是核心功能稳定后才开始压测&#xff0c;但是在需求阶段就应该参与&#xff0c;这样可以深入了解系统业务、重要功能的业务逻辑&#xff0c;为后续做准备。 二、性能需求分析&#xff08;评审&#xff09; 评审时&#xff0c;要明确性能测试范围、目…

MySQL执行更新的流程

一、加载缓存数据 引擎要执行更新语句的时候 &#xff0c;比如对“id10”这一行数据&#xff0c;他其实会先将“id10”这一行数据看看是否在缓冲池里&#xff0c;如果不在的话&#xff0c;那么会直接从磁盘里加载到缓冲池里来&#xff0c;而且接着还会对这行记录加独占锁。 二…

【项目 计网7】4.20 多进程实现并发服务器 4.22 多线程实现并发服务器

文章目录 4.20 多进程实现并发服务器server_process.cclient.c4.22 多线程实现并发服务器客户端代码&#xff1a;服务端代码&#xff1a; 4.20 多进程实现并发服务器 要实现TCP通信服务器处理并发的任务&#xff0c;使用多线程或者多进程来解决。 思路&#xff1a; 1、一个父进…

【Python】PySpark

前言 Apache Spark是用于大规模数据&#xff08;large-scala data&#xff09;处理的统一&#xff08;unified&#xff09;分析引擎。 简单来说&#xff0c;Spark是一款分布式的计算框架&#xff0c;用于调度成百上千的服务器集群&#xff0c;计算TB、PB乃至EB级别的海量数据…

ADC芯片CS1238,CS1237介绍和代码

一.芯片介绍 CS1238是一款高精度、低功耗 模数转换芯片&#xff0c;两路差分输入通道&#xff0c;内置温度传感器和高精度振荡器。MCU可以通过2线的SPI 接口SCLK、DRDY与CS1237进行通信&#xff0c;对其进行配置&#xff0c;例如通道选择、PGA选择、输出速率选择等。下面是CS1…

9. 解谜游戏

目录 题目 Description Input Notes 思路 暴力方法 递归法 注意事项 C代码&#xff08;递归法&#xff09; 关于DFS 题目 Description 小张是一个密室逃脱爱好者&#xff0c;在密室逃脱的游戏中&#xff0c;你需要解开一系列谜题最终拿到出门的密码。现在小张需要打…

解决CMake报“Compatible with CMake < 2.8.12 will be removed“问题

今天在使用CMake编译zlib开源库时&#xff0c;弹出编译警告"Compatibility with CMake < 2.8.12 will be removed from a future "&#xff0c;如图(1)所示&#xff1a; 图(1) CMake报版本太低错误 将CMakeList.txt里的cmake版本调高 出现该问题的原因是&#xff…

2023.08.27 学习周报

文章目录 摘要文献阅读1.题目2.重点3.引言4.方法5.实验结果6.结论 深度学习Majorization-Minimization算法1.基本思想2.要求3.示意图 总结 摘要 This week, I read a computer science on the prediction of atmospheric pollutants in urban environments based on coupled d…

PostgreSQL命令行工具psql常用命令

1. 概述 通常情况下操作数据库使用图形化客户端工具&#xff0c;在实际工作中&#xff0c;生产环境是不允许直接连接数据库主机&#xff0c;只能在跳板机上登录到Linux服务器才能连接数据库服务器&#xff0c;此时就需要使用到命令行工具。psql是PostgreSQL中的一个命令行交互…

达梦数据库修改超级管理员密码

ENABLE_LOCAL_OSAUTH0 开启认证 ENABLE_LOCAL_OSAUTH1不认证、免密登陆 谨慎操作 目录 修改账户密码 锁定解锁账户 登录成功 修改账户密码 alter user SYSDBA IDENTIFIED by "Passw0rd!!"; 锁定解锁账户 ALTER USER 用户名 ACCOUNT UNLOCK; 问题分析&#xff1a…

SD 总线引脚介绍

参考 https://www.cnblogs.com/justin-y-lin/p/12259851.html SD卡与TF卡的引脚定义 - 360文档中心

网络服务第一次作业

1.配置ntp时间服务器&#xff0c;确保客户端主机能和服务主机同步时间 2.配置ssh免密登陆&#xff0c;能够实现客户端主机通过服务器端的redhat账户进行基于公钥验证方式的远程连接 timedatetectl---查看时间 修改配置文件 文件路径 vim /etc/chrony.conf-----修改服务…

学习ts(十)装饰器

定义 装饰器是一种特殊类型的声明&#xff0c;它能够被附加到类声明&#xff0c;方法&#xff0c;访问符&#xff0c;属性或参数上&#xff0c;是一种在不改变原类和使用继承的情况下&#xff0c;动态的扩展对象功能。 装饰器使用expression形式&#xff0c;其中expression必须…

软考:中级软件设计师:网络类型与拓扑结构,网络规划与设计,ip地址与子网划分,特殊含义的IP地址

软考&#xff1a;中级软件设计师:网络类型与拓扑结构 提示&#xff1a;系列被面试官问的问题&#xff0c;我自己当时不会&#xff0c;所以下来自己复盘一下&#xff0c;认真学习和总结&#xff0c;以应对未来更多的可能性 关于互联网大厂的笔试面试&#xff0c;都是需要细心准…

「料见」vol27.回顾 | 知名视觉SLAM专家高翔:一起来聊聊视觉SLAM在自动驾驶和机器人领域的实际应用

高翔老师继畅销书《视觉SLAM十四讲》之后&#xff0c;又推出了新作《自动驾驶与机器人中的SLAM技术》。该书自出版以来备受瞩目&#xff0c;为读者提供了关于SLAM技术的全面而深入的理解。 第27期“料见”闭门分享会&#xff0c;我“门”非常开心邀请到知名视觉SLAM专家———…

集合类的线程安全问题

集合类 原来的集合类,大部分都不是线程安全的 Vector, Stack, HashTable, 是线程安全的(不建议用), 其他的集合类不是线程安全的. 加了锁,不一定就是线程安全的,不加锁也不一定是线程不安全的,需要具体问题具体分析 虽然get,set方法都加了synchronized,但是如果不能正确使用,也…

RabbitMQ从原理到实战—基于Golang【万字详解】

文章目录 前言一、MQ是什么&#xff1f;优势劣势 二、MQ的用途1、应用解耦2、异步加速3、削峰填谷4、消息分发 三、RabbitMQ是什么1、AMQP 协议2、RabbitMQ 包含的要素3、RabbitMQ 基础架构 四、实战1、Simple模式(即最简单的收发模式)2、Work Queues 模型3、Publish/Subscribe…

ESP8266固件烧录

文章目录 硬件电路烧录工具完整固件资料+烧录工具硬件电路 烧写模式: GPIO0:0 此时通过REST复位引脚复位,8266进入烧写模式。 烧写通过串口烧写,波特率设置115200 运行模式: GPIO0:1 此时通过REST复位引脚复位,8266进入烧写模式。 烧录工具 烧写工具下载链接:https:…