蓝牙模块—BLE-CC41-A

1. 蓝牙的特点


蓝牙模块采用的 TI 公司设计的 CC2541芯片,主要面向低功耗蓝牙通信方案,该模块的工作频段为 2.4Ghz,这个频段属于国际通用频段

注意:蓝牙集成了一个状态指示灯,LED灯如果均匀慢速闪烁,就表示蓝牙未连接,如果LED灯常亮,表示已连接

2. 蓝牙的模式

蓝牙具有两种工作模式,一种是 AT 指令模式,一种是 数据透传模式,两种模式的特点如下

a. AT 指令模式

        AT指令模式指的是蓝牙未连接的工作模式,在该模式可以获取或配置蓝牙的参数(蓝牙名字、蓝牙密码、蓝牙地址......),需要利用固定的 AT 指令,注意不同公司设计的蓝牙模块的AT 指令大同小异,具体指令参考手册

        代码里面:换行字符结尾 (\r\n)         串口调试助手里面:回车结尾


练习:编写程序,利用电脑的串口调试助手发送对应的 AT 指令,设置蓝牙模块的参数信息

如果USART1的波特率和USART3不一致,就可能会出现丢包,两种解决方法:

        (1) 波特率设置一致

        (2) 把接收的数据都接收完,再发送给其他串口

usart.h

#ifndef __USART_H__
#define __USART_H__#include "stm32f4xx.h"
#include "stdio.h"/*串口1的初始化函数@baudrate:串口传输的波特率
*/
void USART1_Init(int baudrate);/*串口3的初始化函数@baudrate:串口传输的波特率
*/
void USART3_Init(int baudrate);// 发送一个字节
void USART_SendByte(USART_TypeDef *USARTx, uint16_t data);// 发送一个字符串
void USART_SendDatas(USART_TypeDef *USARTx, const char *str);// 蓝牙的初始化,只需要调用一次
// void BLE_Init(void);// 将printf函数重定向到串口  注意:windows 中换行符为 \r\n
int fputc(int c, FILE *stream);#endif

usart.c

