Android Things 设备输入/输出指南下 ——GPIO、PWM、I2C

在上一篇文章里,我们介绍了《Android Things 教程:Android Things 设置输入/输出指南上:GPIO、PWM、I2C》,在这篇文章里,我们将介绍剩下的 SPI、UART 以及其他高级接口。

SPI

除了支持全双工通信外,串行外设接口(SPI)连接与 I2C 连接类似。这意味着数据可以同时读写外设,而不需要主设备从从外设请求信息。仍然需要一个时钟信号,来控制来自 SPI 信号总线上多个器件的数据流。SPI 需要至少四个连接才能工作:

  • 主输出从输入(MOSI)
  • 主输入从输出(MISO)
  • 时钟信号(CLK)
  • 共地(GND)

另外,如果多个 SPI 设备连接到 SPI 总线,则需要第五个连接。这是片选(CS),用于发信号给外设的硬件地址,以便您的主器件可以与特定的从器件通信。

使用 SPI 的外设的一些例子,包括 LED 点阵板和 SD 卡读卡器,值得注意的是许多支持 I2C 的外设也将支持 SPI。

就像前面的例子一样,您需要知道 Android Things 板上 SPI 连接的名称。你可以通过创建一个 PeripheralManagerService 并在该对象上调用 getSpiBusList() 来找到它。在一个树莓派,你将有以下可用:

[SPI0.0, SPI0.1]

一旦知道了将要使用的 SPI 总线的名称,就可以打开它的连接。

private SpiDevice mDevice;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    try {
        PeripheralManagerService manager = new PeripheralManagerService();
        mDevice = manager.openSpiDevice(SPI_DEVICE_NAME);
    } catch (IOException e) {
    }
}

为了使设备通过 SPI 总线进行通信,它们都必须 “说同一种语言”,也就是说,它们必须配置为相同的时钟频率和数据格式。虽然有些外设可以调整数据格式和时钟频率,但其他的则不行。由于 SPI 总线上的所有器件必须以相同配置运行,所以在尝试将其包含在 SPI 总线上之前,了解外设的功能非常重要。有四个设置/参数需要为您的 SPI 总线设置:

  • SPI 模式:SPI 模式有两个主要部分:时钟信号是高电平还是低电平,没有数据正在传输,以及哪个边沿用于传输数据。
  • 频率:这代表以 Hz 为单位的共享时钟信号,并且很可能是由从属设备的能力决定的值。
  • 位对齐:用于设置数据的字节顺序。默认情况下,Android Things 将使用 big-endian,首先把最重要的大(MSB)。
  • 每字位(BPW):控制在切换片选信号之前将多少位发送到从器件。默认情况下,每个字 8 位将被发送。

在您的 Android Things java 代码中,您可以在 SPI 总线上设置以下四个值:

// Low clock, leading edge transfer
device.setMode(SpiDevice.MODE0);

device.setFrequency(16000000);
device.setBitsPerWord(8);
device.setBitJustification(false);

如何在 SPI 总线上与您的设备进行交互,取决于您是在全双工还是半双工模式下工作。如果您的设备配置为半双工模式,那么您将需要使用 SpiDevice 对象上的 read()write() 方法在从设备和主设备之间交换数据。如果以全双工模式运行,则需要使用带有两个字节数组缓冲区的 transfer() 方法:一个用于发送数据,另一个用于存储响应数据的空缓冲区。

//Half-duplex mode
public void sendCommand(SpiDevice device, byte[] buffer) throws IOException {
    // Shift data out to slave
    device.write(buffer, buffer.length);

    // Read the response
    byte[] response = new byte[32];
    device.read(response, response.length);
}

// Full-duplex mode
public void sendCommand(SpiDevice device, byte[] buffer) throws IOException {
    byte[] response = new byte[buffer.length];
    device.transfer(buffer, response, buffer.length);
}

当您的应用准备关闭 Android Things 设备时,请务必注销您的 SPI 设备。

