QT210开发板android应用程序控制led灯[android应用程序控制硬件]

来源:互联网 发布:mysql order by count 编辑:程序博客网 时间:2024/05/22 11:42

QT210 开发板 LED应用程序

    目的编写一个android应用程序来控制开发板上led灯的亮与灭.

编译环境: Ubuntu12.04

Android系统: android4.0 (linux3.0.8)

一.驱动

1. 查看原理图,QT210开发板上led D5, D6, D7, D8 对应引脚为EINT0, EINT1, EINT2, EINT3.

     Tigerboard-II底板.pdf

    

 

 

   

   

     2. 根据底板上的EINT引脚,在核心板上找到与之相对应的引脚,最终对应到了GPIOGPH0_0, GPH0_1, GPH0_2, GPH0_3

         QT210V2核心板.pdf:

        

 

     

     

     

     3.  接下来在三星 S5PV210芯片手册上找到相应寄存器.控制led灯实际就是控制相应寄存器.

           S5PV210_EVT1_Usermanual_20100218.pdf

          

         

         

 

      

       4.  编写驱动文件led.c

          

#include <linux/module.h>  #include <linux/kernel.h>  //#include <linux/io.h>  #include <asm/irq.h>#include <asm/io.h>#include <linux/fs.h>  #include <asm/uaccess.h>  #include <linux/miscdevice.h>  #include <linux/pci.h>  #include <linux/ioctl.h>  #include <linux/init.h>  #include <linux/delay.h> #define DEVICE_NAME "leds" //设备名(/dev/leds)  #define LED_MAJOR 240   unsigned long *gph0con = NULL;unsigned long *gph0dat = NULL;int major;    static int led_ioctl(struct file *file, unsigned int cmd, unsigned long arg)  {      printk(KERN_ALERT"\ncmd = %d  arg = %d \n", cmd, arg);      switch(cmd)      {          case 0:              printk(KERN_ALERT"led%d off\n", arg);              switch(arg)              {              case 0:  *gph0dat &= ~0x01;                break;              case 1:  *gph0dat &= ~0x02;                break;              case 2:  *gph0dat &= ~0x04;                break;              case 3:  *gph0dat &= ~0x08;                break;              default:                  break;              }              break;          case 1:              printk(KERN_ALERT"led%d on\n", arg);              switch(arg)              {              case 0:  *gph0dat |= 0x01;                break;              case 1:  *gph0dat |= 0x02;                break;              case 2:  *gph0dat |= 0x04;                break;              case 3:  *gph0dat |= 0x08;               break;              default:                  break;              }                break;          case 11:              printk(KERN_ALERT"led all on\n");  *gph0dat |= 0xf;            break;          case 10:              printk(KERN_ALERT"led all off\n");  *gph0dat &= ~0xf;            break;          default:              break;          }        return 0;  }   struct file_operations led_fops={      .owner = THIS_MODULE,      .unlocked_ioctl = led_ioctl,  };    static struct miscdevice misc = {      .minor = MISC_DYNAMIC_MINOR, //动态设备号      .name = DEVICE_NAME,      .fops = &led_fops,  };      static int __init led_init(void)  {      int rc;gph0con = (unsigned long *)ioremap(0xE0200C00, 16);gph0dat = (unsigned long *)ioremap(0xE0200C04, 8);*gph0con &= ~0xffff;*gph0con |= 0x1111;*gph0dat &= ~0xf;   rc = misc_register(&misc);        if(rc<0)      {      printk(KERN_ALERT"register %s char dev error\n","leds");          return -1;      }  else   printk(KERN_ALERT" lcd module OK!\n");         return 0;  }    static void __exit led_exit(void)   {    unregister_chrdev(LED_MAJOR, "leds");      printk(KERN_ALERT"module exit\n");  }    module_init(led_init);  module_exit(led_exit);    MODULE_LICENSE("GPL");  MODULE_AUTHOR("cw");  


 

       5. 编写led.cMakefile. 这里将led驱动编译成模块的方式.

           注意编写Makefile,行的开头只能用Tab,不能用空格.

         

  KERNELDIR :=/home/share/210/android4.0/4.0/qt210_ics_kernel3.0.8  PWD :=$(shell pwd)  modules:   $(MAKE) -C $(KERNELDIR) M=$(PWD) modules  modules_install:  $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install  obj-m:=led.o  clean:  rm -rf *.o *~core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers


 

      6. 编译

      

          编译成功后生成led.ko模块.

      7. 将led.ko 拷贝到开发板上,半加载.加载之后会在/dev/目录下生成leds这个设备.

         

 

