嵌入式Linux设备驱动开发之:按键驱动程序实例
f((ucKey>=1)(ucKey=16))
{
/*如果缓冲区已满,则不添加*/
if(((key_buffer.head+1)(MAX_KEY_COUNT-1))!=key_buffer.tail)
{
spin_lock_irq(buffer_lock);
key_buffer.buf[key_buffer.tail]=ucKey;
key_buffer.jiffy[key_buffer.tail]=get_tick_count();
key_buffer.tail++;
key_buffer.tail=(MAX_KEY_COUNT-1);
spin_unlock_irq(buffer_lock);
}
}
init_gpio();/*初始化GPIO端口,主要是为了恢复中断端口配置*/
enable_irqs();/*开启中断*/
returnIRQ_HANDLED;/*2.6内核返回值一般是这个宏*/
}
/*申请4个中断*/
staticintrequest_irqs(void)
{
intret,i,j;
for(i=0;iMAX_COLUMN;i++)
{
ret=request_irq(key_info_matrix[i][0].irq_no,
button_irq,SA_INTERRUPT,BUTTONS_DEVICE_NAME,NULL);
if(ret0)
{
for(j=0;ji;j++)
{
free_irq(key_info_matrix[j][0].irq_no,NULL);
}
return-EFAULT;
}
}
return0;
}
/*释放中断*/
static__inlinevoidfree_irqs(void)
{
inti;
for(i=0;iMAX_COLUMN;i++)
{
free_irq(key_info_matrix[i][0].irq_no,NULL);
}
}
中断处理函数在每次中断产生的时候会被调用,因此它的执行时间要尽可能得短。通常中断处理函数只是简单地唤醒等待资源的任务,而复杂且耗时的工作则让这个任务去完成。中断处理函数不能向用户空间发送数据或者接收数据,不能做任何可能发生睡眠的操作,而且不能调用schedule()函数。
为了简单起见,而且考虑到按键操作的时间比较长,在本实例中的中断处理函数button_irq()里,通过调用睡眠函数来消除毛刺信号。读者可以根据以上介绍的对中断处理函数的要求改进该部分代码。
按键扫描函数如下所示。首先根据中断号确定操作按键所在行的位置,然后采用逐列扫描法最终确定操作按键所在的位置。
/*
**进入中断后,扫描铵键码
**返回:按键码(1~16),0xff表示错误
*/
static__inlineunsignedcharbutton_scan(intirq)
{
unsignedcharkey_id=0xff;
unsignedcharcolumn=0xff,row=0xff;
s3c2410_gpio_cfgpin(S3C2410_GPF0,S3C2410_GPF0_INP);/*GPF0*/
s3c2410_gpio_cfgpin(S3C2410_GPF2,S3C2410_GPF2_INP);/*GPF2*/
s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_INP);/*GPG3*/
s3c2410_gpio_cfgpin(S3C2410_GPG11,S3C2410_GPG11_INP);/*GPG11*/
switch(irq)
{/*根据irq值确定操作按键所在行的位置*/
caseIRQ_EINT0:
{
column=0;
}
break;
caseIRQ_EINT2:
{
column=1;
}
break;
caseIRQ_EINT11:
{
column=2;
}
break;
caseIRQ_EINT19:
{
column=3;
}
break;
}
if(column!=0xff)
{/*开始逐列扫描,扫描第0列*/
s3c2410_gpio_setpin(S3C2410_GPE11,0);/*将KSCAN0置为低电平*/
s3c2410_gpio_setpin(S3C2410_GPG6,1);
s3c2410_gpio_setpin(S3C2410_GPE13,1);
s3c2410_gpio_setpin(S3C2410_GPG2,1);
if(!s3c2410_gpio_getpin(key_info_matrix[column][0].irq_gpio_port))
{/*观察对应的中断线的输入端口值*/
key_id=key_info_matrix[column][0].key_id;
returnkey_id;
}
/*扫描第1列*/
s3c2410_gpio_setpin(S3C2410_GPE11,1);
s3c2410_gpio_setpin(S3C2410_GPG6,0);/*将KSCAN1置为低电平*/
s3c2410_gpio_setpin(S3C2410_GPE13,1);
s3c2410_gpio_setpin(S3C2410_GPG2,1);
if(!s3c2410_gpio_getpin(key_info_matrix[column][1].irq_gpio_port))
{
key_id=key_info_matrix[column][1].key_id;
returnkey_id;
}
/*扫描第2列*/
s3c2410_gpio_setpin(S3C2410_GPE11,1);
s3c2410_gpio_setpin(S3C2410_GPG6,1);
s3c2410_gpio_setpin(S3C2410_GPE13,0);/*将KSCAN2置为低电平*/
s3c2410_gpio_setpin(S3C2410_GPG2,1);
if(!s3c2410_gpio_getpin(key_info_matrix[column][2].irq_gpio_port))
{
key_id=key_info_matrix[column][2].key_id;
returnkey_id;
}
/*扫描第3列*/
s3c2410_gpio_setpin(S3C2410_GPE11,1);
s3c2410_gpio_setpin(S3C2410_GPG6,1);
s3c2410_gpio_setpin(S3C2410_GPE13,1);
s3c2410_gpio_setpin(S3C2410_GPG2,0);/*将KSCAN3置为低电平*/
if(!s3c2410_gpio_getpin(key_info_matrix[column][3].irq_gpio_port))
{
key_id=key_info_matrix[column][3].key_id;
returnkey_id;
}
}
returnkey_id;
}
以下是read函数接口的实现。首先在按键缓冲中删除已经过时的按键操作信息,接下来,从按键缓冲中读取一条信息(按键ID)并传递给用户层。
/*从缓冲删除过时数据(5s前的按键值)*/
staticvoidremove_timeoutkey(void)
{
unsignedlongtick;
spin_lock_irq(buffer_lock);/*获得一个自旋锁*/
while(key_buffer.head!=key_buffer.tail)
{
tick=get_tick_count()-key_buffer.jiffy[key_buf
嵌入式Linux 设备驱动 按键驱动程序 操作系统 相关文章:
- 嵌入式Linux技术在工业控制网络中的应用(10-30)
- 基于嵌入式Linux的组态软件实时数据库的设计(02-01)
- 基于ARM+DSP的嵌入式Linux数控系统设计(11-18)
- 基于嵌入式Linux的细胞特征提取算法设计(11-19)
- 基于S3C2410的嵌入式Linux系统构建(03-02)
- 嵌入式Linux网络编程之:网络基础编程(08-13)