/*======================================================================
A tangjinxing driver as an example of char device drivers
The initial developer of the original code is Baohua Song
<author@linuxdriver.cn>. All Rights Reserved.
======================================================================*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/proc_fs.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <linux/seq_file.h>
#include <linux/cdev.h>
#include <linux/sched.h>
#include <asm/hardware.h>
#include <asm/system.h> /* cli(), *_flags */
#include <asm/uaccess.h> /* copy_*_user */
#include"keydev.h"
#include "key.h"
int KEY_MAJOR = 0; /*预设的key的主设备号 "0"表示动态分配内存*/
#define MEM_CLEAR 0x1
int write_key=0; /*记入按键下该按键之前的按键值*/
unsigned int New_Key=NO_KEY;
unsigned int Old_Key=NO_KEY;
unsigned int key1;
unsigned int key2;
/*key设备结构体*/
struct key_dev
{
struct cdev cdev; /*cdev结构体*/
unsigned char mem[KEY_SIZE]; /*全局内存*/
};
struct key_dev *key_devp; /*设备结构体指针*/
struct KeyValue key={0}; /*自定义led结构体*/
/*****************************功能函数*********************************************/
/*开发板寄存器初始化*/
void led_init(void)
{
/*led寄存器 初始化*/
volatile unsigned int temp=0;
temp=__raw_readl(rGPFCON);
temp &= ~((3<<8) | (3<<10) | (3<<12) | (3<<14));//将rGPFCON控制寄存器高八位置零
temp |=((1<<8) | (1<<10) | (1<<12) | (1<<14));//初始化rGPFCON为0x5500
__raw_writel(temp,rGPFCON);
//
temp=__raw_readl(rGPFUP);
temp |=((1<<4) | (1<<5) |(1<<6) | (1<<7) );//将rGPFUP控制寄存器高四位变为可用;高四位置’1‘
__raw_writel(temp , rGPFUP);
//
temp=__raw_readl(rGPFDAT);
temp |= ( (1<<4) | (1<<5) | (1<<6) |(1<<7) );//灯全灭
__raw_writel(temp,rGPFDAT);
printk("<0>" "scull_ledopen\n");
/*初始化完成*/
}
/*控制led灯程序*/
void led_value(int led_num, int led_stata)
{
volatile unsigned int temp=0;
switch(led_num)
{
case LED1:
if(ON==led_stata)
{
//输出低电平灯亮
temp=__raw_readl(rGPFDAT);
temp &= ~(1<<4);//LED_1亮
__raw_writel(temp,rGPFDAT);
/*打印出寄存器中的值*/
//printk("<0>" "-----LED1 light\n");
}
else
{
//输出高电平灯灭
temp=__raw_readl(rGPFDAT);
temp |=(1<<4);//LED_1灭
__raw_writel(temp,rGPFDAT);
/*打印出寄存器中的值*/
//printk("<0>" "*****LED1 shut up\n");
}
break;
case LED2:
if(ON==led_stata)
{
//输出低电平灯亮
temp=__raw_readl(rGPFDAT);
temp &= ~(1<<5);//LED_1亮
__raw_writel(temp,rGPFDAT);
/*打印出寄存器中的值*/
//printk("<0>" "-----LED2 light\n");
}
else
{
//输出高电平灯灭
temp=__raw_readl(rGPFDAT);
temp |=(1<<5);//LED_1灭
__raw_writel(temp,rGPFDAT);
/*打印出寄存器中的值*/
//printk("<0>" "*****LED2 shut up\n");
}
break;
case LED3:
if(ON==led_stata)
{
//输出低电平灯亮
temp=__raw_readl(rGPFDAT);
temp &= ~(1<<7);//LED_1亮
__raw_writel(temp,rGPFDAT);
/*打印出寄存器中的值*/
//printk("<0>" "-----LED3 light\n");
}
else
{
//输出高电平灯灭
temp=__raw_readl(rGPFDAT);
temp |=(1<<7);//LED_1灭
__raw_writel(temp,rGPFDAT);
/*打印出寄存器中的值*/
//printk("<0>" "*****LED3 shut up\n");
}
break;
case LED4:
if(ON==led_stata)
{
//输出低电平灯亮
temp=__raw_readl(rGPFDAT);
temp &= ~(1<<6);//LED_1亮
__raw_writel(temp,rGPFDAT);
/*打印出寄存器中的值*/
//printk("<0>" "-----LED4 light\n");
}
else
{
//输出高电平灯灭
temp=__raw_readl(rGPFDAT);
temp |=(1<<6);//LED_1灭
__raw_writel(temp,rGPFDAT);
/*打印出寄存器中的值*/
//printk("<0>" "*****LED4 shut up\n");
}
break;
default:
break;
}
}
void beep(unsigned int freq)
{
/*蜂鸣器初始化*/
volatile unsigned int temp=0;
//设置引脚GPB2为Timer功能引
temp=__raw_readl(rGPBCON);
temp &=~((1<<2) | (1<<3));
temp |=(1<<3);
__raw_writel(temp,rGPBCON);
temp=__raw_readl(rGPBUP);
temp |=(1<<1);
__raw_writel(temp,rGPBUP);
//定时器配置寄存器0的前8位置一
//预分频器Prescaler 0配置成255
temp=__raw_readl(rTCFG0);
temp |=0xff;
__raw_writel(temp,rTCFG0);
//定时器配置寄存器0的前8位置一
//预分频器Prescaler 0配置成255
temp=__raw_readl(rTCFG1);
temp &=~((1<<4) | (1<<5) | (1<<6) | (1<<7));
temp |=(1<<5);
__raw_writel(temp,rTCFG1);
//定时器配置寄存器0的前8位置一
//预分频器Prescaler 0配置成255
temp=__raw_readl(rTCNTB1);
temp=((50000>>11)*freq);
__raw_writel( temp,rTCNTB1);
//当定时器数到总数的一半时电平翻转
temp=__raw_readl(rTCMPB1);
temp=((50000>>12)*freq);
__raw_writel(temp, rTCMPB1);
//BIT[11]:Timer 1 auto reload on/off = Interval mode (auto reload)
//BIT[10]:Timer 1 output inverter on/off = Inverter off
//BIT[9]:Timer 1 manual update = Update TCNTB1 & TCMPB1
//BIT[8]:Timer 1 start/stop = Stop
temp=__raw_readl(rTCON);
temp &=~((1<<8) | (1<<9) | (1<<10) | (1<<11));
temp |=(1<<9);
__raw_writel(temp,rTCON);
//设置为auto reload并且Start for Timer 1
//open [9] [8]
temp = __raw_readl(rTCON);
temp &= ~(0xf<<8);
temp |= (1<<11)|(1<<8);
__raw_writel(temp,rTCON);
temp = __raw_readl(rTCON);
temp &=(~(1<<9));
__raw_writel(temp,rTCON);
printk("<0>" "----------beep_init scuessful\n");
/*蜂鸣器初始化完毕*/
}
/*关闭蜂鸣器*/
void beep_stop(void)
{
volatile unsigned int temp=0;
temp = __raw_readl(rTCON);
temp &=(~(1<<8));
__raw_writel(temp,rTCON);
}
/*********************************key**************************************/
/*键盘寄存器初始化*/
void key_Init(void)
{
volatile unsigned int temp=0;
temp=__raw_readl(rGPFCON);
temp &=~( (3<<4) | 3);
__raw_writel(temp,rGPFCON);
temp=__raw_readl(rGPGCON);
temp &=~( (3<<6) | (3<<22) );
__raw_writel(temp,rGPGCON);
temp=__raw_readl(rGPFUP);
temp |=( (0x1) | (1<<3));
__raw_writel(temp,rGPFUP);
temp=__raw_readl(rGPGUP);
temp |=((1<<3) | (1<<11));
__raw_writel(temp,rGPGUP);
printk("<0>" "key_init()\n");
}
/*键盘初始化完成*/
int key_scanf(void)
{
volatile unsigned int temp=0;
temp= __raw_readl(rGPFDAT) ;
//printk("rGPFDAT = 0x%x\n",temp);
temp=( (~temp) & (0x1 |(0x1<<2) ) );
switch( temp )
{
case 0x1:
return KEY_1;
case 1<<2:
return KEY_2;
default:
break;
}
temp= __raw_readl(rGPGDAT) ;
//printk("rGPGDAT = 0x%x\n",temp);
temp=(~temp) & ( (1<<3) | (1<<11) ) ;
switch(temp)
{
case 0x8:
return KEY_3;
case 0x1<<11:
return KEY_4;
default:
break;
}
return NO_KEY;
}
void key_delay(int time)
{
int i;
int j;
for( i=0; i<=time; i++)
{
for(j=0; j<=650; j++);
}
}
/*获取按键值*/
int get_key(void)
{
key1=key_scanf();//防抖动
key_delay(1000);
key2=key_scanf();
if(key1 != key2)
return NO_KEY;
New_Key=key2;
//防重复
//防止按一个按键有多个信号产生;判断连个标志位的值
//由于此函数在while(1)循环中执行,防止无限发送信号,标准位进行判断
if(New_Key == Old_Key)
{
return NO_KEY;
}
else
{
Old_Key=New_Key;
return New_Key;
}
}
/*初始化模块结束*/
/*********************************************************************************/
/*文件打开函数*/
int key_open(struct inode *inode, struct file *filp)
{
#ifdef LED_INIT
led_init();
#endif
#ifdef KEY_INIT
key_Init();//键盘初始化
#endif
return 0;
}
/*文件释放函数*/
int key_release(struct inode *inode, struct file *filp)
{
return 0;
}
/* ioctl设备控制函数 */
static int key_ioctl(struct inode *inodep, struct file *filp, unsigned int cmd, unsigned long arg)
{
/*
struct key_dev *dev = filp->private_data; //获得设备结构体指针
switch (cmd)
{
case MEM_CLEAR:
memset(k
GEC2440A 按键 用扫描按键方式实现Linux 驱动程序实现
需积分: 9 148 浏览量
2009-10-10
20:05:52
上传
评论
收藏 19KB RAR 举报
tjx163
- 粉丝: 18
- 资源: 392
最新资源
- Screenshot_20240427_031602.jpg
- 网页PDF_2024年04月26日 23-46-14_QQ浏览器网页保存_QQ浏览器转格式(6).docx
- 直接插入排序,冒泡排序,直接选择排序.zip
- 在排序2的基础上,再次对快排进行优化,其次增加快排非递归,归并排序,归并排序非递归版.zip
- 实现了7种排序算法.三种复杂度排序.三种nlogn复杂度排序(堆排序,归并排序,快速排序)一种线性复杂度的排序.zip
- 冒泡排序 直接选择排序 直接插入排序 随机快速排序 归并排序 堆排序.zip
- 课设-内部排序算法比较 包括冒泡排序、直接插入排序、简单选择排序、快速排序、希尔排序、归并排序和堆排序.zip
- Python排序算法.zip
- C语言实现直接插入排序、希尔排序、选择排序、冒泡排序、堆排序、快速排序、归并排序、计数排序,并带图详解.zip
- 常用工具集参考用于图像等数据处理
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