1. 程式人生 > >Android驅動入門-Led控制+app+ndk庫+底層驅動

Android驅動入門-Led控制+app+ndk庫+底層驅動



硬體平臺: FriendlyARM Tiny4412 Cortex-A9

作業系統: UBUNTU 14.04 LTS

本次實驗使用的是 安卓APP + NDK庫 + Linux底層驅動。

一、 首先在 Android Studio 上編寫APP。

對軟體進行佈局。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    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="com.example.zws.test_led.MainActivity">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="horizontal">
            <CheckBox
                android:id="@+id/checkbox_cmd_led1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Led1"/>  <!--id在判斷複選框狀態時使用-->

            <CheckBox
                android:id="@+id/checkbox_cmd_led2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Led2"/>

            <CheckBox
                android:id="@+id/checkbox_cmd_led3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Led3"/>

            <CheckBox
                android:id="@+id/checkbox_cmd_led4"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Led4"/>
        </LinearLayout>
        <Button
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="傳送命令"
            android:onClick="on_click_cmd"/>    <!--按鈕響應函式名稱-->
    </LinearLayout>

</RelativeLayout>

其中, android:id="@+id/checkbox_cmd_led1"在程式中識別複選框的狀態時使用。

     android:onClick="on_click_cmd"   on_click_cmd為在按下按鈕時,呼叫的函式名稱。

編寫app程式。

package com.example.zws.test_led;

import android.app.Activity;        //可更改
import android.os.Bundle;
import android.view.View;
import android.widget.CheckBox;

import java.util.zip.CheckedInputStream;


public class MainActivity extends Activity {    //需和import android.app.Activity;一致

    private CheckBox[] cbCmdLeds  = new CheckBox[4];    //建立按鈕陣列
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        cbCmdLeds[0] = (CheckBox)findViewById(R.id.checkbox_cmd_led1);  //需要強制轉化
        cbCmdLeds[1] = (CheckBox)findViewById(R.id.checkbox_cmd_led2);
        cbCmdLeds[2] = (CheckBox)findViewById(R.id.checkbox_cmd_led3);
        cbCmdLeds[3] = (CheckBox)findViewById(R.id.checkbox_cmd_led4);
    }

    public void on_click_cmd( View view )
    {
        for( int i=0; i<4; i++ )
        {
            if( cbCmdLeds[i].isChecked() )   //如複選框被選中
                CmdLeds( 1,i ); //此函式在下面有宣告。
            else
                CmdLeds( 0,i );
        }
    }

    public native void CmdLeds( int cmd, int arg ); //需要呼叫的外部函式可自己設定

    static
    {
        System.loadLibrary("ndk_test_myled");       //外部庫的名稱,可自己設定
    }
}

編寫完成後需要在工程的app/src/main目錄下建立目錄jniLibs.這裡將放ndk生成的庫檔案。

然後在Build->make project.

二、編寫底層驅動。

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/cdev.h>


MODULE_LICENSE("GPL");

#define GPM4CON 0X110002E0    //io口控制暫存器硬體地址
#define GPM4DAT 0X110002E4    //io口資料暫存器硬體地址

#define LED_ON _IOW('G',0,int)  //開啟命令

#define LED_OFF _IOW('G',1,int) //關閉命令

static struct cdev dev;//1.1 分配cdev結構

static dev_t dev_no;  //裝置號
struct class *led_class;

static unsigned int *led_con;
static unsigned int *led_dat;

long led_ioctl( struct file *file, unsigned int cmd, unsigned long arg )
{
    switch( cmd )
    {
        case LED_ON:
            writel((readl(led_dat)&(~(0x1<<(arg-1)))),led_dat);
            break;

        case LED_OFF:
            writel( (readl(led_dat)|(0x1<<(arg-1))),led_dat);
            break;

        default: 
            return -EINVAL;        
            break;
    }
    return 0;
}

struct file_operations led_fops = {
    .owner = THIS_MODULE,
    .unlocked_ioctl = led_ioctl,
};


static void hw_init()
{
    
    //初始化GPIO控制暫存器
    led_con = ioremap( GPM4CON, 4 );    //地址對映  將實際的硬體地址對映成可訪問的虛擬地址
    led_dat = ioremap( GPM4DAT, 4 );
    writel((readl(led_con)&~0xffff)|0x1111,led_con);    
    writel(readl(led_dat)|0xf,led_dat);    
    
}

static int led_init()
{
    
    //1.2 初始化cdev結構
    alloc_chrdev_region( &dev_no, 0, 1, "my_led" );
    cdev_init( &dev, &led_fops );    
    dev.owner = THIS_MODULE;
    //1.3 註冊cdev結構
    cdev_add( &dev, dev_no, 1 );
    //2.硬體初始化
    hw_init();
    //3.建立裝置檔案
    led_class = class_create(THIS_MODULE,"my_led");                //建立裝置類
    device_create( led_class, NULL, dev_no,NULL,"%s","my_led");  // 建立裝置檔案 my_led

    printk("init led device ok!\n");

    return 0;
}

