1. 程式人生 > >Android驅動例子(LED燈控制)

Android驅動例子(LED燈控制)

文章來源:http://blog.csdn.net/ok138ok/article/details/6317212

本例子,講述在android2.1上完全自已開發一個驅動去控制硬體口並寫應用測試該驅動,通過這樣一個例子,解析Android下的驅動開發流程的應用呼叫流程,可以說是很好的入門引導

要達到的效果:通過android的應用,呼叫驅動程式,在開發板上控制4個LED的亮滅。

一、硬體原理

clip_image001

如上圖,通過4個IO口控制這LED,低電平LED亮,

這4個IO口分別是GPM1, GPM2, GPM3, GPM4,

二、驅動程式

1、在kernel資料夾下的driver目錄,新鍵驅動資料夾

# cd kernel_android_2.6.28.6/drivers

進到開發板的kernel目錄,建驅動資料夾

#mkdir ledtest

2、在/driver/ledtest目錄下,新建leddriver.c ,leddriver.h , Kconfig, Makefile 等4個檔案

leddriver.c

#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/init.h>            /* For __init/__exit/... */
#include <linux/module.h>
#include
<mach/hardware.h> #include <asm/io.h> #include <asm/uaccess.h> #include <plat/gpio-cfg.h> #include <plat/regs-clock.h> #include <plat/regs-lcd.h> #include <plat/regs-gpio.h> #include <mach/map.h> #include <linux/gpio.h> #include <plat/gpio-bank-m.h> #include
<linux/cdev.h> #include <linux/fs.h> //for register_chrdev() #include <linux/device.h> #include <mach/map.h> #include "leddriver.h" #include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV (WATCHDOG_MINOR) */ #include <linux/watchdog.h> /* For the watchdog specific items */ #include <linux/fs.h> /* For file operations */ #define Viberator_MAJOR 97 //主裝置號 #define SCULL_NR_DEVS 4 #define SCULL_QUANTUM 4000 #define SCULL_QSET 1000 //---do as the GIO driver #define DEVCOUNT 4 #define GIO_MINOR 2 /* GIO minor no. */ static dev_t dev; //申 請 到的主 裝置 號 static struct cdev *cdev_p; static int openCnt; //--全域性變數------------ int VIB_major = 97;//we asigment it for test int VIB_minor = 0; int VIB_nr_devs = SCULL_NR_DEVS; int VIB_quantum = SCULL_QUANTUM; int VIB_qset = SCULL_QSET; static struct class *vib_dev_class; #define GPNCON S3C64XX_GPNCON #define GPNDAT S3C64XX_GPNDAT #define GPNPUD S3C64XX_GPNPUD #define GPMCON S3C64XX_GPMCON #define GPMDAT S3C64XX_GPMDAT #define GPMPUD S3C64XX_GPMPUD #define VIB_ON 0x11 #define VIB_OFF 0x22 static const struct file_operations GPIO_Viberator_ctl_ops={ .owner = THIS_MODULE, .open = GPIO_VIB_open, .read =GPIO_VIB_read, .write =GPIO_VIB_write, .ioctl = GPIO_VIB_ioctl, .release =GPIO_VIB_release, }; ssize_t GPIO_VIB_read(struct file * file,char * buf,size_t count,loff_t * f_ops) { char sdas[5]={1,3,8,1,6}; ssize_t status = 5; unsigned long missing; missing = copy_to_user(buf, sdas, status); if (missing == status) status = -EFAULT; else status = status - missing; printk(" GPIO_VIB_read = %d ,count = %d/r/n",status,count); gpio_direction_output(S3C64XX_GPM(3), 0);// return status ; } ssize_t GPIO_VIB_write (struct file * file,const char * buf, size_t count,loff_t * f_ops) { unsigned long missing; char inbuffer[512]={0}; int i; missing = copy_from_user(inbuffer, buf, count); printk(" GPIO_VIB_write count = %d missing =%d /r/n",count,missing); gpio_direction_output(S3C64XX_GPM(3), 1);// for(i=0;i<count;i++) { printk("Write:inbuffer[%d]=%d /r/n",i,inbuffer[i]); } return count; } //ssize_t GPIO_VIB_ioctl(struct inode * inode,struct file * file,unsigned int cmd, long data) static int GPIO_VIB_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { printk(KERN_ERR"VIB:GPIO_VIB_ioctl --CMD=%x /n",cmd); switch(cmd) { case VIB_ON: gpio_direction_output(S3C64XX_GPM(1), 0);// gpio_direction_output(S3C64XX_GPM(2), 0);// gpio_direction_output(S3C64XX_GPM(3), 0);// gpio_direction_output(S3C64XX_GPM(4), 1);// printk(KERN_ERR"VIB:GPIO_VIB_ioctl --VIB_ON/n"); break; case VIB_OFF: { printk(KERN_ERR"VIB:GPIO_VIB_ioctl --VIB_OFF/n"); gpio_direction_output(S3C64XX_GPM(1), 1);// gpio_direction_output(S3C64XX_GPM(2), 1);// gpio_direction_output(S3C64XX_GPM(3), 1);// gpio_direction_output(S3C64XX_GPM(4), 0);// break; } default:break; } //gpio_free(S3C64XX_GPN(7)); } ssize_t GPIO_VIB_open(struct inode * inode,struct file * file) { //模組數 //MOD_INC_USE_COUNT; printk("GPIO_VIB_open() /n"); return 0; } ssize_t GPIO_VIB_release(struct inode * inode, struct file * file) { // MOD_DEC_USE_COUNT;//模組數減1 printk("GPIO_VIB_release() /n"); return 0; } static int GPIO_VIB_CTL_init(void) { int ret = -ENODEV; int error ; printk("---------------------------------------------- /r/n"); //初始化埠 s3c_gpio_cfgpin(S3C64XX_GPM(1), S3C_GPIO_SFN(1));//GPM1 output s3c_gpio_cfgpin(S3C64XX_GPM(2), S3C_GPIO_SFN(1));//GPM2 output s3c_gpio_cfgpin(S3C64XX_GPM(3), S3C_GPIO_SFN(1));//GPM3 output s3c_gpio_cfgpin(S3C64XX_GPM(4), S3C_GPIO_SFN(1));//GPM4 output #if 1 /*靜態方式註冊驅動*/ ret = register_chrdev(Viberator_MAJOR, "viberator", &GPIO_Viberator_ctl_ops); if (ret < 0) { printk(KERN_ERR "VIB: unable to get major %d/n", ret); return ret; } //建立class vib_dev_class = class_create(THIS_MODULE, "viberator"); if (IS_ERR(vib_dev_class)) { unregister_chrdev(Viberator_MAJOR, "capi20"); return PTR_ERR(vib_dev_class); } //建立節點, device_create(vib_dev_class, NULL, MKDEV(Viberator_MAJOR, 0), NULL, "vib"); // create a point under /dev/class/vib //通過上面這兩步,驅動載入後,就會在/dev/class/下面生成vib節點,應用程式可以像操作檔案那樣操作這個節點,通過open ,write,read 等函式操作,詳情可以看後面的應用示例程式。 return 0; #endif #if 0/* 註冊動態 */ if ((error = alloc_chrdev_region(&dev, 0, DEVCOUNT, "vibrate")) < 0) { printk(KERN_ERR "VIB: Couldn't alloc_chrdev_region, error=%d/n", error); return 1; } printk("dev = %d /n",dev); cdev_p = cdev_alloc(); cdev_p->ops = &GPIO_Viberator_ctl_ops; error = cdev_add(cdev_p, dev, DEVCOUNT); if (error) { printk(KERN_ERR "VIB: Couldn't cdev_add, error=%d/n", error); return 1; } vib_dev_class = class_create(THIS_MODULE, "vib-dev"); if (IS_ERR(vib_dev_class)) { res = PTR_ERR(vib_dev_class); goto out_unreg_class; } return 0; #endif out_unreg_class: class_destroy(vib_dev_class); return 1; } static int __init S3C6410_VIB_init(void) { int ret = -ENODEV; //呼叫函式 printk(KERN_ERR "Auly: S3C6410_VIB_init---/n"); ret = GPIO_VIB_CTL_init(); if(ret) { printk(KERN_ERR "Auly: S3C6410_VIB_init--Fail !!!/n"); return ret; } return 0; } static void __exit cleanup_GPIO_VIB(void) { //登出裝置 // devfs_unregister_chrdev(Viberator_MAJOR,"gpio_vib_ctl"); #if 0 cdev_del(cdev_p); unregister_chrdev_region(dev, DEVCOUNT); class_destroy(vib_dev_class); #endif device_destroy(vib_dev_class, MKDEV(Viberator_MAJOR, 0)); class_destroy(vib_dev_class); unregister_chrdev(Viberator_MAJOR, "viberator"); } MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Peter first driver"); MODULE_ALIAS_CHARDEV(Viberator_MAJOR, 0); module_init(S3C6410_VIB_init); module_exit(cleanup_GPIO_VIB);

