bate2000的个人空间 https://blog.eetop.cn/bate [收藏] [复制] [分享] [RSS]

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

VOD视频点播系统(四)

已有 1455 次阅读| 2008-3-27 17:02 |个人分类:VOD

Ø四个输出引脚:        

Ø                  KEYSCAN0---( GPE11 )----OUTPUT

Ø                          KEYSCAN1---( GPG6  )----OUTPUT

Ø                          KEYSCAN2---( GPE13 )----OUTPUT

Ø                          KEYSCAN3---( GPG2  )----OUTPUT

 

键盘的驱动实现

Ø引入结构体key_info对按键进行描述

Østatic struct key_info {

Ø    int irq_no; //外部中断号

Ø    unsigned int gpio_port; //输入端口,EINT

Ø    unsigned int gpio_port_kscan; //输出端口,OUTPUT

Ø    int key_no; //按键序号,或者名字

Ø} key_info_tab[16] = {

Ø    ……

Ø}

键盘初始化程序

Østatic int __init matrix4_buttons_init(void)

Ø{

Ø    注册字符设备  register_chrdev(……);

Ø    初始化按键对应的输出端口  buttons_io_port_init();

Ø    采用中断机制,注册中断号  request_irqs();

Ø}

 

键盘初始化程序

Ø/* 初始化kscan口为输出0 */

Østatic void buttons_io_port_init(void)

Ø{

Ø    int i;

 

Ø    for(i=0; i < sizeof kscan / sizeof kscan[1]; i++) {

Ø           set_gpio_ctrl(kscan[i] | GPIO_PULLUP_DIS | GPIO_MODE_OUT);

Ø           write_gpio_bit(kscan[i], 0);

Ø    }

Ø}

请求注册中断

Østatic int request_irqs(void)

Ø{

Ø    for (i = 0; i < 使用中断个数; i++) {

Ø           设置与外部中断号相对应的GPIO端口以及模式        请求中断号,并注册中断响应函数。

Ø    }

Ø}

键盘驱动的卸载函数

Østatic void __exit matrix4_buttons_exit(void)

Ø{

Ø    释放中断 free_irqs(…);

Ø    注销字符设备unregister_chrdev(…);

Ø}

按键中断处理 buttons_irq

Østatic void buttons_irq(int irq, void *dev_id, struct pt_regs *reg)

Ø{

Ø    设置GPIO为输入状态

Ø    键盘扫描

Ø    唤醒按键等待队列的进程

Ø    重新设置GPIO为输出

Ø    重新设置中断

Ø}

通过延时去键盘抖动

Ø理想的情况下,当按键被按下时,I/O口电平被拉低,即逻辑0,当按键松开时,为逻辑1

Ø但实际机械的触点动作与微处理器快速的执行速度不匹配,导致开关被按下或松开时产生抖动,如同弹簧一样,不能立刻产生稳定的01

Ø常用的去抖动方法有硬件和软件两种,硬件可采用单稳态触发起、高通滤波器等硬件实现,但该方法一般要对每一路输入添加特殊的硬件,比较复杂。软件去抖动则简单多了,可通过增加延时和判断来解决。

matrix4_buttons_fops

Ø由于按键不具有I/O功能,它只会在按下的时候产生中断,所以这里不需要实现openreadwriteioctl等功能。

Ø为了测试驱动,可以添加这些函数。

 

源代码:

/********************************************
*  *GEC2410-BOX
*  *date : created at 2007-09-19 by baijb
********************************************/

#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/devfs_fs_kernel.h>

#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>

#define DEVICE_NAME "key_driver"
#define LEDRAW_MINOR 1
#define KBD_TIMER_DELAY (HZ/50)

static int keyMajor = 0;

//--------------------------------------------
static struct key_info
{
 unsigned int   irq_num;
 unsigned int   gpio_port;
 unsigned int   key_num;
} keys[2] = {
  { IRQ_EINT10, S3C2410_GPG2, 1 },
  { IRQ_EINT11, S3C2410_GPG3, 2 }, 
 };

static int key_value = 0;
static int ready = 0;
static struct timer_list kbd_timer;
static DECLARE_WAIT_QUEUE_HEAD(key_wait);

/****************************************
*  *Pin function: EXINT
****************************************/
static void init_key_exint(void)
{
 __raw_writel(__raw_readl(S3C2410_GPGCON) & (~(0x0f<<4)) | (0x0a<<4), S3C2410_GPGCON);  //GPG2,3--EXINT10,11
 __raw_writel(__raw_readl(S3C2410_EXTINT1) & (~(0x77<<8)) | (0x22<<8), S3C2410_EXTINT1); //EXINT10,11--falling edge triger
}

