[香橙派开发系列]使用蓝牙和手机进行信息的交换

文章目录

  • 前言
  • 一、HC05蓝牙模块
    • 1.HC05概述
    • 2.HC05的连接图
    • 3.进入HC05的命令模式
    • 4.常用的AT指令
      • 4.1 检查AT是否上线
      • 4.2 重启模块
      • 4.3 获取软件版本号
      • 4.4 恢复默认状态
      • 4.5 获取蓝牙的名称
      • 4.6 设置蓝牙模块的波特率
      • 4.7 查询蓝牙的连接模式
      • 4.8 查询模块角色
    • 5.连接电脑
    • 6.通过HC05发送消息
    • 7.stm32完整代码
  • 二、香橙派串口通讯
    • 1.打开串口设备
    • 2.接线
    • 3.串口函数
      • 3.1 打开串口文件
      • 3.2 关闭串口文件
      • 3.3 发送一个字符
      • 3.4 发送一个规定好的字符串
      • 3.5 printf
      • 3.6 返回等待读取的字符数
      • 3.7 读取字符
      • 3.8 缓冲区函数
    • 4.输出内容
    • 5.接收内容
    • 6.接收字符串
  • 三、使用hc05连接香橙派
    • 1.通过蓝牙发送字符串给手机
    • 2.手机发送内容给香橙派
  • 总结

前言

隔了这么久我准备再玩一下香橙派,最近这段时间还是比较的忙,我搭建了个论坛和博客,经常被网络攻击,所以我也是一直在弄网络去了,然后今天比较空闲就想着把单子做一下,这个单子需要使用到HC05蓝牙模块,所以我准备写一篇博客来使用香橙派控制HC05蓝牙模块。

一、HC05蓝牙模块

这个模块是非常经典的一个蓝牙模块,我之前有一单也是使用到这个模块,可以看一下我的这个视频【作息控制系统使用说明】,这个项目也是使用到蓝牙模块的,只不过当时时间紧任务重所以就没有写一篇博客来好好记录一下这个项目,等后面我会单独拿一个模块来介绍一下我做的这些小项目。

1.HC05概述

HC05是嵌入式蓝牙串口通讯模块,也就是使用串口就可以和HC05进行通讯并发送信息给蓝牙的接收端,这个模块有两种工作方式:

1 命令响应工作模式

2 自动连接工作模式

在自动连接的工作模式下又可以分为主、从、回环这三种模式,当传输数据时,根据事先设定的方式连接并传输数据。

在命令模式下,用户可以使用串口连接模块,并发送AT指令对模块进行设置。

2.HC05的连接图

这里我直接使用TTL to USB进行连接,因为我要设置一下这个模块的一些传输和内容。

img

这里和串口连接的模式一样

HC05TTL
3.3VCC
TXDRXD
RXDTXD
GNDGND

3.进入HC05的命令模式

首先我们需要通过AT指令来设置模块的一些内容,然后我们才好进入下面的一些操作,首先在这个模块上有一个按钮

img

在上电之前需要长按这个按键,然后再上电就可以进入命令模式,在进入命令模式后,模块上的LED等会缓慢的闪烁,如果没有进入就会闪得很快。

4.常用的AT指令

AT指令列表已经烂大街了,所以这里不全部说明,我只拿出一些常用的来说明即可。

4.1 检查AT是否上线

AT\r\n

如果模块在就会返回OK

img

4.2 重启模块

AT+RESET\r\n

如果执行成功就会返回OK,并进入自动连接模式

img

4.3 获取软件版本号

AT_VERSION?\r\n

执行完成后会返回版本信息和OK

img

4.4 恢复默认状态

AT+ORGL\r\n

执行完成后会返回OK,并将模块恢复为出厂设置。

4.5 获取蓝牙的名称

AT+NAME?\r\n

执行完成后会返回蓝牙名称并返回OK

img

4.6 设置蓝牙模块的波特率

AT+UART=波特率,停止位,校验位\r\n