leddriver.h檔案

leddriver.h檔案
  1. ssize_t GPIO_VIB_read(struct file * file,char * buf,size_t count,loff_t * f_ops);
  2. ssize_t GPIO_VIB_write (struct file * file,constchar * buf, size_t count,loff_t * f_ops);
  3. static int GPIO_VIB_ioctl(struct inode *inode,struct file *file,unsignedint cmd,unsignedlong arg);
  4. ssize_t GPIO_VIB_open(struct inode * inode,struct file * file);
  5. ssize_t GPIO_VIB_release(struct inode * inode,struct file * file);
  6. staticint GPIO_VIB_CTL_init(void);

Kconfig 檔案

Kconfig 檔案
  1. config LEDTEST
  2.   tristate "LED test for ARMeasy"
  3.   default n
  4.   help
  5.   this is a LED driver for ARMEASY with S3C6410

Makefile檔案

Makefile檔案
  1. obj-$(CONFIG_LEDTEST)+=leddriver.o

3、在核心配置裡選單里加入本驅動的配置項

達到的效果是,可以通過核心配置來選擇是否把本驅動編譯進核心裡,也就是出現在make menuconfig 後出來的介面裡,可以參考9.8章<android新增新驅動方法>

1)在arch/arm/Kconfig檔案裡 menu "Device Drivers"與 endmenu之間新增

  1. source "drivers/ledtest/Kconfig"

