1 SPI
1.1 概念
SPI是串行外设接口(Serial Peripheral Interface)的缩写,SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便。SPI的原理以及通信过程不是本文要研究的内容,如有兴趣可以自行查找资料。
1.2 特性
(1)SPI总线是一种同步的串行接口: SPI是属于串行通信的一种,这就意味着SPI依赖于共享的时钟信号来同步设备之间的数据传输。控制时钟信号的设备被称为Master。其它所有连接的外设被认为是Slaves。每个设备连接到同一组数据信号以形成总线。从理论上讲,SPI数据传输率是仅限于Master切换时钟信号的快慢。时钟速度通常在16MHz到25MHz范围。
(2)SPI支持全双工数据传输:全双工数据传输意味着Master和Slave可以同时交换数据。为了支持全双工传输,总线必须提供下列单独的信号,使得SPI最少四线接口:
- Master出Slave入(MOSI);
- Mater入Slave出(MISO);
- 共享时钟信号(CLK);
- 共同的接地参考(GND);
(3)SPI支持同一总线连接多个从设备 在SPI通信中,Slave设备采用硬件寻址方式。每个Slave都需要外部芯片选择信号,来让Master定位特定的设备作为数据传输的目标。如果仅仅使用一个Slave这个信号就不必须。
SPI引脚图:
2 Android Things
2.1 概念
Android Things是谷歌发布的一套帮助开发者在安卓端开发嵌入式设备的开发工具。 Android Things将通信底层过程封装为应用层可以调用的API方法,大大简化了Android平台下开发嵌入式设备的过程。
2.2 特性
(1)单一自启动APP,通常设备会只运行单一的程序,即开发者的APP会自动启动,系统APP不会呈现出来。
(2)显示可选,设备可以没有屏幕,通过按钮、触摸、LED灯、语音或其他形式与用户交互。
(3)提供了通过I/O驱动外设的接口,让开发者可以与传感器和执行器进行通讯交互,支持GPIO、PWM、I2C、SPI和UART。
(4)用户驱动API,用户驱动继承Android Framework Services,允许APP将硬件事件注入到Framework中,使得其他APP可以使用标准的Android API访问。
(5)物联网云,通过Google物联网云平台,开发者可以方便且安全的连接、管理数百万计遍布全球的设备,并从中获取数据。Google物联网云平台和一些其他的Google服务,提供了包括数据采集、处理分析和可视化物联网数据的完整解决方案。
Android Things架构图:
3 Android SPI开发
Android SPI这里指的是调用Android Things的API开发程序。值得注意的是Java中也有一套简称为SPI的机制,全名为Service Provider Interface,Java中的SPI是为某个接口寻找服务的机制,有点类似IOC的思想,将装配的控制权移交给ServiceLoader。与本文所说的SPI完全是两个概念。
3.1 申请权限
使用 Android Things进行开发时需要在Androidmanifest.xml添加如下权限。
<uses-permission android:name="com.google.android.things.permission.USE_PERIPHERAL_IO" />
3.2 添加依赖
在build.gradle中添加依赖库:
compileOnly 'com.google.android.things:androidthings:1.0'
在Androidmanifest.xml的application标签下添加:
<uses-library android:name="com.google.android.things" />
注:若开发过程中,无法向设备中执行install apk可以将修改为,则可以执行apk的安装。
3.3 管理SPI设备
Android Things将各类外围设备的管理封装在PeripheralManager类中(在之前Android Things版本中为PeripheralManagerService),PeripheralManager采用单例模式获取。
PeripheralManager manager = PeripheralManager.getInstance();
//获取设备中支持SPI的序列号
List<String> deviceList = manager.getSpiBusList();
if (deviceList.isEmpty()) {
//如果SPI列表为空,则表明没有可用SPI串口
Log.e(TAG, "No SPI bus available on this device.");
} else {
Log.e(TAG, "List of available devices: " + deviceList);
}
SPI串口号可以通过adb命令在/dev/目录下查看,通常SPI的名称定义为"spi1.0","spi2.0"方式。
注:若提示requires unavailable shared library com.google.android.things; failing!则需检查用于开发的安卓系统是否添加了Android Things库。若缺失此库则直接在PeripheralManager.getInstance();处崩溃。
3.4 获取SpiDevice
SpiDevice是封装的SPI通信设备对象,对于SPI的通信过程主要通过操作此对象完成。获取对象方法如下:
//SPI端口名称
String spiDeviceName = "/dev/spidev1.0";
SpiDevice spiDevice = null;
try {
//打卡SPI通信
spiDevice = manager.openSpiDevice(spiDeviceName);
} catch (IOException e) {
e.printStackTrace();
}
3.5 参数配置
SPI既然属于串口通信的一种,则需要配置相应的参数,才能保证完整的通信过程。需要配置的参数主要有以下几种:
1. 配置SPI时钟
SPI时钟如下图所示:
1)空闲电平:当没有数据传输时,时钟信号的电平(低或高)。
2)前沿:每个时钟脉冲的前沿,也称为上升沿。
3)后沿:在每个时钟脉冲中与前沿相反的过渡,也可称为下降沿。
SPI支持以下四种模式:
- MODE0 - 时钟信号空闲,数据在前沿时钟边沿传输。
- MODE1 - 时钟信号空闲为低电平,数据在后沿时钟边沿传输。
- MODE2 - 时钟信号空闲,数据在前沿时钟边沿传输。
- ODE3 - 时钟信号空闲为高电平,数据在后沿时钟边沿传输。
2. 配置时钟频率
SPI通信以Hz为单位指定共享时钟信号。时钟信号的能力在不同的设备之间有所不同。此频率应与设备配置相同。
3. 配置对齐方式
对齐方式用于设置字节指定在总线上传输的每个比特的顺序,这也被称为数据的字节序。默认情况下,数据将会把最高有效位(MSB)首先发送。即按照字节的高位到低位依次发送。
4. 配置每个字的比特
此方法用于设置配置在切换给定从器件的片选线之间一次传输的位数。 默认值为每个字节8位。
public void configureSpiDevice(SpiDevice spiDevice) throws IOException {
// 低时钟,前沿传输
spiDevice.setMode(SpiDevice.MODE0);
//配置时钟频率
spiDevice.setFrequency(112500);
//配置字的比特数
spiDevice.setBitsPerWord(8);
//配置字节序
spiDevice.setBitJustification(false);
3.5 数据通信
SPI支持半双工和全双工数据传输两种方式。两种方式的调用数据通信方法是不同的。
1. 半双工通信
半双工通信:半双工通信方式可以实现双向的通信,但不能在两个方向上同时进行,必须轮流交替地进行。也就是说,通信信道的每一端都可以是发送端,也可以是接收端。但同一时刻里,信息只能有一个传输方向。例如:日常生活中的对讲机等。 通过半双工通信的特点可以看出,在半双工通信方式中设备可以write与read方式即可实现。因为设备是不能同时实现write与read的。
发送数据:
public void sendCommand(SpiDevice spiDevice, byte[] buffer) throws IOException {
spiDevice.write(buffer, buffer.length);
读取数据:
//创建线程读取数据
private class ReadThread implements Runnable {
public void run() {
byte[] response = new byte[1024];
while (true) {
spiDevice.read(response, response.length);
}
}
}
2. 全双工通信
全双工(Full Duplex)是 在处理器与外围设备之间采用发送线和接受线各自独立的方法,可以使数据在两个方向上同时进行传送操作。指在发送数据的同时也能够接收数据,两者同步进行,这好像我们平时打电话一样,说话的同时也能够听到对方的声音。
全双工通信设备可以同时完成数据的收发,SpiDevice中封装transfer方法进行全双工通信,调用方式如下:
public void sendCommand(SpiDevice spiDevice, byte[] buffer) throws IOException {
//采用全双工方式收发数据
byte[] response = new byte[buffer.length];
spiDevice.transfer(buffer, response, buffer.length);
4 结语
Android Things相比于其他平台优势:
(1)统一的开发框架和接口
(2)适合Android开发者进行智能设备的创新
(3)先进的基础框架
(4)安全的物联网云
(5)丰富的云服务资源
Android Things同样存在局限性:
(1)成本
(2)硬件控制实时性
公众号:程序员喵大人(专注于Android各类学习笔记、面试题以及IT类资讯的分享。)