【Android】【Bluetooth Stack】蓝牙电话协议分析(超详细)

1. 精讲蓝牙协议栈(Bluetooth Stack):SPP/A2DP/AVRCP/HFP/PBAP/IAP2/HID/MAP/OPP/PAN/GATTC/GATTS/HOGP等协议理论

2. 欢迎大家关注和订阅,【蓝牙协议栈】和【Android Bluetooth Stack】专栏会持续更新中.....敬请期待!

目录

1. 协议架构

1.1 Profile Dependencies

1.2 HFP Protocol Stack

2. HFP功能支持情况

3. AT 指令集

3.1 GSM 07.07 & 3GPP 27.077 重用的 AT 功能

3.2 蓝牙定义的 AT 功能

3.3 AT+CIND 相关 indicators及范围

3.4 AT+CLCC


1. 协议架构

1.1 Profile Dependencies

在蓝牙电话的数据传输中使用的是SCO协议(同步定向链接)。支持对时延敏感的信息如语音。

使用保留带宽进行同步通信,即两台设备在LMP层利用保留时隙在物理信道上周期传送数据包,这种类型的链接主要用于传送SCO包(语音数据)。SCO不包括CRC码,且不进行重传,主要支持传输有时间限制的信息,例如声音。

仅仅在ACL链接已经建立之后,才可以建立SCO链接;

  • AT CMD:AT指令是应用于终端设备和PC应用之间的连接与通信的指令;

  • SPP:蓝牙串口协议,在蓝牙设备之间建立虚拟的串口进行数据通信,简单的说就是两个蓝牙设备对端发送自定义数据;iPhone不支持SPP协议;

  • GAP:通用访问配置文件,该Profile保证不同的Bluetooth产品可以互相发现对方并建立连接;GAP定义了蓝牙设备如何发现和建立与其他设备的安全/不安全连接,它处理一些一般模式的业务(询问、命名和搜索)和一些安全性问题;GAP一般有4个作用:

    • Profile Role
    • 可发现模式和过程
    • 连接模式和过程
    • 安全模式和过程
  • eSCO:可以简单的理解为和SCO不同点:支持数据包的重传;

  • incoming call:由Phone Network到AG的通话,即称为来电;

  • outgoing call:由AG到Phone Network的通话,即称为拨号,去电;

1.2 HFP Protocol Stack

针对蓝牙电话,涉及到的协议有:HFP、RFCOMM;

目前HFP的使用场景常见的有车载蓝牙、耳机、PDA(Personal Digital Assistant - 掌上电脑,类似于智能手机、平板电脑、手持游戏机等),其中HFP协议中定义了AG和HFP两种角色:

  • AG(Audio Gate):音频网关 - 音频设备输入输出网关;
  • HF(Hands Free):免提 - 该设备作为音频网关的远程音频输入 / 输出机制,并可提供若干遥控功能;

在车载领域,手机侧为AG,车载侧为HF,在Android源码定义中,通常将AG称为HFP/AG,将HF称为HFPClient/HF;

2. HFP功能支持情况

(M代表强制支持,O代表可选)

NumfunctionHFAGNumfunctionHFAG
1连接管理MM14噪声抑制回声消除OO
2电话状态信息MM15语音识别OO
3音频连接处理MM16号码绑定语音标签OO
4接收语音来电MM17传输多音频能力OM
5拒绝语音来电MO18远程音量控制OO
6中断电话MM19回复和保持OO
7通话中音频链路切换MM20描述号码信息OM
8免提设备拨号OM21a扩展电话状态OM
9历史列表拨号OM21b扩展电话控制OO
10拨打最后一个电话OM22特有指示OM
11拨号等待通知OM23宽频语音OO
12三方通话OO24编解码器协商OO
13CLI(呼叫线路识别)OM25手持设备指示器OO

3. AT 指令集

3.1 GSM 07.07 & 3GPP 27.077 重用的 AT 功能

