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颗独立按键的驱动全部正常。