Android Things物联网开发--外围I/O接口之I2C(五)
2017-04-06 23:42
447 查看
I2C
I2C总线连接一些简单的设备,这些设备的数据负载较小。传感器和执行器用的就是I2C,还有其他的比如加速度计,温度计,LED显示器和电机驱动器。I2C是一个同步串行接口,这意味着它依赖一个共享的时钟信号来在设备间同步传输数据。控制触发时钟信号的器件称为主设备,所有连接上的外设称为从设备。每一个设备连接到同一组数据信号以形成总线。
I2C设备使用3线接口连接,包括:
共享时钟信号(SCL)
共享数据总线(SDA)
地线(GND)
因为所有数据都通过一根线传输,I2C仅仅支持半双工通信。所有的通信都由主设备启动,主设备传输完成后从设备必须响应。
I2C支持同一个总线连接多个从设备。不同于 SPI ,从设备使用 I2C 软件协议来寻址。每一个设备都有一个唯一的地址,并且仅响应主设备发送到的地址。
管理从设备的连接
为了打开一个到普通 I2C 从设备的连接,你必须知道那个总线的唯一的名字。在开发的初始阶段,或者移植一个app到新设备的时候,使用PeripheralManagerService 的getI2CBusList()方法获取所用可用的设备名是很有帮助的。PeripheralManagerService manager = new PeripheralManagerService(); List<String> deviceList = manager.getI2cBusList(); if (deviceList.isEmpty()) { Log.i(TAG, "No I2C bus available on this device."); } else { Log.i(TAG, "List of available devices: " + deviceList); }
一旦你知道了目标设备的名称,使用PeripheralManagerService 来连接到这个设备。当你完成与外设的通信后,应该关闭连接释放资源。另外,你不能在同一个设备连接关闭之前再次打开一个新的连接。使用 close() 方法来关闭连接:
public class HomeActivity extends Activity { // I2C Device Name private static final String I2C_DEVICE_NAME = ...; // I2C Slave Address private static final int I2C_ADDRESS = ...; private I2cDevice mDevice; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Attempt to access the I2C device try { PeripheralManagerService manager = new PeripheralManagerService(); mDevice = manager.openI2cDevice(I2C_DEVICE_NAME, I2C_ADDRESS); } catch (IOException e) { Log.w(TAG, "Unable to access I2C device", e); } } @Override protected void onDestroy() { super.onDestroy(); if (mDevice != null) { try { mDevice.close(); mDevice = null; } catch (IOException e) { Log.w(TAG, "Unable to close I2C device", e); } } } }
注意:设备名称代表了 I2C 总线,地址代表了总线上的指定从设备。因此,一个 I2cDevice 是一个连接到相应 I2C 总线上的指定从设备 。
与寄存器进行交互
I2C 从设备将他们的内容放到可写或者可读的寄存器中。可读寄存器–包含了从设备想要传输给主设备的数据,比如传感器的值或者状态位。
可写寄存器–包含了主设备可以控制的配置数据。
在 I2C 之上有一个通用的协议实现叫做 系统管理总线(SMBus),它以标准的方式与寄存器进行交互。SMBus由以下两个 I2C 事物组成:
Register Address标识了要访问的寄存器的地址,Data
是要读取或者写入的数据。从设备上的逻辑数据通常由多位组成,因此可以包含多个寄存器地址。
注意:对于SMBus协议,设备将会在地址(Register Address)和数据(Data
)之间发送一个重复的开始位。
外围I/O接口为访问寄存器数据提供SMBus命令的三种类型。
读写字节数据(Byte Data): readRegByte() 和 writeRegByte() 方法读或者写单字节(8-Bit)的寄存器数据;
读写字节数据(Word Data): readRegWord() 和 writeRegWord() 方法读或者写2个连续的寄存器值作为一个16位的小端存储(little-endian)的字。第一个寄存器地址对应字中的低位字节(LSB),后面的寄存器对应着高位字节(MSB)。
读写块数据(Block Data): readRegBuffer() 和 writeRegBuffer() 方法以数组的形式读或写最多32个连续寄存器的值。
// Modify the contents of a single register public void setRegisterFlag(I2cDevice device, int address) throws IOException { // Read one register from slave byte value = device.readRegByte(address); // Set bit 6 value |= 0x40; // Write the updated value back to slave device.writeRegByte(address, value); } // Read a register block public byte[] readCalibration(I2cDevice device, int startAddress) throws IOException { // Read three consecutive register values byte[] data = new byte[3]; device.readRegBuffer(startAddress, data, data.length); return data; }
传输原始数据
当需要与定义了跟SMBus不同的寄存器的 I2C 外设交互时,或者根本不用寄存器,使用原始的 read() 和 write()方法来完全控制在线缆上传输的字节数据。这些方法将会向下面那样执行一个单个的 I2C 事物:使用原始传输方法,设备将在传输之前发送开始标志,并在传输完成之后发送停止标志。这使得通过 传输重复的开始标识来结合多个事物变的不再可能。
注意:原始传输方式能处理的数据没有明确的最大长度,但是在你设备上的 I2C 控制硬件在它能处理的字节数上有一个限制。如果你的外设要求传输大量的数据,那么请查看硬件的说明书。
下面的代码展示了如何构造一个原始的字节缓冲区,并把它写入到 I2C 从设备:
public void writeBuffer(I2cDevice device, byte[] buffer) throws IOException { int count = device.write(buffer, buffer.length); Log.d(TAG, "Wrote " + count + " bytes over I2C."); }
相关文章推荐
- Android Things物联网开发--外围I/O接口之GPIO(三)
- Android Things物联网开发--外围I/O接口之UART(七)
- Android Things物联网开发--外围I/O接口之PWM(四)
- Android Things物联网开发--外围I/O接口之SPI(六)
- Android Things物联网开发--基础介绍(一)
- Android Things物联网开发--硬件和软件环境(二)
- 树莓派Android Things物联网开发:GitHub案例程序汇总
- [置顶] 树莓派Android Things物联网开发:入门及资料汇总
- 树莓派Android Things物联网开发:树莓派3上手就是这么简单
- Android Things:外设I/O接口-I2C
- 树莓派Android Things物联网开发:按键中断及消抖
- 树莓派Android Things物联网开发:已知Bug发行说明
- Android Things专题3 开发环境搭建
- GDE专栏 | Android Things中的I2C
- Android平台读写i2c设备开发笔记
- 树莓派3 安装谷歌物联网系统-Android Things
- Android Things 学习开发笔记 (1)
- Android Things:外设I/O接口-PWM