android jni 通過GPIO控制LED燈(rockchip rk3288)

Android 通過GPIO 控制LED燈的亮滅,給菜鳥小白用的

開發環境

版本 Android studio 3.5 Gradle 5.4.1

Android 設備環境:

rockchip rk3288

查看GPIO信息

如果不清楚自己的開發板gpio編號對應的是什麼可以查看下這篇文章地址

文章原創地址

我不會jni,所以jni部分是別人的,地址

源碼

github
csdn

代碼部分

jni部分(非原創) 地址

gpio-manager.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_zhongyi_gpiodemo_MainActivity */

#ifndef _Included_com_zhongyi_gpiolibrary_GpioManager
#define _Included_com_zhongyi_gpiolibrary_GpioManager
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_beep_GpioCtr
 * Method:    exportGpio
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_com_zhongyi_gpiolibrary_GpioManager_exportGpio
        (JNIEnv *, jclass, jint);

/*
 * Class:     com_example_beep_GpioCtr
 * Method:    setGpioDirection
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_zhongyi_gpiolibrary_GpioManager_setGpioDirection
        (JNIEnv *, jclass, jint, jint);

/*
 * Class:     com_example_beep_GpioCtr
 * Method:    readGpioStatus
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_com_zhongyi_gpiolibrary_GpioManager_readGpioStatus
        (JNIEnv *, jclass, jint);

/*
 * Class:     com_example_beep_GpioCtr
 * Method:    writeGpioStatus
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_zhongyi_gpiolibrary_GpioManager_writeGpioStatus
        (JNIEnv *, jclass, jint, jint);

/*
 * Class:     com_example_beep_GpioCtr
 * Method:    unexportGpio
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_com_zhongyi_gpiolibrary_GpioManager_unexportGpio
        (JNIEnv *, jclass, jint);

#ifdef __cplusplus
}
#endif
#endif

gpio-manager.cpp

#include <jni.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <android/log.h>
#include "gpio-manager.h"

#define TAG "jni_gpio"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__)
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__)

#define IN              0
#define OUT             1
#define LOW             0
#define HIGH            1

#define BUFFER_MAX    3
#define DIRECTION_MAX 48

/**
 * 文件所有者是root,所以在操作之前修改文件的權限
 */

