AndroidThings系列之五:I2C通信

发布于 2021-2-21 09:35
浏览
0收藏

其实AndroidThings的API已将底层的细节大大抽象了,正如Arduino简化了底层细节一样,这样一来将大大提高生产效率。本例的复杂之处在LCD的具体操作上,所以除了掌握AndroidThings基础知识,要想在Maker领域中取得更好的效果,学会看数据手册也算是基本功之一,如果实在啃不动数据手册,也可以参考别人的代码来改,不过适用性就差了一点点。

本文将介绍如何通过I2C通信来实现屏幕点亮和显示。

先给小白讲下I2C,大神直接略过就好。

 

I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。 主器件用于启动总线传送数据,并产生时钟以开放传送的器件,此时任何被寻址的器件均被认为是从器件.在总线上主和从、发和收的关系不是恒定的,而取决于此时数据传送方向。如果主机要发送数据给从器件,则主机首先寻址从器件,然后主动发送数据至从器件,最后由主机终止数据传送;如果主机要接收从器件的数据,首先由主器件寻址从器件.然后主机接收从器件发送的数据,最后由主机终止接收过程。在这种情况下.主机负责产生定时时钟和终止数据传送。AndroidThings系列之五:I2C通信-开源基础软件社区

I2C器件使用3线接口连接,包括:

 

• 共享时钟信号(SCL)

• 共享数据线(SDA)

• 公共地参考(GND)

 

I2C支持沿同一总线连接的多个从设备。与SPI不同,从设备使用I2C软件协议进行寻址。每个设备都使用唯一的地址进行编程,并仅响应主设备发送到该地址的传输。即使总线仅包含一个从站,每个从站设备也必须具有一个地址。

i.MX7D的I2C接口如下

AndroidThings系列之五:I2C通信-开源基础软件社区

要在AndroidThings中使用I2C设备,需要启用如下权限

<uses-permission android:name="com.google.android.things.permission.USE_PERIPHERAL_IO" />

正如上一节介绍的一样,如果想要查看I2C接口列表,可以使用PeripheralManager来实现,下面是具体的代码及输出

Log.d(TAG, "I2C: " + PeripheralManager.getInstance().getI2cBusList());
 

在LogCat窗口会看到如下的输出:

/com.example.netlh.lcd1602 D/AndroidThings: I2C: [I2C1, I2C2]

实现I2C通信需要I2C设备,这里我们使用的是Grove RGB LCD显示屏,这是一个1602显示屏,支持RGB三色背光。该屏包括两个I2C设备,一个地址为0x62(RGB地址),另一个为0x3e(LCD地址)。AndroidThings系列之五:I2C通信-开源基础软件社区

我们知道在Linux下,可以使用 i2c-tools来方便的调试I2C设备,该工具包括i2cdetect,i2cdump等常用命令,可以方便的检测并操作i2c设备。

使用i2c-tools源码,可以编译出android可用的版本,具体编译方法请自行参考。

利用adb命令将编译后的工具上传到i.MX7D,下面是在i.MX7D上的用法

adb root
adb push i2cdetect /data
...
adb shell 
imx7d_pico:/ #

总而言之,就是将i2cdetect等工具上传到开发板,然后其它的附加操作例如添加执行权限等都省略不提,接下来使用i2cdetect来检测下设备是否在线

127|imx7d_pico:/ # /data/i2cdetect -l
i2c-3   i2c             30a50000.i2c                            I2C adapter
i2c-1   i2c             30a30000.i2c                            I2C adapter
i2c-0   i2c             30a20000.i2c                            I2C adapter
imx7d_pico:/ # /data/i2cdetect -y 0
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          03 -- -- -- -- -- -- UU -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- 3e --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- 62 -- -- -- -- -- -- -- -- -- -- -- -- --
70: 70 -- -- -- -- -- -- --
imx7d_pico:/ #

设备地址已检测,接下来就开始写代码了。

 

LCD的数据手册请参考官方给出的文档,这里我们专门定义了一个类Lcd1602,代码内容如下

 

package com.example.netlh.lcd1602;
 
import com.google.android.things.pio.I2cDevice;
import com.google.android.things.pio.PeripheralManager;
 
import java.io.IOException;
 
public class Lcd1602 {
    private final static int LCD_I2C_ADDRESS = 0x3E;
    private final static int RGB_I2C_ADDRESS = 0x62; 
 
