⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 7.5.2.txt

📁 键盘ledlcd的3个驱动程序,以WORD的格式打开,有设计思想,步骤,框图,为你学习带来方便
💻 TXT
字号:
 7.5.2  键盘驱动程序的实现

1.键盘驱动程序的主要函数
应用程序通过
            fd1 = open(“/dev/kbd7312”,0)
指向设备端口,然后再for(;;)死循环中调用ioctl(fd1,0,0),进程进入驱动程序执行kbd_kernel_ioctl()。

//对键盘设备文件进行读/写之外的其他操作
static int kbd_kernel_ioctl(struct inode * inode,struct file *file,unsigned int cmd,unsigned long arg)
{
     switch(cmd)
     {
        //接收一个按键
        case KBD_GETKEY:
            return kbd_kernel_getkey();
        default:
            printk(“Unknown Keyboard command ID.\n”);
     }
     return 0;
}
//获取一个键值
static int kbd_kernel_getkey()
{
int i,j,k;
enable_irq(16);    //开启键盘中断
KeyValue=0;        //初始化键值
//循环将各列扫描线为高电平,检测是否有键按下
for(i=0;i<4;i++)
  {   //循环置列线为高电平
      //系统寄存器1的低4位为1000B,列线0高电平     
      //系统寄存器1的低4位为1001B,列线1高电平
      //系统寄存器1的低4位为1010B,列线2高电平
      //系统寄存器1的低4位为1011B,列线3高电平
      SYSCON1 &= ~0xf;
      SYSCON1 |=I % 4 + 8;
      //延时循环,避免键盘抖动
      for(j =0;j<1000;j++)
        for(k=0;k<650;k++);
      //如果有键按下,则返回键值
      if(KeyValue){
          return KeyValue;
       }
    }
    //无键按下,返回0
    return 0;
}
   键盘驱动定义的全局变量KeyValue为键值,标志是否有键按下。初始值为0,表示没有键按下。这里cmd为KBD_GETKEY执行取键值程序段。i为键盘的列,先将它赋值为0,然后加以判断。当它为0时,将寄存器0x80000100中低4位置为100B,此时键盘第0列为高,其他为高阻态。如果没有中断,延时一段时间后,将i赋值为1,此时,键盘第1列为高,其他为高阻态。依此类推,直到键盘第4列为高。此间如果没有键按下,则不作任何操作返回应用程序。由于应用程序为一个死循环,所以进程将通过循环调用ioctl(fd1,0,0)进入驱动程序,执行kbd_kernel_ioctl()。继续进行如上所示操作,直到按下一个键,进程接收到中断信息,转入执行中断服务程序kbd_Interrupt()。

//键盘中断服务程序
static void kbd_Interrupt(int irq,void *dev_id,struct pt_regs *regs)
{
    unsigned char LHB_PortA;    /* 端口A数据寄存器的低4位 */
    unsigned char row,col;      /* 按键的行列值 */
    unsigned char keypressed;   /* 是否有键按下的标志 */
    //屏蔽键盘中断
    disable_irq(16);
    //获取端口A数据寄存器的低4位
    LHB_PortA = PADR & 0xf;
    //判断列值:
    //系统寄存器1低4位为1000B,列值为0
    //系统寄存器1低4位为1001B,列值为1
    //系统寄存器1低4位为1010B,列值为2
    //系统寄存器1低4位为1011B,列值为3
    col = (SYSCON1 & 0xF) – 0x8;
    //判断行值
    //端口A数据寄存器的低4位为0001B,行值为0
    //端口A数据寄存器的低4位为0010B,行值为1
    //端口A数据寄存器的低4位为0100B,行值为2
   //端口A数据寄存器的低4位为1000B,行值为3
   keypressed = 0;
   for(row=0;row<4;row++)
  {
    if(LHB_PortA>>row) & 0x1)
    {
      keypressed = 1;
      break;
    }
  }
  //计算键值
  if(keypressed){
   KeyValue = (row * 4 + 1)+col;
  }
  else
    enable_irq(16);
}

 
   此时keypressed被赋值为1,表示有键按下。键盘中断服务程序将端口A数据寄存器中的值赋给LHB_PortA。LHB_PortA值的低4位代表键盘的4行。判断LHB_PortA值,如果为01H,则第0位为1,即按下键在键盘第0行;如果LHB_PortA值为02H,则第1位为1,则按下键在键盘第1行;如果LHB_PortA值为04H,则第2位为1,则按下键在键盘第2行;如果LHB_PortA值为08H,则第3位为1,则按下键在键盘第3行。由row和col的值来计算键值。
   中断程序执行完后,进程返回中断点,继续执行KbdIoctl(),返回键值到应用程序,供应用程序使用。如果中间有另一次中断,则将中断值放入键盘中断使用的寄存器,等待下一次读取。
   值得注意的是,如果当键盘的第0列为高时,按下的键并不在这一列,则并没有中断产生,但是由于人手按下按键要持续很短的时间,而列轮流置高的速度又很快,所以在按键还没有弹起的瞬间,就已经将按下键所在列置高,产生中断,进程转入中断程序。为了去除抖动问题,由两个嵌套的空的for循环实现一小段时间延时。