extern "C"
JNIEXPORT jint JNICALL
Java_com_zhongyi_gpiolibrary_GpioManager_exportGpio(JNIEnv *env, jclass clazz, jint gpio) {
    system("su");
    system("sudo");
    char buffer[BUFFER_MAX];
    int len;
    int fd;

    fd = open("/sys/class/gpio/export", O_WRONLY);
    if (fd < 0) {
        LOGE("Failed to open export for writing!\n");
        return(0);
    }
    LOGE("sizeof(buffer) : %d", sizeof(buffer));
    len = snprintf(buffer, BUFFER_MAX, "%d", gpio);
    LOGE("gpio : %d , len : %d, buffer : %s , sizeof(buffer) : %d", gpio, len, buffer, sizeof(buffer));
    if (write(fd, buffer, len) < 0) {
        LOGE("Fail to export gpio!\n");
        return 0;
    }

    close(fd);
    return 1;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_zhongyi_gpiolibrary_GpioManager_setGpioDirection(JNIEnv *env, jclass clazz, jint gpio,
                                                        jint direction) {
    static const char dir_str[]  = "in\0out";
    char path[DIRECTION_MAX];
    int fd;

    snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/direction", gpio);
    LOGE("path : %s", path);
    fd = open(path, O_WRONLY);
    if (fd < 0) {
        LOGE("failed to open gpio direction for writing!\n");
        return 0;
    }

    if (write(fd, &dir_str[direction == IN ? 0 : 3], direction == IN ? 2 : 3) < 0) {
        LOGE("failed to set direction!\n");
        return 0;
    }

    close(fd);
    return 1;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_zhongyi_gpiolibrary_GpioManager_readGpioStatus(JNIEnv *env, jclass clazz, jint gpio) {
    char path[DIRECTION_MAX];
    char value_str[3];
    int fd;

    snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/value", gpio);
    fd = open(path, O_RDONLY);
    if (fd < 0) {
        LOGE("failed to open gpio value for reading!\n");
        return -1;
    }

    if (read(fd, value_str, 3) < 0) {
        LOGE("failed to read value!\n");
        return -1;
    }

    LOGD("fd %d\n", fd);

    close(fd);
    return (atoi(value_str));
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_zhongyi_gpiolibrary_GpioManager_writeGpioStatus(JNIEnv *env, jclass clazz, jint gpio,
                                                       jint value) {
    static const char values_str[] = "01";
    char path[DIRECTION_MAX];
    int fd;

    snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/value", gpio);
    LOGE("write path: %s\n", path);
    fd = open(path, O_WRONLY);
    if (fd < 0) {
        LOGE("failed to open gpio value for writing!\n");
        return 0;
    }

    if (write(fd, &values_str[value == LOW ? 0 : 1], 1) < 0) {
        LOGE("failed to write value!\n");
        return 0;
    }

    close(fd);
    return 1;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_zhongyi_gpiolibrary_GpioManager_unexportGpio(JNIEnv *env, jclass clazz, jint gpio) {
    char buffer[BUFFER_MAX];
    int len;
    int fd;

    fd = open("/sys/class/gpio/unexport", O_WRONLY);
    if (fd < 0) {
        LOGE("Failed to open unexport for writing!\n");
        return 0;
    }

    len = snprintf(buffer, BUFFER_MAX, "%d", gpio);
    if (write(fd, buffer, len) < 0) {
        LOGE("Fail to unexport gpio!");
        return 0;
    }

    close(fd);
    return 1;
}
java部分

命令執行工具CommandExec.java 用於在操作gpio之前,先修改文件的權限。

/**
 * 命令行執行工具
 */
public class CommandExec {

    private CommandExec() {
    }

    /**
     * 修改gpio下文件的權限,讓他可以使用
     * @param ledId gpio 編號
     * @return 成功true
     */
    public static boolean execRedLed(int ledId) {
        return execCommand(String.format("cd /sys/class/gpio/gpio%d/ && chmod 777 value", ledId));
    }

    /**
     * 還原 gpio文件的權限
     * @param ledId gpio 編號
     * @return 成功 true
     */
    public static boolean releaseLed(int ledId) {
        return execCommand(String.format("cd /sys/class/gpio/gpio%d/ && chmod 644 value", ledId));
    }


    public static boolean execCommand(String command) {
        boolean status = false;
        if (TextUtils.isEmpty(command)) {
            return status;
        }
        try {
            Process exec = Runtime.getRuntime().exec("su");
            OutputStream outputStream = exec.getOutputStream();
            outputStream.write(command.getBytes(Charset.forName("utf-8")));
            outputStream.write("\n".getBytes());
            outputStream.write("exit\n".getBytes());
            outputStream.flush();
            int waitFor = exec.waitFor();
            Log.e("execCommand", "execCommand command:"+command+";waitFor=" + waitFor);
            if (waitFor == 0) {
                //chmod succeed
                status = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("execCommand", "execCommand exception=" + e.getMessage());
            return false;
        }
        return status;
    }
}

jni java部分 GpioManager.java 用於調用jni

/**
 * 控制gpio
 */
public class GpioManager {

    public static int out = 1;
    public static int in = 0;

    static {
        System.loadLibrary("gpio-manager");
    }


    public static native int exportGpio(int gpio);

    public static native int setGpioDirection(int gpio, int direction);

    public static native int readGpioStatus(int gpio);

    /**
     * 修改gpio狀態
     * @param gpio
     * @param value
     * @return
     */
    public static native int writeGpioStatus(int gpio, int value);

    public static native int unexportGpio(int gpio);
}

調用

    static int LED_WHITE = 11;
	....
	 @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ...
        execLed(); //使led文件可讀寫
		...
    }
    
   @Override
    protected void onDestroy() {
        super.onDestroy();
        releaseLed(); //還原led讀寫權限
    }
    
    /**
     * 讓led可執行
     */
    private void execLed() {
        CommandExec.execRedLed(LED_WHITE);
        CommandExec.execRedLed(LED_RED);
        CommandExec.execRedLed(LED_GREEN);
    }

    /**
     * 釋放led燈
     */
    private void releaseLed() {
        CommandExec.releaseLed(LED_WHITE);
        CommandExec.releaseLed(LED_RED);
        CommandExec.releaseLed(LED_GREEN);
    }
	....

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_write:
                flag_white = (flag_white == 0 ? 1 : 0); //1 燈亮 0 燈滅
                GpioManager.writeGpioStatus(LED_WHITE, flag_white);
                ((TextView) v).setText(flag_white == 1 ? "白燈亮" : "白燈滅");
                break;
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章