【Qzone】把喜欢的事做到极致 Kernel->JNI->Application

本文介绍如何在Android应用中通过JNI调用C语言函数控制PWM。包括编写Android应用界面、JNI C语言文件、Android.mk配置文件等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


2015-4-1 22:49 

ANDROID 应用控制 PWM

从硬件到软件
从C语言到JAVA语言

中间没有涉及HAL和Framework

GEC210 S5PV210
20150401  为什么骗我?  

图片 

1st
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Kernel
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

/*

 * linux/drivers/char/gec210_pwm.c

 * This program is free software; you can redistribute it and/or modify

 * it under the terms of the GNU General Public License version 2 as

 * published by the Free Software Foundation.

 */

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/init.h>

#include <linux/platform_device.h>

#include <linux/fb.h>

#include <linux/backlight.h>

#include <linux/err.h>

#include <linux/pwm.h>

#include <linux/slab.h>

#include <linux/miscdevice.h>

#include <linux/delay.h>

#include <mach/gpio.h>

#include <mach/regs-gpio.h>

#include <plat/gpio-cfg.h>


#define DEVICE_NAME    "pwm"

#define PWM_IOCTL_SET_FREQ    1

#define PWM_IOCTL_STOP    0

#define NS_IN_1HZ    (1000000000UL)

#define BUZZER_PWM_ID    0

#define BUZZER_PMW_GPIO    S5PV210_GPD0(0)


static struct pwm_device *pwm4buzzer;

static struct semaphore lock;
 

static void pwm_set_freq(unsigned long freq) {

    int period_ns = NS_IN_1HZ / freq;

    pwm_config(pwm4buzzer, period_ns / 2, period_ns);

    pwm_enable(pwm4buzzer);

}


static void pwm_stop(void) {

    pwm_config(pwm4buzzer, 0, NS_IN_1HZ / 100);

    pwm_disable(pwm4buzzer);

}

static int gec210_pwm_open(struct inode *inode, struct file *file) {

    if (!down_trylock(&lock))

        return 0;

    else

        return -EBUSY;

}

static int gec210_pwm_close(struct inode *inode, struct file *file) {

    up(&lock);

    return 0;

}

static long gec210_pwm_ioctl(struct file *filep, unsigned int cmd,

unsigned long arg)

{

    switch (cmd) {

        case PWM_IOCTL_SET_FREQ:

            if (arg == 0)

                return -EINVAL;

            pwm_set_freq(arg);

        break;

        case PWM_IOCTL_STOP:

        default:

        pwm_stop();

        break;

}

return 0;

}

static struct file_operations gec210_pwm_ops = {

    .owner    = THIS_MODULE,

    .open = gec210_pwm_open,

    .release= gec210_pwm_close, 

    .unlocked_ioctl= gec210_pwm_ioctl,

};

static struct miscdevice gec210_misc_dev = {

    .minor = MISC_DYNAMIC_MINOR,

    .name = DEVICE_NAME,

    .fops = &gec210_pwm_ops,

};

static int __init gec210_pwm_dev_init(void) {

    int ret;

    ret = gpio_request(BUZZER_PMW_GPIO, DEVICE_NAME);

    if (ret) {

        printk("request GPIO %d for pwm failed\n", BUZZER_PMW_GPIO);

        return ret;

    }

    gpio_set_value(BUZZER_PMW_GPIO, 0);

    s3c_gpio_cfgpin(BUZZER_PMW_GPIO, S3C_GPIO_OUTPUT);

    gpio_set_value(BUZZER_PMW_GPIO, 0);

    pwm4buzzer = pwm_request(BUZZER_PWM_ID, DEVICE_NAME)

    if (IS_ERR(pwm4buzzer)) {

    printk("request pwm %d for %s failed\n", BUZZER_PWM_ID, DEVICE_NAME);

    return -ENODEV;

    }

    pwm_stop();

    gpio_set_value(BUZZER_PMW_GPIO, 0);

    s3c_gpio_cfgpin(BUZZER_PMW_GPIO, S3C_GPIO_SFN(2));

    gpio_free(BUZZER_PMW_GPIO);

    gpio_set_value(BUZZER_PMW_GPIO, 0);

    init_MUTEX(&lock);

    ret = misc_register(&gec210_misc_dev);

    printk(DEVICE_NAME "\tinitialized\n");

    return ret;

}