CMD发送方SyntaxResponseNameDescription
ATAOK标准呼叫应答命令
ATDdd...dd车机OK标准AT命令,用于拨打电话号码本规范仅包括语音通话
ATD>nnn...车机OK标准ATD命令的扩展,用于内存拨号本规范仅涉及语音通话
ERROR标准错误指示代码
OK对命令执行的标准确认
NO CARRIER, BUSY, NO ANSWER, DELAYED, BLACKLISTEDAT命令的扩展响应指示代码这些指令由AG向HF发送,作为对HF向AG发出的AT命令的响应,或从AG发出,作为未经请求的结果代码
RING标准来电指示
AT+CCWA车机AT+CCWA=[[,[,]]]+CCWA标准的呼叫等待通知AT命令在该规范中,仅适用参数启动/禁用呼叫等待通知主动结果代码
+CCWA手机标准“呼叫等待通知”主动结果代码该规范中仅包含两个属性:number和type number:文本字符串,并应始终包含在双引号内 type:字段指定提供的电话号码的格式
AT+CHLD车机AT+CHLD=标准呼叫保持和多方处理AT命令的取值范围: 0:释放所有保持的呼叫或将用户确定的用于忙(UDUB)设置为等待呼叫 1:释放所有活动呼叫(如果存在),并接收其他呼叫(保持或等待) 1:释放具有指定索引(索引值为值)的调用 2:保持所有活动呼叫(如果存在)并接受另一个(保持或等待)呼叫 2:使用指定呼叫()请求私人咨询模式。(将所有呼叫置于保持状态,指示的呼叫除外) 3:将保持的呼叫添加到对话中 4:连接两个呼叫并断开用于与两个呼叫的连接(显式呼叫转移)。
AT+CHUP车机标准挂起AT命令执行命令使AG终止当前活动的调用
AT+CIND车机AT+CIND=?:获取对方特性支持情况 AT+CIND?:获取对方特性值+CIND标准指示更新AT命令
+CIND手机当前电话指示器的标准列表
AT+CLCC车机OK标准列表当前呼叫命令
+CLCC手机OK标准列表当前调用结果代码
AT+COPS车机+COPS:,,用于读取网络运营商信息:包含当前模式并且不提供有关操作员名称的信息 :指定参数字符串的格式,在本规范中应始终为0 :以字母数据格式指定带引号的字符串,表示网络运营商的名称。该字符串不得超过16个字符
AT+CMEE车机标准AT命令用于启用
+CME ERROR+CME ERROR:扩展音频网关错误结果代码响应使用结果代码+CME ERROR:作为与AG功能相关的错误的指示
AT+CLIP车机AT+CLIP=+CLIP标准呼叫线路识别通知激活AT命令它启用/禁用呼叫线路识别通知主动结果代码 +CLIP
+CLIP手机+CLIP: , type> [,, [,[] [,]]]标准呼叫线路识别通知主动结果代码:参数应为文本字符串,并应始终包含在双引号内 :字段指定提供的电话号码的格式
AT+CMER车机AT+CMER=[[,[,[, [,]]]]]OK标准事件报告激活/停用AT命令:该参数一般情况下value = 3 :分为两种情况:0代表禁用,1代表激活
+CIEV手机+CIEV: ,标准的指标事件报告主动结果代码:AT+CIND=?命令。列表的第一个元素应具有=1 :指标的当前状态
AT+VTS车机AT+VTS=标准DTMF生成AT命令
AT+CNUM车机AT+CNUM AT+CNUM=?+CNUM检索用户号码信息 测试用户号码信息 - 未实施HF为AG中的“用户号码信息”功能发出的命令。仅使用AT+CNUM格式的动作命令
+CNUM手机+CNUM: [],, ,[ ,]将“订户号码信息”从AG发送到HF的标准响应:不支持此可选字段,应留空 :包含电话号码的引用字符串,格式由指定 :字段指定提供的电话号码的格式 :不支持此可选字段,应留空 :表示此电话号码与哪个服务相关,4代表语音,5代表传真

3.2 蓝牙定义的 AT 功能

