2017年9月,英創(chuàng)在Linux的文件系統(tǒng)中移植了針對(duì)嵌入式Linux的JRE(Java Runtime Environment),能夠支持Java應(yīng)用程序的運(yùn)行。由于Java語言不能直接訪問硬件資源,英創(chuàng)提供了Java硬件支持包,主要支持的工控接口有:以太網(wǎng)、串口、CAN、GPIO、SPI、I2C、RTC等。本文主要介紹使用Java語言調(diào)用英創(chuàng)Java硬件支持包,操作英創(chuàng)主板I2C接口的過程。
1、I2C簡介
I2C(Inter-Integrated Circuit)總線是一種2線制(串行數(shù)據(jù)SDA、串行時(shí)鐘頻率SCL)的主從通訊協(xié)議,主要運(yùn)用于器件之間的數(shù)據(jù)通訊。SDA和SCL雙向漏極開路(Open Drain)并利用電阻將電位上拉,同一個(gè)I2C總線上可以掛載多個(gè)I2C設(shè)備,如下圖所示。
圖1I2C掛載設(shè)備示意圖
圖2I2C時(shí)序圖
I2C總線是電平有效,在SCL信號(hào)為高電平的時(shí)候采樣SDA信號(hào)。如上圖所示,其通信過程為:SDA從1變動(dòng)到0,而SCL還是1時(shí),表示開始數(shù)據(jù)傳輸。接下來的7位,就是設(shè)備的地址。緊接著的是讀寫標(biāo)志,其為1時(shí)是讀取,為0則是寫。如果I2C總線上存在著和請(qǐng)求的地址相對(duì)應(yīng)的設(shè)備,則從設(shè)備會(huì)發(fā)送一個(gè)ACK信號(hào)通知主設(shè)備,可以發(fā)送數(shù)據(jù)了。接到ACK信號(hào)后,主設(shè)備則發(fā)送一個(gè)8位的數(shù)據(jù),然后等待ACK。當(dāng)傳輸完畢之后,SCL保持為1,SDA從0變換到1時(shí),表明傳輸結(jié)束。
2、I2C傳輸數(shù)據(jù)結(jié)構(gòu)
英創(chuàng)提供的I2C傳輸數(shù)據(jù)結(jié)構(gòu)源文件為emtronix.hardware.I2CParam.java。每一個(gè)I2CParam類實(shí)例代表一次I2C通信,其主要成員變量如下所示:
public class I2CParam {
public byte SlaveAddr; //I2C從設(shè)備地址
public char RegAddr; //要訪問的I2C從設(shè)備寄存器地址
public byte[] Databuf; //寫入/讀出的數(shù)據(jù)緩存
}
其中,SlavaAddr是要訪問的從設(shè)備的地址,RegAddr是要訪問的從設(shè)備的寄存器地址,Databuf是用戶申請(qǐng)好的緩存區(qū)域,讀寫的長度由此緩存區(qū)域的長度(Databuf.length)決定。
3、I2C傳輸接口函數(shù)
英創(chuàng)提供的I2C傳輸接口源文件為emtronix.hardware.I2C.java。用戶在實(shí)例化I2C類后可以調(diào)用Open、Read、Write、Close對(duì)I2C硬件接口進(jìn)行操作。I2C類的具體信息如下,其中mFd為設(shè)備描述符,用戶不用設(shè)置,由接口函數(shù)自動(dòng)修改。
public class I2C {
private int mFd;
public I2C() {
mFd = -1;
}
public void info() {
System.out.println("mfd " + mFd);
}
/**
* 打開/dev/i2c-0設(shè)備
* @return 成功返回非負(fù)設(shè)備描述符;失敗返回-1
*/
public native int Open();
/**
* 從I2C總線發(fā)送一幀數(shù)據(jù),從設(shè)備的地址和寄存器地址由i2cparam指定
* @param i2cparam 指定發(fā)送從設(shè)備的地址和寄存器地址,以及攜帶的數(shù)據(jù),數(shù)據(jù)長度由i2cParam.DataBuf.length決定
* @return 成功返回非負(fù);失敗返回-1
*/
public native int Write(I2CParam i2cparam);
/**
* 從I2C總線讀一幀數(shù)據(jù),從設(shè)備地址和寄存器地址由i2cparam指定
* @param i2cparam 指定發(fā)送從設(shè)備的地址和寄存器地址,以及攜帶的數(shù)據(jù),數(shù)據(jù)長度由i2cParam.DataBuf.length決定
* @return 成功返回非負(fù);失敗返回-1
*/
public native int Read(I2CParam i2cparam);
/**
* 關(guān)閉I2C設(shè)備
* @return 成功返回0;失敗返回-1
*/
public native int Close();
}
4、I2C從設(shè)備(鍵盤)程序
測試SPI接口的時(shí)候可以直接將MISO和MOSI短接就可以測試發(fā)送和接收數(shù)據(jù),但I(xiàn)2C的測試不能,需要連接到真正的I2C從設(shè)備,根據(jù)其工作時(shí)序,完成I2C通信的測試。這里選擇英創(chuàng)ETA202 I2C鍵盤擴(kuò)展模塊。英創(chuàng)已經(jīng)封裝好了一個(gè)I2CKeypad.java類,對(duì)外提供OpenKeypad、ReadKeypad、CloseKeypad等接口來操作I2C鍵盤。這些接口的內(nèi)部實(shí)現(xiàn)是通過I2C類的接口函數(shù)來完成對(duì)I2C鍵盤的操作。I2CKeyPad類的OpenKeypad接口主要內(nèi)容如下:
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 failed\n");
return -1;
}
// 2. config tca8418
i2cparam.SlaveAddr = TCA8418_ADDR;
for(i=0;ilength;i++) {
i2cparam.RegAddr = (char) (TCA8418Config[i].ControlReg & 0x0ffff);
i2cparam.Databuf = new byte[1];
i2cparam.Databuf[0] = TCA8418Config[i].Command;
if(mI2C.Write(i2cparam) < 0) {
System.out.println("I2C write failed\n");
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()) {
KeyScan();
}
}
System.out.println("scanThread exit");
}
});
scanThread.start();
}
I2CKeypad類在OpenKeyPad接口中使用I2C的Write接口對(duì)鍵盤掃描芯片tca8418進(jìn)行了初始化設(shè)置,并開啟了監(jiān)聽中斷處理線程。中斷處理線程中的KeyScan函數(shù)調(diào)用了I2C的Read接口去讀取事件信息,更新按鍵值。tca8418的各個(gè)寄存器功能,請(qǐng)參考模塊ETA202中的數(shù)據(jù)手冊(cè)。I2CKeypad類具體實(shí)現(xiàn)請(qǐng)結(jié)合tca8418的數(shù)據(jù)手冊(cè)參考源碼。
5、I2C鍵盤測試程序
I2C傳輸接口中操作I2C的接口函數(shù)聲明都有native的前綴,表明其實(shí)現(xiàn)部分在本地的庫當(dāng)中。英創(chuàng)將所有英創(chuàng)主板的硬件接口訪問函數(shù)的實(shí)現(xiàn)部分編譯成了動(dòng)態(tài)鏈接庫libemtronixhardware.so,放在了文件系統(tǒng)/lib目錄下。
在編寫I2C傳輸主程序的時(shí)候,首先需要加載該庫,如下所示:
public class testI2CMain {
static {
System.loadLibrary("emtronixhardware");
}
public static void main(String[] args) {
...
}
}
然后,就可以在main函數(shù)中實(shí)例化I2CKeypad類,先調(diào)用OpenKeypad接口初始化鍵盤,接著可調(diào)用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鍵盤測試程序運(yùn)行結(jié)果
運(yùn)行I2C傳輸Java主程序需要把編譯結(jié)果bin文件中的所有目錄文件拷貝到主板/mnt/nandflash,或者通過nfs掛載到主板/mnt/nfs目錄下。然后,使用“java 包名.類名”運(yùn)行,如下圖所示:
圖2運(yùn)行I2C鍵盤測試程序
以上就是使用Java操作英創(chuàng)主板I2C接口的介紹,感興趣的客戶可以通過電話或者郵件聯(lián)系英創(chuàng)工程師。我們將提供Java示例程序源碼供客戶參考。
-
Linux
+關(guān)注
關(guān)注
87文章
11304瀏覽量
209535 -
嵌入式主板
+關(guān)注
關(guān)注
7文章
6085瀏覽量
35344
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論