CSR867x学习笔记:SPP Server and Client
为了让CSR867x的开发更容易,现与思度科技联合推出CSR867x学习板【淘宝链接:思度科技CSR开发板】。
技术交流QQ群号:743434463
开发板会员QQ群号:725398389(凭订单号入群,赠PPT、项目源码、视频教程)
——————————正文分割线———————————–
1. 引言
两个通过SPP协议连接的蓝牙设备之间的数据通信如串口通信一般简单方便,遗憾的是ADK中并没有给出简单的例程,使很多初学者难以快速学会使用SPP协议。
本文给出SPP Server和Client的使能示例代码,并给出运行于matlab的Client端测试方法。
2. SPP简介
SPP是Serial Port Profile(串口配置文件)的缩写,其定义了使用蓝牙进行RS232(或类似)串行电缆仿真的设备应使用的协议和过程。简单来说就是在蓝牙设备之间建立虚拟的串口进行数据通信。
先来看一下SPP协议与其他协议之间的关系图:
从上图中可见SPP协议是很多协议的基础协议。蓝牙设备之间通过SDP协议发现彼此的SPP服务。无绳电话和对讲也利用了SPP协议。
接下来看一下协议模型:
SPP协议需要SDP协议和RFCOMM协议作为支撑,分别负责服务的发现和数据的传输。在下文的示例代码中会有体现。通常我们将发起SPP连接请求的设备称为Client,接受SPP请求的设备称为Server。建立SPP连接的消息流如下:
3. VM工程中添加SPP协议
ADK中的SPP相关的代码路径如下:
- src\lib\spp_common\ spp server和spp client共用的代码
- src\lib\sppc\ spp client代码
- src\lib\spps\ spp server代码
VM project properties->build system->Libraries添加spps, sppc, spp_common,源代码中包含spps.h, sppc.h, spp_common.h头文件。
3.1. 启用SPP Server
需要启用SPP Server服务并创建消息处理函数:
/* 启用SPP服务 */
void sink_intercom_init(void)
{ITC_DEBUG(("ITC %s\n", __func__));intercom_task.handler = intercom_handle_message;SppStartService(&intercom_task);
}
消息处理函数中对SPP Client发起的连接和断开请求作出响应:
/* SPP连接响应 */
case SPP_CONNECT_IND:
{SPP_CONNECT_IND_T *m = (SPP_CONNECT_IND_T *)message;ITC_DEBUG(("ITC: SPP_CONNECT_IND\n"));intercom_server.addr = m->addr;intercom_server.server_channel = m->server_channel;intercom_server.sink = m->sink;/* 响应Client设备的请求,payload size = 64 */SppConnectResponse(&intercom_task, &intercom_server.addr,TRUE,intercom_server.sink,intercom_server.server_channel,INTERCOM_SPP_MAX_PAYLOAD_SIZE);
}
break;/* SPP断开响应 */
case SPP_DISCONNECT_IND:
{SPP_DISCONNECT_IND_T *m = (SPP_DISCONNECT_IND_T *)message;ITC_DEBUG(("ITC: SPP_DISCONNECT_IND\n"));SppDisconnectResponse(m->spp);
}
break;
在收到SPP Client发来的消息后,原封不动地再发送给Client:
case SPP_MESSAGE_MORE_DATA:
{ /* Move data from source into message */Source src = ((SPP_MESSAGE_MORE_DATA_T*)message)->source;const uint8 *s = SourceMap(src);uint16 len = SourceBoundary(src);uint8 * spp_buf;bool status;uint16 claim_result;spp_buf = SinkMap(intercom_server.sink);claim_result = SinkClaim(intercom_server.sink, len);if (claim_result == 0xFFFF){SourceDrop(src, len);return;}memmove (spp_buf+claim_result, s, len);status = SinkFlush(intercom_server.sink, len);ITC_DEBUG(("ITC: status %d", status));SourceDrop(src, len);
}
break;
3.2. 启用SPP Client
SPP Client不需要注册SDP服务,只需向指定的蓝牙设备直接发起SPP请求:
SppConnectRequest(&bluedongleTask, &addr, 0, 0); /* 0代表默认参数 */
同时需要准备好处理SPP Client库发送给VM的消息:
/* SPP连接成功,保存sink留作发送数据时用 */
case SPP_CLIENT_CONNECT_CFM:
{SPP_CLIENT_CONNECT_CFM_T *m = (SPP_CLIENT_CONNECT_CFM_T *) message;/* bool success = m->status == spp_connect_success; */spp_sink = m->sink;BD_DEBUG(("BD: SPP_CLIENT_CONNECT_CFM: %u, payload size: %d\n", m->status, m->payload_size));
}
break;/* 断开SPP响应 */
case SPP_DISCONNECT_IND:
{SPP_DISCONNECT_IND_T *m = (SPP_DISCONNECT_IND_T *) message;spp_sink = NULL;BD_DEBUG(("BD: SPP_DISCONNECT_IND: %u\n", m->status));SppDisconnectResponse(m->spp);
}
break;
处理接收到的SPP Server的数据:
case SPP_MESSAGE_MORE_DATA:
{Source src = ((SPP_MESSAGE_MORE_DATA_T*)message)->source;const uint8 *s = SourceMap(src);uint16 len = SourceBoundary(src);spp_server_data_process((const char *)s, len);SourceDrop(src, len);
}
break;
我们可以在spp_server_data_process里添加程序以处理SPP Server发送来的数据,也可以将数据通过stream机制直接传送给DSP,作为两个蓝牙设备之间DSP数据的透传通道。
4. matlab环境验证SPP收发数据
matlab提供了两种工具可用来验证目标设备的SPP Server是否工作正常。一是虚拟串口,二是蓝牙SPP。
4.1. 虚拟串口
当蓝牙设备与PC机通过蓝牙适配器连接后,如果蓝牙设备支持SPP协议,PC机在扫描到此协议后会虚拟出串口:
此时我们需要在matlab中通过访问串口的方式与蓝牙设备建立通信:
spp_uart = serial('COM7'); % 获取串口句柄
fopen(spp_uart); % 打开串口
fwrite(spp_uart,'111'); % 发送字符串111
recv = fread(spp_uart,9); % 阻塞在此函数直到读取到9个字节
fprintf('%s\n',recv);
fclose(spp_uart); % 关闭串口
delete(spp_uart); % 删除句柄
此方式的优点是连接建立速度较快,缺点是有些设备不能在PC端虚拟出串口(如CSR8670)。
4.2. 蓝牙SPP
matlab支持通过调用蓝牙SPP连接蓝牙设备的SPP Server,此方式支持不能正常枚举出虚拟串口的蓝牙设备,前提是用户已经知道目标设备的SPP server channel并已与其完成配对。示例代码如下:
r=instrhwinfo('Bluetooth'); % 搜索附近的蓝牙设备
d=r.RemoteNames; % 获取这些设备的名称
[m,n] = listdlg('PromptString','Select Your Bluetooth device:','SelectionMode','single','ListString',d); % 列表选择目标蓝牙设备
dn=cell2mat(d(m));
dev = Bluetooth(dn, 2) % 通过SPP server channel(此处是2)获取目标蓝牙设备的SPP连接句柄
fopen(dev); % 建立蓝牙SPP连接
fwrite(dev,'1'); % 发送字符1
fread(dev, 5); % 阻塞等待接收满5字节数据
fclose(dev); % 断开蓝牙SPP连接
5. 总结
在掌握了SPP Server和Client的使能和验证方法后,可以基于SPP协议定制上层协议,开发各种独特应用。这里要注意SPP协议在与安卓设备通信时不受限制,但与iOS设备通信的前提条件是蓝牙设备支持MFi协议。此处可见苹果对任何能够穿透iOS操作系统直达应用的连接技术都是严格管控的,明面上是增加系统稳定性,实质是通过切断客户与终端用户的直接联系,强收过路费。
6. 参考文档
- Serial Port Profile.pdf
CSR867x学习笔记:SPP Server and Client相关推荐
- Go语学习笔记 - grpc server/client protobuf | 从零开始Go语言
目录 创建Proto文件 生成proto文件对应的go文件 创建服务结构体 创建客户端测试 小结 学习笔记,写到哪是哪. 上一篇是写的redis操作来着,最近主要研究了一下grpc. 在玩grpc的过 ...
- CSR867x学习笔记:低音炮音频传输协议(SWAT)
为了让CSR867x的开发更容易,现与思度科技联合推出CSR867x学习板[淘宝链接:思度科技CSR开发板]. 技术交流QQ群号:743434463 开发板会员QQ群号:725398389(凭订单号入 ...
- 【运维学习笔记】在 vSphere Client上创建新的虚拟机
具体步骤如下: 1. 创建新的虚拟机 打开vSphere Client(可以是客户端也可以是网页端) 如果是网页端仅能使用火狐浏览器或者谷歌浏览器打开,输入网址:192.168.22.22,进入如下界 ...
- Go语学习笔记 - websocket gorilla(附测试代码) | 从零开始Go语言
目录 项目结构 消息结构 服务端代码 定义客户端行为 服务启动 测试代码 总结 学习笔记,写到哪是哪. websocket也是常用的协议了,在上一篇中主要测试使用了一下grpc. 下面我会把代码贴出来 ...
- python word 操作 doc 文件格式转docx 格式 学习笔记
python word 操作 doc 文件格式转docx 格式 学习笔记 from win32com import client as wc import time # TODO file_0 = & ...
- ROS 学习笔记(三):自定义服务数据srv+server+client 示例运行
ROS 学习笔记(三):自定义服务数据srv+Server+Client 示例运行 一.自定义服务数据: 1.向功能包添加自定义服务文件(AddTwoInts.srv) cd ~/catkin_ws/ ...
- mysql数据实时同步:Canal安装部署、kafka安装、zk安装、mysql安装、Canal Server+Canal Client HA,Canal+mysql+Kafka,相关验证(学习笔记)
目录 Canal安装部署 1.1. 服务器准备 1.2. 设置主机名并配置hosts 1.3. 免密设置 1.4. 设置ntp时间 1.5. 关闭防火墙 1.6. 关闭selinux 1.7. 安装J ...
- ASP.NET Core分布式项目实战(oauth2 + oidc 实现 client部分)--学习笔记
任务16:oauth2 + oidc 实现 client部分 实现 client 之前启动一下上一节的 server,启动之前需要清除一些代码 注释 Program 的 MigrateDbContex ...
- ASP.NET Core分布式项目实战(oauth2 + oidc 实现 server部分)--学习笔记
任务15:oauth2 + oidc 实现 server部分 基于之前快速入门的项目(MvcCookieAuthSample): ASP.NET Core快速入门(第5章:认证与授权)--学习笔记 A ...
最新文章
- 一本书带你入门商业数据科学
- flask从服务器获取html页面,flask的ajax、获取服务器数据、放到前端页面、如果数据存在显示标签、如果不存在不显示标签...
- 免焊vga3加6接线图_计数器和接近开关两线怎么接,计数器接近开关接线图
- sqlserver shiwu
- 山东联通中兴B860 AV1.1机顶盒 刷机问题解决
- SpreadJS 15.1 ~【SpreadJS 15.0】
- TeamTalk服务器编译与部署
- linux下制作dos启动u盘启动,linux dos启动盘怎样做
- android学习code3 布局上
- Xcode 报错及解决办法汇总
- UIView Animation 动画学习总结
- WFP之关联上下文数据以及注意事项
- kodi linux版本,Linux下安装多媒体中心 Kodi 18.8 新版本并设置中文界面
- 数字图像处理-DFTDCTWHT小波变换分解重构(Matlab)
- 显示远程计算机或设备将不接受连接的解决办法
- Excel全自动项目管理甘特图
- 南卫理公会大学 计算机排名,南卫理公会大学全球排名及其优秀校友
- gitBash快速清屏,git命令行操作,快速清屏,清屏
- Android果冻效果(阻尼动画)
- 什么是IP Core?