@Override
protected void onDestroy() {
    super.onDestroy();

    if (mDevice != null) {
        try {
            mDevice.close();
            mDevice = null;
        } catch (IOException e) {}
    }
}

UART

当与主设备通信时,更复杂的外设(如LCD显示器,SD卡读卡器和GPS模块)通常会通过 UART 端口使用串行通信。 UART允许设备将原始数据异步发送到其他设备上的缓冲区。然后以先进先出的顺序读取这个缓冲区。它还允许在两个连接的设备上配置数据格式和传输速度。由于 UART 不支持时钟信号,所以两个器件必须达到传输速度,但传输速度往往比 I2C 更快,数据可以在器件之间以全双工模式传输。与 I2C 和 SPI 不同,每个 UART 连接只允许连接一个外设。

UART 外设有三根芯线:

  • RX,用于接收数据。
  • TX,用于传输数据。
  • GND,电气接地。

UART

在外设组件上,这些引脚通常会被标记为:

UART 示例1

另外,一些 UART 设备可能还包括两个用于控制数据流的连接:

  • 请求发送(RTS)
  • 清除发送(CLS)

UART 示例2

类似于前面的所有例子,您需要知道您的 Android Things 设备的 UART 连接的名称。 你可以用下面的代码找到:

PeripheralManagerService manager = new PeripheralManagerService();
List<String> deviceList = manager.getUartDeviceList();

if (!deviceList.isEmpty()) {
    Log.d("Tuts+", deviceList.toString());
}

在 Raspberry Pi 上,日志输出如下所示:

[UART0]

一旦知道了 UART 连接的名称,就可以像打开其他设备连接一样创建 Android Things UART 设备。

PeripheralManagerService manager = new PeripheralManagerService();
mDevice = manager.openUartDevice(UART_DEVICE_NAME);

一旦你有了你的设备,你将需要配置将在设备之间发送的数据帧的格式。有四个属性需要注意:

  • 数据位数:UART 可以发送 5 位和 9 位来表示数据字符。发送较少的位允许更快的数据传输速率,但是限制了可以发送的字符的范围。
  • 奇偶位:用于检查传输数据的内容是否为偶数或奇数。如果奇偶校验位设置为无,则从传输中删除奇偶校验位。这用于传输错误检查。
  • 停止位:可以设置为 1 或 2 位。传输将空闲一段时间,等于停止位的数量,以指示数据帧已经结束。
  • 波特率:波特率是数据帧的传输速度。由于 UART 中没有时钟信号,因此两个器件在传输开始之前必须配置波特率。

这些设置中的每一个都可以在 UART 设备上进行配置,如下所示:

uart.setBaudrate(9600);
uart.setDataSize(6);
uart.setParity(UartDevice.PARITY_NONE);
uart.setStopBits(2);

之前您了解到,UART 设备有两个接线设置,那些设备有附加的控制信号,没有的设备。 您可以使用 setHardwareFlowControl() 方法在代码中配置 UART 设备。

uartDevice.setHardwareFlowControl(UartDevice.HW_FLOW_CONTROL_AUTO_RTSCTS);
//or
uartDevice.setHardwareFlowControl(UartDevice.HW_FLOW_CONTROL_NONE);

完成设备配置后,就可以读取、写入 Android Things 开发板与 UART 外设的数据了。写入是通过调用具有字节数组缓冲区的 write() 方法,以及该数组的长度来处理的。

uartDevice.write(buffer, buffer.length);

虽然,可以不断轮询设备读缓冲区中的数据,但最好还是创建一个 UartDeviceCallback 对象,该对象提供了一个名为 onUartDeviceDataAvailable() 的方法,当数据可用时将会触发该方法。如果是这样,您可以从设备的数据缓冲区中读取数据。您将能够使用 registerUartDeviceCallback 将此回调与您的 UART 设备相关联,不过您将需要记住在完成回调时,调用 unregisterUartDeviceCallback。当数据可用时,可以使用 UART 的 read() 方法检索数据。

