又是点灯,没有错,学硬件,什么时候都是从点灯开始的,对不,而且还是用Android应用程序点灯。

要用Android控制自定义的硬件,如何实现呢?用JNI即可。

1、准备工作

好了,先做些准备工作。准备工作无非就是搭建下环境,下载些东西。请看些链接。点我点我!


2、led驱动

照理说,点灯的程序,我不应该贴出来的,但是,考虑到有同学做Android没学过驱动,我就贴出来,仅供参考哈:

#include <linux/kernel.h>#include <linux/module.h>#include <linux/miscdevice.h>#include <linux/fs.h>#include <linux/types.h>#include <linux/moduleparam.h>#include <linux/slab.h>#include <linux/ioctl.h>#include <linux/cdev.h>#include <linux/delay.h>#include <mach/gpio.h>#include <mach/regs-gpio.h>#include <plat/gpio-cfg.h>#define DEVICE_NAME "leds"static int led_gpios[] = {S5PV210_GPJ2(0),S5PV210_GPJ2(1),S5PV210_GPJ2(2),S5PV210_GPJ2(3),};#define LED_NUMARRAY_SIZE(led_gpios)static long gec210_leds_ioctl(struct file *filp, unsigned int cmd,unsigned long arg){switch(cmd) {case 0:case 1:if (arg > LED_NUM) {return -EINVAL;}gpio_set_value(led_gpios[arg], !cmd);//printk(DEVICE_NAME": %d %d\n", arg, cmd);break;default:return -EINVAL;}return 0;}static struct file_operations gec210_led_dev_fops = {.owner= THIS_MODULE,.unlocked_ioctl= gec210_leds_ioctl,};static struct miscdevice gec210_led_dev = {.minor= MISC_DYNAMIC_MINOR,.name= DEVICE_NAME,.fops= &gec210_led_dev_fops,};static int __init gec210_led_dev_init(void) {int ret;int i;for (i = 0; i < LED_NUM; i++) {ret = gpio_request(led_gpios[i], "LED");if (ret) {printk("%s: request GPIO %d for LED failed, ret = %d\n", DEVICE_NAME,led_gpios[i], ret);return ret;}s3c_gpio_cfgpin(led_gpios[i], S3C_GPIO_OUTPUT);gpio_set_value(led_gpios[i], 1);}ret = misc_register(&gec210_led_dev);printk(DEVICE_NAME"\tinitialized\n");return ret;}static void __exit gec210_led_dev_exit(void) {int i;for (i = 0; i < LED_NUM; i++) {gpio_free(led_gpios[i]);}misc_deregister(&gec210_led_dev);}module_init(gec210_led_dev_init);module_exit(gec210_led_dev_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("GEC Inc.");

Makefile也附出来了:

ifneq ($(KERNELRELEASE),)obj-m :=led_drv.oelsemodule-objs :=led_drv.oKERNELDIR :=/home/gec/linux_kernel/linux-2.6.35.7/PWD :=$(shell pwd)default:$(MAKE) -C $(KERNELDIR) M=$(PWD) modulesendifclean:$(RM)  *.ko *.mod.c *.mod.o *.o *.order *.symvers *.cmd

那个linux-2.6.35.7是指GEC210板上Android系统的Linux内核版本,而且在PC机的Linux下也要有这个内核的源码,路径按Makefile里面放,也可以改Makefile需要的同学可以自行下载哈。

好了。执行make,之后,就能得到一个.ko结尾的文件,把这个.ko文件放进GEC210板的文件系统里,怎么放进去?SD卡也可以,网线nfs也可以,串口线也可以。这里不详说。


3、编写Android应用程序

不多说,看代码吧,都是最基本的。2.2版

LedDemoTestActivity.java

