新聞中心

        EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > [ARM應(yīng)用]按鍵中斷驅(qū)動(dòng)實(shí)例

        [ARM應(yīng)用]按鍵中斷驅(qū)動(dòng)實(shí)例

        作者: 時(shí)間:2016-12-02 來(lái)源:網(wǎng)絡(luò) 收藏

          1 實(shí)驗(yàn)?zāi)康?/p>本文引用地址:http://www.104case.com/article/201612/341050.htm

          (1)了解按鍵原理及其與S3C2410的接口電路設(shè)計(jì)

          (2)了解S3C2410芯片的外部中斷處理機(jī)制

          (3)掌握驅(qū)動(dòng)的編寫及測(cè)試過(guò)程

          2 實(shí)驗(yàn)原理

          (1)按鍵的硬件原理

          在嵌入式系統(tǒng)中,按鍵的硬件原理比較簡(jiǎn)單,通過(guò)一個(gè)上拉電阻將處理器的外部中斷(或GPIO)引腳拉高,電阻的另一端連接按鍵并接地即可實(shí)現(xiàn)。如圖2-1所示:

            

        [ARM應(yīng)用]按鍵中斷驅(qū)動(dòng)實(shí)例 - Fantity Wei - Footprint

          圖

          2-1按鍵接口電路

          仔細(xì)看圖2-1,不難知道,當(dāng)按鍵被按下時(shí),EINT0上將產(chǎn)生低電平,這個(gè)低電平將中斷CPU,CPU可以依據(jù)中斷判斷按鍵被按下。

          (2)按鍵“消抖”

          所有按鍵、觸摸屏等機(jī)械設(shè)備都存在一個(gè)固有的問(wèn)題,那就是"抖動(dòng)",按鍵從最初接通到穩(wěn)定接通要經(jīng)過(guò)數(shù)毫秒乃至數(shù)十毫秒,其間可能發(fā)生多次"接通―斷開(kāi)"的過(guò)程。因此僅僅依據(jù)中斷被產(chǎn)生就認(rèn)定有一次按鍵行為是很不準(zhǔn)確的。如果不消除"抖動(dòng)"的影響,一次按鍵可能被理解為多次按鍵。

          消除按鍵抖動(dòng)影響的方法是:在判斷有鍵按下后,進(jìn)行軟件延時(shí)(如20ms,在延時(shí)過(guò)程中要屏蔽對(duì)應(yīng)中斷),再判斷鍵盤狀態(tài),如果仍處于按鍵按下?tīng)顟B(tài),則可以判定該按鍵被按下。圖2-2是典型的包含消抖功能的處理流程。

            

        [ARM應(yīng)用]按鍵中斷驅(qū)動(dòng)實(shí)例 - Fantity Wei - Footprint

         

          圖2-2 處理流程

          3 實(shí)驗(yàn)任務(wù)

          (1)編寫按鍵中斷設(shè)備驅(qū)動(dòng)程序,驅(qū)動(dòng)程序中手動(dòng)定義設(shè)備名稱及主設(shè)備號(hào)為213,實(shí)現(xiàn)與BUTTON設(shè)備相應(yīng)的端口配置,中斷的申請(qǐng),以及讀寫設(shè)備的接口函數(shù)等。

          (2)將驅(qū)動(dòng)編譯成模塊,并實(shí)現(xiàn)模塊的加載及卸載。

          (3)編寫驅(qū)動(dòng)的測(cè)試程序,在程序中實(shí)現(xiàn)打開(kāi)BUTTON設(shè)備和LED設(shè)備,主循環(huán)中不斷讀取按鍵的狀態(tài),當(dāng)按鍵按下時(shí),控制LED亮一段時(shí)間(1S左右)后滅掉。

          4. 實(shí)驗(yàn)步驟

          以下操作都在nfs文件系統(tǒng)目錄(/home/kernel/rootfs/rootfs)下進(jìn)行,因此先執(zhí)行如下命令。獲取

          cd /home/kernel/rootfs/rootfs

          (1)編寫led.c文件

          建立led目錄:

          mkdir usr/button

          進(jìn)入button目錄,在該目錄下建立兩個(gè)子目錄driver 和test ,前者用來(lái)存放驅(qū)動(dòng)程序,后者用來(lái)存放驅(qū)動(dòng)測(cè)試程序:

          cd usr/ button

          mkdir driver test

          進(jìn)入驅(qū)動(dòng)程序目錄,建立設(shè)備驅(qū)動(dòng)文件button.c:

          cd driver

          vi button.c

          按鍵驅(qū)動(dòng)程序如下button.c所示:

          /*************************** 頭文件 ***************************/

          #include

          #include

          #include

          #include

          #include

          #include

          #include

          #include

          #include

          #include

          #include

          #include

          #include

          #include

          #include

          #include

          //*********************** 定義設(shè)備結(jié)構(gòu)體及相關(guān)宏 ***************************

          #define DEVICE_NAME "button" //定義設(shè)備名

          #define DEVICE_MAJOR 213 //手動(dòng)定義BUTTON設(shè)備的主設(shè)備號(hào)為213

          static int button_major = DEVICE_MAJOR ;

          #define BUTTON_IRQ IRQ_EINT0 //定義BUTTON對(duì)應(yīng)S3C2410的外部中斷0

          #define BUTTON S3C2410_GPF0 //定義BUTTON對(duì)應(yīng)S3C2410的GPF0端口

          #define BUTTON_EINT0 S3C2410_GPF0_EINT0

          #define BUTTON_INP S3C2410_GPF0_INP

          #define BUTTON_UP 0 //按鍵抬起狀態(tài)

          #define BUTTON_DOWN 1 //按鍵按下?tīng)顟B(tài)

          #define BUTTON_X 2 //不確定狀態(tài),本實(shí)例中可理解為抖動(dòng)狀態(tài)

          //定義BUTTON設(shè)備結(jié)構(gòu)體

          struct button_dev

          {

          struct cdev cdev; //BUTTON設(shè)備對(duì)應(yīng)一個(gè)字符設(shè)備結(jié)構(gòu)體

          int status; //按鍵狀態(tài)標(biāo)識(shí):抬起、按下、抖動(dòng)

          };

          static struct button_dev dev;

          //***************************** 函數(shù)聲明 *********************************

          void s3c2410_button_s3c2410_button_InitIO(void); //初始化IO端口的函數(shù)

          /*

          ******************************s3c2410_button_InitIO**********************

          *描述 :初始化IO端口

          *參數(shù) :無(wú)

          *返回值:無(wú)

          *************************************************************************

          */

          void s3c2410_button_InitIO(void)

          {

          s3c2410_gpio_cfgpin(BUTTON,BUTTON_EINT0); //配置按鍵中斷的端口為中斷功能

          }

          /*

          ******************************isr_button()*******************************

          *描述 :EINT0的中斷處理函數(shù),設(shè)置按鍵狀態(tài)為BUTTON_X

          *參數(shù) :irq :中斷號(hào); dev_id;regs;

          *返回值:成功返回0

          *在linux/interrupt.h中定義了typedef irqreturn_t (*irq_handler_t)(int, void *);

          *************************************************************************

          */

          static irqreturn_t isr_button(int irq,void *dev_id,struct pt_regs *regs)

          {

          disable_irq(0); //禁止中斷

          dev.status = BUTTON_X;//將按鍵置為抖動(dòng)狀態(tài),說(shuō)明有按鍵中斷,但不一定有鍵按下

          enable_irq(0); //使能中斷

          return 0;

          }

          /*

          **************************s3c2410_button_open()**************************

          *描述 :打開(kāi)設(shè)備函數(shù),向系統(tǒng)申請(qǐng)中斷

          *參數(shù) :struct inode *inode,struct file *filp

          *返回值:失敗返回錯(cuò)誤代碼ret,成功返回0

          *************************************************************************

          */

          static int s3c2410_button_open(struct inode *inode,struct file *filp)

          {

          int ret;

          ret=request_irq(BUTTON_IRQ,isr_button,IRQF_SAMPLE_RANDOM,DEVICE_NAME,NULL); //申請(qǐng)中斷

          if(ret) {//申請(qǐng)失敗

          printk("BUTTON_IRQ: could not register interruptn");

          return ret;

          }

          return 0;

          }

          /*

          ************************s3c2410_button_release()*************************

          *描述 :注銷設(shè)備函數(shù),實(shí)現(xiàn)中斷釋放

          *參數(shù) :struct inode *inode,struct file *filp

          *返回值:0

          *************************************************************************

          */

          static int s3c2410_button_release(struct inode *inode,struct file *filp)

          {

          free_irq(BUTTON_IRQ,NULL); //釋放中斷

          return 0;

          }

          /*

          **************************3c2410_button_ioctl()**************************

          *描述 :IO控制函數(shù),本實(shí)例中不做任何事

          *參數(shù) :cmd: 用戶定義的IO控制命令; arg: 傳遞用戶參數(shù)

          *返回值:0

          *************************************************************************

          */

          static int s3c2410_button_ioctl(struct inode *inode,struct file *filp,

          unsigned int cmd,unsigned long arg)

          {

          return 0;

          }

          /*

          **************************s3c2410_button_read()**************************

          *描述 :讀函數(shù),讀取按鍵的狀態(tài)

          *參數(shù) :buffer: 用來(lái)存儲(chǔ)按鍵狀態(tài);

          count: 用來(lái)記錄用戶讀取了多少個(gè)字符

          *返回值:count:用戶讀取的字符數(shù)

          *************************************************************************

          */

          static ssize_t s3c2410_button_read(struct file *filp,char *buffer,size_t count,loff_t *ppos)

          {

          int ret = count ;

          if(dev.status = BUTTON_X){//如果按鍵狀態(tài)是BUTTON_X,說(shuō)明有按鍵中斷產(chǎn)生。

          msleep(20); //延時(shí)20毫秒去除按鍵抖動(dòng)

          disable_irq(0); //禁止中斷

          s3c2410_gpio_cfgpin(BUTTON,BUTTON_INP); //配置按鍵中斷的端口為輸入功能

          if(!s3c2410_gpio_getpin(BUT

          if(!s3c2410_gpio_getpin(BUTTON)){//讀取端口的值,如果是0說(shuō)明按鍵按下

          dev.status = BUTTON_DOWN;

          }

          else dev.status = BUTTON_UP; //如果為1,說(shuō)明只是按鍵抖動(dòng)

          //重新配置按鍵中斷的端口為中斷功能

          s3c2410_gpio_cfgpin(BUTTON,S3C2410_GPF0_EINT0);

          enable_irq(0); //使能中斷

          }

          put_user(dev.status,(int *)buffer); //將按鍵狀態(tài)提交給用戶

          return ret;

          }

          /*

          **************************3c2410_button_write()**************************

          *描述 :寫操作函數(shù),本實(shí)例中不做任何事

          *參數(shù) :

          *返回值:count

          *************************************************************************

          */

          static ssize_t s3c2410_button_write(struct file *filp,char *buffer,size_t count,loff_t *ppos)

          {

          int ret = count;

          return ret;

          }

          /*

          **************************s3c2410_button_fops****************************

          *描述 :文件操作結(jié)構(gòu)體,實(shí)現(xiàn) s3c2410_button_open()等函數(shù)與open()等系統(tǒng)調(diào)用的連接

          *參數(shù) :

          *返回值:

          *************************************************************************

          */

          static struct file_operations s3c2410_button_fops = {

          .owner = THIS_MODULE,

          .open = s3c2410_button_open,

          .release = s3c2410_button_release,

          .ioctl = s3c2410_button_ioctl,

          .read = s3c2410_button_read,

          .write = s3c2410_button_write,

          };

          /*

          **************************button_setup_cdev()****************************

          *描述 :安裝模塊的函數(shù),在設(shè)備加載模塊里面調(diào)用

          *參數(shù) :無(wú)

          *返回值:無(wú)

          *************************************************************************

          */

          static void button_setup_cdev(void)

          {

          int err,devno = MKDEV(button_major,0);

          cdev_init(&dev.cdev,&s3c2410_button_fops);

          dev.cdev.owner = THIS_MODULE;

          dev.cdev.ops = &s3c2410_button_fops;

          err = cdev_add(&dev.cdev,devno,1);

          if(err)

          printk("Error %d adding BUTTON%d",err);

          }

          /*


        上一頁(yè) 1 2 下一頁(yè)

        關(guān)鍵詞: ARM 按鍵中斷

        評(píng)論


        相關(guān)推薦

        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 讷河市| 枝江市| 夹江县| 陇南市| 建平县| 太白县| 姚安县| 织金县| 平安县| 通辽市| 罗源县| 兴义市| 田阳县| 台南县| 东丰县| 淮阳县| 思南县| 格尔木市| 富平县| 岳阳县| 汤原县| 大冶市| 灌云县| 嘉定区| 唐山市| 康定县| 扬州市| 蓝田县| 盘山县| 博白县| 巴彦淖尔市| 阜新市| 化德县| 太康县| 乌鲁木齐市| 镇雄县| 景洪市| 新巴尔虎左旗| 泽普县| 德惠市| 抚远县|