Android 驱动编写LED-NDK程序

针对"Android 驱动编写LED-NDK程序",下面是详细的攻略过程:

1. 准备工作

开发过程中需要的一些准备工作:

(1)Android驱动编写LED开发板

正常情况下,开发板上都会有LED指示灯,我们可以通过控制这些指示灯达到验证驱动是否正常执行的效果。

(2)NDK

NDK 是一个让你用 C 或 C++ 来构建 Android 应用的工具集。通常情况下,NDK会集成在Android Studio中,我们不需要进行相应的下载安装。如果不存在,使用Android Studio自带的SDK Manager,安装NDK对应版本即可。

2. 搭建开发环境

(1)创建Android工程文件

首先,在Android Studio中创建一个新的 Native Activity 工程,选择 C++。如果不知道如何创建,可以参考 Android 官方文档:创建 Android 项目

(2)建立jni目录

\"jni\"目录是一个特殊的目录,用于存放我们编写的 C/C++ 源代码,将其放至位于\"app/src/main/"\"下。

(3)编写led.c驱动程序文件

此处我们提供两个示例:c_led_dev 和 c_gpio_led_dev,用于验证LED是否开启。

// c_led_dev.c示例

#include <linux/fs.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/delay.h>

#include <asm/gpio.h>
#include <asm/uaccess.h>

MODULE_AUTHOR("luojing3");
MODULE_LICENSE("GPL");

#define LED_DEV_NAME "c_led_dev"

static int c_gpio_led_open(struct inode *inode, struct file *file) {
    printk("c_gpio_led_dev c_gpio_led_open!\n");
    return 0;
}

static ssize_t c_gpio_led_read(struct file *file,
    char __user *buf, size_t len, loff_t *pos) {
    printk("c_gpio_led_dev c_gpio_led_read!\n");
    return 0;
}

static ssize_t c_gpio_led_write(struct file *file,
    const char __user *buf, size_t len, loff_t *pos) {

    int res;
    char kbuf[6] = {0};

    memset(kbuf, 0, sizeof(kbuf));

    res = copy_from_user(kbuf, buf, len);
    if (res) {
        printk("%s: copy_from_user failed!\n", LED_DEV_NAME);
        return -EFAULT;
    }

    if (strcmp(kbuf, "on") == 0) {
        printk("%s: led on!\n", LED_DEV_NAME);
        gpio_direction_output(12, 1);
    } else if (strcmp(kbuf, "off") == 0) {
        printk("%s: led off!\n", LED_DEV_NAME);
        gpio_direction_output(12, 0);
    } else {
        printk("%s: Unknown Command!\n", LED_DEV_NAME);
        return -EINVAL;
    }

    return len;
}

static int c_gpio_led_release(struct inode *inode, struct file *file) {
    printk("%s: c_gpio_led_release!\n", LED_DEV_NAME);
    return 0;
}

static struct file_operations c_gpio_led_ops = {
    .owner = THIS_MODULE,
    .open = c_gpio_led_open,
    .read = c_gpio_led_read,
    .write = c_gpio_led_write,
    .release = c_gpio_led_release,
};

static void c_register_led_dev(int led_port) {
    gpio_request(led_port, "led");
    gpio_direction_output(led_port, 0);
    gpio_export(led_port, false);
}

static int c_gpio_led_init(void) {
    dev_t devno;
    int res;
    struct device *dev;

    devno = MKDEV(0, 0);

    if (register_chrdev_region(devno, 1, LED_DEV_NAME) < 0) {
        printk("Failed to register_chdev_region!\n");
        return -1;
    }

    c_register_led_dev(12);

    c_gpio_led_dev_major = MAJOR(devno);

    c_led_dev = cdev_alloc();
    c_led_dev->ops = &c_gpio_led_ops;
    c_led_dev->owner = THIS_MODULE;

    res = cdev_add(c_led_dev, devno, 1);
    if (res) {
        printk("Failed to add c_gpio_led_device!\n");
        goto fail_1;
    }

    c_gpio_led_class = class_create(THIS_MODULE, LED_DEV_NAME);
    if (IS_ERR(c_gpio_led_class)) {
        printk("Failed to create class_c_gpio_led_device!\n");
        goto fail_2;
    }

    dev = device_create(c_gpio_led_class, NULL, devno, NULL, LED_DEV_NAME);
    if (IS_ERR(dev)) {
        printk(KERN_ALERT "Failed to create device!\n");
        goto fail_3;
    }

    return 0;

fail_3:
    class_destroy(c_gpio_led_class);
fail_2:
    cdev_del(c_led_dev);
fail_1:
    unregister_chrdev_region(devno, 1);
    return -1;
}

static void c_gpio_led_exit(void) {
    dev_t devno = MKDEV(c_gpio_led_dev_major, 0);

    device_destroy(c_gpio_led_class, devno);
    class_destroy(c_gpio_led_class);
    cdev_del(c_led_dev);
    unregister_chrdev_region(devno, 1);

    gpio_set_value(12, 0);
    gpio_unexport(12);
    gpio_free(12);
}

module_init(c_gpio_led_init);
module_exit(c_gpio_led_exit);
// c_gpio_led_dev.c示例

#include "jni.h"
#include <stdio.h>

JNIEXPORT void JNICALL
Java_com_example_ledtest_MainActivity_nativeLedOn(JNIEnv *env, jobject instance) {

    FILE *fp;
    fp = fopen("/dev/c_led_dev", "w");

    if (fp < 0) {
        printf("open failed!\n");
        return ;
    }

    fprintf(fp, "%s", "on");
    fclose(fp);
}