CMD发送方SyntaxResponseDesc
AT+BIA车机AT+BIA=[<indrep 1>[,…[,[]]]]]]蓝牙指示激活,单独激活或停用指示器:代表了指标x的状态,1代表激活,0代表禁用
AT+BINP车机AT+BINP=+BINP: …蓝牙输入,用于从AG请求某些特定数据输入的命令收到此命令后,AG应执行适当的操作,以便使用+BINP响应将请求的信息发送回HF :数据请求,其中value = 1对应于HF中记录的最后一个语音标签的电话号码 :AG返回的数据参数。该参数内容取决于,一般情况下为Phone number
AT+BLDN车机AT+BLDN蓝牙最后拨打的号码用于呼叫最后拨打的电话号码。收到此命令后,AG应建立对最后拨打的电话号码的语音呼叫。
AT+BVRA车机AT+BVRA=+BVRA蓝牙语音识别激活启用/禁用AG中的语音识别功能,如果支持增强语音识别状态功能,则此命令用于向AG指示HF已准备号呈现音频输出 :0代表了在AG中禁用语音识别,1代表在AG中启用语音识别,2代表仅当AG和HF都支持增强语音识别状态功能时才应使用该值
+BVRA手机+BVRA: ,蓝牙语音识别激活当AG中的语音识别功能由AG自主激活/停用时,用于通知HF的非请求结果代码 :0代表了在AG中禁用语音识别,1代表在AG中启用语音识别 :反映AG上语音识别引擎当前状态的位掩码 :仅当AG和HF都支持语音识别文本功能,才会出现
AT+BRSF车机AT+BRSF=+BRSF蓝牙检索支持的功能通知AG HF中可用的支持功能,并请求有关AG中支持的功能的信息。支持的特性应以十进制值表示 0:EC / NR 功能 1:三方通话 2:CLI演示功能 3:语音识别激活 4:远程音量控制 5:增强的通话状态 6:增强的呼叫控制 7:编解码器协商 8:HF 指标 9:支持的eSCO S4 设置 10:增强的语音识别状态 11:语音识别文本 12-31:留作将来使用
+BRSF手机+BRSF:蓝牙检索支持的功能AG响应AT+BRSF命令发送的结果码,用于通知HF AG支持哪些功能。支持的特性应以十进制值表示 0:三方通话 1:EC / NR 功能 2:语音识别功能 3:带内铃声功能 4:将号码附加到语音标签 5:拒绝来电的功能 6:增强的通话状态 7:增强的呼叫控制 8:扩展错误结果代码 9:编解码器协商 10:HF 指标 11:支持的 eSCO S4 设置 12:增强的语音识别状态 13:语音识别文本 14-31:留作将来使用
AT+NREC车机AT+NREC=降噪和回声消除发出命令以禁用嵌入AG中的任何回声消除和降噪功能 :0代表了在AG中禁用 EC / NR
AT+VGM车机AT+VGM=+VGM=麦克风增益HF发出的命令,用于向AG报告其当前的麦克风增益级别设置 :是一个十进制数字,与由HF控制的特定(取决于实现)音量级别有关。该命令不会改变AG的麦克风增益,它仅指示HF中麦克风增益的当前值,取值范围:0~15
AT+VGS车机AT+VGS=+VGS=扬声器增益HF发出的命令,用于向AG报告其当前的扬声器增益水平设置 :是一个十进制数字,与由HF控制的特定(取决于实现)音量级别有关。该命令不会改变AG的扬声器增益,它仅指示HF中麦克风增益的当前值,取值范围:0~15
+VGM手机+VGM=麦克风增益由AG主动发出的结果代码,用于设置HF的麦克风增益。
+VGS手机+VGS=扬声器增益由AG主动发出的结果代码,用于设置HF的扬声器增益
+BSIR手机+BSIR:带内铃声的蓝牙设置由AG发出的主动结果代码,用于向HF指示带内铃声设置已在本地更改。HF可以通过改变自己的警报方法作出响应的反应 :0代表了AG不提供带内铃声,1代表AG提供带内铃声
AT+BTRH车机AT+BTRH=:设置指令 AT+BTRH?:读取当前状态+BTRH蓝牙响应和保持功能HF为AG中的“响应和保持”功能发出的命令。本规范定义了set和read命令的使用,AT+BTRH ? HF应使用命令来查询 AG 的当前“响应和保持”状态 :0代表保留来电,1代表接受保持的来电,2代表拒绝保持的来电
+BTRH手机+BTRH=蓝牙响应和保持功能每当来电被搁置或接受或拒绝时,用于通知HF的结果代码。对于AT+BTRH,AG是否也应回复此响应 ? 来自 HF 的命令 :0代表了来电在 AG中保持,1代表了在AG中接受保持的来电,2代表了在AG中拒绝保持的来电
AT+BCC车机AT+BCC蓝牙编解码连接HF使用该命令请求AG启动编解码器连接过程
AT+BCS车机AT+BCS=蓝牙编解码器选择此命令向远程设备(AG)确认编解码器,并隐含地确认将在同步连接上使用哪个同步协议,如果不包含任何值,则该命令无效 :所有可能的Codec ID,将AT+BAC的定义
+BCS手机+BCS:蓝牙编解码器选择该命令将编解码器通知给远程设备(HF),并隐含地通知将在同步连接上使用哪种同步协议 :所有可能的Codec ID,将AT+BAC的定义
AT+BAC车机AT+BAC= [[,[,...[,]]]] (u1,u2, ..., un are a codec IDs)OK蓝牙可用编解码器此命令通知远程设备(AG)HF支持哪些编解码器 :所有可能的Codec ID,将AT+BAC的定义
AT+BIND车机AT+BIND= ,,,...,:列出HF支持的指标 AT+BIND=?:阅读AG支持的指标 AT+BIND?:读取指示的AG启用/禁用状态+BIND蓝牙HF指示功能该命令使HF能够通知AG支持哪些HF到AG指示符。指示器可以启用或禁用。除非“HF 指示器”功能的 AG 和 HF BRSF 位都设置为1,否则不应使用AT+BIND命令 ...:0-65535,作为十进制无符号整数值输入,不带前导零,引用 HF 指示器分配的编号。
+BIND手机+BIND: (,,,...,):响应AT+BIND=? +BIND: ,:主动或响应AT+BIND?蓝牙HF指示功能该响应使AG能够通知HF支持哪些HF指示器及其状态,启用或禁用。 除非“HF 指示器”功能的AG和HF BRSF为都设置为1,否则不应使用+BIND响应 ...:0-65535,作为十进制无符号整数值输入,不带前导零,引用 HF 指示器分配的编号。 :0 - 1,其中0代表了指示器被禁用,不应为此指示器发送值更改,1代表了指示器已启用,可以为该指示器发送值更改
AT+BIEV车机AT+BIEV= ,蓝牙HF指示功能此命令使HF能够将启用的HF指示器的更新值发送到AG

