Linux内核驱动开发-001字符设备开发-003独立按键杂项驱动

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

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/582358.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

不同语言在算法使用方面的差异(Java 、C++篇)

由于我认为的会了是能得到结果了&#xff0c;所以我亲自去把题解的C代码给改成了Java的&#xff0c;尽管代码和逻辑上的高度统一。编译器还是报错了。 第三个死都过不去。而且后面的还超时了。 这使我十分怀疑是不是超时或者空间不够所导致的。但是去问讯飞星火&#xff0c;它…

PhotosCollage for Mac:优雅且实用的照片拼贴软件

PhotosCollage for Mac是一款优雅且实用的照片拼贴软件&#xff0c;为Mac用户提供了一个便捷、高效的平台&#xff0c;以创建精美、个性化的照片拼贴作品。 PhotosCollage for Mac v1.4.1激活版下载 该软件界面简洁直观&#xff0c;操作便捷。用户只需将想要拼贴的照片拖入“照…

社交媒体数据恢复:Singal

Signal 数据恢复方法 Signal 是一款主打安全的即时通信应用&#xff0c;它采用了端到端加密的聊天方式。然而&#xff0c;有时候用户可能会遇到数据丢失的问题&#xff0c;例如不小心删除了重要的聊天记录或者忘记了 PIN 码导致无法访问账户数据。以下是针对 Signal 数据恢复的…

花生壳域名收费?那就用免费的dnsexit动态域名解析保姆级图文教程,效果杠杠的

免费dnsexit动态域名解析教程 在互联网上有很多不同的域名解析服务&#xff0c;其中dnsexit是一个流行的免费动态域名解析服务&#xff0c;它允许用户动态更新其IP地址&#xff0c;确保域名始终指向正确的服务器。以下是一个dnsexit动态域名解析的图文教程&#xff0c;帮助你了…

区块链 | OpenSea 相关论文:Toward Achieving Anonymous NFT Trading(三)

&#x1f951;原文&#xff1a; Toward Achieving Anonymous NFT Trading VII 讨论&#xff1a;关于匿名性与市场平台的困境 在本文的这一部分&#xff0c;我们将讨论关于隐藏 NFT 所有者地址的困境&#xff0c;以及为什么像 OpenSea 这样的 NFT 市场平台几乎必须得到完全的信…

Python-VBA函数之旅-min函数

目录 一、min函数的常见应用场景 二、min函数使用注意事项 三、如何用好min函数&#xff1f; 1、min函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推荐阅读&#xff1a; 个人主页&#xff1a;神奇夜光杯-CSDN博客 一、min函数的常见应用场景 mi…

vue跟jQuery中的事件冒泡、事件捕获、事件委托(事件代理)

1、事件捕获、事件冒泡 在JS中&#xff0c;我们管事件发生的顺序叫“事件流” 标准的事件流&#xff1a;当dom触发了事件后&#xff0c;会先通过事件传播捕获到目标元素&#xff0c;然后目标节点通过事件传播实现事件冒泡 事件传播&#xff1a;无论是捕获还是冒泡&#xff0…

百面算法工程师 | 池化相关总结

目录 14.1 什么是池化 14.2 池化层的作用 14.3 平均池化 14.4 最大池化 14.5 空间金字塔池化 14.6 ROI Pooling 14.7 最大池化与平均池化是如何进行反向传播的 14.8 卷积层与池化层的区别 欢迎大家订阅我的专栏一起学习共同进步 祝大家早日拿到offer&#xff01; lets…

位运算、状态压缩、枚举子集汇总

本文涉及知识点 证明容斥原理和证明集合枚举都用到了&#xff1a;二项式定理 【数学归纳法 组合数学】容斥原理 基础知识 位运算优先级 位运算的结合性都是从左到右。优先级低的先运算。 优先级位运算符说明7<< >>位左移/位右移10&按位与11^按位异或12按位…

织梦云端:网络信号原理的艺术解码

hello &#xff01;大家好呀&#xff01; 欢迎大家来到我的Linux高性能服务器编程系列之《织梦云端&#xff1a;网络信号原理的艺术解码》&#xff0c;在这篇文章中&#xff0c;你将会学习到网络信号原理以及应用&#xff0c;并且我会给出源码进行剖析&#xff0c;以及手绘UML图…