2)在drivers/Kconfig menu "Device Drivers" 和 endmenu之間新增

  1. source "drivers/ledtest/Kconfig"

3)修改/drivers/Makefile檔案

  1. Obj-$(CONFIG_LEDTEST) +=ledtest/

4、編譯驅動

在kernel目錄下,終端輸入

  1. #make menuconfig

“Device Drivers” 下面會看到 “LED test for ARMeasy”,選擇它,

儲存並退出

  1. #make

這樣,就會在/drivers/ledtest目錄下得到leddrivr.ko檔案,它就是驅動目標檔案,已級編譯進了zImage 裡了,只要用這個kernel燒錄到開發板,開機就會自動載入本驅動,

PS,如果發現如上編譯,沒有在ledtest目錄下生成leddriver.ko檔案,也就是本根沒有去編譯本驅動,那就把ledtest目錄入到/drivers/misc目錄下,相應的修改misc下面,然後,在makefile裡,不用選直接寫成obj-y += leddriver.o,這樣強制的包含進去編譯。

三、 應用程式(測試驅動)

C語言寫一個應用,測試上面寫的驅動是否工作正常,這是一般的驅動開發流程

主要有兩個檔案:Android.mk和ledtest.c

1、

在$(YOUR_ANDROID)/external/LEDTEST/目錄編寫ledtest.c檔案,

ledtest.c

ledtest.c
  1. #include <stdio.h>
  2. #include<stdlib.h>
  3. #include <fcntl.h>// contact the open(),close(),read(),write() and so on!
  4.   #define DEVICE_NAME"/dev/vib"//device point
  5. #define LED_ON     0x11
  6. #define LED_OFF     0x22
  7. int main(int argc,char **argv)
  8. {   
  9.     int fd;
  10.     int ret;
  11.     char *i;
  12.     printf("\n start gpio_led_driver test \r\n");
  13.     fd = open(DEVICE_NAME,O_RDWR);//Open device ,get the handle
  14.     printf("fd = %d \n",fd);
  15.     if(fd == -1) //open fail
  16.     {
  17.       printf("open device %s error \n",DEVICE_NAME);
  18.     }
  19.     else
  20.     {
  21.         while(1)
  22.         {
  23.           ioctl(fd,LED_OFF); //call the output function to off LEDs
  24.           sleep(1);//wait 1 second
  25.           ioctl(fd,LED_ON);
  26.           sleep(1);
  27.         }
  28.         ret = close(fd); //close device
  29.         printf("ret = %d \n",ret);
  30.         printf("close gpio_led test \n");
  31.     }
  32.   return 0;
  33. }

2、在$(YOUR_ANDROID)/external/ LEDTEST /目錄編寫Android.mk檔案。這是Android Makefile的標準命名,不要更改。Android.mk檔案的格式和內容可以參考其他已有的Android.mk檔案的寫法,針對helloworld程式的Android.mk檔案內容如下:

Android.mk
  1. LOCAL_PATH:= $(call my-dir)
  2. include $(CLEAR_VARS)
  3. LOCAL_SRC_FILES:= \/par     hello.c
  4. LOCAL_MODULE := ledtestapp
  5. include $(BUILD_EXECUTABLE)