void led_exit()
{
    device_destroy(led_class,dev_no);
    class_destroy(led_class);

    iounmap(led_con);
    iounmap(led_dat);

    cdev_del(&dev);
    unregister_chrdev_region(dev_no,1);
}

module_init( led_init );
module_exit( led_exit );

編寫Makefile。

obj-m := led.o
KDIR := /home/share/linux-3.0.86  //核心地址

all:
    make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm
clean:
    rm -f *.ko *.o

然後make即可。將生成led.ko檔案。

通過adb將檔案穿傳送到安卓裝置。這裡將ko檔案傳送到安卓裝置的/data/local目錄下。

adb push led.ko  /data/local/  

三、 NDK程式庫編寫。

首先生成之前app中寫的介面標頭檔案。

javah -d jni -classpath /opt/android-sdk-linux/platforms/android-23/android.jar:/home/my_Android/led\
/NDK/NDK_APP/app/build/intermediates/classes/debug/ com.android.jack.ndk.happy.MainActivity

其中/opt/android-sdk-linux/platforms/android-23/android.jar是安卓sdk中的地址。

/home/my_Android/led/NDK/NDK_APP/app/build/intermediates/classes/debug/ 是相應安卓app原始檔工程中的地址。

com.android.jack.ndk.happy.MainActivity為安卓的專案名稱。

執行命令後,會在目錄中生成jni資料夾。其中com_android_jack_ndk_happy_MainActivity.h為我們需要的標頭檔案

建立ndk_led.c檔案,編寫相應的介面。

#include "com_example_zws_test_led_MainActivity.h"  //生成的標頭檔案

#include <jni.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>

#define LED_ON _IOW('G',0,int)
#define LED_OFF _IOW('G',1,int)

JNIEXPORT void JNICALL Java_com_example_zws_test_1led_MainActivity_CmdLeds
  (JNIEnv *env, jobject this, jint cmd, jint arg)    //標頭檔案中的介面函式  此函式名稱為系統自動生成的  勿修改。
{
    int fd;
    int tmp_cmd;
    
    fd = open("/dev/my_led",O_WRONLY);        //此為在寫驅動程式時,生成的裝置檔名稱

    if( cmd == 1 )
        tmp_cmd = LED_ON;
    else if(cmd==0)
        tmp_cmd = LED_OFF;

    ioctl(fd,tmp_cmd,arg+1);
    close(fd);
}

建立編寫 Android.mk 檔案

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ndk_test_myled    //這個是庫的名稱 可自己設定
LOCAL_SRC_FILES := ndk_led.c    //之前寫的c檔名稱
include $(BUILD_SHARED_LIBRARY)

編寫完成後,回到本層目錄的上一層。

執行命令生成ndk庫。

ndk-build

即會生成 libs/armeabi/libndk_test_myled.so

將armeabi/libndk_test_myled.so複製到安卓app目錄下的 app/src/mian/jinLibs中。

重新編譯工程。

連線開發板的串列埠進入控制檯。

執行一下命令獲取root許可權並安裝核心模組。

$ su
$ insmod /data/local/led.ko
$ chmod 777 /dev/my_led

led.ko為在編寫NDK時,生成的KO模組名稱。

my_led為在裝置安裝後生成的裝置檔名稱,將其許可權改為任何人均可訪問。

在studio上點選run app ,讓app在tiny4412上執行即可。

相關推薦

Android驅動入門-Led控制+app+ndk+底層驅動

 硬體平臺: FriendlyARM Tiny4412 Cortex-A9 作業系統: UBUNTU 14.04 LTS 本次實驗使用的是 安卓APP + NDK庫 + Linux底層驅動。 一、 首先在 Android Studio 上編寫APP。 對軟體進行佈局。

linux 驅動入門程式,寫一個塊裝置驅動 (1)

+---------------------------------------------------+ |                 寫一個塊裝置驅動                  | +---------------------------------------------------+ |

Androidled控制(下)--Linux驅動部分--script與gpio(全志)

前面寫了三篇關於全志CQA83T下Android控制led的博文,但是還是有很多東西可以學習,可以寫寫作為學習記錄。如果看原始碼,繞不過script這個東西,這個不是像其他系統指令碼一樣,這裡的script應該是全志自己加上去的,不是原生系統的內容(暫時給感覺是這樣)。這一