#include "usart.h"
#include "systick.h"/*串口1的初始化函数@baudrate:串口传输的波特率
*/
void USART1_Init(int baudrate) {// (1) GPIO 引脚初始化// a. 使能 GPIO 分组时钟RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);// b. 初始化 GPIO// PA9 Tx   PA10 RxGPIO_InitTypeDef g;g.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;g.GPIO_Mode = GPIO_Mode_AF;g.GPIO_Speed = GPIO_Speed_2MHz;g.GPIO_OType = GPIO_OType_PP; // 输出推挽g.GPIO_PuPd = GPIO_PuPd_NOPULL;GPIO_Init(GPIOA, &g);// c. 配置GPIO复用功能GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);// (2) USART配置// a. 使能 USART 分组时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);// b. 初始化配置USARTUSART_InitTypeDef u;// 波特率u.USART_BaudRate = baudrate;// 指定数据帧数据位,也就是传输字长 = 数据位数 + 校验位数u.USART_WordLength = USART_WordLength_8b;// 指定停止位长度u.USART_StopBits = USART_StopBits_1;// 指定校验方式 不要校验u.USART_Parity = USART_Parity_No;// 指定串口模式  全双工u.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;// 指定硬件控制流   不要硬件流控u.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_Init(USART1, &u);// (3) 中断配置// a. 中断源的控制(中断控制位使能)USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);// b. 配置NVICNVIC_InitTypeDef v;v.NVIC_IRQChannel = USART1_IRQn;v.NVIC_IRQChannelPreemptionPriority = 2;v.NVIC_IRQChannelSubPriority = 2;v.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&v);// (4) 使能串口USART_Cmd(USART1, ENABLE);
}/*串口3的初始化函数@baudrate:串口传输的波特率
*/
void USART3_Init(int baudrate) {// (1) GPIO 引脚初始化// a. 使能 GPIO 分组时钟RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);// b. 初始化 GPIO// USART3_TX --- PB10    USART3_RX --- PB11GPIO_InitTypeDef g;g.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;g.GPIO_Mode = GPIO_Mode_AF;g.GPIO_Speed = GPIO_Speed_2MHz;g.GPIO_OType = GPIO_OType_PP; // 输出推挽g.GPIO_PuPd = GPIO_PuPd_NOPULL;GPIO_Init(GPIOB, &g);// c. 配置GPIO复用功能GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3);GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3);// (2) USART配置// a. 使能 USART 分组时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);// b. 初始化配置USARTUSART_InitTypeDef u;// 波特率u.USART_BaudRate = baudrate;// 指定数据帧数据位,也就是传输字长 = 数据位数 + 校验位数u.USART_WordLength = USART_WordLength_8b;// 指定停止位长度u.USART_StopBits = USART_StopBits_1;// 指定校验方式 不要校验u.USART_Parity = USART_Parity_No;// 指定串口模式  全双工u.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;// 指定硬件控制流   不要硬件流控u.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_Init(USART3, &u);// (3) 中断配置// a. 中断源的控制(中断控制位使能)USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);// b. 配置NVICNVIC_InitTypeDef v;v.NVIC_IRQChannel = USART3_IRQn;v.NVIC_IRQChannelPreemptionPriority = 2;v.NVIC_IRQChannelSubPriority = 2;v.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&v);// (4) 使能串口USART_Cmd(USART3, ENABLE);
}// 发送一个字节
void USART_SendByte(USART_TypeDef *USARTx, uint16_t data) {// 发送USART_SendData(USARTx, data);// 等待发送寄存器为空事件产生while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) != SET);// 清除发送寄存器为空事件标志USART_ClearFlag(USARTx, USART_FLAG_TXE);
}// 发送一个字符串
void USART_SendDatas(USART_TypeDef *USARTx, const char *str) {const char *s = str;while (*s) {USART_SendByte(USARTx, *s);s++;}	
}/*串口1 的中断服务函数
*/
void USART1_IRQHandler(void) {// 如果产生了接收中断  RXNE 事件产生if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET) {uint8_t RecvData = USART_ReceiveData(USART1);USART_SendByte(USART3, RecvData);// 清除中断标志USART_ClearITPendingBit(USART1, USART_IT_RXNE);}
}/*串口3 的中断服务函数
*/
void USART3_IRQHandler(void) {// 如果产生了接收中断  RXNE 事件产生if (USART_GetITStatus(USART3, USART_IT_RXNE) == SET) {uint8_t RecvData = USART_ReceiveData(USART3);USART_SendByte(USART1, RecvData);// 清除中断标志USART_ClearITPendingBit(USART3, USART_IT_RXNE);}
}// 蓝牙的初始化,只需要调用一次
//void BLE_Init(void) {
//	
//	USART_SendDatas(USART3, "AT\r\n"); // 发送测试指令
//	delay_ms(500);
//	
//	USART_SendDatas(USART3, "AT+NAME666\r\n"); // 设置蓝牙名称
//	delay_ms(500);
//	
//	USART_SendDatas(USART3, "AT+LADDR\r\n"); // 获取蓝牙地址
//	delay_ms(500);
//	
//	USART_SendDatas(USART3, "AT+RESET\r\n"); // 复位蓝牙重启
//	delay_ms(500);
//	
//	printf("ble init success\r\n");	
//}// 将printf函数重定向到串口  注意:windows 中换行符为 \r\n
int fputc(int c, FILE *stream) {USART_SendData(USART1, c & 0xFF);while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);// 清除发送寄存器为空事件标志USART_ClearFlag(USART1, USART_FLAG_TXE);return 0;
}

main.c

#include "stm32f4xx.h"
#include "usart.h"int main(void) {NVIC_PriorityGroupConfig(2);	USART1_Init(9600);USART3_Init(9600);while (1);
}

b. 数据透传模式
        数据透传模式指的是蓝牙已经被手机连接,该模式下蓝牙就相当于一根透明的串口线,蓝牙只负责把数据发送到目的地,不对数据进行处理

练习:编写代码,把超声波获取的距离每隔 2000 ms 发送到手机端进行查看

#include "stm32f4xx.h"
#include "usart.h"
#include "systick.h"
#include "HC_SR04.h"
#include "systick.h"int main(void) {NVIC_PriorityGroupConfig(2);	USART3_Init(9600);HC_SR04_Init();while (1) {uint32_t distance = HC_SR04_GetDistance();// 方法一:重定向串口3  printf// 方法二:char res[50] = {0};sprintf(res, "distance = %d mm", distance);USART_SendDatas(USART3, res);delay_ms(2000);}
}