3.3 AT+CIND 相关 indicators及范围

indicatorindexindex 范围Desc
call:Call Status indicator10 1there are no calls in progress — 没有电话在进行中 at least one call is in progress — 至少有一个电话在进行中
callsetup:Call set up status indicator20 1 2 3not currently in call set up — 当前没在呼叫中设置 an incoming call process ongoing — 来电进行中 an outgoing call set up is ongoing — 正在设置一个传出呼叫 remote party being alerted in an outgoing call — 呼叫的对方正在响铃
service:Service availability indication30 1No Home/Roam network available — 没有信号 Home/Roam network available — 有信号服务
signal:Signal Strength indicator40~5电话信号质量
roam:Roaming Status indicator50 1roaming is not active — 没有漫游 a roaming is active — 漫游中
battchg:Battery Charge indicator of AG60~5AG侧的电量值
callheld:Call hold status indicator70 1 2No calls held Call is placed on hold or active/held calls swapped(The AG has both an active AND a held call) — 电话被设置为保持或者电话切换中 Call on hold, no active call — 电话保持中,没有电话处于通话中

3.4 AT+CLCC

HF请求当前的电话信息列表,构造格式:+CLCC: < idx >,< dir >,< status >,< mode >,< mpty >,< number >,< type >,AG侧回复当前的电话信息列表。如果当前没有电话,AG侧也需回复OK指令,不然将电话信息以列表形式发送给HF;

  • < idx >:当前电话是第几路,从 1 开始计数

  • < dir >:电话方向,0代表往外拨打的电话outgoing;1代表来电incoming;

  • < status >:电话状态

    • 0:Active
    • 1:Held
    • 2:Dialing(outgoing calls only)
    • 3:Alerting(outgoing calls only)
    • 4:Incoming(incoming calls only)
    • 5:Waiting(incoming calls only)
    • 6:Call held by Response and Hold
  • < mode >:电话模式

    • 0:voice
    • 1:data
    • 2:FAX
  • < mpty >:是否为多方通话的电话

    • 0:this call is NOT a member of a multi-party(conference)call
    • 1:this call is a member of a multi-party(conference)call
  • < number >:可选项,电话号码

  • < type >:可选项,电话类型

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

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

