Android NDK GPIO操作(pcduino 装Android系统)

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

开发工具: Eclipse
开发语言: Java和c++
     Pcduino跑Android系统让我兴奋了很长时间,也由此幻想了很多有趣的应用。例如 结合Yeelink做远程加电控制;结合微信开放接口与传感器向好友推送信息等等。 当然这些有趣的应用都离不开PCDUINO硬件的操作。那么在Android系统下怎么来操作硬件呢?我想大概有以下几种方式:


1、利用Arduino 库自己写c++程序然后编译成可执行文件,然后把可执行文件拷到PCDUINO中,添加权限,在模拟中端里运行可执行文件。
     优点:Arduino库函数完善,非常容易操作。
     缺点:貌似和Android开发的应用不能完美的结合。

2、利用Android 的Jni编程,直接驱动GPIO。
     优点:开发工具简单,利用Eclipse进行交叉编译,同时编译Java和c++代码。并且把硬件操作函数生成.so文件直接打包APK中。

     下面我们利用ANDROID NDK来开发一个简单实例: "光电开关控制UI上的灯泡亮灭"

      第一步:开发环境的搭建
                  1、安装Eclipse
                  2、安装ADT-v20插件(该版本已经直接支持Native编程)
                  3、安装CDT(编译c++代码)
                  3、安装android-ndk-r8e(该版本支持Windows,不用在Cygwin下编译了)
       按照这种模式搭建的开发环境用起来非常上手,java和c++程序直接交叉编译,然后打包生成APK.
      第二步:实例演练
                  1、新建Android 工程HelloJni,编写Java代码如下(定义本地函数)
                 public class MainActivity extends Activity 
            {        
                  @Override
                  protected void onCreate(Bundle savedInstanceState) 
        
              {
                super.onCreate(savedInstanceState);
                setTitle(getHelloJniData());
        
               }

                //c++中要实现的函数接口
                 public native String getHelloJniData();    //从本地函数获得字符串
                 public native void OpenLed();                //打开LED灯,本例子对应GPIO3
                 public native void CloseLed();                //关闭LED灯
                 public native int  ReadGpioState(int i);    //读取某个GPIO的状态,然后返回给Java层

                 //库载入代码
                 static
                 {
                     System.loadLibrary("Hellojni");          //Hellojni本地SO库
                  }
             }
                    2、实现本地c++代码
            (此处注意可以利用 javah 生成头文件,也可以自己按照Jni规则写)


             #define GPIO_MODE_DIR "/sys/devices/virtual/misc/gpio/mode/"
             #define GPIO_PIN_DIR "/sys/devices/virtual/misc/gpio/pin/"
             #define GPIO_IF_PREFIX "gpio"



            JNIEXPORT jstring JNICALL Java_com_hellojni_MainActivity_getHelloJniData (JNIEnv * env, jobject obj )
             
             {
                  return (*env)->NewStringUTF(env, "hello jni");
             }


              JNIEXPORT void JNICALL Java_com_hellojni_MainActivity_OpenLed (JNIEnv * env, jobject obj)   //打开LED
           {




                __android_log_print(ANDROID_LOG_INFO,LOG_TAG,"OPEN- LED");


                memset(path, 0, sizeof(path));
                sprintf(path, "%s%s%d", GPIO_MODE_DIR, GPIO_IF_PREFIX, 3);    //此处对应地址/sys/devices/virtual/misc/gpio/mode/gpio3 设置为输出
                fd = open(path, O_RDWR);
                write(fd,"1",1);
                close(fd);


                 memset(path, 0, sizeof(path));
                sprintf(path, "%s%s%d", GPIO_PIN_DIR, GPIO_IF_PREFIX, 3);         //此处对应地址/sys/devices/virtual/misc/gpio/pin/gpio3 设置为高定平
                fd = open(path, O_RDWR);
                write(fd,"1",1);
                close(fd);
        }


       JNIEXPORT void JNICALL Java_com_hellojni_MainActivity_CloseLed(JNIEnv * env, jobject obj) //关闭LED
               
       {
              __android_log_print(ANDROID_LOG_INFO,LOG_TAG,"CLOSE LED");
                memset(path, 0, sizeof(path));
                sprintf(path, "%s%s%d", GPIO_MODE_DIR, GPIO_IF_PREFIX, 3);
                fd = open(path, O_RDWR);
                write(fd,"1",1);
                close(fd);


                memset(path, 0, sizeof(path));
                sprintf(path, "%s%s%d", GPIO_PIN_DIR, GPIO_IF_PREFIX, 3);
                fd = open(path, O_RDWR);
                write(fd,"0",1);
                close(fd);
       }



       JNIEXPORT jint JNICALL Java_com_hellojni_MainActivity_ReadGpioState (JNIEnv *env, jobject obj,jint i) //读取某个IO口的状态
            {
                   char buf[4];
                    int ret = -1;
                    int fd = -1;
                    int state;


                    memset((void *)buf, 0, sizeof(buf));


                    memset(path, 0, sizeof(path));
                    sprintf(path, "%s%s%d", GPIO_PIN_DIR, GPIO_IF_PREFIX, i);
                    fd = open(path, O_RDWR);
                    ret = read(fd, buf, sizeof(buf));


                    ret = buf[0] - '0';
                           switch( ret )
                           {
                               case 0:
                                       state=0;
                                    //   __android_log_print(ANDROID_LOG_INFO,LOG_TAG,"LOW");    返回LOG调试信息
                                         break;
                               case 1:
                                       state=1;
                                    //   __android_log_print(ANDROID_LOG_INFO,LOG_TAG,"HIGHT");
                                     break;
                               default:
                                       state=-1;
                                   ret = -1;
                                   break;
                           }
                      close(fd);
                             //  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,"READ GPIO STATE");
            return state;
        }



                  3、到这里关键代码就都准备好了,可以直接在Java层调用这些接口函数操作IO了。下面最后再配置一下Eclipse交叉编译环境。
                         
                       右击HelloJni的工程属性,弹出 窗口,选Builders --->New---NDK_Builder。

Android NDK GPIO操作(pcduino 装Android系统)_第1张图片 




Android NDK GPIO操作(pcduino 装Android系统)_第2张图片 




Android NDK GPIO操作(pcduino 装Android系统)_第3张图片 




Android NDK GPIO操作(pcduino 装Android系统)_第4张图片 




Android NDK GPIO操作(pcduino 装Android系统)_第5张图片 




到此开发环境搭建完毕!具体的细节哪里有问题,可以问度娘哦!!!


工程文件见附件!!!


感谢Lucifer㊣(1094294)大神的指导!!!




 hellojni.rar (985.58 KB, 下载次数: 22) 







  




转载于:https://my.oschina.net/u/1777508/blog/339749

你可能感兴趣的:(Android NDK GPIO操作(pcduino 装Android系统))