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

嵌入式系统针对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过来就可以
这里写图片描述

  1. 生成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

(0)
上一篇 2021年7月17日
下一篇 2021年7月17日

相关推荐

发表回复

登录后才能评论