1驱动程序
/*************************************************************************
> File Name: key_misc.c
> Author: yas
> Mail: rage_yas@hotmail.com
> Created Time: 2024年04月22日 星期一 17时20分42秒
************************************************************************/
#if 1
/*=========================The key_misc driver=========================*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <asm/io.h>
/*寄存器地址映射*/
#define GPGCON (0x56000060)
#define GPGUP (0x56000068)
#define GPGDAT (0x56000064)
/*保存寄存器地址映射*/
unsigned int *regGPGCON;
unsigned int *regGPGUP;
unsigned int *regGPGDAT;
/*接收返回的键值*/
u8 key=0;
/*key函数声明*/
void key_init(void);
u8 key_press(void);
void delay_nms(u32 t);
/*驱动函数声明*/
void ioremap_r(void);
static int __init key_driver_init(void);
static int key_driver_open(struct inode *node, struct file *fp);
static ssize_t key_driver_read(struct file *fp, char __user *user_buffer, size_t len, loff_t *offset);
static ssize_t key_driver_write(struct file *fp, const char __user *user_buffer, size_t len, loff_t *offset);
static int key_driver_close(struct inode *node, struct file *fp);
void iounmap_r(void);
static void __exit key_driver_exit(void);
/*定义字符设备文件操作结构体变量*/
static struct file_operations fops =
{
.owner = THIS_MODULE,
.open = key_driver_open,
.read = key_driver_read,
.write = key_driver_write,
.release = key_driver_close
};
static struct miscdevice key_dev =
{
.minor = MISC_DYNAMIC_MINOR,
.name = "key_r",
.fops = &fops
};
#if 1
/*******************************************************************************
* 函 数 名 : ioremap_r
* 函数功能 : 寄存器映射
* 输 入 :无
* 输 出 :无
*******************************************************************************/
void ioremap_r(void)
{
/*寄存器映射*/
regGPGCON = ioremap(GPGCON, 4);//【源地址】【需要映射的地址大小】<返回目标地址>
regGPGUP = ioremap(GPGUP,4);
regGPGDAT = ioremap(GPGDAT, 4);
}
#endif
#if 1
/*******************************************************************************
* 函 数 名 : key_driver_init
* 函数功能 : key驱动初始化
* 输 入 :无
* 输 出 :无
*******************************************************************************/
static int __init key_driver_init(void)
{
int ret=0;
ret=misc_register(&key_dev);
if(ret<0)
{
printk("misc_register is failed\n");
goto misc_register_err;
}
/*寄存器映射*/
ioremap_r();
/*key初始化*/
key_init();
printk("key_driver_init OK\n");
return 0;
misc_register_err:
return -1;
}
#endif
#if 1
static int key_driver_open(struct inode *node, struct file *fp)
{
return 0;
}
#endif
#if 1
static ssize_t key_driver_read(struct file *fp, char __user *user_buffer, size_t len, loff_t *offset)
{
key_press();
copy_to_user(user_buffer,&key,4);
// key=0;
return sizeof(key);
}
#endif
#if 1
/*******************************************************************************
* 函 数 名 : key_driver_write
* 函数功能 : key驱动写数据
* 输 入 :
* fp:
* user_buffer:
* offset:
* 输 出 :无
*******************************************************************************/
static ssize_t key_driver_write(struct file *fp, const char __user *user_buffer, size_t len, loff_t *offset)
{
return 0;
}
#endif
#if 1
static int key_driver_close(struct inode *node, struct file *fp)
{
return 0;
}
#endif
#if 1
/*******************************************************************************
* 函 数 名 : ioremap_r
* 函数功能 : 寄存器反映射
* 输 入 :无
* 输 出 :无
*******************************************************************************/
void iounmap_r(void)
{
/*寄存器反映射*/
iounmap(regGPGCON);
iounmap(regGPGUP);
iounmap(regGPGDAT);
}
#endif
#if 1
/*******************************************************************************
* 函 数 名 : key_driver_exit
* 函数功能 : 退出key驱动
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
static void __exit key_driver_exit(void)
{
iounmap_r();
misc_deregister(&key_dev);
printk("key_driver_exit OK\n");
}
#endif
/*=========================key配置函数=========================*/
/*******************************************************************************
* 函 数 名 : key_init
* 函数功能 : 独立按键初始化
* 输 入 :无
* 输 出 :无
*******************************************************************************/
//K1-EINT8-GPG0,K2-EINT11-GPG3,K3-EINT13-GPG5,
//K4-EINT14-GPG6,K5-EINT15-GPG7,K6-EINT19-GPG11
void key_init(void)
{
*regGPGCON&=~((0X03<<0)|(0X03<<6)|(0X03<<10)|(0X03<<12)|(0X03<<14)|(0X03<<22));//KEY控制引脚配置-输入状态
*regGPGUP|=(0X01<<0)|(0X01<<11);//上拉使能寄存器-置位-禁止上拉
//思考:为何要关闭K1和K6按键对应引脚内部的上拉电阻?(原理图)
//这里和LED的区别是:不需要将按键的数据寄存器初始化,
//而LED是需要保证初始状态为关闭
}
/*******************************************************************************
* 函 数 名 : key_press
* 函数功能 : 检测按键按下
* 输 入 :
* 无
* 输 出 : 返回键值
*******************************************************************************/
u8 key_press(void)
{
if((*regGPGDAT&(0X01<<0))==0)//问题1:【&】和【==】的优先级不确定,导致按键功能故障;解决:使用括号
{
key=1;
}
else if((*regGPGDAT&(1<<3))==0)
{
key=2;
}
else if((*regGPGDAT&(1<<5))==0)
{
key=3;
}
else if((*regGPGDAT&(1<<6))==0)
{
key=4;
}
else if((*regGPGDAT&(1<<7))==0)
{
key=5;
}
else if((*regGPGDAT&(1<<11))==0)
{
key=6;
}
else
{
key=0;
}
return key;
}
/*******************************************************************************
* 函 数 名 : delay_nms
* 函数功能 : 延时nms
* 输 入 :
* t:延时时间
* 输 出 : 无
*******************************************************************************/
void delay_nms(u32 t)
{
u32 i=0;
u32 j=0;
for(i=0;i<t;i++)
{
for(j=0;j<100;j++);
}
}
module_init(key_driver_init);
module_exit(key_driver_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("XXX");
/*=========================The key_misc driver=========================*/
#endif
2应用程序
/*************************************************************************
> File Name: main.c
> Author: yas
> Mail: rage_yas@hotmail.com
> Created Time: 2024年04月22日 星期一 17时20分42秒
************************************************************************/
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
int main(void)
{
#if 1
/*====================key-r====================*/
int fd=0;
int n=0;
fd=open("dev/key_r",O_RDWR);//这里路径一定要对,尤其是手动创建设备结点的时候
if(fd<0)
{
printf("opening is failed\n");
return -1;
}
while(1)
{
read(fd,&n,4);
printf("%d\n",n);
sleep(1);
}
return 0;
/*========================================*/
#endif
}
3运行结果
由运行结果可以看到,6颗独立按键的驱动全部正常。