private UartDeviceCallback mUartCallback = new UartDeviceCallback() {
    @Override
    public boolean onUartDeviceDataAvailable(UartDevice uart) {
        byte[] buffer = new byte[MAX_BUFFER_SIZE];
        try {
            uartDevice.read(buffer, buffer.length)
            //do something with the data in the buffer byte array
        } catch (IOException e) {}

        //Returning true keeps the callback active. If you return false,
        //the callback will automatically unregister.
        return true;
    }

    @Override
    public void onUartDeviceError(UartDevice uart, int error) {}
};

@Override
protected void onStart() {
    super.onStart();
    mDevice.registerUartDeviceCallback(mUartCallback);
}

@Override
protected void onStop() {
    super.onStop();
    mDevice.unregisterUartDeviceCallback(mUartCallback);
}

Activity 结束(finish)后,请务必关闭并取消对 UART 设备的引用。

@Override
protected void onDestroy() {
    super.onDestroy();

    if (uartDevice != null) {
        try {
            uartDevice.close();
            uartDevice = null;
        } catch (IOException e) {}
    }
}

高级 I/O 和未来更新

虽然 Peripheral API 允许您与几乎所有可连接到 Android Things 开发板的设备进行通信,但 Google 还提供了一些额外的支持,使构建您的物联网设备变得更加容易。本节将介绍 Android Things 提供的一些附加外设支持。

Native I/O

虽然 Android Things 为 Android 开发人员提供了一种,使用 Android SDK 和 Java 进入物联网开发的简单方法,但许多物联网应用程序已经存在于 C 和 C++ 中,而其他开发人员由于各种原因,会更愿意使用这些语言。为了支持它,Google 补充了支持本地应用程序和 NDK 的外设 API。关于这个话题,我不会深入探讨,但是建立和使用的连接方式与上面讨论的非常类似。

WiFi和蓝牙

没有办法连接到互联网,物联网设备就只是物(Things)。借助内置的无线支持,您的 Android Things 设备可以连接到互联网,并使用各种在线资源,例如 Firebase 和其他 Google 服务,或任何其他后端服务。另外,使用 Google Play Services 和 Nearby Connections API 等工具,可以让用户通过 WLAN 网络直接与您的设备进行通信。

尽管 Android Things 的开发人员预览版本目前尚未启用,但蓝牙连接也是一项重要的物联网功能。使用蓝牙,您可以创建多个物联网设备或附件,并让它们在短距离内通信。这允许每个设备具有关于其环境的附加上下文信息,诸如用户的家庭或工作空间,以便为用户提供最好的服务。

USB

有些设备可以使用原型板的 USB 端口,尽管在 Android Things 开发者预览的当前版本中并没有完全启用。在第二个开发者预览版中,Google 已经将 USB 音频文件添加到语音支持,开发者已经确认其他设备能工作,比如 USB 麦克风。随着 USB API 在 Android Things 的更高版本中的测试和认可,将会有大量的设备可以作为附件,简单地插入到您的物联网设备中。

相机和显示器

某些设备(如Raspberry Pi)附带内置的附加 I/O 连接,如 HDMI,显示器和相机。幸运的是,所有这些都在 Android Things 上工作,可以让您连接一个 15 厘米的带状电缆相机...

Raspberry Pi 相机

...或者,通过带状电缆或 HDMI 连接显示:

Raspberry Pi 显示器

结论

恭喜!你已经了解了,但已经学习了使用 Android Things 开发连接、控制外围设备的非常有价值的信息。使用这些知识,您应该能够连接并与各种硬件组件进行通信。

在本系列的下一篇文章中,我们将使用我们的 Peripherals API 知识为 GPIO 运动传感器组件创建一个软件驱动程序,然后将其用于更大的 Android Things 项目。

原文链接:Android Things: Peripheral Input/Output

尚未评分
您的评分将帮助我们做出更好的玩法

观光\评论区

Copyright © 2017 玩点什么. All Rights Reserved.