package com.gec.leddemotest.activity;import android.app.Activity;import android.os.Bundle;import android.widget.RadioGroup;import android.widget.RadioGroup.OnCheckedChangeListener;import android.widget.Toast;public class LedDemoTestActivity extends Activity {private RadioGroup radioGroupLed01;private RadioGroup radioGroupLed02;private RadioGroup radioGroupLed03;private RadioGroup radioGroupLed04;static{System.loadLibrary("leddemotest");}    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        openRunLed();        radioGroupLed01=(RadioGroup)findViewById(R.id.radioGroupLed01);                radioGroupLed01.setOnCheckedChangeListener(new OnCheckedChangeListener() {public void onCheckedChanged(RadioGroup group, int checkedId) {// TODO Auto-generated method stubif(checkedId==R.id.chooseLed01_1){    startRunLed(0,1);Toast.makeText(LedDemoTestActivity.this, R.string.led1_on, Toast.LENGTH_LONG).show();}else if(checkedId==R.id.chooseLed01_2){    startRunLed(0,0);Toast.makeText(LedDemoTestActivity.this, R.string.led1_off, Toast.LENGTH_LONG).show();}}});                        radioGroupLed02=(RadioGroup)findViewById(R.id.radioGroupLed02);                radioGroupLed02.setOnCheckedChangeListener(new OnCheckedChangeListener() {public void onCheckedChanged(RadioGroup group, int checkedId) {// TODO Auto-generated method stubif(checkedId==R.id.chooseLed02_1){    startRunLed(1,1);Toast.makeText(LedDemoTestActivity.this, R.string.led2_on, Toast.LENGTH_LONG).show();}else if(checkedId==R.id.chooseLed02_2){    startRunLed(1,0);Toast.makeText(LedDemoTestActivity.this, R.string.led2_off, Toast.LENGTH_LONG).show();}}});                        radioGroupLed03=(RadioGroup)findViewById(R.id.radioGroupLed03);                radioGroupLed03.setOnCheckedChangeListener(new OnCheckedChangeListener() {public void onCheckedChanged(RadioGroup group, int checkedId) {// TODO Auto-generated method stubif(checkedId==R.id.chooseLed03_1){    startRunLed(2,1);Toast.makeText(LedDemoTestActivity.this, R.string.led3_on, Toast.LENGTH_LONG).show();}else if(checkedId==R.id.chooseLed03_2){    startRunLed(2,0);Toast.makeText(LedDemoTestActivity.this, R.string.led3_off, Toast.LENGTH_LONG).show();}}});                        radioGroupLed04=(RadioGroup)findViewById(R.id.radioGroupLed04);                radioGroupLed04.setOnCheckedChangeListener(new OnCheckedChangeListener() {public void onCheckedChanged(RadioGroup group, int checkedId) {// TODO Auto-generated method stubif(checkedId==R.id.chooseLed04_1){    startRunLed(3,1);Toast.makeText(LedDemoTestActivity.this, R.string.led4_on, Toast.LENGTH_LONG).show();}else if(checkedId==R.id.chooseLed04_2){    startRunLed(3,0);Toast.makeText(LedDemoTestActivity.this, R.string.led4_off, Toast.LENGTH_LONG).show();}}});            }    protected void onDestroy() {closeRunLed();    }    public native void startRunLed(int whichLed,int on);    public native void openRunLed();    public native void closeRunLed();    }

要在工程目录下创建jni文件,把下面的文件放进去。

appleds.c

#include <android/log.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/ioctl.h>#include <jni.h>#define  LED_ON  1#define  LED_OFF 0int fd;JNIEXPORT void JNICALL Java_com_gec_leddemotest_activity_LedDemoTestActivity_openRunLed(JNIEnv *env, jobject this,jint whichLed,jint on){  fd = open("/dev/leds", 0);}JNIEXPORT void JNICALL Java_com_gec_leddemotest_activity_LedDemoTestActivity_startRunLed(JNIEnv *env, jobject this,jint whichLed,jint on){if (fd < 0) {perror("open device leds");exit(1);}ioctl(fd, on,whichLed);}JNIEXPORT void JNICALL Java_com_gec_leddemotest_activity_LedDemoTestActivity_closeRunLed(JNIEnv *env, jobject this,jint whichLed,jint on){  close(fd);}

上面的JNIEXPORT是必须的,void是返回类型,JNICALL也是必须的,后面的Java也是必须的,Java后面跟的就是com.gec.leddemotest.activity包下的LedDemoTestActivity下调用的函数名,把.改为_就可以了。大概是这意思。在JNI的.c文件中,所以要调用的函数的参数最少是两个,一个是JNIEnv *env,一个是jobject this.具体有什么用,大伙们自己上网查一下JNI即可。另外,像int这样的参数,在JNI里要写成jint,虽然int跟jint其实是一样的,但是JNI格式还是选择jint比较适合,也就是在JNI的.c中,用到的所有数据类型都可以在上面加个j。当然头文件要包jni.h才行。


4、编写Android.mk

Android.mk是编译.so文件的重要部分,分别有两个。

下面是JNI文件夹下的Android.mk

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := libleddemotest                                          aLOCAL_SRC_FILES :=appleds.c                                             bLOCAL_C_INCLUDES += \                                                   c$(JNI_H_INCLUDE)LOCAL_PRELINK_MODULE := falseinclude $(BUILD_SHARED_LIBRARY)                                         d

a:生成C 动态库名称libleddemotest(JAVA层就是通过加载此库名称来实现互调)

b:编译C文件

c:加载jni库头文件

d:生成libleddemotest动态库


下面是工程目录下的Android.mk

LOCAL_PATH:= $(call my-dir)                                               ainclude $(CLEAR_VARS)                                                     bLOCAL_SRC_FILES := $(call all-subdir-java-files)                          cLOCAL_PACKAGE_NAME := LedDemoTest                                         dLOCAL_JNI_SHARED_LIBRARIES := libleddemotest                              einclude $(BUILD_PACKAGE)                                                  finclude $(LOCAL_PATH)/jni/Android.mk                                      g# Use the folloing include to make our test apk.include $(call all-makefiles-under,$(LOCAL_PATH))                         h

a:一个Android.mk文件首先必须定义好LOCAL_PATH,获得当前目录

b:用来初始化Android.mk文件中”LOCAL_XXX”的变量

c:编译Java文件

d:生成Android应用apk文件名称

e:生成Android应用apk文件名称

f:生成Android应用

g:编译jni目录里面的Android.mk文件

h:编译此工程里面所有的Android.mk文件



5、执行ndk-build

在cygwin中执行,用linux命令,进入工程目录,执行ndk-build.


6、将leds设备文件设置权限

用串口线,连接GEC210板,执行insmod XXXX.ko文件,将设备文件装进内核,然后在/dev下会有一个leds的设备文件,

用chmod 777 leds,将leds的设备权限加大,好了。可以将应用程序运行在GEC210板上了。享受吧。


过会会把源代码附上。


更多相关文章

  1. 使用Android内置的Pull解析器解析XML文件
  2. android moudle 资源文件重命名
  3. CrossWalk - android 动态加载so库文件实践
  4. Android中使用pull解析器操作xml文件的解决办法
  5. rdp文件和vnc软件
  6. 简单的使用腾讯X5内核浏览器替代Android原生的WebView
  7. Android so 文件进阶 从dlsym()源码看android 动态链接过程
  8. Android使用JNI生成.so文件并调用(使用传统生成.h的方法)

随机推荐

  1. Android GLES多线程处理
  2. 基于android和arduino 的小车控制
  3. OnClick与android:focusableInTouchMode=
  4. 应届毕业生Android面试经验小谈
  5. 控制UI界面的方法
  6. 个人对http请求的理解
  7. Android视频播放框架Vitamio
  8. Android SeekBar的使用,进度条的另一种实
  9. Android 使用LayerDrawable自定制SeekBar
  10. Android上的Native以及JNI开发(1)