键盘ledlcd的3个驱动程序,以WORD的格式打开,有设计思想,步骤,框图,为你学习带来方便

源代码在线查看: 7.5.2.txt

软件大小: 106 K
上传用户: pore
关键词: ledlcd WORD 键盘 设计思想
下载地址: 免注册下载 普通下载 VIP

相关代码

				 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				  {   //循环置列线为高电平
				      //系统寄存器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				        for(k=0;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				  {
				    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				   {
				      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,   /* 设备文件的其他操作 */
				 };
				
				
				
				
				
				
				
				
				
				
				
				
				
				   			

相关资源