static void __exit gec210_pwm_dev_exit(void) {

    pwm_stop();

    misc_deregister(&gec210_misc_dev);

}

module_init(gec210_pwm_dev_init);

module_exit(gec210_pwm_dev_exit);
 

MODULE_LICENSE("GPL");

MODULE_AUTHOR("GEC");【资料来自班主任周老师的光盘】

MODULE_DESCRIPTION("S5PV210 PWM Driver");


------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/Kernel
------------------------------------------------------------------------------------------------------------------------------------------------------------------------

2nd

------------------------------------------------------------------------------------------------------------------------------------------------------------------------
JNI
------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 

#include <jni.h>
 

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <utils/Log.h>


#define LOG_NDEBUG 0

#define LOG_TAG "pwm"


int fd=-1;


/ *

*此方法为上述Java文件openPwmDev方法的实现体

*native方法代表此方法实现体在C组件动态库完成

*/


JNIEXPORT void JNICALL Java_com_gec_pwmjnitest_activity_PwmJniTestActivity_openPwmDev(JNIEnv * env, jobject object)

{

    LOGE("Java_com_gec_pwmjnitest_activity_PwmJniTestActivity_openPwmDev\n");

    //打开PWM设备节点

    fd=open("/dev/pwm",O_RDWR);

}


/*

*freq变量就是从Java层传入的频率

*通过ioctl调用驱动控制pwm频率

*/

JNIEXPORT void JNICALL Java_com_gec_pwmjnitest_activity_PwmJniTestActivity_opPwm(JNIEnv * env, jobject object,jint op,jlong freq)

{

    LOGE("Java_com_gec_pwmjnitest_activity_PwmJniTestActivity_opPwm\n");

    ioctl(fd, op , freq );

}


JNIEXPORT void JNICALL Java_com_gec_pwmjnitest_activity_PwmJniTestActivity_closePwmDev(JNIEnv * env, jobject object)

{

    LOGE("Java_com_gec_pwmjnitest_activity_PwmJniTestActivity_closePwmDev\n");

    //关闭PWM设备节点

    close(fd);


------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/JNI
------------------------------------------------------------------------------------------------------------------------------------------------------------------------

3rd

------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Application
------------------------------------------------------------------------------------------------------------------------------------------------------------------------

package com.gec.pwmjnitest.activity;


import android.app.Activity;

import android.os.Bundle;

import android.view.View;


import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.EditText;

public class PwmJniTestActivity extends Activity {


/** Called when the activity is first created. */

private EditText freId;

private Button btnStart,btnStop;


/ *

*静态加载C组件动态库(动态库名称是libpwmtest.so)

*注意动态库名称不是pwmtest.so,必须要在pwmtest前面加上lib

*/


static

{

System.loadLibrary("pwmtest");

}


@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);


openPwnDev();



       freId=(EditText)findViewById(R.id.freId);

       btnStart=(Button)findViewById(R.id.btn_start_id);

       btnStop=(Button)findViewById(R.id.btn_stop_id);




    btnStart.setOnClickListener(new OnClickListener() {

        public void onClick(View v) {

    // TODO Auto-generated method stub

    String sfreq=freId.getText().toString();

    //输入参数频率

    opPwm(1,Long.parseLong(sfreq));

    }

    });


    btnStop.setOnClickListener(new OnClickListener() {

    public void onClick(View v) {

    // TODO Auto-generated method stub

    String sfreq=freId.getText().toString();

    opPwm(0,Long.parseLong(sfreq));


    }

    });


   }


    @Override

    protected void onDestroy() {

    // TODO Auto-generated method stub

    super.onDestroy();

    closePwmDev();

    }


    /*

    *声明三个native方法

    *native方法代表此方法实现体在C组件动态库完成

    *op=1:代表启动蜂鸣器, op=0:代表停止蜂鸣, freq:输入蜂鸣器的频率

    */

    public native void openPwmDev();


    / *

    *op=1:代表启动蜂鸣器, op=0:代表停止蜂鸣, freq:输入蜂鸣器的频率

    */


    public native void opPwm(int op,long freq);

    public native void closePwmDev();

}