/****************************************
*  * Pin funciton: input
****************************************/
static void init_key_input(void)
{
 __raw_writel(__raw_readl(S3C2410_GPGCON) & (~(0x0f<<4)), S3C2410_GPGCON);  //GPG2,3--EXINT10,11
}

//-------------------------------------------
static void kbd_timer_handler(unsigned long date)
{
 struct key_info *key=NULL;

 key_value = 0;
 if((__raw_readl(S3C2410_GPGDAT) &  (1<<2)) == 0 )  {  //GPG2--pressed
  key = &keys[0];
  key_value = key->key_num;
 }
 else if((__raw_readl(S3C2410_GPGDAT) &  (1<<3)) == 0 ) { //GPG3--pressed
  key = &keys[1];
  key_value = key->key_num;
 }

 ready = 1;
 del_timer(&kbd_timer);
 
 wake_up_interruptible(&key_wait);
 
 init_key_exint();
}

//--------------------------------------------
static irqreturn_t key_irq_handle(int irq, void *devid, struct pt_regs *regs){
 
 init_key_input(); //GPG2,3--input.delay 20 ms,then query which key is pressed.
 
 kbd_timer.expires = jiffies + KBD_TIMER_DELAY;  //delay 20 ms
 add_timer(&kbd_timer);
 
 return IRQ_HANDLED;
}

//---------------------------------------------
static int s3c2410_key_open(struct inode *inode, struct file *filp)
{
 int ret;
 struct key_info *key=NULL;
 
 printk(KERN_INFO DEVICE_NAME ": opened.\n");

 init_key_exint();
 
 ready = 0;
 key = &keys[0];
 
 ret = request_irq(key->irq_num, key_irq_handle, SA_INTERRUPT, DEVICE_NAME, NULL);
 if(ret) {
  printk(KERN_INFO DEVICE_NAME " Failed to request irq.\n");
  return ret;
 }

 key = &keys[1];
 ret = request_irq(key->irq_num, key_irq_handle, SA_INTERRUPT, DEVICE_NAME, NULL);
 if(ret) {
  printk(KERN_INFO DEVICE_NAME " Failed to request irq.\n");
  return ret;
 }

 init_timer(&kbd_timer);
 kbd_timer.function = kbd_timer_handler;
 
 return 0;
}

//-------------------------------------------------
static ssize_t s3c2410_key_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
{
 static int value;

 wait_event_interruptible(key_wait, ready == 1);
// interruptible_sleep_on(&key_wait);

 if(count != sizeof(key_value)) {
  printk("there is no key pressed!\n");
  return -EINVAL;
 }

 value = key_value;
        copy_to_user(buffer, &value, sizeof(value));
 ready = 0;
 
        return sizeof(value);
}

//----------------------------------------------------------
static int s3c2410_key_release(struct inode *inode, struct file *filp)
{
 struct key_info *key=NULL;
 
 printk(KERN_INFO DEVICE_NAME ": released.\n");

 key = &keys[0];
 free_irq(key->irq_num, NULL);
 key = &keys[1];
 free_irq(key->irq_num, NULL);
 
 return 0;
}

//--------------------------------------------------------
static struct file_operations s3c2410_fops = {
 owner: THIS_MODULE,
 open: s3c2410_key_open,
 read:    s3c2410_key_read,
 release: s3c2410_key_release,
};

static int __init key_driver_init(void)
{
 int ret;

 printk("s3c2410 key_driver init\n");

 ret = register_chrdev(0, DEVICE_NAME, &s3c2410_fops);
 if (ret < 0) {
    printk(DEVICE_NAME " can't get major number\n");
    return ret;
 }
 keyMajor = ret;

 #ifdef CONFIG_DEVFS_FS
  devfs_mk_dir("key");
  devfs_mk_cdev(MKDEV(keyMajor, LEDRAW_MINOR), S_IFCHR|S_IRUGO|S_IWUSR, "key/%d", 0);
 #endif
 
 return ret;
}


static void __exit key_driver_exit(void)
{
 printk("key_driver exit!\n");
#ifdef CONFIG_DEVFS_FS 
 devfs_remove("key/%d", 0); 
 devfs_remove("key");   
#endif 

 unregister_chrdev(keyMajor, DEVICE_NAME);
}

module_init(key_driver_init);
module_exit(key_driver_exit);

 

VOD视频点播系统(五)


点赞

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 0

    关注
  • 1

    粉丝
  • 0

    好友
  • 0

    获赞
  • 6

    评论
  • 104

    访问数
关闭

站长推荐 上一条 /2 下一条


小黑屋| 手机版| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-11-26 08:37 , Processed in 0.018019 second(s), 7 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部