扩展:

        (1) 编写代码,可以利用超声波检测障碍物的距离,根据不同的距离进行提示,如果距离小于 30cm 则蜂鸣器叫的声音频率较高,如果距离大于 30cm 并小于 60 cm,则蜂鸣器声音较小,如果距离大于60cm,则蜂鸣器不响。可以利用手机 APP 设置距离的上下限,比如发送"SetDis=15cm\r\n",则距离小于 15cm 时蜂鸣器叫的声音频率较高

        思考:如何对接收到的字符串进行处理 "SetDis=15cm"               

                提示:strstr   strtok       字符串转整型:atoi     整型转字符串:sprintf

        

        比如利用手机 APP 发送特定的数据包,格式为"beep=on\r\n",就可以让蜂鸣器鸣叫,发送"beep=off\r\n",可以让蜂鸣器不叫
       

        (2) 利用手机APP,控制距离的两个阈值  dis1  +  -    dis2 + -

如果程序中定义的局部数组太多太大了,需要在启动文件中修改栈空间大小

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

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

相关文章

【渗透测试】-vulnhub源码框架漏洞-Os-hackNos-1

vulnhub源码框架漏洞中的CVE-2018-7600-Drupal 7.57 文章目录  前言 1.靶场搭建: 2.信息搜集: 主机探测: 端口扫描: 目录扫描: 3.分析: 4.步骤: 1.下载CVE-2018-7600的exp 2.执行exp: 3.写入木…

Docker安装rabbitmq并配置延迟队列

下载rabbitmq镜像 docker pull rabbitmq:management 运行rabbitmq镜像 docker run -id --namerabbitmq -p 5671:5671 -p 5672:5672 -p 4369:4369 -p 15671:15671 -p 15672:15672 -p 25672:25672 -e RABBITMQ_DEFAULT_USERtom -e RABBITMQ_DEFAULT_PASStom rabbitmq:management …

idea上传jar包到nexus

注意&#xff1a;确保idea中项目为maven项目&#xff0c;并且在nexus中已经创建了maven私服。 1、配置pom.xml中推送代码配置 <distributionManagement> <repository> <id>releases</id> <url>http://127.0.0.1:8001/repository/myRelease/<…

Mybatis自定义TypeHandler,直接存储枚举类对象

在这篇文章中&#xff0c;我们已经知道如何使用枚举类直接接受前端的数字类型参数&#xff0c;省去了麻烦的转换。如果数据库需要保存枚举类的code&#xff0c;一般做法也是代码中手动转换&#xff0c;那么能不能通过某种机制&#xff0c;省去转换&#xff0c;达到代码中直接保…

【Unity-UGUI组件拓展】| Image 组件拓展,支持FIlled和Slice功能并存

🎬【Unity-UGUI组件拓展】| Image 组件拓展,支持FIlled和Slice功能并存一、组件介绍二、组件拓展方法三、完整代码💯总结🎬 博客主页:https://xiaoy.blog.csdn.net 🎥 本文由 呆呆敲代码的小Y 原创,首发于 CSDN🙉 🎄 学习专栏推荐:Unity系统学习专栏 🌲 游戏…

博睿谷IT认证-订阅试学习

在这个信息爆炸的时代&#xff0c;拥有一张IT认证证书&#xff0c;就像拿到了职场晋升的通行证。博睿谷&#xff0c;作为IT认证培训的佼佼者&#xff0c;帮你轻松拿下华为、Oracle等热门认证。下面&#xff0c;让我们一起看看博睿谷如何助你一臂之力。 学习时间&#xff0c;你说…

将阮一峰老师的《ES6入门教程》的源码拷贝本地运行和发布

你好同学&#xff0c;我是沐爸&#xff0c;欢迎点赞、收藏、评论和关注。 阮一峰老师的《ES6入门教程》应该是很多同学学习 ES6 知识的重要参考吧&#xff0c;应该也有很多同学在看该文档的时候&#xff0c;想知道这个教程的前端源码是怎么实现的&#xff0c;也可能有同学下载…

移动技术开发:ListView水果列表

1 实验名称 ListView水果列表 2 实验目的 掌握自定义ListView控件的实现方法 3 实验源代码 布局文件代码&#xff1a; activity_main.xml: <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.androi…

远程连接MySQL并操作

配置MySQL开发环境 如果你使用的是基于Debian的系统&#xff08;如Ubuntu&#xff09;&#xff0c;可以在终端通过如下步骤安装MySQL开发包。 更新软件包列表 运行以下命令以确保你拥有最新的软件包列表。 sudo apt-get update安装libmysqlclient-dev开发包 执行以下命令以…

【Java注解】