这里我们设置一个比较常见的,波特率9600,停止位1位,无校验位

AT+UART=9600,1,0

这样就可以了。

4.7 查询蓝牙的连接模式

AT+CMODE?\r\n

返回当前模式,1代表任意模式,也就是蓝牙名称和蓝牙地址都可以连接,这里就不多说了,一般默认是1就可以了。

4.8 查询模块角色

AT+ROLE?

这里默认的是Slave从角色,也就是被动连接,不用动。

5.连接电脑

这里我踩了个大坑,因为我之前的设置是将波特率改为9600了,所以在串口的时候我就用9600进行连接,结果没有任何的反应,后面查了一下手册才发现它默认的波特率是38400,就很尴尬。

这里连接好电脑后先发送个AT指令来查看一下是否返回OK,如果没返回有可能是因为坏了或者是你没长按按键进入命令模式。

然后修改一下波特率,因为我们后面初始化串口不想给那么大的波特率

img

初始化完成后要记得重启一下模块,然后模块的波特率就设置好看,但是AT指令模式下还是那个波特率(又踩坑了,当不想改文章)。

6.通过HC05发送消息

这里我先用stm32来演示,因为我还在做单子所以先拿这个演示。

首先先写串口的初始化函数,这里我使用的是USART1,初始化代码就不展示了,因为今天的主题不是stm32,然后在main函数中我们使用重写的printf来通过串口发送数据。不知道的可以看我这篇博客异步通讯点灯。

int main(){OLED_Init();MX_Init_KEY();MX_Init_HC05();while(1){printf("hello\r\n");OLED_ShowString(1, 1, "hello");}
}

然后需要在手机上下载蓝牙调试宝,在应用商城都可以下载,这我就不给你们压缩包了,要不然我老喜欢挂码。

首先要把蓝牙模块连接到面包板上,然后就用手机连接好蓝牙

img

记住串口反接并且要接地即可。

然后打开蓝牙助手的界面

img

找到里面有一个HC-05,然后连接即可,第一次连接需要你输入一个配对码,这里输入1234或者0000都可以

img

然后给单片机上电后就会显示出hello来

img

学到这你已经会使用蓝牙进行发送信息了,stm32就先不再出现了,后面就是香橙派的内容了。

7.stm32完整代码

usart.c

#include "hc05.h"void MX_Init_HC05(){GPIO_InitTypeDef GPIO_InitStruct = {0};USART_InitTypeDef USART_InitStruct = {0};RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;GPIO_Init(GPIOA, &GPIO_InitStruct);USART_InitStruct.USART_BaudRate = 9600;USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_InitStruct.USART_Parity = USART_Parity_No;USART_InitStruct.USART_StopBits = USART_StopBits_1;USART_InitStruct.USART_WordLength = USART_WordLength_8b;USART_Init(USART1, &USART_InitStruct);USART_Cmd(USART1, ENABLE);
}int fputc(int ch, FILE *f)
{      while((USART1->SR&0X40)==0);  USART1->DR = (u8) ch;      return ch;
}

二、香橙派串口通讯

在介绍使用香橙派使用HC05模块前先介绍一下串口通讯,并如何配置串口通讯。

1.打开串口设备

在香橙派中,串口通讯是使用设备来进行传输的, 所以我们需要在系统设置中将串口进行打开。

在打开之前先了解一下香橙派的串口引脚分布

img

在3b中有3个串口可供选择,然后通过

sudo orangepi-config

来开启设备,进入到设置页面

img

然后选择第一个,按一下回车即可,然后在下面的页面中选择Hardware

img

然后找到你要开启的串口

img

我这选择的是UART7,使用方向键移动到那后按一下空格就选中,然后按一下回车保存,之后会提示是否重启,然后按一下回车就可以重启了。

重启完成后使用

ls /dev/ ttyS*

来查看可操作的设备文件,这里只会显示你开启的设备

img

我们刚才选择了UART7后它这里就会有相应的设备,那个ttyS1是默认开启的,我们不用理他。