相关文章

VS Code 跳板机登录服务器(手打密码+秘钥登录)

目录 0.为什么要用跳班机登陆服务器&#xff1f; 1.VS Code插件安装及ssh安装 2.密码链接方式 1&#xff09;添加ssh设置&#xff0c;设置主机 2)设置跳板机 Tips:可以直接通过窗口连接文件管理 3.密钥连接方式&#xff08;更安全更方便&#xff09; 1&#xff09;mac版…

C# 对App.config、Web.config的appSettings节点数据进行加密

appSettings加密原因&#xff0c;就是因为容易暴露服务器账号和密码&#xff0c;而且客户也不允许 使用ASP.NET提供的命令工具aspnet_regiis来创建加密命令&#xff1b;aspnet_regiis是提供了直接对配置文件加密的功能的&#xff1b;并且使用aspnet_regiis加密的配置节点在读取…

部署Zabbix Agents添加使能监测服务器_Linux平台_Yum源/Archive多模式

Linux平台 一、从yum源脚本安装部署Zabbix-Agent,添加Linux Servers/PC 概述 Zabbix 主要有以下几个组件组成: Zabbix Server:Zabbix 服务端,Zabbix的核心组件,它负责接收监控数据并触发告警,还负责将监控数据持久化到数据库中。 Zabbix Agent:Zabbix客户端,部署在被监…

discuz、ecshop、帝国cms部署https(ssl)后会员无法登录

discuz、ecshop、帝国cms部署https&#xff08;ssl&#xff09;后会员无法登录 注意&#xff0c;以下教程特网科技虚拟主机或者亚数的云主机独立IP部署SSL后的301跳转 1.discuz部署https后台无法登录&#xff1a; discuz采用&#xff1a; $_SERVER[‘HTTPS’] 方式判断&#…

运维小技能:IP多号段配置、重置Mac电脑密码、修改系统级别的文件

文章目录 ES集群部署前期工作I 清除last_run_metadata_path数据。1.1 删除文件1.2 清空一个目录下所有文件的内容1.3 定期重启Logstash,并清除last_run_metadata_path数据。II 配置IP2.1 CentOS系统的IP参数2.2 shell脚本-静态网络配置III 电脑的IP多号段配置3.1 Mac电脑3.2 wi…

在 Swift 中, enumerated() 有哪些常用的使用方式 ?

在 Swift 中&#xff0c;enumerated() 是一个用于遍历集合类型的方法&#xff0c;它返回一个由每个元素的索引和值组成的元组。以下是一些常用的使用方式&#xff1a; 遍历数组并获取元素的索引和值&#xff1a; let array ["apple", "banana", "o…

使用C语言采用概率分析与随机算法求解特征序列长度下界-以抛硬币问题为例

使用C语言采用概率分析与随机算法求解特征序列长度下界 总结 在概率论与随机算法的研究中&#xff0c;我们经常遇到需要求解某类特定事件发生的概率问题。特别是在处理大量独立随机试验时&#xff0c;如何准确评估某类特殊事件&#xff08;如连续正面特征序列&#xff09;出现的…

S29GL064S的数据手册

这份文件是Cypress Semiconductor Corporation关于64-Mbit&#xff08;8 Mbyte&#xff09;3.0V闪存内存S29GL064S的数据手册。以下是对文档内容的翻译和详细分析&#xff1a; 特性&#xff08;Distinctive Characteristics&#xff09; CMOS 3.0伏核心&#xff0c;具有多功能…

GlusterFS 分布式文件系统使用

一、概述 GlusterFS 是一个开源的分布式文件系统。 由存储服务器、客户端以及NFS/Samba 存储网关&#xff08;可选&#xff0c;根据需要选择使用&#xff09;组成。 没有元数据服务器组件&#xff0c;这有助于提升整个系统的性能、可靠性和稳定性。 GlusterFS同时也是Scale-…

asp.net mvc 重新引导视图路径,改变视图路径

asp.net mvc 重新引导视图路径&#xff0c;改变视图路径 使用指定的控制器上下文和母版视图名称来查找指定的视图 通过本文学习&#xff0c;你可以根据该技法&#xff0c;去实现&#xff0c;站点自定义皮肤&#xff0c;手机站和电脑站&#xff0c;其他设备站点&#xff0c;在不…