    public final static String DEBUG_TAG = "GROVE LCD RGB";
    private final static String I2C_NAME = "I2C1";
 
    private I2cDevice mLcdDevice, mRgbDevice;
 
 
    public void setColor(int r, int g, int b) throws IOException {
        mRgbDevice.writeRegByte(0, (byte)1);
        mRgbDevice.writeRegByte(1, (byte) 0);
        mRgbDevice.writeRegByte(0x08, (byte) 0xaa);
        mRgbDevice.writeRegByte(4, (byte) r);
        mRgbDevice.writeRegByte(3, (byte) g);
        mRgbDevice.writeRegByte(2, (byte) b);
 
 
    }
 
    private void textCommand(int cmd) throws IOException{
        mLcdDevice.writeRegByte(0x80, (byte)cmd);
    }
 
    private void setPosition(int row, int col) throws IOException {
        if(row == 0) {
            textCommand(0x80 + col);
        }
 
        if(row == 1) {
            textCommand(0xC0 + col);
        }
    }
 
    public void setText(int row, int col, byte[] msg) throws IOException {
        //textCommand(0x01);
        textCommand(0x08 | 0x04);  //display on, no cursor
        textCommand(0x28); //two lines
 
        setPosition(row, col);
 
        for(int i = 0; i < msg.length; i ++) {
            mLcdDevice.writeRegByte(0x40, msg[i]);
        }
 
 
    }
 
    public void clear() throws IOException {
        textCommand(0x01); //clear screen
    }
 
    public void setup() {
        PeripheralManager peripheralManager = PeripheralManager.getInstance();
        try {
            mLcdDevice = peripheralManager.openI2cDevice(I2C_NAME, LCD_I2C_ADDRESS);
            mRgbDevice = peripheralManager.openI2cDevice(I2C_NAME, RGB_I2C_ADDRESS);
        } catch (IOException e) {
            e.printStackTrace();
        }
 
    }
 
    public void close(){
 
        if(mLcdDevice != null) {
            try {
                mLcdDevice.close();
                mLcdDevice = null;
 
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
 
        if(mRgbDevice != null) {
            try {
                mRgbDevice.close();
                mRgbDevice = null;
 
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

该类的内容比较简单,只提供一些简单的操作功能,如设备背景,显示字串内容,以及关闭设备等操作。这里包括的大部分命令项比如0x01, 0x04需要查询LCD的数据手册。

 

主要的功能实现如下

public class MainActivity extends Activity {
    private static final String TAG = "AndroidThings";
 
    private Lcd1602 mLcd1602;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main);
 
        Log.d(TAG, "I2C: " + PeripheralManager.getInstance().getI2cBusList());
 
        mLcd1602 = new Lcd1602();
        mLcd1602.setup();
 
        //byte[] msg = "For more complex peripherals, look for an existing user-space driver".getBytes();
        Log.d(Lcd1602.DEBUG_TAG, "onCreate: " + PeripheralManager.getInstance().getUartDeviceList());
        try {
            mLcd1602.clear();
            mLcd1602.setColor(33, 28, 28);
 
            mLcd1602.setText(0, 0, "ABCDEFGHIJKLMNOP".getBytes());
            mLcd1602.setText(1, 1, "TEMP: 11 C".getBytes()); 
        } catch (IOException e) {
            e.printStackTrace();
        }
 
    }
 
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(Lcd1602.DEBUG_TAG, "onDestroy: ");
        if(mLcd1602 != null) {
            mLcd1602.close();
            mLcd1602 = null;
        }
 
    } 
}

整体代码框架和led工程的差不多,首先在onCreate里面初始化设备,设置RGB的背光色,然后显示一些简单的文字信息。

AndroidThings系列之五:I2C通信-开源基础软件社区

运行的结果,倒也不是很复杂。

其实AndroidThings的API已将底层的细节大大抽象了,正如Arduino简化了底层细节一样,这样一来将大大提高生产效率。本例的复杂之处在LCD的具体操作上,所以除了掌握AndroidThings基础知识,要想在Maker领域中取得更好的效果,学会看数据手册也算是基本功之一,如果实在啃不动数据手册,也可以参考别人的代码来改,不过适用性就差了一点点。

 

下一节来个PWM式点灯。

已于2021-2-21 09:35:05修改
收藏
回复
举报
回复
添加资源
添加资源将有机会获得更多曝光,你也可以直接关联已上传资源 去关联
    相关推荐