新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > [ARM应用]按键中断驱动实例

[ARM应用]按键中断驱动实例

作者: 时间:2016-12-02 来源:网络 收藏

  1 实验目的

本文引用地址:https://www.eepw.com.cn/article/201612/341050.htm

  (1)了解按键原理及其与S3C2410的接口电路设计

  (2)了解S3C2410芯片的外部中断处理机制

  (3)掌握驱动的编写及测试过程

  2 实验原理

  (1)按键的硬件原理

  在嵌入式系统中,按键的硬件原理比较简单,通过一个上拉电阻将处理器的外部中断(或GPIO)引脚拉高,电阻的另一端连接按键并接地即可实现。如图2-1所示:

    

[ARM应用]按键中断驱动实例 - Fantity Wei - Footprint

  图

  2-1按键接口电路

  仔细看图2-1,不难知道,当按键被按下时,EINT0上将产生低电平,这个低电平将中断CPU,CPU可以依据中断判断按键被按下。

  (2)按键“消抖”

  所有按键、触摸屏等机械设备都存在一个固有的问题,那就是"抖动",按键从最初接通到稳定接通要经过数毫秒乃至数十毫秒,其间可能发生多次"接通―断开"的过程。因此仅仅依据中断被产生就认定有一次按键行为是很不准确的。如果不消除"抖动"的影响,一次按键可能被理解为多次按键。

  消除按键抖动影响的方法是:在判断有键按下后,进行软件延时(如20ms,在延时过程中要屏蔽对应中断),再判断键盘状态,如果仍处于按键按下状态,则可以判定该按键被按下。图2-2是典型的包含消抖功能的处理流程。

    

[ARM应用]按键中断驱动实例 - Fantity Wei - Footprint

 

  图2-2 处理流程

  3 实验任务

  (1)编写按键中断设备驱动程序,驱动程序中手动定义设备名称及主设备号为213,实现与BUTTON设备相应的端口配置,中断的申请,以及读写设备的接口函数等。

  (2)将驱动编译成模块,并实现模块的加载及卸载。

  (3)编写驱动的测试程序,在程序中实现打开BUTTON设备和LED设备,主循环中不断读取按键的状态,当按键按下时,控制LED亮一段时间(1S左右)后灭掉。

  4. 实验步骤

  以下操作都在nfs文件系统目录(/home/kernel/rootfs/rootfs)下进行,因此先执行如下命令。获取

  cd /home/kernel/rootfs/rootfs

  (1)编写led.c文件

  建立led目录:

  mkdir usr/button

  进入button目录,在该目录下建立两个子目录driver 和test ,前者用来存放驱动程序,后者用来存放驱动测试程序:

  cd usr/ button

  mkdir driver test

  进入驱动程序目录,建立设备驱动文件button.c:

  cd driver

  vi button.c

  按键驱动程序如下button.c所示:

  /*************************** 头文件 ***************************/

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  //*********************** 定义设备结构体及相关宏 ***************************

  #define DEVICE_NAME "button" //定义设备名

  #define DEVICE_MAJOR 213 //手动定义BUTTON设备的主设备号为213

  static int button_major = DEVICE_MAJOR ;

  #define BUTTON_IRQ IRQ_EINT0 //定义BUTTON对应S3C2410的外部中断0

  #define BUTTON S3C2410_GPF0 //定义BUTTON对应S3C2410的GPF0端口

  #define BUTTON_EINT0 S3C2410_GPF0_EINT0

  #define BUTTON_INP S3C2410_GPF0_INP

  #define BUTTON_UP 0 //按键抬起状态

  #define BUTTON_DOWN 1 //按键按下状态

  #define BUTTON_X 2 //不确定状态,本实例中可理解为抖动状态

  //定义BUTTON设备结构体

  struct button_dev

  {

  struct cdev cdev; //BUTTON设备对应一个字符设备结构体

  int status; //按键状态标识:抬起、按下、抖动

  };

  static struct button_dev dev;

  //***************************** 函数声明 *********************************

  void s3c2410_button_s3c2410_button_InitIO(void); //初始化IO端口的函数

  /*

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

  *描述 :初始化IO端口

  *参数 :无

  *返回值:无

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

  */

  void s3c2410_button_InitIO(void)

  {

  s3c2410_gpio_cfgpin(BUTTON,BUTTON_EINT0); //配置按键中断的端口为中断功能

  }

  /*

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

  *描述 :EINT0的中断处理函数,设置按键状态为BUTTON_X

  *参数 :irq :中断号; 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;//将按键置为抖动状态,说明有按键中断,但不一定有键按下

  enable_irq(0); //使能中断

  return 0;

  }

  /*

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

  *描述 :打开设备函数,向系统申请中断

  *参数 :struct inode *inode,struct file *filp

  *返回值:失败返回错误代码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); //申请中断

  if(ret) {//申请失败

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

  return ret;

  }

  return 0;

  }

  /*

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

  *描述 :注销设备函数,实现中断释放

  *参数 :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控制函数,本实例中不做任何事

  *参数 :cmd: 用户定义的IO控制命令; arg: 传递用户参数

  *返回值:0

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

  */

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

  unsigned int cmd,unsigned long arg)

  {

  return 0;

  }

  /*

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

  *描述 :读函数,读取按键的状态

  *参数 :buffer: 用来存储按键状态;

  count: 用来记录用户读取了多少个字符

  *返回值:count:用户读取的字符数

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

  */

  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){//如果按键状态是BUTTON_X,说明有按键中断产生。

  msleep(20); //延时20毫秒去除按键抖动

  disable_irq(0); //禁止中断

  s3c2410_gpio_cfgpin(BUTTON,BUTTON_INP); //配置按键中断的端口为输入功能

  if(!s3c2410_gpio_getpin(BUT

  if(!s3c2410_gpio_getpin(BUTTON)){//读取端口的值,如果是0说明按键按下

  dev.status = BUTTON_DOWN;

  }

  else dev.status = BUTTON_UP; //如果为1,说明只是按键抖动

  //重新配置按键中断的端口为中断功能

  s3c2410_gpio_cfgpin(BUTTON,S3C2410_GPF0_EINT0);

  enable_irq(0); //使能中断

  }

  put_user(dev.status,(int *)buffer); //将按键状态提交给用户

  return ret;

  }

  /*

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

  *描述 :写操作函数,本实例中不做任何事

  *参数 :

  *返回值: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****************************

  *描述 :文件操作结构体,实现 s3c2410_button_open()等函数与open()等系统调用的连接

  *参数 :

  *返回值:

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

  */

  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()****************************

  *描述 :安装模块的函数,在设备加载模块里面调用

  *参数 :无

  *返回值:无

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

  */

  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);

  }

  /*


上一页 1 2 下一页

关键词: ARM 按键中断

评论


相关推荐

技术专区

关闭