嵌入式系统针对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);
}
在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 <jni.h>
/* 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 jint JNICALL Java_com_diego_jni_FriendarmLib_boardInit
(JNIEnv *, jclass);
/*
* Class: com_diego_jni_FriendarmLib
* Method: initPinGPIO
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_diego_jni_FriendarmLib_initPinGPIO
(JNIEnv *, jclass, jint);
/*
* Class: com_diego_jni_FriendarmLib
* Method: pintoGPIO
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_diego_jni_FriendarmLib_pintoGPIO
(JNIEnv *, jclass, jint);
/*
* Class: com_diego_jni_FriendarmLib
* Method: exportGPIOPin
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_diego_jni_FriendarmLib_exportGPIOPin
(JNIEnv *, jclass, jint);
/*
* Class: com_diego_jni_FriendarmLib
* Method: unexportGPIOPin
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_diego_jni_FriendarmLib_unexportGPIOPin
(JNIEnv *, jclass, jint);
/*
* Class: com_diego_jni_FriendarmLib
* Method: setGPIOValue
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_diego_jni_FriendarmLib_setGPIOValue
(JNIEnv *, jclass, jint, jint);
/*
* Class: com_diego_jni_FriendarmLib
* Method: getGPIOValue
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_diego_jni_FriendarmLib_getGPIOValue
(JNIEnv *, jclass, jint);
/*
* Class: com_diego_jni_FriendarmLib
* Method: setGPIODirection
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_diego_jni_FriendarmLib_setGPIODirection
(JNIEnv *, jclass, jint, jint);
/*
* Class: com_diego_jni_FriendarmLib
* Method: getGPIODirection
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_diego_jni_FriendarmLib_getGPIODirection
(JNIEnv *, jclass, jint);
/*
* Class: com_diego_jni_FriendarmLib
* Method: initPwmGPIO
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_diego_jni_FriendarmLib_initPwmGPIO
(JNIEnv *, jclass, jint);
/*
* Class: com_diego_jni_FriendarmLib
* Method: PWMPlay
* Signature: (III)I
*/
JNIEXPORT jint JNICALL Java_com_diego_jni_FriendarmLib_PWMPlay
(JNIEnv *, jclass, jint, jint, jint);
/*
* Class: com_diego_jni_FriendarmLib
* Method: PWMStop
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_diego_jni_FriendarmLib_PWMStop
(JNIEnv *, jclass, jint);
#ifdef __cplusplus
}
#endif
#endif
com_diego_jni_FriendarmLib.h文件是项目中,供C语言调用的头文件,只需要实现此头文件中定义的接口函数,就可以了。com_diego_jni_FriendarmLib.c文件的代码如下:
/*
* com_diego_jni_FriendarmLib.c
*
* Created on: Oct 3, 2016
* Author: william
*/
#include <stdio.h>
#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);
}
将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);
}
执行后输出入下:
输出信息中T3的主板是NANOPI3和M3是一样的,官方应该及时更新库文件。
4.在本例中只用到了GPIO,和PWM所以只打包了相应的接口函数,可以按照此方法打包其他需要的接口,在Java中调用;如果方便,还是使用树莓派的比较方便,有开源项目pi4j 项目专门针对树莓派的硬件接口提供Java调用接口。友善之臂的板子性能不错,但需要加强针对生态的建设,另外要吐槽的是,虽然板子集成了蓝牙,但蓝牙不能用,官方也不解决。
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/6914.html