【树莓派】yolov5 Lite,目标检测,行人检测入侵报警,摄像头绑定

延续之前的程序&#xff1a; https://qq742971636.blog.csdn.net/article/details/138172400 文章目录 播放声音pygame不出声音怎么办&#xff08;调节音量&#xff09;树莓派上的音乐播放器&#xff08;可选&#xff09;命令行直接放歌&#xff08;尝试放mp3歌曲&#xff09; …

数据结构-二叉搜索树(BST)

目录 什么是二叉搜索树 二叉搜索树的特性 (1)顺序性 (2)局限性 二叉搜索树的应用 二叉搜索树的操作 (1)查找节点 (2)插入节点 (3)删除节点 (4)中序遍历 什么是二叉搜索树 如图所示&#xff0c;二叉搜索树&#xff08;binary search tree&#xff09;满足以下条件。…

【Vivado那些事儿】使用 Python 提取 ILA 数据

ILA应该是调试AMD-Xilinx FPGA最常用的IP。 在调试中&#xff0c;我们希望 ILA 中的波形可以提供有关设计问题的所有信息&#xff0c;但情况并非如此。对于复杂的调试&#xff0c;我们还需要将 ILA 捕获的真实数据存储到可以进一步处理的文件中。根据放置 ILA 的位置&#xff0…

C语言阶段的题目解析

前言 我们C语言已经学习的差不多了&#xff0c;但是C语言之中存在的一些问题与难点我们还不一定能够又快又好地解决&#xff0c;为了夯实我们的基础&#xff0c;我们来练习几道稍微有点难度的C语言习题吧 例题一 题目 int main(void) {unsigned char i 7;int j 0;for (; i…

【PyTorch 实战3:YOLOv5检测模型】10min揭秘 YOLOv5 检测网络架构、工作原理以及pytorch代码实现(附代码实现!)

YOLOv5简介 YOLOv5&#xff08;You Only Look Once, Version 5&#xff09;是一种先进的目标检测模型&#xff0c;是YOLO系列的最新版本&#xff0c;由Ultralytics公司开发。该模型利用深度学习技术&#xff0c;能够在图像或视频中实时准确地检测出多个对象的位置及其类别&…

千锤百炼之每日算法(三)

题外话 不会再水了,先把算法任务完成! 正题 第一题 简写单词 规定一种对于复合词的简写方式为只保留每个组成单词的首字母,并将首字母大写后再连接在一起 比如“College English Test"可以简写成“CET",“Computer Science 可以简写为"CS"&#xff0c;I a…

【深度学习】【Lora训练1】StabelDiffusion,Lora训练过程,秋叶包,Linux,SDXL Lora训练

文章目录 一、环境搭建指南二、个性化安装流程三、启动应用四、打开web五、开始训练 19.27服务器 一、环境搭建指南 打造一个高效且友好的开发环境&#xff1a; 项目源码获取&#xff1a; 通过以下命令轻松克隆项目及所有子模块至您的Linux系统&#xff1a; git clone --recu…

《ElementUI 基础知识》el-tabs header 监听鼠标中键滚动时左右滑动(ElementPlus同样适用)

前言 收到需求&#xff0c;可监听 el-tabs 头在鼠标 hover 时。滑动鼠标中键&#xff0c;可左右滑动&#xff01; 效果 鼠标中键上下滑动时&#xff1b;向上滑&#xff0c;向左移动&#xff1b;向下滑&#xff0c;向右移动&#xff1b; 实现 代码56 - 60行&#xff0c;添加…

寝室快修|基于SprinBoot+vue的贵工程寝室快修小程序(源码+数据库+文档)

贵工程寝室快修目录 目录 基于SprinBootvue的贵工程寝室快修小程序 一、前言 二、系统设计 三、系统功能设计 1学生信息管理 2 在线报修管理 3公告信息管理 4论坛信息管理 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&a…

操作系统安全:安全审计,Windows系统日志详解,Windows事件ID汇总

「作者简介」&#xff1a;2022年北京冬奥会网络安全中国代表队&#xff0c;CSDN Top100&#xff0c;就职奇安信多年&#xff0c;以实战工作为基础对安全知识体系进行总结与归纳&#xff0c;著作适用于快速入门的 《网络安全自学教程》&#xff0c;内容涵盖系统安全、信息收集等…