注意上面LOCAL_SRC_FILES用來指定原始檔;

LOCAL_MODULE指定要編譯的模組的名字,下一步驟編譯時就要用到;

include $(BUILD_EXECUTABLE)表示要編譯成一個可執行檔案,如果想編譯成動態庫則可用BUILD_SHARED_LIBRARY,這些可以在

$(YOUR_ANDROID)/build/core/config.mk查到。

3、 回到Android原始碼頂層目錄進行編譯:

# cd $(YOUR_ANDROID) && make ledtestapp

例如我這裡的實際操作是

#cd android2.1
#make ledtestapp

注意make ledtestapp中的目標名ledtestapp就是上面Android.mk檔案中由LOCAL_MODULE指定的模組名。編譯結果如下

make ledtestapp
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=2.1-update1
TARGET_PRODUCT=generic
TARGET_BUILD_VARIANT=eng
TARGET_SIMULATOR=
TARGET_BUILD_TYPE=release
TARGET_ARCH=arm
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=ECLAIR
============================================
/bin/bash: line 0: cd: sdk/layoutopt/app/src/resources: No such file or directory
target thumb C: ledtestapp <= external/LEDTEST/ledtest.c
Install: <span class="kwrd">out</span>/host/linux-x86/bin/apriori
Install: out/host/linux-x86/bin/soslim
target Executable: ledtestapp (<span class="kwrd">out</span>/target/product/generic/obj/EXECUTABLES/ledtestapp_intermediates/LINKED/ledtestapp)
target Non-prelinked: ledtestapp (out/target/product/generic/symbols/system/bin/ledtestapp)
target Strip: ledtestapp (<span class="kwrd">out</span>/target/product/generic/obj/EXECUTABLES/ledtestapp_intermediates/ledtestapp)
Install: out/target/product/generic/system/lib/libdl.so
Install: <span class="kwrd">out</span>/target/product/generic/system/lib/libc.so
Install: out/target/product/generic/system/lib/libstdc++.so
Install: <span class="kwrd">out</span>/target/product/generic/system/lib/libm.so
Install: out/target/product/generic/system/bin/ledtestapp

4、如上面的編譯結果所示,編譯後的可執行檔案存放在

out/target/product/generic/system/bin/目錄 可執行檔案是ledtestapp

5、拷貝ledtestapp可執行檔案到T卡,插入開發板

6、開電,在啟動進入android的過程中,串列埠終端 按回車,進入命令列模式

7、拷貝可執行檔案到根目錄

#cp /sdcard/ledtestapp /   

8、執行程式

#./ledtestapp

通過上面的步驟,可以看到開發板上相應的LED在閉,每秒鐘閃一次!

  推薦使用 著名開源專案:樹莓派3 卡片電腦,我個人覺得挺不錯的,也非常的便宜,

 介紹看這裡


相關推薦

Android驅動例子LED控制

文章來源:http://blog.csdn.net/ok138ok/article/details/6317212 本例子,講述在android2.1上完全自已開發一個驅動去控制硬體口並寫應用測試該驅動,通過這樣一個例子,解析Android下的驅動開發流程的應用呼叫流程,

簡單javaAndroidpi4j和Socke實現respberry 3B上GPIO的LED控制

首先下載http://get.pi4j.com/download/pi4j-1.2-SNAPSHOT.zip(使用SNAPSHOT是因為3B要用這個新版本才正常,1.1版本不能在3B上執行),解的jar檔案使用eclipse進行開發,把3B作為伺服器進行socket埠監聽,沒

STM32-自學筆記8.使用STM32的SysTick定時器控制LED閃爍

SysTick定時器,被稱為“系統節拍時鐘”。SysTick屬於ARM  Cortex-M3核心的一個內設,STM32也帶有SysTick定時器。 SysTick定時器的基本結構 SysTick工作原理: SysTick從時鐘源介面獲得時鐘驅動 從重灌暫存器將

Android開發筆記一百六十休眠模式下的定時器控制

定時器AlarmManager常常用於需要週期性處理的場合,比如鬧鐘提醒、任務輪詢等等。並且定時器來源於系統服務,即使App已經不在運行了,也能收到定時器發出的廣播而被喚醒。似此迴光返照的神技,便遭到開發者的濫用,造成使用者手機充斥著各種殺不光程序,就算通過手機安全工具一再地

cocos2dx開發-讓例子新建cocos專案android機器上跑起來