Java注解&#xff08;Annotation&#xff09;让其他程序根据注解信息来决定怎么执行该程序。 是Java 5中引入的一种特殊类型的注释&#xff0c;它可以被用来为代码添加元数据&#xff0c;即关于代码的数据。 注解不会改变程序的逻辑&#xff0c;但它们可以被其他程序使用&…

Datawhale X 南瓜书 task02学习笔记

算法原理引入 样本点通常应该在模型的2侧&#xff0c;原因&#xff1a;在实际中&#xff0c;因为某种不可控的因素&#xff0c;测出来的样本点肯定是有误差的。如果样本数据点都在模型上&#xff0c;则说明在建立模型时&#xff0c;把误差也考虑进去了&#xff0c;这就是我们说…

【技术解析】消息中间件MQ:从原理到RabbitMQ实战(深入浅出)

文章目录 【技术解析】消息中间件MQ&#xff1a;从原理到RabbitMQ实战(深入浅出)1.简介1.1 什么是消息中间件1.2 传统的http请求存在那些缺点1.3 Mq应用场景有那些1.4 为什么需要使用mq1.5 Mq与多线程之间区别1.6 Mq消息中间件名词1.7主流mq区别对比1.8 Mq设计基础知识 2.Rabbi…

前端框架Vue、React、Angular、Svelte对比

在对比 React、Vue.js、Angular 和 Svelte 时&#xff0c;除了在高层次的特性上有显著差异&#xff0c;它们在核心设计理念和底层实现机制上也有明显的不同。为了清晰地理解这些框架&#xff0c;我们可以从以下几个方面来分析它们的核心不同点和底层不同点。 1. 框架类型和设计…

Golang | Leetcode Golang题解之第415题字符串相加

题目&#xff1a; 题解&#xff1a; func addStrings(num1 string, num2 string) string {add : 0ans : ""for i, j : len(num1) - 1, len(num2) - 1; i > 0 || j > 0 || add ! 0; i, j i - 1, j - 1 {var x, y intif i > 0 {x int(num1[i] - 0)}if j &g…

ChatGPT 4o 使用指南 (9月更新)

首先基础知识还是要介绍得~ 一、模型知识&#xff1a; GPT-4o&#xff1a;最新的版本模型&#xff0c;支持视觉等多模态&#xff0c;OpenAI 文档中已经更新了 GPT-4o 的介绍&#xff1a;128k 上下文&#xff0c;训练截止 2023 年 10 月&#xff08;作为对比&#xff0c;GPT-4…

深度学习自编码器 - 去噪自编码器篇

序言 在深度学习的广阔天地中&#xff0c;自编码器作为一种强大的无监督学习工具&#xff0c;通过重构输入数据的方式&#xff0c;不仅实现了数据的有效压缩&#xff0c;还探索了数据的内在表示。而去噪自编码器&#xff08; Denoising Autoencoder, DAE \text{Denoising Auto…

软件设计师——操作系统

&#x1f4d4;个人主页&#x1f4da;&#xff1a;秋邱-CSDN博客☀️专属专栏✨&#xff1a;软考——软件设计师&#x1f3c5;往期回顾&#x1f3c6;&#xff1a;C: 类和对象&#xff08;上&#xff09;&#x1f31f;其他专栏&#x1f31f;&#xff1a;C语言_秋邱 一、操作系统…

VGG16模型实现新冠肺炎图片多分类

1. 项目简介 本项目的目标是通过深度学习模型VGG16&#xff0c;实现对新冠肺炎图像的多分类任务&#xff0c;以帮助医疗人员对患者的影像进行快速、准确的诊断。新冠肺炎自爆发以来&#xff0c;利用医学影像如X光和CT扫描进行疾病诊断已成为重要手段之一。随着数据量的增加&am…

华为---以太网静态路由配置使用下一跳通信正常,而使用出接口无法通信

目录 1. 实验环境 2. 结果测试 3. 分析验证 3.1 以太网静态路由配置使用下一跳跨网段通信抓包分析 3.2 以太网静态路由配置使用出接口跨网段通信抓包分析 3.3 以太网静态路由配置使用出接口无法跨网段通信问题解决办法 1. 实验环境 以太网静态路由配置使用下一跳跨网段通…

网络丢包定位记录(二)

网卡驱动丢包 查看&#xff1a;ifconfig eth1/eth0 等接口 1.RX errors: 表示总的收包的错误数量&#xff0c;还包括too-long-frames错误&#xff0c;Ring Buffer 溢出错误&#xff0c;crc 校验错误&#xff0c;帧同步错误&#xff0c;fifo overruns 以及 missed pkg 等等。 …