二. Android应用程序

       1.  新建一个Android应用程序

     

     

 

     2. 打开 src/LedActivity.java, 

        添加public static native int led_ioctl(int i, int j);

        添加一个接口是为了利用java来生成jni的头文件.

       src/LedActivity.java:

      

  package com.example.led;    import android.os.Bundle;  import android.app.Activity;  import android.view.Menu;    public class LedActivity extends Activity {    @Override  protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_led);  }    @Override  public boolean onCreateOptionsMenu(Menu menu) {  // Inflate the menu; this adds items to the action bar if it is present.  getMenuInflater().inflate(R.menu.led, menu);  return true;  }    public static native int led_ioctl(int i, int j);    }


     3. 编译整个android项目,将整个Led项目文件拷贝到ubuntu.

             

 

             新建一个jni目录

      

 

      4. 利用java文件自动生成jni头文件.

          javah -classpath bin/classes -d jni com.example.led.LedActivity

        

 

      5. jni目录下编写led.c led测试程序led.c.

        

        Led/jni/led.c:

       

#include <jni.h>  #include <stdio.h>     #include <stdlib.h>     #include <fcntl.h>  #include <unistd.h>     #include <sys/ioctl.h>     #include <android/log.h>    #define LOG_TAG "LED"       //android logcat  #define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__    )  #define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS_    _)    //int main(int argc, char **argv)    jint JNICALL Java_com_example_led_LedActivity_led_1ioctl(JNIEnv *env, jclass thiz, jint led_nu, jint on)   {        int fd;              fd = open("/dev/leds", O_RDWR);      if(fd < 0)        printf("Can't open /dev/leds!\n");              ioctl(fd, on, led_nu);        LOGI("led_nu=%d,state=%d\n", led_nu, on);      close(fd);              return 0;    }


      6.  jni目录下编写Android.mk

          Led/jni/Android.mk

        

  LOCAL_PATH := $(call my-dir)    include $(CLEAR_VARS)  LOCAL_MODULE := Led_ctrl  LOCAL_SRC_FILES := led.c  LOCAL_LDLIBS := -llog  LOCAL_C_INCLUDES := $(MY_ANDROID_SOURCE)/frameworks/base/core/jni/android/graphics \     $(MY_ANDROID_SOURCE)/external/skia/include/core \     $(MY_ANDROID_SOURCE)/external/skia/include/images \     $(MY_ANDROID_SOURCE)/frameworks/base/include \     $(MY_ANDROID_SOURCE)/system/core/include  include $(BUILD_SHARED_LIBRARY)

 

      7.  Led目录下运行ndk-bluild, 将led.c文件编译成so库文件.

           前提是你已经安装了android-ndk 工具(http://blog.csdn.net/colwer/article/details/8944166)

          

     

      8.  将生成的libLed_ctrl.so拷贝到eclipseLed应用程序中的libs/armeabi目录(如果没有armeabi目录需手动创建一个)

         

 

     9. 在应用程序布局文件中加入4个开关按钮,对应四个led开关,也可以再添加一个总开关来同时控制四个led.

        res/layout/activity_led.xml 

       

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context=".LedActivity" >    <ToggleButton                 android:id="@+id/btn1"                        android:layout_width="140dip"                        android:layout_height="wrap_content"                        android:textOn="led1 on"                        android:textOff="led1 off"                        android:layout_gravity="center_horizontal"                 />      <ToggleButton                 android:id="@+id/btn2"                        android:layout_width="140dip"                        android:layout_height="wrap_content"                        android:textOn="led2 on"                        android:textOff="led2 off"                        android:layout_gravity="center_horizontal"                 />      <ToggleButton                 android:id="@+id/btn3"                        android:layout_width="140dip"                        android:layout_height="wrap_content"                        android:textOn="led3 on"                        android:textOff="led3 off"                        android:layout_gravity="center_horizontal"                 />      <ToggleButton                 android:id="@+id/btn4"                        android:layout_width="140dip"                        android:layout_height="wrap_content"                        android:textOn="led4 on"                        android:textOff="led4 off"                        android:layout_gravity="center_horizontal"                 /> </LinearLayout>

 

      10.  编写java文件.

        src/LedActivity.java:

       

package com.example.led;import android.os.Bundle;import android.app.Activity;import android.util.Log;import android.view.Menu;import android.view.View;import android.widget.Button;import android.widget.ToggleButton;public class LedActivity extends Activity {private static final String TAG = "LED";      private ToggleButton button1;      private ToggleButton button2;      private ToggleButton button3;      private ToggleButton button4;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_led);button1 = (ToggleButton)findViewById(R.id.btn1);            button2 = (ToggleButton)findViewById(R.id.btn2);            button3 = (ToggleButton)findViewById(R.id.btn3);          button4 = (ToggleButton)findViewById(R.id.btn4);                         button1.setOnClickListener(new Button.OnClickListener()          {              public void onClick(View v)              {                  if (button1.isChecked())                       led_ioctl(0, 1);  //led1 on                else                      led_ioctl(0, 0);  //led1 off            }          });                    button2.setOnClickListener(new Button.OnClickListener()          {              public void onClick(View v)              {                  if (button2.isChecked())                       led_ioctl(1, 1);  //led2 on                else                      led_ioctl(1, 0);  //led2 off            }          });                 button3.setOnClickListener(new Button.OnClickListener()          {              public void onClick(View v)              {                  if (button3.isChecked())                       led_ioctl(2, 1);  //led3 on                else                      led_ioctl(2, 0);  //led3 off            }          });               button4.setOnClickListener(new Button.OnClickListener()          {              public void onClick(View v)              {                  if (button4.isChecked())                       led_ioctl(3, 1);  //led4 on                else                      led_ioctl(3, 0);  //led4 off             }          }); }@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.led, menu);return true;}public static native int led_ioctl(int i, int j);static{System.loadLibrary("Led_ctrl");//    libs/armeabi/libLed_ctrl.so}}

 

          编译生成Led.apk,并安装到开发板上.

 

 

至此,整个工作已经完成,开发板上打开应用程序就可以控制led.但有几点需要注意

    1. 开发板上D5这个灯已经被占用了,所以led1不能控制D5.

    2. 记住运行应用程序前确保内核中led.ko已被加载,并修改 /dev/leds的权限,否则led灯不受控制.

 

    整个代码已打包上传到我的博客:

     http://download.csdn.net/detail/colwer/5403281

     本人新手,欢迎大家帮忙指正错误和提供建议.

     下一步计划做一个远程控制的.就是局域网内通过另一个android设备来操控开发板.