新建Cocos專案 解壓原始碼得到資料夾cocos2d-x-3.2alpha0 進入目錄cocos2d-x-3.2alpha0\tools\cocos2d-console\bin執行 python cocos.py new BuckGameCC -p com.cocos2

用go的goroutine和channel實現一個簡單的“生產、消費”帶有超時控制例子

直接上程式碼 1、沒有超時的時候 package main import ( "fmt" "time" ) func main() { //存放生產的ch

android service 例子電話錄音和獲取系統當前時間

關於android service 的詳解請參考: android四大元件--android service詳解,下面將用兩個例項具體呈現Android Service的兩種實現。 一個是startService()方法來啟動一個服務,這裡用電話錄音的例子; 另一個是bin

Android開發系列二十四:Notification的功能與使用方法

font _id when ice extends 開發 content androi mark 關於消息的提示有兩種:一種是Toast,一種就是Notification。前者維持的時間比較短暫,後者維持的時間比較長。 並且我們尋常手機的應用比方網易、貼吧等等都有非常多

js封裝的一行半顯示省略號。字數自由控制

break 顯示 tco data tex 控制 test jquery 隱藏 $(function() { //控制一行半隱藏 (function ($) { $.fn.displayPart = function (opts) {

android Toast大全五種情形建立屬於你自己的Toast

right 其它 activity make div ins case tco title 搬運而來,如有雷同。絕非意外! Toast用於向用戶顯示一些幫助/提示。以下我做了5中效果,來說明Toast的強大,定義一個屬於你自己的Toast。

Android學習路線二十一運用Fragment構建動態UI——創建一個Fragment

動態 app idt 文檔 部分 roi 現實 調用 android學習 你能夠把fragment看成是activity的模塊化部分。它擁有自己的生命周期,接受它自己的輸入事件,你能夠在activity執行時加入或者刪除它(有點像是一個“子activity”。你

uCOS-II的學習筆記共九期例子共六個

操作 第七篇 wip target 恢復 第一篇 ont load -i 源:uCOS-II的學習筆記(共九期)和例子(共六個) 第一篇 :學習UCOS前的準備工作http://blog.sina.com.cn/s/blog_98ee3a930100w0eu.htm

MySQL遇到經典例子--遇到就寫

set 標題 sql per 經典 cnblogs spa fse mysql 1,一般的搜索只會搜索標題,也有特殊的情況,就是標題和內容一起搜索! 1 -- 模糊搜索只是搜索標題 2 $sql = "select count(*) as sum from publ

android things samplesample-button-master測試

key 階段 按鈕 但是 tps body post class str android things組件組裝好後,開始運行一下官方的sample。 官方sample地址 https://github.com/androidthings 從最簡單的按鈕控制led燈亮的sam

android things samplesample-tensorflow-imageclassifier測試

googl google button img .com 之前 技術分享 peak 組裝 今天來運行的是tensorflow-imageclassifier的sample。 這個sample的功能是,當led亮的時候,點擊button,進行照相,系統會對圖片進行分析,圖片中

python2.7練習小例子二十六

mat list num 題目 stdout AC number python2.7 打印 26):題目:給一個不多於5位的正整數,要求:一、求它是幾位數,二、逆序打印出各位數字。 程序分析:學會分解出每一位數。 程序源代碼: #!/usr/b

python2.7練習小例子二十四

[] sum output inf Coding == sys pop lse 24):1、題目:利用遞歸方法求5!。 程序分析:遞歸公式:fn=fn_1*4! #!/usr/bin/python # -*- coding: UTF-8 -*- de

python2.7練習小例子二十五

點贊 實例 net mil 感覺 format 經典題目 tty 遞推 25):題目:有5個人坐在一起,問第五個人多少歲?他說比第4個人大2歲。問第4個人歲數,他說比第3個人大2歲。問第三個人,又說比第2人大兩歲。問第2個人,說比第一個人大兩歲。最後問第一個人,他說

python2.7練習小例子二十七

IT 個數字 如果 dia yar gson pri python 實例 27):題目:一個5位數,判斷它是不是回文數。即12321是回文數,個位與萬位相同,十位與千位相同。 #!/usr/bin/python # -*- coding: UTF-8 -

python2.7練習小例子二十八

tail pen start 首字母 != 如果第一個字母一樣 append 程序 eight 28):題目:請輸入星期幾的第一個字母來判斷一下是星期幾,如果第一個字母一樣,則繼續判斷第二個字母。 程序分析:用情況語句比較好,如果第一個字母一樣,則判斷用情況