2017年9月,英创在Linux的文件系统中移植了针对嵌入式Linux的JRE(Java Runtime Environment),能够支持Java应用程序的运行。由于Java语言不能直接访问硬件资源,英创提供了Java硬件支持包,主要支持的工控接口有:以太网、串口、CAN、GPIO、SPI、I2C、RTC等。本文主要介绍使用Java语言调用英创Java硬件支持包,操作英创主板I2C接口的过程。
1、I2C简介
I2C(Inter-Integrated Circuit)总线是一种2线制(串行数据SDA、串行时钟频率SCL)的主从通讯协议,主要运用于器件之间的数据通讯。SDA和SCL双向漏极开路(Open Drain)并利用电阻将电位上拉,同一个I2C总线上可以挂载多个I2C设备,如下图所示。
图1 I2C挂载设备示意图
图2 I2C时序图
I2C总线是电平有效,在SCL信号为高电平的时候采样SDA信号。如上图所示,其通信过程为:SDA从1变动到0,而SCL还是1时,表示开始数据传输。接下来的7位,就是设备的地址。紧接着的是读写标志,其为1时是读取,为0则是写。如果I2C总线上存在着和请求的地址相对应的设备,则从设备会发送一个ACK信号通知主设备,可以发送数据了。接到ACK信号后,主设备则发送一个8位的数据,然后等待ACK。当传输完毕之后,SCL保持为1,SDA从0变换到1时,表明传输结束。
2、I2C传输数据结构
英创提供的I2C传输数据结构源文件为emtronix.hardware.I2CParam.java。每一个I2CParam类实例代表一次I2C通信,其主要成员变量如下所示:
public class I2CParam {
public byte SlaveAddr; //I2C从设备地址
public char RegAddr; //要访问的I2C从设备寄存器地址
public byte[] Databuf; //写入/读出的数据缓存
}
其中,SlavaAddr是要访问的从设备的地址,RegAddr是要访问的从设备的寄存器地址,Databuf是用户申请好的缓存区域,读写的长度由此缓存区域的长度(Databuf.length)决定。
3、I2C传输接口函数
英创提供的I2C传输接口源文件为emtronix.hardware.I2C.java。用户在实例化I2C类后可以调用Open、Read、Write、Close对I2C硬件接口进行操作。I2C类的具体信息如下,其中mFd为设备描述符,用户不用设置,由接口函数自动修改。
public class I2C {
private int mFd;
public I2C() {
mFd = -1;
}
public void info() {
System.out.println("mfd " + mFd);
}
/**
* 打开/dev/i2c-0设备
*@Return成功返回非负设备描述符;失败返回-1
*/
public native int Open();
/**
* 从I2C总线发送一帧数据,从设备的地址和寄存器地址由i2cparam指定
* @param i2cparam 指定发送从设备的地址和寄存器地址,以及携带的数据,数据长度由i2cParam.DataBuf.length决定
* @return 成功返回非负;失败返回-1
*/
public native int Write(I2CParam i2cparam);
/**
* 从I2C总线读一帧数据,从设备地址和寄存器地址由i2cparam指定
* @param i2cparam 指定发送从设备的地址和寄存器地址,以及携带的数据,数据长度由i2cParam.DataBuf.length决定
* @return 成功返回非负;失败返回-1
*/
public native int Read(I2CParam i2cparam);
/**
* 关闭I2C设备
* @return 成功返回0;失败返回-1
*/
public native int Close();
}
4、I2C从设备(键盘)程序
测试SPI接口的时候可以直接将MISO和MOSI短接就可以测试发送和接收数据,但I2C的测试不能,需要连接到真正的I2C从设备,根据其工作时序,完成I2C通信的测试。这里选择英创ETA202 I2C键盘扩展模块。英创已经封装好了一个I2CKeypad.java类,对外提供OpenKeypad、ReadKeypad、CloseKeypad等接口来操作I2C键盘。这些接口的内部实现是通过I2C类的接口函数来完成对I2C键盘的操作。I2CKeyPad类的OpenKeypad接口主要内容如下:
public int OpenKeypad()
{
I2CParam i2cparam = new I2CParam();
......
mI2C = new I2C();
mIrq = new IRQ();
//1. open i2c bus
if(mI2C.Open() < 0)
{
System.out.println("I2C open failedn");
return -1;
}
// 2. config tca8418
i2cparam.SlaveAddr = TCA8418_ADDR;
for(i=0;i
i2cparam.RegAddr = (char) (TCA8418Config.ControlReg & 0x0ffff);
i2cparam.Databuf = new byte[1];
i2cparam.Databuf[0] = TCA8418Config.Command;
if(mI2C.Write(i2cparam) < 0) {
System.out.println("I2C write failedn");
return -1;
}
}
//3. open irq1
if(mIrq.Open("/dev/esm6800_irq1") < 0) {
System.out.println("can not open irq");
return -1;
}
...
//4. 开启中断处理线程
scanThread = new Thread(new Runnable() {
public void run() {
mIrq.setTimeout(1000);
while(!Thread.currentThread().isInterrupted()) {
if(mIrq.WaitForIrq()>0) {
KeyScan();
}
}
System.out.println("scanThread exit");
}
});
scanThread.start();
}
I2CKeypad类在OpenKeyPad接口中使用I2C的Write接口对键盘扫描芯片tca8418进行了初始化设置,并开启了监听中断处理线程。中断处理线程中的KeyScan函数调用了I2C的Read接口去读取事件信息,更新按键值。tca8418的各个寄存器功能,请参考模块ETA202中的数据手册。I2CKeypad类具体实现请结合tca8418的数据手册参考源码。
5、I2C键盘测试程序
I2C传输接口中操作I2C的接口函数声明都有native的前缀,表明其实现部分在本地的库当中。英创将所有英创主板的硬件接口访问函数的实现部分编译成了动态链接库libemtronixhardware.so,放在了文件系统/lib目录下。
在编写I2C传输主程序的时候,首先需要加载该库,如下所示:
public class testI2CMain {
static {
System.loadLibrary("emtronixhardware");
}
public static void main(String[] args) {
...
}
}
然后,就可以在main函数中实例化I2CKeypad类,先调用OpenKeypad接口初始化键盘,接着可调用I2CKeypad的ReadKeypad接口读取按键信息:
public static void main(String[] args) {
I2CKeypad pad = new I2CKeypad();
int i1 = pad.OpenKeypad();
int key;
if(i1 < 0)
{
System.out.println("open keypad failed");
return;
}
for(i1 = 0; i1 < 10; ) {
key = pad.ReadKeypad();
if(key > 0) {
i1++;
System.out.println("-----key: 0x" + Integer.toHexString(key));
}
}
pad.CloseKeypad();
return ;
}
6、I2C键盘测试程序运行结果
运行I2C传输Java主程序需要把编译结果bin文件中的所有目录文件拷贝到主板/mnt/nandflash,或者通过nfs挂载到主板/mnt/nfs目录下。然后,使用“java 包名.类名”运行,如下图所示:
图2 运行I2C键盘测试程序
以上就是使用Java操作英创主板I2C接口的介绍,感兴趣的客户可以通过电话或者邮件联系英创工程师。我们将提供Java示例程序源码供客户参考。
0