2.接线

这里就需要非常非常注意了,我在测试的时候就是这里没有弄好,线接反了,导致一直发送不了。

按照前面给的那张图进行接线后我们就可以写代码了。

注意:这里很重要,很多人玩51单片机来玩这个会忽略一个问题就是GND必须要和单片机的GND接在一起,很多人会单独给这个引脚接GND是错误的。

3.串口函数

这里使用的串口函数库是

#include <wiringSerial.h>

3.1 打开串口文件

int serialOpen(const char* path, int butrl);

第一个参数是设备的路径,比如说我们这需要使用到UART1,那设备地址就是/dev/ttyS7

第二个参数是波特率,比如9600。

这个函数的返回值是一个文件描述符,我们使用一个变量来接收就可以了。

3.2 关闭串口文件

void serialClose(int fd);

参数是打开的设备描述符。

3.3 发送一个字符

void serialPutchar(int fd, char c);

将一个字符发送到打开的文件描述符fd所对应的设备文件。

3.4 发送一个规定好的字符串

void serialPuts(int fd, char* s);

发送一个规定好的字符串,然后以0结尾。

3.5 printf

void serialPrintf(int fd, char* message, ...);

这个和printf的用法类似。

3.6 返回等待读取的字符数

int serialDataAvail(int fd);

返回的是等待读取的字符数。

3.7 读取字符

int serialGetChar(int fd);

返回下一个待读取的字符,如果这个在10s内没有读取到字符就会返回-1。

3.8 缓冲区函数

void serialFlush(int fd);

抛弃所有接收的数据或者等待写入设备完成。

4.输出内容

通过学习了上面的内容后我们可以简单写一个输出字符的代码来输出0~9

#include <stdio.h>
#include <wiringPi.h>
#include <wiringSerial.h>int main(){int fd = -1, i;wiringPiSetup();fd = serialOpen("/dev/ttyS7", 9600);    // 设置串口设备和波特率if (fd < 0){// 设备打开失败printf("设备打开失败\n");return -1;}serialFlush(fd);for (i = 0; i < 10; i++){serialPutchar(fd, i + '0');}serialClose(fd);     // 关闭设备
}

运行效果如下:

img

然后也可以使用printf来个高级一点的输出

#include <stdio.h>
#include <wiringPi.h>
#include <wiringSerial.h>int main(){int fd = -1, i;wiringPiSetup();fd = serialOpen("/dev/ttyS7", 9600);    // 设置串口设备和波特率if (fd < 0){// 设备打开失败printf("设备打开失败\n");return -1;}serialFlush(fd);for (i = 0; i < 10; i++){serialPrintf(fd, "this is%d\r\n", i);}serialClose(fd);     // 关闭设备
}

输出的内容如下:

img

5.接收内容

我们可以通过串口来接收一下用户输入的内容,并判断输入的字符是不是我们需要的,然后通过串口返回

#include <stdio.h>
#include <wiringPi.h>
#include <wiringSerial.h>int main(){int fd = -1, i;int c;wiringPiSetup();fd = serialOpen("/dev/ttyS7", 9600);    // 设置串口设备和波特率if (fd < 0){// 设备打开失败printf("设备打开失败\n");return -1;}serialFlush(fd);while(1){c = serialGetchar(fd);if (c == -1){break;}if (c == '1'){serialPrintf(fd, "this is 1");}printf("%c", c);}serialClose(fd);     // 关闭设备
}

输出的内容:

img

这里大家可以看到我在这个while循环中添加了一个printf,但是没有截屏给出效果,是因为在这个串口运行的过程中一直在读取的是串口的设备,没有使用输入输出流设备,所以导致我们在输入后没办法显示出内容来,这个的解决办法我还不太清楚,等我研究好了我在出一篇文章来介绍。

6.接收字符串

做串口最让人沉醉的就是读取字符串的操作了,在wiringSerial中有一个函数可以获取缓冲区的长度,我们可以判断这个来读取输入的数据的长度,然后使用一个for循环来循环读取和放置在一个数组中,之后进行输出即可,代码如下:

#include <stdio.h>
#include <wiringPi.h>
#include <wiringSerial.h>int main(){int fd = -1;int i, ch, j = 0, len;char str[1024];wiringPiSetup();fd = serialOpen("/dev/ttyS7", 9600);if (fd < 0){printf("打开设备文件失败\n");return -1;}while(1){len = serialDataAvail(fd);     // 获取缓冲区的长度if (len == -1){// 超时退出循环break;}else if(len > 0){serialPrintf(fd, "%d\n", len);    // 这一行是测试的for (i = 0; i < len;  i++){ch = serialGetchar(fd);       // 读取字符str[j++] = ch;}break;}}str[j] = '\0';printf("%s\n", str);serialClose(fd);return 0;
}

三、使用hc05连接香橙派

学会了上面的操作后我们就可以来用香橙派连接hc05了,这个操作也非常非常的简单,和单片机的连接一致,注意不要连错就行了。

img

1.通过蓝牙发送字符串给手机

本质的思路还是一样的,就是使用串口是输入输出就可以搞定,代码如下:

#include <stdio.h>
#include <wiringPi.h>
#include <wiringSerial.h>int main(){int fd = -1, i;int c;wiringPiSetup();fd = serialOpen("/dev/ttyS7", 9600);    // 设置串口设备和波特率if (fd < 0){// 设备打开失败printf("设备打开失败\n");return -1;}serialFlush(fd);while(1){serialPrintf(fd, "hello\r\n");delayMicroseconds(30000);     // 延时函数,免得发送得过快}serialClose(fd);     // 关闭设备
}

然后在调试助手中就可以看到蓝牙模块发送的内容了:

img

2.手机发送内容给香橙派

这里可以使用刚才我们测试的接收字符串,只不过这里有一个问题就是这个工具只能发送字符所对应的ascii码,不能正常的输入字符进行输出。

比如我们手机输入字符0,那就得输入ascii码的30

img

然后在香橙派中就会显示:

img

然后我们还可以用这个来输入0~9

img

然后显示

img

学会了这个后我们就可以编写一个用蓝牙点灯的程序了,其实就是使用蓝牙接收到关键字后给LED灯高低电平,这里就直接给代码了,不展示图片了

#include <stdio.h>
#include <wiringPi.h>
#include <wiringSerial.h>
#include <string.h>int main(){int fd = -1;int i, ch, j = 0, len;char str[1024];wiringPiSetup();fd = serialOpen("/dev/ttyS7", 9600);if (fd < 0){printf("打开设备文件失败\n");return -1;}while(1){len = serialDataAvail(fd);if (len == -1){break;}else if(len > 0){serialPrintf(fd, "%d\n", len);for (i = 0; i < len;  i++){ch = serialGetchar(fd);str[j++] = ch;}break;}}str[j] = '\0';printf("%s\n", str);if (strcmp(str, "0")){// 点灯}else{// 灭灯}serialClose(fd);return 0;
}

总结

串口很好玩,蓝牙模块也好玩,学会了这一节我们就可以使用蓝牙做一个简单的远程开关灯的项目了,当然拿香橙派做这个项目就很浪费,毕竟香橙派可以直接使用网络来实现,做一个网页,然后内网穿透,这样可以很容易的在远程进行控制了,等我最近忙完有时间我做一个。

大家可以关注一下我的论坛和博客,有不懂的或者有趣的问题可以放在我的论坛中进行提问

马桶论坛

马桶博客

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

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

相关文章

2024美赛MCM Problem A: Resource Availability and Sex Ratios资源可用性和性别比例 完整代码以及思路分享

虽然一些动物物种存在于通常的雄性或雌性性别之外&#xff0c;但大多数物种实质上是雄性或雌性。虽然许多物种在出生时的性别比例为1&#xff1a;1&#xff0c;但其他物种的性别比例并不均匀。这被称为适应性性别比例的变化。例如&#xff0c;美洲短吻鳄孵化卵的巢穴的温度会影…

sql指南之null值用法

注明&#xff1a;参考文章&#xff1a; SQL避坑指南之NULL值知多少&#xff1f;_select null as-CSDN博客文章浏览阅读2.9k次&#xff0c;点赞7次&#xff0c;收藏21次。0 引言 SQL NULL&#xff08;UNKNOW&#xff09;是用来代表缺失值的术语&#xff0c;在表中的NULL值是显示…

Git解决分支合并冲突的问题:分支合并提交出现了不同分支同一个文件的修改的冲突解决

有些时候我们合并分支的时候&#xff0c;会出现冲突&#xff0c;原因就是我们修改了分支A 的第一行代码&#xff0c;我们还修改了主分支上面同一个文件中的第一行代码&#xff08;分支A已经提交过一次&#xff09;&#xff0c;此时我们在次合并的时候就会出现冲突&#xff0c;需…

智慧养老成关键力量,全视通智慧机构养老解决方案来助力

近日&#xff0c;国新办举行国务院政策例行吹风会&#xff0c;国家发展改革委、工业和信息化部、民政部、商务部有关负责人介绍《关于发展银发经济增进老年人福祉的意见》有关情况并答记者问。 会上&#xff0c;民政部养老服务司负责人李永新透露&#xff0c;将发展智慧养老服务…

tidb节点重启后,服务无法重连

大家好&#xff0c;我是烤鸭&#xff1a; 前几天遇到tidb节点重启后服务无法重连&#xff0c;确切地说是两个服务&#xff0c;一个可以正常重连&#xff0c;一个不行。 问题复现 由于线上执行慢SQL&#xff0c;导致TiDB 单个节点宕机重启。 其中A服务的3个节点和B服务的1个节…

Sketch使用手册:从入门到精通的完整教程

Sketch软件是Mac平台上流行的矢量图形编辑软件&#xff0c;旨在帮助用户创建网站、移动应用、图标等各种设计原型。Sketch软件的设计风格简洁明了&#xff0c;界面操作简单易用&#xff0c;非常适合UI/UX设计师、平面设计师等数字创意人员。本文将根据如何使用Sketch&#xff0…

IEPE数据采集卡的作用说明

IEPE传感器是一种特殊的加速度传感器&#xff0c;其特点是自带电量放大器或电压放大器。这种传感器产生的电信号非常微弱&#xff0c;很容易受到噪声干扰&#xff0c;因此需要使用灵敏的电子器件进行放大和信号调理。为了实现更好的抗噪声性能和更方便的封装&#xff0c;IEPE传…

xmind思维导图 for mac v24.01中文版

mac电脑上思维导图软件哪个好呢&#xff1f; xmind for mac一个功能强大、易于使用的思维导图软件&#xff0c;够帮助你更好地组织思维、管理信息、规划项目和解决问题&#xff0c;提高个人和团队的工作效率。 软件下载&#xff1a;xmind思维导图 for mac v24.01中文版 XMind f…

数据可视化工具选择指南:六款主流工具的综合评测

随着大数据时代的来临&#xff0c;数据可视化已成为各行业不可或缺的工具。本文将为您介绍市面上六款主流数据可视化工具&#xff0c;包括山海鲸可视化、Echarts、D3.js、Tableau、Power BI和Funnel.io&#xff0c;帮助您更好地了解并选择适合您的工具。 山海鲸可视化 山海鲸…

【Django开发】美多商城项目第2篇:Django用户注册和登录开发(附代码,已分享)

本系列文章md笔记&#xff08;已分享&#xff09;主要讨论django商城项目相关知识。项目利用Django框架开发一套前后端不分离的商城项目&#xff08;4.0版本&#xff09;含代码和文档。功能包括前后端不分离&#xff0c;方便SEO。采用Django Jinja2模板引擎 Vue.js实现前后端…

C# .Net学习笔记—— 异步和多线程(异常处理)

一、异常处理 1、下面for循环20个线程&#xff0c;到11&#xff0c;12号的时候执行失败&#xff0c;这里我也用了try catch来捕获异常。 private void button11_Click(object sender, EventArgs e){TaskFactory taskFactory new TaskFactory();List<Task> taskList ne…

回归预测 | Matlab基于POA-LSSVM鹈鹕算法算法优化最小二乘支持向量机的数据多输入单输出回归预测

回归预测 | Matlab基于POA-LSSVM鹈鹕算法算法优化最小二乘支持向量机的数据多输入单输出回归预测 目录 回归预测 | Matlab基于POA-LSSVM鹈鹕算法算法优化最小二乘支持向量机的数据多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Matlab基于POA-LSSVM…

【数据结构与算法】之排序系列-20240201

【数据结构与算法】之排序系列-20240201 一、88. 合并两个有序数组二、169. 多数元素三、217. 存在重复元素四、242. 有效的字母异位词五、268. 丢失的数字六、349. 两个数组的交集七、350. 两个数组的交集 II 一、88. 合并两个有序数组 简单 给你两个按 非递减顺序 排列的整数…

【Uni-App】运行微信小程序时报错routeDone with a webviewId 2 that is not the current page

使用HBuilderX开发微信小程序&#xff0c;运行项目的时有可能会出现routeDone with a webviewId 1 that is not the current page的报错&#xff0c;但不影响运行。如果强迫症介意的话&#xff0c;可以考下面的方法进行修复。 产生原因 由于微信开发者工具的调试基础库处于灰度…

私域流量如何变现?一站式产品体系搭建与运营策略大公开

在互联网日新月异的今天&#xff0c;我们面临着人口红利逐渐消失的问题&#xff0c;各行各业的广告投放获客成本也在不断上涨。为了降低成本并提高用户转化和复购率&#xff0c;我们需要寻找新的解决方案。此时&#xff0c;私域流量的概念应运而生&#xff0c;成为了一个值得考…

【计算机二级考试C语言】C递归

目录 C 递归 数的阶乘 实例 斐波那契数列 实例 C 递归 递归指的是在函数的定义中使用函数自身的方法。 举个例子&#xff1a; 从前有座山&#xff0c;山里有座庙&#xff0c;庙里有个老和尚&#xff0c;正在给小和尚讲故事呢&#xff01;故事是什么呢&#xff1f;"从…

Python 的 pass 语句到底是什么?

Python 中的 pass 语句是一个简单的概念&#xff0c;即使没有编程经验的初学者也能很快掌握。官方文档提供了非常简单的介绍&#xff0c;下面的三个示例可以让我们快速了解如何使用它。 pass 本质上是一个空操作&#xff0c;除了允许解释器在跳过语法之前检查语法是否有效之外&…

apk反编译修改教程系列---修改apk的默认颜色 布局颜色 手机电脑同步演示【十】

往期教程&#xff1a; apk反编译修改教程系列-----修改apk应用名称 任意修改名称 签名【一】 apk反编译修改教程系列-----任意修改apk版本号 版本名 防止自动更新【二】 apk反编译修改教程系列-----修改apk中的图片 任意更换apk桌面图片【三】 apk反编译修改教程系列---简单…

PMP备考的三个阶段及学习方法分享

PMP证书是项目管理必备的关键技能证书&#xff0c;是具备进行项目管理的重要技能体现。无论升职加薪&#xff0c;还是从事项目管理工作&#xff0c;都非常重要。 个人主要从事产品开发工作&#xff0c;开始逐渐承担一些项目经理角色&#xff0c;但目前项目管理知识薄弱&#x…

深度剖析Sentinel热点规则

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 深度剖析Sentinel热点规则 前言核心概念解析&#xff1a;数字守护者的起源核心概念解析&#xff1a;简单示例演示&#xff1a; 参数索引&#xff1a;规则的基石参数索引的作用&#xff1a;不同场景下选…