2.键盘驱动程序的初始化

   当键盘设备打开后,kbd_kernel_init(void)向内核注册模块所能提供的设备,传递的参数为指向描述这个新设备的数据结构和姚注册的设备名称,同时对该设备的各寄存器赋初始化值。
//初始化键盘设备
int kbd_kernel_init(void)
{
   int result;              /* 注册设备结果 */
   //注册键盘设备
   printk("\nRegistering Keyboard Device\t- - ->\t");
   result=register_chrdev(KEYBOARD_MAJOR,"keryboard_ep7312",&Kbd_fops);
   if(result<0)
   {
      printk(KERN_INFO"[FAILED:Cannot register keyboard_ep7312!]\n");
      return result;
    }
   else
     printk("Initializing Keyboard Device\t- - ->\t");
   //设置键盘设备
   setup_kbd();
   //注册键盘中断
   if(request_irq(16,kbd_Interrupt,0,"kbd_interrupt",NULL))
   {
     printk(KERN_INFO"[FAILED:Cannot register keyboard interrupt!]\n");
     return -EBUSY;
    }
    else
      printk("[OK]\n");
    //显示成功加载信息
    printk("\nEP7312 Keyboard Driver installed:\n");
    return 0;
}

所用到的定义和函数如下:

#define SYSCON1		*(unsigned long * )0xff000100		/* 系统寄存器1 */
#define SYSCON2		*(unsigned long * )0xff001100		/* 系统寄存器2 */
#define PADR		*(unsigned char * )0xff000000  		/* 端口A数据寄存器 */
#define PADDR		*(unsigned char * )0xff000040  		/* 端口A方向寄存器 */
#define PBDR		*(unsigned char * )0xff000001  		/* 端口B数据寄存器 */
#define PBDDR		*(unsigned char * )0xff000041  		/* 端口B方向寄存器 */
//ioctl 命令ID
#define KBD_GETKEY	1
//定义键盘的主设备号
#define KEYBOARD_MAJOR	59
static char KeyValue;       /* 键值 */
//设置键盘设备
static void setup_kbd(void)
{
   //设置系统寄存器
   SYSCON1 &= ~0xf;
   SYSCON1 |= 0x8;

   SYSCON2 |= 0x000000008;
   PADDR |= 0xfffffffff;
   //初始化键值
   KeyValve = 0;
}

3.键盘驱动程序提供给文件系统的接口
   当一个进程试图对键盘设备进行操作时就利用了下面的结构。这个结构就是提供给操作系统的接口,其指针保存在设备列表中,在kbd_kernel_init(void)中被传递给操作系统。
//键盘设备文件操作结构
struct file_operations Kbd_fops =
{
   open: 	kbd_kernel_open,    /* 打开设备文件 */
   ioctl:       kbd_kernel_ioctl,   /* 设备文件的其他操作 */
 };













   

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -