Linux和qtopia下的矩阵键盘驱动程序(一)

2014-11-24 09:12:45 · 作者: · 浏览: 0

基于s3c2440和linux,实现了3*4的矩阵键盘驱动。


功能:延时消抖,重复按键,多键齐按(??)


更详细的说明文档:“基于S3C24440和嵌入式Linux的矩阵键盘设计”,电子技术,2008,45(5):21-23


/**********************************************************
* s3c2440-keyboard.c
*
* keyboard driver for S3C2440 based PDA
*
*
* History:2007/04/30
*
*
***********************************************************/

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define DEVICE_NAME "s3c2440-kb" //键盘设备名

static int kbMajor = 0; //默认的主设备号

#define MAX_KB_BUF 10 //循环队列的尺寸

typedef struct {
unsigned int keyStatus;
int irq;
// int timeCount;
u_short buf[MAX_KB_BUF]; /* 循环队列*/
unsigned int head, tail; /* 循环队列的读写指针*/
spinlock_t lock; /*锁*/
} KB_DEV;

static KB_DEV kbdev;

#define KEY_UP 0 //按键弹起
#define KEY_DOWN 1 //按键按下
#define NO_KEY_DOWN 2 //没有键按下

#define EINT1_DOWN 0
#define EINT3_DOWN 1
#define EINT8_DOWN 2
#define NO_EINT_DOWN 3

/*循环队列操作*/
#define BUF_HEAD (kbdev.buf[kbdev.head])
#define BUF_TAIL (kbdev.buf[kbdev.tail])
#define INCBUF(x) if((++x)==MAX_KB_BUF) x=0

/*定时器设置*/
#define KB_TIMER_DELAY (HZ/50) /*HZ表示每秒产生的时钟滴答数,定时器超时为20ms*/
#define REPEAT_START_DELAY (HZ) /* 自动重复开始延时:1秒*/
#define REPEAT_DELAY (HZ/2) /*自动重复延时:0.5秒*/

static struct timer_list kb_timer;
static struct timer_list repeat_timer;
spinlock_t repeat_lock;
static int timeCount =1;
static int TIME_OUT =5;

/*键盘矩阵*/

static u_short keyboard_code_map[4][3]={
{1 , 2 , 3 },
{4 , 5 , 6 },
{7 , 8 , 9 },
{10, 11, 12}
}; //每个按键对应的键盘码
static u_short pre_keyboard_code = 0; //上次扫描得到的按键值
static u_short curr_keyboard_code = 0;//当前扫描得到的按键值
static u_short snap_keyboard_code[4][3]={
{0 , 0 , 0 },
{0 , 0 , 0 },
{0 , 0 , 0 },
{0, 0, 0}
}; //临时按键值
#define DETECTION_THROLD 3


static int requestIrq();
static int s3c2440_kb_release(struct inode *inode, struct file *filp);



/*----------------------------------------------------
* func: 初始化GPJCON寄存器,将GPJ9,GPJ10,GPJ11,GPJ12
* 配置成output管腿
*
------------------------------------------------------*/
static void init_gpjcon()
{

//GPJ9,GPJ10,GPJ11,GPJ12------>output
GPJCON &= 0xFC03FFFF;
GPJCON |= 0x01540000;
}

/*----------------------------------------------------
* func: 向GPJ9,GPJ10,GPJ11,GPJ12输出value
* param:
* value: 输出值
*
------------------------------------------------------*/
//
static inline void output_giop(int value ) //往所有行输出
{
value &= 0x0000000F;
value <<= 9;
GPJDAT &= 0xE1FF;
GPJDAT |= value;
udelay(2);
}

/*----------------------------------------------------
* func: 判断eint当前是否是低电平
* param:
* irq: 当前引发中断的eint的irq号
* return:
* EINT1_DOWN: eint1上是低电平
* EINT3_DOWN: eint3上是低电平
* EINT8_DOWN: eint8上是低电平
* NO_EINT_DOWN:eint上不是低电平
------------------------------------------------------*/
int get_eint_value(int irq)
{
u_int IOValue;

IOValue = GPFDAT ;

if( (irq == 1) && (( IOValue & 0x00000002)==0) )
{
return EINT1_DOWN;
}
if((irq ==3 ) && (( IOValue & 0x00000008)==0) )
{
return EINT3_DOWN;
}
IOValue = GPGDAT ;
if((irq ==36) && (( IOValue & 0x0000001)==0) )
{

return EINT8_DOWN;
}

return NO_EINT_DOWN;

}

/*----------------------------