嵌入式系统针对GPIO的开发,大部分都是采用c/c++进行开发,也有在树莓派上针对GPIO的java开发包,但必须要用树莓派平台,但友善之臂Friendarm的板子并不支持,只能自己想办法,在这里我们用Jni技术,直接调用友善之臂Friendarm的驱动包接口
1.首先下载友善之臂Friendarm的开发包Matrix,并编译
apt-get update && apt-get install git git clone https://github.com/friendlyarm/matrix.git
2 . 针对NanoPC T3修改common.h, common.c两个文件
可能T3比较新,官方的开发包并没有包含对T3的初始化的支持,所以需要修改这两个文件
在common.h中增加BOARD_NANOPI_T3 的宏定义
在common.c getBoardType函数中增加T3的识别
在gpio.c initPinGPIO函数中增加T3的初始化代码,T3和M3的一样,copy过来就可以
在pwm.c initPwmGPIO函数中增加T3的初始化代码,T3和M3的一样,copy过来就可以
生成Java Jni类包装C语音库的函数,并实现c语言代码,并编译打包
java代码如下:
public class FriendarmLib {
static
{
System.loadLibrary("friendarm");调用的动态链接库文件名为libfriendarm.so;
}
///common
public native static int boardInit();
public native static int initPinGPIO(int board);
public native static int pintoGPIO(int pin);
public native static int exportGPIOPin(int pin);
public native static int unexportGPIOPin(int pin);
// GPIO_LOW or GPIO_HIGH
public native static int setGPIOValue(int pin, int value);
public native static int getGPIOValue(int pin);
// GPIO_IN or GPIO_OUT
public native static int setGPIODirection(int pin, int direction);
public native static int getGPIODirection(int pin);
//PWM GPIO
public native static int initPwmGPIO(int board);
public native static int PWMPlay(int pin, int freq, int duty);
public native static int PWMStop(int pin);
}
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
在FriendarmLib.java目录下执行javac FriendarmLib.java在此目录下编译生成 FriendarmLib.class文件。
在src目录下执行javah com.diego.jni.FriendarmLib在src目录下生成com_diego_jni_FriendarmLib.h文件;注意的是一定在src目录下,javah后面是包路径。
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class com_diego_jni_FriendarmLib */
#ifndef _Included_com_diego_jni_FriendarmLib
#define _Included_com_diego_jni_FriendarmLib
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_diego_jni_FriendarmLib
* Method: boardInit
* Signature: ()I
*/
JNIEXPORT jintJNICALL Java_com_diego_jni_FriendarmLib_boardInit
(JNIEnv *, jclass);
/*
* Class: com_diego_jni_FriendarmLib
* Method: initPinGPIO
* Signature: (I)I
*/
JNIEXPORT jintJNICALL Java_com_diego_jni_FriendarmLib_initPinGPIO
(JNIEnv *, jclass, jint);
/*
* Class: com_diego_jni_FriendarmLib
* Method: pintoGPIO
* Signature: (I)I
*/
JNIEXPORT jintJNICALL Java_com_diego_jni_FriendarmLib_pintoGPIO
(JNIEnv *, jclass, jint);
/*
* Class: com_diego_jni_FriendarmLib
* Method: exportGPIOPin
* Signature: (I)I
*/
JNIEXPORT jintJNICALL Java_com_diego_jni_FriendarmLib_exportGPIOPin
(JNIEnv *, jclass, jint);
/*
* Class: com_diego_jni_FriendarmLib
* Method: unexportGPIOPin
* Signature: (I)I
*/
JNIEXPORT jintJNICALL Java_com_diego_jni_FriendarmLib_unexportGPIOPin
(JNIEnv *, jclass, jint);
/*
* Class: com_diego_jni_FriendarmLib
* Method: setGPIOValue
* Signature: (II)I
*/
JNIEXPORT jintJNICALL Java_com_diego_jni_FriendarmLib_setGPIOValue
(JNIEnv *, jclass, jint, jint);
/*
* Class: com_diego_jni_FriendarmLib
* Method: getGPIOValue
* Signature: (I)I
*/
JNIEXPORT jintJNICALL Java_com_diego_jni_FriendarmLib_getGPIOValue
(JNIEnv *, jclass, jint);
/*
* Class: com_diego_jni_FriendarmLib
* Method: setGPIODirection
* Signature: (II)I
*/
JNIEXPORT jintJNICALL Java_com_diego_jni_FriendarmLib_setGPIODirection
(JNIEnv *, jclass, jint, jint);
/*
* Class: com_diego_jni_FriendarmLib
* Method: getGPIODirection
* Signature: (I)I
*/
JNIEXPORT jintJNICALL Java_com_diego_jni_FriendarmLib_getGPIODirection
(JNIEnv *, jclass, jint);
/*
* Class: com_diego_jni_FriendarmLib
* Method: initPwmGPIO
* Signature: (I)I
*/
JNIEXPORT jintJNICALL Java_com_diego_jni_FriendarmLib_initPwmGPIO
(JNIEnv *, jclass, jint);
/*
* Class: com_diego_jni_FriendarmLib
* Method: PWMPlay
* Signature: (III)I
*/
JNIEXPORT jintJNICALL Java_com_diego_jni_FriendarmLib_PWMPlay
(JNIEnv *, jclass, jint, jint, jint);
/*
* Class: com_diego_jni_FriendarmLib
* Method: PWMStop
* Signature: (I)I
*/
JNIEXPORT jintJNICALL Java_com_diego_jni_FriendarmLib_PWMStop
(JNIEnv *, jclass, 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
com_diego_jni_FriendarmLib.h文件是项目中,供C语言调用的头文件,只需要实现此头文件中定义的接口函数,就可以了。com_diego_jni_FriendarmLib.c文件的代码如下:
/*
* com_diego_jni_FriendarmLib.c
*
* Created on: Oct 3, 2016
* Author: william
*/
#include
#include "com_diego_jni_FriendarmLib.h"
#include "common.h"
#include "libfahw-gpio.h"
#include "libfahw-filectl.h"
#include "libfahw-pwm.h"
/*
* Class: com_diego_jni_FriendarmLib
* Method: boardInit
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_diego_jni_FriendarmLib_boardInit
(JNIEnv * env, jclass jc){
//printf("******this is in c file\n");
return (jint)boardInit();
}
/*
* Class: com_diego_jni_FriendarmLib
* Method: initPinGPIO
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_diego_jni_FriendarmLib_initPinGPIO
(JNIEnv * env, jclass jc, jint board){
return (jint)initPinGPIO(board);
}
/*
* Class: com_diego_jni_FriendarmLib
* Method: pintoGPIO
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_diego_jni_FriendarmLib_pintoGPIO
(JNIEnv * env, jclass jc, jint pin){
return (jint)pintoGPIO(pin);
}
/*
* Class: com_diego_jni_FriendarmLib
* Method: exportGPIOPin
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_diego_jni_FriendarmLib_exportGPIOPin
(JNIEnv * env, jclass jc, jint pin){
return (jint)exportGPIOPin(pin);
}
/*
* Class: com_diego_jni_FriendarmLib
* Method: unexportGPIOPin
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_diego_jni_FriendarmLib_unexportGPIOPin
(JNIEnv * env, jclass jc, jint pin){
return (jint)unexportGPIOPin(pin);
}
/*
* Class: com_diego_jni_FriendarmLib
* Method: setGPIOValue
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_diego_jni_FriendarmLib_setGPIOValue
(JNIEnv * env, jclass jc, jint pin, jint value){
return (jint)setGPIOValue(pin,value);
}
/*
* Class: com_diego_jni_FriendarmLib
* Method: getGPIOValue
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_diego_jni_FriendarmLib_getGPIOValue
(JNIEnv * env, jclass jc, jint pin){
return (jint)getGPIOValue(pin);
}
/*
* Class: com_diego_jni_FriendarmLib
* Method: setGPIODirection
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_diego_jni_FriendarmLib_setGPIODirection
(JNIEnv * env, jclass jc, jint pin, jint direction){
return (jint)setGPIODirection(pin,direction);
}
/*
* Class: com_diego_jni_FriendarmLib
* Method: getGPIODirection
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_diego_jni_FriendarmLib_getGPIODirection
(JNIEnv * env, jclass jc, jint pin){
return (jint)getGPIODirection(pin);
}
/*
* Class: com_diego_jni_FriendarmLib
* Method: initPwmGPIO
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_diego_jni_FriendarmLib_initPwmGPIO
(JNIEnv * env, jclass jc, jint board){
return (jint)initPwmGPIO(board);
}
/*
* Class: com_diego_jni_FriendarmLib
* Method: PWMPlay
* Signature: (III)I
*/
JNIEXPORT jint JNICALL Java_com_diego_jni_FriendarmLib_PWMPlay
(JNIEnv * env, jclass jc, jint pin, jint freq, jint duty){
return (jint)PWMPlay(pin,freq,duty);
}
/*
* Class: com_diego_jni_FriendarmLib
* Method: PWMStop
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_diego_jni_FriendarmLib_PWMStop
(JNIEnv * env, jclass jc, jint pin){
return (jint)PWMStop(pin);
}
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
将com_diego_jni_FriendarmLib.h上传到友善之臂Friendarm T3主板~/matrix/lib/includes目录。
将com_diego_jni_FriendarmLib.c上传到友善之臂Friendarm T3主板~/matrix/lib目录。
修改~/matrix/lib目录下Makefile文件的编译段,增加jvm相关头文件的包含目录,修改后的代码如下:
接下来执行在~/matrix/lib目录下执行make命令,在/matrix/lib/.obj目录下会生成所有的.o文件, 注意.obj目录是隐藏目录,在lib目录下执行cd .obj目录即可进入此目录,执行ls目录可以看到所有生成的.o 文件
打包动态链接.so文件,执行如下命令:
gcc -Wall -rdynamic -shared -o libfriendarm.so com_diego_jni_FriendarmLib.o common.o gpio.o pwm.o filectl.o
注意这里需要用的目标文件.o 文件全部打包进去,否则调用会出错。执行完成后会生成libfriendarm.so文件
执行mv libfriendarm.so /usr/lib命令将libfriendarm.so文件移动到java的搜索目录下。
接下来就可以在java中调用官方的c语言包,调用的示例代码如下:
try{
int i=FriendarmLib.boardInit();
System.out.println("****** the result for gpio is :"+i);
}catch(Exception e){
e.printStackTrace();
System.exit(0);
}
1
2
3
4
5
6
7
执行后输出入下:
输出信息中T3的主板是NANOPI3和M3是一样的,官方应该及时更新库文件。
4.在本例中只用到了GPIO,和PWM所以只打包了相应的接口函数,可以按照此方法打包其他需要的接口,在Java中调用;如果方便,还是使用树莓派的比较方便,有开源项目pi4j 项目专门针对树莓派的硬件接口提供Java调用接口。友善之臂的板子性能不错,但需要加强针对生态的建设,另外要吐槽的是,虽然板子集成了蓝牙,但蓝牙不能用,官方也不解决。