1 试验意图
(1)了解按键原理及其与S3C2410的接口电路设计
(2)了解S3C2410芯片的外部中止处理机制
(3)把握按键中止驱动的编写及测验进程
2 试验原理
(1)按键的硬件原理
在嵌入式体系中,按键的硬件原理比较简单,经过一个上拉电阻将处理器的外部中止(或GPIO)引脚拉高,电阻的另一端衔接按键并接地即可完成。如图2-1所示:
图
2-1按键接口电路
细心看图2-1,不难知道,当按键被按下时,EINT0大将发生低电平,这个低电平将中止CPU,CPU能够根据中止判别按键被按下。
(2)按键“消抖”
一切按键、触摸屏等机械设备都存在一个固有的问题,那就是"颤动",按键从开始接通到安稳接通要经过数毫秒甚至数十毫秒,其间或许发生屡次"接通―断开"的进程。因而仅仅根据中止被发生就确定有一次按键行为是很不精确的。假如不消除"颤动"的影响,一次按键或许被理解为屡次按键。
消除按键颤动影响的办法是:在判别有键按下后,进行软件延时(如20ms,在延时进程中要屏蔽对应中止),再判别键盘状况,假如仍处于按键按下状况,则能够断定该按键被按下。图2-2是典型的包括消抖功用的按键中止处理流程。
图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,DEV%&&&&&%E_NAME,NULL); //请求中止
if(ret) {//请求失利
printk("BUTTON_IRQ: could not register interrupt\n");
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);
}
/*