JNIEXPORT void JNICALL
Java_com_example_ledtest_MainActivity_nativeLedOff(JNIEnv *env, jobject instance) {
    FILE *fp;
    fp = fopen("/dev/c_led_dev", "w");

    if (fp < 0) {
        printf("open failed!\n");
        return ;
    }

    fprintf(fp, "%s", "off");
    fclose(fp);
}

(4)修改Android.mk和Application.mk文件

在\"app/src/main/"\"下,我们需要修改\"Android.mk\"和\"Application.mk\"文件。

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := c_led_dev
LOCAL_SRC_FILES := jni/c_led_dev.c

include $(BUILD_SHARED_LIBRARY)

Application.mk

APP_ABI := all
APP_PLATFORM := android-21

(5)编译测试

执行\"make\"命令进行编译,执行\"ndk-build\"命令进行组合编译并生成相应的so文件和apk文件。

最后在Android设备中进行测试即可。示例中我们可以在MainActivity.java文件的相应按钮(如led on)进行检测,看看是否有输出。

以上为Android 驱动编写LED的完整攻略。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Android 驱动编写LED-NDK程序 - Python技术站

(0)
上一篇 2023年6月26日
下一篇 2023年6月26日

相关文章

  • [EasyUI美化换肤]更换EasyUi图标

    EasyUI是一款基于jQuery的UI框架,提供了丰富的UI组件和易于使用的API,可以帮助开发人员快速构建Web应用程序。本文将详细讲解如何更换EasyUI图标,包括使用自定义图标和使用FontAwesome图标库,并提供两个示例说明。 使用自定义图标 使用自定义图标可以让我们更好地控制EasyUI的外观,可以根据自己的需求来定制图标。下面是使用自定义图…

    other 2023年5月5日
    00
  • Spring Bean实例化实现过程解析

    关于“Spring Bean实例化实现过程解析”,以下是详细的攻略: 1. 概述 Spring框架是一种轻量级的框架,其核心是IoC容器和AOP框架,而Bean是Spring中最重要的概念之一,它是应用程序中的基本构建块。Bean的实例化、配置和管理都由Spring容器负责。在本篇文章中,我将详细讲解Spring Bean实例化的流程。 2. Spring …

    other 2023年6月26日
    00
  • python3 遍历删除特定后缀名文件的方法

    当需要遍历删除特定后缀名的文件时,可以使用Python的os模块和shutil模块来完成。下面是一个完整的攻略,包含了两个示例说明。 首先,导入所需的模块: import os import shutil 然后,定义一个函数来遍历删除特定后缀名的文件: def delete_files_with_extension(folder_path, extensio…

    other 2023年8月5日
    00
  • 解决lombok 父类和子类builder不兼容的问题

    当使用Lombok框架时,有时会遇到使用父类的Builder创建子类实例时出现兼容性问题的情况。这是因为父类和子类在使用Lombok注解生成的Builder时,使用的是不同的构造器和setter方法。 要解决这个问题,我们可以使用下面的步骤来解决: 1. 使用 @SuperBuilder 注解 在父类和子类中都添加 @SuperBuilder 注解,这个注解…

    other 2023年6月26日
    00
  • win10无法新建文件夹该怎么办?win10右键没有新建文件夹的解决办法

    首先,我们需要明确一下为什么会出现win10无法新建文件夹的问题。通常情况下,这可能是因为Windows对“新建文件夹”项进行了禁用或删除。下面是解决这个问题的两种常用方法: 方法一:使用注册表修复 使用 Win+R 快捷键打开“运行”对话框,然后输入“regedit”并按下 Enter。 在注册表编辑器中,转到以下路径:HKEY_CLASSES_ROOT\…

    other 2023年6月27日
    00
  • dnf刺客按键设置方法 dnf刺客技能键设置技巧

    DNF刺客按键设置方法和技巧 DNF(地下城与勇士)是一款非常受欢迎的网游,而刺客是其中非常流行的职业之一。本文将详细介绍如何设置刺客的按键,并提供一些技巧和示例说明。 设置方法 在设置刺客的按键前,我们需要了解一些基本知识。刺客的技能分为主动技能和被动技能。主动技能需要手动触发,而被动技能则会在特定条件下自动触发。鉴于此,我们需要将主动技能设置为易于按下的…

    other 2023年6月27日
    00
  • Spring IoC学习之ApplicationContext中refresh过程详解

    下面是关于“Spring IoC学习之ApplicationContext中refresh过程详解”的完整攻略。 前言 在使用Spring框架时,我们经常会用到ApplicationContext容器,并在容器初始化时调用refresh()方法来启动容器。那么这个过程中都做了些什么呢?本文将详细解析ApplicationContext容器的refresh()…

    other 2023年6月26日
    00
  • chatgpt 1020 错误码成功解决的三种方案(推荐)

    chatgpt 1020 错误码成功解决的三种方案(推荐) 问题背景 在使用 chatgpt 进行文本生成时,有时会遇到 “chatgpt 1020” 的错误码,该错误码表示调用 chatgpt API 出现了错误,导致无法正常生成文本。 解决方案 方案一: 升级 chatgpt API 版本 尝试升级 chatgpt API 版本,通常可以解决该问题。在 …

    other 2023年6月26日
    00
合作推广
合作推广
分享本页
返回顶部