Chinaunix首页 | 论坛 | 博客
  • 博客访问: 497613
  • 博文数量: 92
  • 博客积分: 3146
  • 博客等级: 中校
  • 技术积分: 2314
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-27 10:20
文章分类

全部博文(92)

文章存档

2014年(3)

2013年(17)

2012年(16)

2011年(22)

2010年(34)

分类: 嵌入式

2010-10-08 18:55:17

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include  
#include
#include
#include
#include
#define  rGPFCON  (*((volatile unsigned *)(ioremap((volatile unsigned *)0x56000050,4))))
#define  rGPFDAT  (*((volatile unsigned *)(ioremap((volatile unsigned *)0x56000054,4))))
#define  rGPGCON  (*((volatile unsigned *)(ioremap((volatile unsigned *)0x56000060,4))))
#define  rSRCPND  (*((volatile unsigned *)(ioremap((volatile unsigned *)0x4a000000,4))))
#define  rINTMOD  (*((volatile unsigned *)(ioremap((volatile unsigned *)0x4a000004,4))))
#define  rINTMSK  (*((volatile unsigned *)(ioremap((volatile unsigned *)0x4a000008,4))))
#define  rINTPND  (*((volatile unsigned *)(ioremap((volatile unsigned *)0x4a000010,4))))
#define rEXTINT0  (*((volatile unsigned *)(ioremap((volatile unsigned *)0x56000088,4))))
#define rEXTINT1  (*((volatile unsigned *)(ioremap((volatile unsigned *)0x5600008c,4))))
#define rEXTINT2  (*((volatile unsigned *)(ioremap((volatile unsigned *)0x56000090,4))))
#define rEINTMASK (*((volatile unsigned *)(ioremap((volatile unsigned *)0x560000a4,4))))
#define rEINTPEND (*((volatile unsigned *)(ioremap((volatile unsigned *)0x560000a8,4))))
#define KEY_1   1
#define KEY_2   2
#define KEY_3   3
#define KEY_4   4
#define NOKEY   0
#define  MJNOR  166  //主设备号
#define  MINOR  0    //次设备号
void delay(int time);           //延时
int  get_keyvalue(void);         //消抖去重复之后的键值
void key_regeister_init(void);  //寄存器的初始化(中断)
static unsigned int key_old = NOKEY;   //保存上一次按键的值
static unsigned int key_new = NOKEY;   //保存当前按键的值
static unsigned int keyflag,keynumber; //记录按键的状态和按键的值
static irqreturn_t key_irq_1(void)     //按键中断1处理函数
{
 rSRCPND |= (1<<0);   //写1 清除
 rINTPND |= (1<<0);   //中断能被响应
 keynumber = KEY_1; 
 keyflag = 1;
 printk("发生中断EINT0\n");
}
static irqreturn_t key_irq_2(void)   //按键中断2处理函数
{
 rSRCPND |= (1<<2);        //写1 清除
 rINTPND |= (1<<2);
 keynumber = KEY_2;
 keyflag = 1;
 printk("发生中断EINT1\n");
}
static irqreturn_t key_irq_34(void)   //按键中断3、4处理函数
{
 if((rEINTPEND & (1<<11))==1)
 {
  rEINTPEND |= (1<<11);     //写1清楚EINTPEND中的EINT11位
  rSRCPND |= (1<<5);        //写1 清除
  rINTPND |= (1<<5);
  keynumber = KEY_3;
  keyflag = 1;
  printk("发生中断EINT11\n");
 }
 else
  
 {
  rEINTPEND |= (1<<11);   //写1清楚EINTPEND中的EINT19位
  rSRCPND |= (1<<5);      //写1 清除
  rINTPND |= (1<<5);
  keynumber = KEY_4;
  keyflag = 1;
  printk("发生中断EINT19\n");
 }
}

//设备结构体
struct key_dev
{
 struct cdev cdev;
 struct semaphore sem;    //并发控制用的信号量
 unsigned int key_value;  //用于判断按键值
};

struct key_dev *key_dev;
int key_major = MJNOR;

static int key_open(struct inode *inode, struct file *filp)
{
 struct key_dev *dev;
 unsigned int temp;
 //获得设备结构体指针
 dev = container_of(inode->i_cdev,struct key_dev,cdev);
 filp->private_data = dev;
 
 //申请key1中断
 temp = request_irq(IRQ_EINT0,key_irq_1,SA_INTERRUPT,"KEY_IRQ",NULL);
 //中断号被占用
 if(temp)
  printk(KERN_ERR"IRQ %d already in use \n",IRQ_EINT0);
 
    //申请key2中断
 temp = request_irq(IRQ_EINT2,key_irq_2,SA_INTERRUPT,"KEY_IRQ",NULL);
 //中断号被占用
 if(temp)
  printk(KERN_ERR"IRQ %d already in use \n",IRQ_EINT2);
 
 //申请key3中断
 temp = request_irq(IRQ_EINT11,key_irq_34,SA_INTERRUPT,"KEY_IRQ",NULL);
 //中断号被占用
 if(temp)
  printk(KERN_ERR"IRQ %d already in use \n",IRQ_EINT11);
 
 //申请key4中断
 temp = request_irq(IRQ_EINT19,key_irq_34,SA_INTERRUPT,"KEY_IRQ",NULL);
 //中断号被占用
 if(temp)
  printk(KERN_ERR"IRQ %d already in use \n",IRQ_EINT19);
 
 //初始化硬件设备
 //初始化按键
 key_regeister_init();
 
  return 0;
}
int key_release(struct inode *inode, struct file *filp)
{
 free_irq(IRQ_EINT0,NULL); //释放中断
 free_irq(IRQ_EINT2,NULL);
 free_irq(IRQ_EINT11,NULL);
 free_irq(IRQ_EINT19,NULL);
 return 0;
}

