用Java语言开发物联网应用(4)
认识外设
外设通常指输入输出设备,是计算机系统最重要的组成部分之一。物联网设备往往要和五花八门的外设打交道,比如传感器、GPS、按钮、摄像头、显示屏、麦克风、扬声器······凡此种种,不一而足。除了要和网络服务器交互以外,从各种外设上取得数据,或是通过外设进行各种控制,是物联网设备的主要特点。
常见的外设接口
物联网设备的外设虽然五花八门,但是外设和主控芯片(CPU)的接口类型,通常就是那么几种:
UART
就是我们常说的“串口”,主要用来用作通讯。很多物联网常用外设,比如GPS模组、蓝牙模组、2G/4G模组等等,都支持使用UART来和主控芯片通讯。
GPIO
通常叫做“通用IO接口”,这里的IO(或说I/O)是指输入/输出。GPIO的操作非常简单,就是高低电平的输入或者输出,比如点亮一个LED灯,或者从一个开关按钮读取按下状态等等。
SPI
串行外设接口,比起UART,SPI接口能支持很高的数据吞吐率,比如网络控制器、FLASH存储器这些需要高速和CPU交换数据的外设,通常是使用SPI接口的。不过SPI是分主从设备的,数据交换是由主SPI设备发起的从SPI听命于主设备的控制。
IIC
是Inter-Integrated Circuit Bus的简称,通常翻译成“集成电路总线”。IIC的特点是需要的连线少,控制逻辑简单易实现,也适用于一主多从的总线式外设连接布局。实际使用中,很多种类型的传感器产品都支持IIC接口,比如温度传感器、加速度传感器等等。
PWM
Pulse Width Modulation,即“脉冲宽度调制器”,或者不那么准确但是简单地理解为“脉冲波发生器”。在机械控制中用的最多,比如步进电机。也可以用来控制简单的喇叭发声。
ADC/DAC
即“模数/数模转换器”。像电压这样的模拟量,计算机需要将其数字化才能够处理,这就是“模-数”转换。反之则是“数-模”转换。
IIS:
Integrate Inte**ce of Sound。从名字就可以看出来,这个接口是接声音输入输出设备的。一般的音频采集芯片、音频编解码芯片或是音频播放芯片都支持IIS接口。
Java对外设接口的支持
Java在外设控制这方面,以前并没有专门的接口。从OpenJDK 7开始,OpenJDK加入了DeviceIO作为外设控制的标准接口,对物联网设备常见的外设接口做了标准化支持。
JOSH针对小型物联网设备,对DeviceIO进行了小幅改动。通过JOSH DeviceIO API(org.joshvm.j2me.dio.* ),目前支持的接口类型有UART、GPIO、SPI和IIC,Java程序员可以实现用Java语言控制外设,比如控制电平开关、读取传感器数据等等。换言之,可以实现用Java语言编写物联网设备的外设驱动程序,并实现驱动程序的动态安装。
下面,我们通过一些示例,看看是如何通过JOSH DeviceIO API实现外设访问功能的。
输出高低电平——GPIO控制篇
首先创建一个GPIO端口配置。这段代码的主要意思,是配置GPIO#2号端口为输出模式。
GPIOPinConfig cfg1 = new GPIOPinConfig(GPIOPinConfig.UNASSIGNED, 2,
GPIOPinConfig.DIR_OUTPUT_ONLY,
GPIOPinConfig.MODE_OUTPUT_OPEN_DRAIN,
GPIOPinConfig.TRIGGER_NONE, false);
然后通过DeviceManager打开GPIO#2端口
GPIOPin gpioPin = (GPIOPin) DeviceManager.open(cfg1, DeviceManager.EXCLUSIVE);
下面这段代码,是将GPIO#2端口置为高电平,一秒钟后再设置为低电平,然后再等待一秒。如此循环10次。
int retry = 10;
while (retry-- > 0) {
// 将GPIO拉高
gpioPin.setValue(true);
Thread.sleep(1000);
// 将GPIO拉低
gpioPin.setValue(false);
Thread.sleep(1000);
}
如果接一个LED灯到GPIO#2上的话,将看到LED灯在以一秒为间隔闪烁10次。
完整的代码可以由此下载:https://doc.joshvm.com/static/ESP32/sample/GpioDemo.zip
使用串口通讯——UART控制篇
首先确定打开的是几号串口,下面这个Demo是打开串口1,也就是COM1。然后确定使用的波特率,这里设为9600。
private static String com = "COM1";
// 波特率
private static int baudrate = 9600;
private static StreamConnection streamConnection;
private static InputStream inputStream;
private static OutputStream outputStream;
public static void main(String[] args) {
String host = "comm:" + com + ";baudrate=" + baudrate;
try {
// 建立连接
streamConnection = (StreamConnection) Connector.open(host);
······
接下来获取输入输出流
inputStream = streamConnection.openInputStream();
outputStream = streamConnection.openOutputStream();
将从外设从串口发来的数据按16进制打印到log,并写回串口
int len = 0;
byte[] buffer = new byte[256];
StringBuffer stringBuffer = null;
// 读数据
while ((len = inputStream.read(buffer)) != -1) {
stringBuffer = new StringBuffer();
for (int i = 0; i < len; i++) {
stringBuffer.append(Integer.toHexString(buffer[i] & 0xFF) + " ");
}
System.out.println(stringBuffer.toString());
//发送数据
sendData(buffer, 0, len);
}
这个是发送数据的函数实现
private static void sendData(byte[] buffer, int off, int len) throws IOException {
if (outputStream != null) {
outputStream.write(buffer, off, len);
}
}
完整的代码可以由此下载:https://doc.joshvm.com/static/ESP32/sample/UartDemo.zip
下一步——访问网络
连接网络是物联网设备的基本需求,Java可以让我们非常方便地编写联网应用,并处理各种复杂的应用层网络协议。我从下一篇起,会向大家介绍如何用Java编写网络应用,将物联网设备与网络服务器连接起来。