智能小车制作过程全纪录: 四、软件平台— Java 控制GPIO

137
0
2021年1月22日 09时05分

更多创客作品,请关注笔者网站园丁鸟,搜集全球极具创意,且有价值的创客作品
ROS机器人知识请关注,diegorobot
业余时间完成的一款在线统计过程分析工具SPC,及SPC知识分享网站qdo

 


嵌入式系统针对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过来就可以

 

这里写图片描述

 

3.生成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调用接口。

 

友善之臂的板子性能不错,但需要加强针对生态的建设,另外要吐槽的是,虽然板子集成了蓝牙,但蓝牙不能用,官方也不解决。

 

发表评论

后才能评论