Android Studio 一個完整的APP實例(附源碼和數據

first auto engine cos 快速 實例 art qlite 功能介紹 前言: 這是我獨立做的第一個APP,是一個記賬本APP。 This is the first APP, I‘ve ever done on my own. It‘s a accountbo

Android入門——基本控制元件詳解

Android應用開發的一項重要內容就是介面開發。對於使用者來說,不管APP包含的邏輯多麼複雜,功能多麼強大,如果沒有提供友好的圖形互動介面,將很難吸引終端使用者。作為一個程式設計師如何才能開發出友好的圖形介面呢。實際上Android提供了非常豐富UI(User Interface)控制元

Android 層疊卡片控制元件,仿"探探app"

StackLayout 簡介:Android 層疊卡片控制元件,防"探探 app" 1.支援自定義卡片的堆疊效果 2.支援自定義卡片移除動畫 3.支援載入更多 更多:作者   提 Bug    標籤: android-stack-card-swipe- 功能

Android 充電LED控制

1、前言 充電LED燈控制是Android裝置的基本功能,主要用於提示裝置的電池狀態,充電狀態,滿電狀態,低電狀態,很多手機廠商還使用呼吸效果來顯示,普通的低端裝置會使用兩個LED燈表示,紅燈表示充電和低電,綠燈表示滿電。   之前寫的文章 《Android充電系統介紹》

Android開發——Android Studio下使用Cmake在NDK環境下移植Dlib

環境要求 使用AS2015平臺,SDK Manager中已經安裝了Cmake(編譯工具),NDK(環境),LLDB(偵錯程式)。沒有裝的話,開啟SDK Manager選中安裝重啟AS就可以了。 AS專案結構: 我從不勾選C++ Support的專案開始

彙編入門---8255IO控制LED燈實驗

彙編繼續,獻上8255 IO控制LED燈實驗程式碼(1)8255 A口輸出控制流水燈,B口輸入,B口最低位控制流水燈流向;Made by X-Ray龍 ;8255流水燈顯示實驗 IOY0 EQU 3000H ;片選IOY0對應的埠始地

樹莓派linux驅動學習之LED控制

#include <linux/miscdevice.h> #include <linux/delay.h> #include <asm/irq.h> #include <linux/kernel.h> #include <linux/module.h&g

Android Architecture 1 -- Guide to App Architecture(App架構入門,示例程式碼演示)

面臨的問題 Android的各大元件可以隨意跳轉,可不遵守順序。比如QQ分享調相簿APP,相簿APP跳檔案管理APP。 還可能被系統殺死。所以最好 you should not store any app data or state in your app

android jni的編寫, 控制led

         jni, java native interface, java的本地介面,如果java程式碼想去呼叫native方法(實際就是c/c++函式),就需要用jni技術,在傳統的java中jni技術就已經存在,但是由於傳統的java程式碼中,不太去寫架構或者平

Androidled控制(中)--Linux部分

首先宣告一下我的實驗平臺,是全志CQA83T,成都啟劃資訊的板子。上面一篇部落格介紹了Android下led控制的Android部分。這一篇我想說說Linux下的部分,從上一篇我們可以知道,jni通過開啟led裝置/dev/led,進而使用ioctl函式來控制led的亮和滅

Android開發入門的正確姿勢,你get到了嗎?

開源 如何 com 正常 它的 接收 應用 切換 角度 在進行Android開發之前,我們先了解一下Android的生態圈現狀。Android系統是開源的,任何手機廠商和開發者都有權限去修改系統源代碼,定制專屬的系統。 這就產生了一個問題,不同手機廠商之間的ROM可能無法安

Android.mk添加本地程序和的經常使用模版

size 例如 center 配置文件 clear hello main 解釋 共享 Android.mk添加本地程序和庫的經常使用模版 Android中添加本地程序或者庫。這些程序和庫與其所在路徑沒有關系。僅僅與它們的配置文件Android.mk有關。Androi

Android 中如何從一個App啟動另外一個App(如啟動支付界面、啟動地圖界面、應用商場下載App等場景)

!= oid 等等 信息 fault next -a return 5.1   假定兩個App,分別是A和B,當A運行某個功能需要啟動B,一種是啟動B應用,一種直接進入B的某個Activity。搜了很多資料,沒有一個完整的。下面就A--Android5.1.1、B--And

Android 遠程連接數據。。。。。

鉤子 null utils list turn use tdi override sta 本來是 6.0.6 換成mysql 5.1.14 驅動ok。。。。 將方法 放在 new Thread() 解決。。。。。 只能在主線程繪制ui。。。。 解決辦法。。。子Thread

AM335x內核模塊驅動LED

author unlock obj magic oct gen sig dev pri 在Ubuntu的任意可操作的文件才建立text目錄 在text中建立zyr-hello.c: #include<linux/kernel.h> #include<li

Android新手入門2016(8)--ListView之ArrayAdapter

pos bject 了解 指定格式 pack extend line avi per 本文來自肥寶傳說之路,引用必須註明出處! ListView是Android中經常使用的控件。 什麽是列表視圖,讓我們先看看圖: 最常見的樣例就是各種菜單的下啦列表。 要實現列表,

Android】Eclipse自己主動編譯NDK/JNI的三種方法

comm tro mman gnu tex android項目 syn color ng- 【Android】Eclipse自己主動編譯NDK/JNI的三種方法 SkySeraph Sep. 18th 2014 Email:[email protec