android应用程序访问I2C接口

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

Java code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

package xxxxxxx.xx;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class I2cRadioTest extends Activity {
private static final String TAG = "I2cRadioTest";

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int[] buf = new int[4];
int slaveAddr = 0xXX;
int fileHander;
int mode = 0xXX | 0xXX;
int i;

I2c i2c = new I2c();
fileHander = i2c.open("/dev/i2c-1");

i2c.read(fileHander, slaveAddr, buf, 4);

Log.w(TAG,
"buf0= " + Integer.toHexString(buf[0]) + " buf1= "
+ Integer.toHexString(buf[1]) + " buf2= "
+ Integer.toHexString(buf[2]) + " buf=3 "
+ Integer.toHexString(buf[3]));

buf[0] = 0x01;
i = 0;// i2c.write(fileHander, slaveAddr, mode, buf, 1);
Log.w(TAG, "write length " + i);

for (int j = 0; j < 4; j++) {
buf[i] = 0;
}

i2c.read(fileHander, slaveAddr, buf, 4);
Log.w(TAG,
"buf0= " + Integer.toHexString(buf[0]) + " buf1= "
+ Integer.toHexString(buf[1]) + " buf2= "
+ Integer.toHexString(buf[2]) + " buf=3 "
+ Integer.toHexString(buf[3]));

i2c.close(fileHander);

if ((buf[0] & 0x10) == 0x01) {
Log.w(TAG, "------success-----");
} else {
Log.w(TAG, "----fail-------");
}

setContentView(R.layout.main);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package xxxxxx.xxx;

/**
* This is a I2C operation class
*/
public class I2c {
/**
* @param nodeName
* node path name
* @return return file hander else return <0 on fail
*/
public native int open(String nodeName);

/**
* @param fileHander
* @param i2c_adr
* slave addr
* @param buf
* @param Lenth
* of buf
* @return read length
*/
public native int read(int fileHander, int i2c_adr, int buf[], int Length);

/**
* @param fileHander
* @param i2c_adr
* slave addr
* @param sub_adr
* sub addr
* @param buf
* @param Lenth
* of buf
* @return write length
*/
public native int write(int fileHander, int i2c_adr, int sub_adr,
int buf[], int Length);

public native void close(int fileHander);

static {
System.loadLibrary("test-i2c");
}
}

C/C++ code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class xxxxxx_xxx_I2c */
#include <stdio.h>
#include <android/log.h>
#include <fcntl.h>
#include <linux/i2c.h>
#include <memory.h>
#include <malloc.h>

#ifndef _Included_xxxxxx_xxx_I2c
#define _Included_xxxxxx_xxx_I2c
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: xxxxxx_xxx_I2c
* Method: open
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_xxxxxx_xxx_I2c_open
(JNIEnv *, jobject, jstring);

/*
* Class: xxxxxx_xxx_I2c
* Method: read
* Signature: (II[II)I
*/
JNIEXPORT jint JNICALL Java_xxxxxx_xxx_I2c_read
(JNIEnv *, jobject, jint, jint, jintArray, jint);

/*
* Class: xxxxxx_xxx_I2c
* Method: write
* Signature: (III[II)I
*/
JNIEXPORT jint JNICALL Java_xxxxxx_xxx_I2c_write
(JNIEnv *, jobject, jint, jint, jint, jintArray, jint);

/*
* Class: xxxxxx_xxx_I2c
* Method: close
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_xxxxxx_xxx_I2c_close
(JNIEnv *, jobject, jint);

#ifdef __cplusplus
}
#endif
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

#include "test-i2c.h"

#define LOG_TAG "i2c"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

JNIEXPORT jint JNICALL Java_xxxxxx_xxx_I2c_open
(JNIEnv *env, jobject obj, jstring file)
{
char fileName[64];
const jbyte *str;

str = (*env)->GetStringUTFChars(env, file, NULL);
if (str == NULL) {
LOGI("Can't get file name!");
return -1;
}
sprintf(fileName, "%s", str);
LOGI("will open i2c device node %s", fileName);
(*env)->ReleaseStringUTFChars(env, file, str);
return open(fileName, O_RDWR);
}

JNIEXPORT jint JNICALL Java_xxxxxx_xxx_I2c_read
(JNIEnv * env, jobject obj, jint fileHander, jint slaveAddr, jintArray bufArr, jint len)
{
jint *bufInt;
char *bufByte;
int res = 0, i = 0, j = 0;

if (len <= 0) {
LOGE("I2C: buf len <=0");
goto err0;
}

bufInt = (jint *) malloc(len * sizeof(int));
if (bufInt == 0) {
LOGE("I2C: nomem");
goto err0;
}
bufByte = (char*) malloc(len);
if (bufByte == 0) {
LOGE("I2C: nomem");
goto err1;
}

(*env)->GetIntArrayRegion(env, bufArr, 0, len, bufInt);

res = ioctl(fileHander, I2C_SLAVE, slaveAddr);
if (res != 0) {
LOGE("I2C: Can't set slave address");
goto err2;
}

memset(bufByte, '\0', len);
if ((j = read(fileHander, bufByte, len)) != len) {
LOGE("read fail in i2c read jni i = %d buf 4", i);
goto err2;
} else {
for (i = 0; i < j ; i++)
bufInt[i] = bufByte[i];
LOGI("return %d %d %d %d in i2c read jni", bufByte[0], bufByte[1], bufByte[2], bufByte[3]);
(*env)->SetIntArrayRegion(env, bufArr, 0, len, bufInt);
}

free(bufByte);
free(bufInt);

return j;

err2:
free(bufByte);
err1:
free(bufInt);
err0:
return -1;
}

JNIEXPORT jint JNICALL Java_xxxxxx_xxx_I2c_write
(JNIEnv *env, jobject obj, jint fileHander, jint slaveAddr, jint mode,
jintArray bufArr, jint len)
{
jint *bufInt;
char *bufByte;
int res = 0, i = 0, j = 0;

if (len <= 0) {
LOGE("I2C: buf len <=0");
goto err0;
}

bufInt = (jint *) malloc(len * sizeof(int));
if (bufInt == 0) {
LOGE("I2C: nomem");
goto err0;
}
bufByte = (char*) malloc(len + 1);
if (bufByte == 0) {
LOGE("I2C: nomem");
goto err1;
}

(*env)->GetIntArrayRegion(env, bufArr, 0, len, bufInt);
bufByte[0] = mode;
for (i = 0; i < len; i++)
bufByte[i + 1] = bufInt[i];

res = ioctl(fileHander, I2C_SLAVE, slaveAddr);
if (res != 0) {
LOGE("I2C: Can't set slave address");
goto err2;
}

if ((j = write(fileHander, bufByte, len + 1)) != len + 1) {
LOGE("write fail in i2c");
goto err2;
}

LOGI("I2C: write %d byte", j);
free(bufByte);
free(bufInt);

return j - 1;

err2:
free(bufByte);
err1:
free(bufInt);
err0:
return -1;
}

JNIEXPORT void JNICALL Java_xxxxxx_xxx_I2c_close
(JNIEnv *env, jobject obj, jint fileHander)
{
close(fileHander);
}

https://www.jianshu.com/p/02dc4bb83c95