ssize_t key_read(struct file *filp,char __user *buf,size_t count,loff_t *f_ops)
{
 struct key_dev *dev;
 dev = filp->private_data;
 
 while(1)
 {
  dev->key_value = get_keyvalue();
  
  if(dev->key_value == 0)
   continue;
  else
   break;
 }
 printk("%d\n",dev->key_value);
 down(&dev->sem);  //获取信号量
 if(copy_to_user(buf,(&dev->key_value),sizeof(int)))
 {
  return -EFAULT;
 }
 up(&dev->sem);   //释放信号量
 return 1;
 
}
 
struct file_operations key_fops =
{
 .owner = THIS_MODULE,
 .open = key_open,
 .release = key_release,
 .read = key_read,
};
static int key_init(void)
{
 int result;
 dev_t dev;
 
 dev = MKDEV(key_major,MINOR);
 //申请字符设备
 if(key_major)
  result = register_chrdev_region(dev, 1, "LED"); //静态申请设备号
 else
 {
  result = alloc_chrdev_region(&dev,0,1,"LED");  //动态申请设备号
  key_major = MAJOR(dev);
 }
 if(result < 0)
  return result;
   
 //分配设备结构体的内存
 key_dev = kmalloc(sizeof(struct key_dev),GFP_KERNEL);
 
 if(!key_dev)
 {
  result = -ENOMEM;
  goto fail_malloc;
 }
 
 memset(key_dev,0,sizeof(struct key_dev));
 cdev_init(&key_dev->cdev,&key_fops);
 key_dev->cdev.owner = THIS_MODULE;
 key_dev->cdev.ops = &key_fops;
 
 result = cdev_add(&key_dev->cdev,dev,1);//向系统增加一个设备
 if(result)
  printk("ERROR adding led\n");
   
 init_MUTEX(&key_dev->sem); //初始化信号量
 return 0;
fail_malloc: unregister_chrdev_region(dev,key_dev);
    return result;
}
static int key_exit(void)
{
 dev_t devno = MKDEV(MJNOR, MINOR); //获得主设备号
    cdev_del(&key_dev->cdev); //删除字符设备结构体
    kfree(key_dev);  //释放在light_init中分配的内存
    unregister_chrdev_region(devno,1);//删除字符设备
 return 0;
}
void delay(int time) //延时
{
 int i,j;
 for(i=0;i<100;i++)
 {
  for(j=0;j  {}
 }
}

int get_keyvalue(void)
{
 
 volatile unsigned int key1,key2;
 key1 = keynumber;
 delay(50);
 key2 = keynumber;
 
 if(key1 != key2)                    //消抖
 {
  return NOKEY;
 }
 
 key_new = key2;                   //扫描到一个新值
 
 if(key_old != key_new)            //去重复
 {
  key_old = key_new;
  return key_new;
 }
 return NOKEY;
}

void key_regeister_init(void)
{
 volatile unsigned int temp;
 temp = rGPFCON;             //将I/O口作为EINT的功能
 temp &= ~((3<<4) | 3);      //SW1--EINT0  SW2--EINT2
 temp |= ((1<<5) | (1<<1));  //配置为EINT=10
 rGPFCON = temp;
 
 temp = rGPGCON;                //SW3-4 对应寄存器
 temp &= ~((3<<6) | (3<<22));   //SW3--EINT11  SW4--EINT19
 temp |= ((1<<23) | (1<<7));    //配置为EINT=10
 rGPGCON = temp;
 
 //SRCPND为中断请求的寄存器 1--accept 0--request
 rSRCPND |= ((1<<5) | (1<<2) | (1<<0));  //中断请求
 
 //INTMOD中断模式寄存器  0---IRQ  1---FIQ
 rINTMOD &= ~((1<<5) | (1<<2) | (1<<0));  //设置为IRQ中断模式
 
 rINTMSK &= ~((1<<5) | (1<<2) | (1<<0));  //使能中断响应
 
 rINTPND |= ((1<<5) | (1<<2) | (1<<0));    //中断能被响应
 
 //EXTINT* 触发中断方式
 //01X= falling edge triggred
 temp = rEXTINT0;               //EINT0  EINT2为下降沿中断
 temp &= ~((7<<8)|(7<<0));
 temp |= ((2<<8)|(2<<0));
 rEXTINT0 = temp;
 
 temp = rEXTINT1;               //EINT11为下降沿中断
 temp &= ~(7<<12);
 temp |= (2<<12);
 rEXTINT1 = temp;
 
 rEXTINT2 = (rEXTINT2& ~(7<<12)) | (2<<12);  //EINT19为下降沿中断
 rEINTMASK &= ~((1<<11) | (1<<19));          //使能EINT11,EINT19中断
 
}
MODULE_LICENSE("GPL");
module_init(key_init);
module_exit(key_exit);
阅读(936) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~