Python核心编程 --- 高级数据类型

Python核心编程 — 高级数据类型 字符串 列表 元组 字典 1.序列 序列&#xff1a;一组按顺序排列的数据集合。 在Python中存在三种内置的序列类型&#xff1a;字符串、列表、元组 优点&#xff1a;可支持索引和切片操作 特点&#xff1a;第一个正索引为0&#xff0c;指…

基于python+vue学生作业管理系统flask-django-nodejs-php

快速发展的社会中&#xff0c;人们的生活水平都在提高&#xff0c;生活节奏也在逐渐加快。为了节省时间和提高工作效率&#xff0c;越来越多的人选择利用互联网进行线上打理各种事务&#xff0c;然后线上管理系统也就相继涌现。与此同时&#xff0c;人们开始接受方便的生活方式…

【深度学习】基于机器学习的无机钙钛矿材料形成能预测,预测形成能,神经网络,回归问题

文章目录 任务分析数据处理处理离散数值处理缺失值处理不同范围的数据其他注意事项 我们的数据处理模型训练网页web代码、指导 任务分析 简单来说&#xff0c;就是一行就是一个样本&#xff0c;要用绿色的9个数值&#xff0c;预测出红色的那1个数值。 数据处理 在进行深度数…

浅析ArcGis中的软件——ArcMap、ArcScene、 ArcGlobe、ArcCatalog

为什么要写这么一篇介绍ArcGis的文章呢&#xff1f;因为大部分人也包括ArcGisdada&#xff0c;在使用ArcMap应用程序创建工程时总以为我们就是使用了ArcGis这个软件的所有。其实不然&#xff0c;在后期的接触和使用中慢慢发现原来ArcMap只是ArcGis这个综合平台的一部分&#xf…

现在阿里云云服务器租用多少钱?一张表,报价单

2024年阿里云服务器优惠价格表&#xff0c;一张表整理阿里云服务器最新报价&#xff0c;阿里云服务器网整理云服务器ECS和轻量应用服务器详细CPU内存、公网带宽和系统盘详细配置报价单&#xff0c;大家也可以直接移步到阿里云CLUB中心查看 aliyun.club 当前最新的云服务器优惠券…

<c语言学习>结构体

结构体类型 为什么要有结构体 我们用c语言描述年龄时候&#xff0c;可以定义一个整形类型来实现&#xff1a; int age; age 18; printf("年龄为%d",age); (c语言描述年龄) 由于年龄这一属性比较单一&#xff0c;类似性别、某游戏角色攻击力、血量都可以用c语言内置…

FFmpeg开发笔记(十三)Windows环境给FFmpeg集成libopus和libvpx

MP4是最常见的视频封装格式&#xff0c;在《FFmpeg开发实战&#xff1a;从零基础到短视频上线》一书的“1.2.3 自行编译与安装FFmpeg”介绍了如何给FFmpeg集成x264和x265两个库&#xff0c;从而支持H.264和H.265两种标准的编解码。 视频的封装格式除了悠久的MP4和ASF之外&…

string类详解及重要函数实现

&#x1fa90;&#x1fa90;&#x1fa90;欢迎来到程序员餐厅&#x1f4ab;&#x1f4ab;&#x1f4ab; 今日主菜&#xff1a;string类 主厨&#xff1a;邪王真眼 所属专栏&#xff1a;c专栏 主厨的主页&#xff1a;Chef‘s blog 前言&#xff1a; 咱们之前也是…

【事务】开发用到的事务,TransactionDefinition实例详解,事务的传播机制

【事务】开发中用到的事务&#xff0c;TransactionDefinition实例详解 一、TransactionDefinition 介绍1、隔离级别&#xff08;Isolation Level&#xff09;&#xff1a;2、传播行为&#xff08;Propagation Behavior&#xff09;&#xff1a;3、超时设置&#xff08;Timeout …

第十三届蓝桥杯物联网试题(省赛)

做后感悟&#xff1a; OLED显示函数需要一直显示&#xff0c;所以在主函数中要一直循环&#xff0c;为了确保这个检错功能error只输出一次&#xff0c;最好用中断串口进行接收数据&#xff0c;数据收完后自动进入中断函数中&#xff0c;做一次数据检查就好了&#xff0c;该开灯…