------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/Application
------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 



步骤:


开发 Android 应用程序输入频率,控制蜂鸣器


掌握编写 Android 应用程序及通过 JNI 调用 C 函数控制 PWN
 

通过 Eclipse 开发 Android 应用程序界面
 

编写 JNI 程序的 C 语言文件
 

编写 Android.mk 文件


编译 Android 程序


本程序原理Android应用层界面开发由JAVA语言实现, 然后静态加载C语言组件动


态库, C语言组件动态库必须以JNI框架标准(Java Native Interface (JNI)标准是java


平台的一部分,它允许Java代码和其他语言写的代码进行交互。 JNI 是本地编程


接口,它使得在 Java 虚拟机 (VM) 内部运行的 Java 代码能够与用其它编程语


言(如 C、 C++ 和汇编语言)编写的应用程序和库进行交互操作。),然后在C语言


组件动态库调用PWM驱动程序。



编写 PWMJNITESTACTIVITY.JAVA 源程序代码
 

工程目录新建 JNI 目录,编写 C 组件动态库 APPPWM.C 文件


根据 JNI1.0 调用规则
 

C 语言: appPwm.c 文件里面的
 

openPwmDev ------->Java_com_gec_pwmjnitest_activity_PwmJniTestActivity_openPwmDev


opPwn ------->Java_com_gec_pwmjnitest_activity_PwmJniTestActivity_opPwm


closePwnDev ------> Java_com_gec_pwmjnitest_activity_PwmJniTestActivity_closePwmDev


左边是在 JAVA 类声明的 native 成员方法,右边是 C 语言函数对应成员方法实现体
 

编写生成 JNI 动态库的配置文件 ANDROID.MK


LOCAL_PATH := $(call my-dir)


include $(CLEAR_VARS)


LOCAL_MODULE:=libpwmtest                     a


LOCAL_SRC_FILES:=appPwm.c                  b


LOCAL_C_INCLUDES+= \                             c


$(JNI_H_INCLUDE)


LOCAL_PRELINK_MODULE := false


LOCAL_MODULE_TAGS:= debug


include $(BUILD_SHARED_LIBRARY)          d


其中abcd为注释,下同 


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


b:编译C文件


c:加载jni库头文件


d:生成libpwmtest动态库,要跟Java静态加载的库名一致

 

编写应用工程 ANDROID.MK 文件


LOCAL_PATH:= $(call my-dir)                                                  a


include $(CLEAR_VARS)                                                          b


LOCAL_SRC_FILES := $(call all-subdir-java-files)                   c


LOCAL_PACKAGE_NAME:= PwmJniTest                                d


LOCAL_JNI_SHARED_LIBRARIES:= libpwmtest                      e


include $(BUILD_PACKAGE)                                                     f


include $(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:生成JNI动态库libpwmtest


f:生成Android应用


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


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

 

PWM 应用编译


将应用工程源代码(PwmJniTest)放到 Android-2.3.1\vendor\samsung\gec210\目录中, 先


对整个 Android-2.3.1 系统进行一次完整的编译。编译后按如下流程编译应用程序:


在 Android 源码目录下输入命令


#source build/envsetup.sh (生成的使用环境及环境中的命令)


#lunch 4(选择 full_gec210-eng 开发板)【full_gec210-eng 不知道这个是怎么来的】


#mmm vendor/samsung/gec210/ PwnJniTest(编译当前应用程序)


成功编译后会在 out/target/product/gec210/system/app/目录下生成对应的 
 

PwmJniTest.apk 文件 【虽这个不曾尝试 但亲测编译过模拟器Goldfish版的 确实如此】


仅仅理论 木有实践


THE  END  
 

114

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值