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

news2024/9/21 2:31:59

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.coloradmin.cn/o/1617017.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【MATLAB源码-第193期】基于matlab的网络覆盖率NOA优化算法仿真对比VFINOA,VFPSO,VFNGO,VFWOA等算法。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 NOA&#xff08;Network Optimization Algorithm&#xff0c;网络优化算法&#xff09;是一个针对网络覆盖率优化的算法&#xff0c;它主要通过优化网络中节点的分布和配置来提高网络的整体覆盖性能。网络覆盖率是衡量一个无…

【三维地图无人机路径规划】基于标准A星算法+平滑度优化

课题名称&#xff1a; 基于标准A星算法平滑度优化的无人机三维地图路径规划 版本时间&#xff1a; 2024-04-22 程序运行&#xff1a; 直接运行AStar.m 文件即可 代码获取方式&#xff1a; QQ&#xff1a;491052175 VX&#xff1a;Matlab_Lover 特殊说明&#xff1a; …

zabbix“专家坐诊”第237期问答

问题一 Q&#xff1a;在一台虚拟机安装了mysql数据库服务器上安装了agent&#xff0c;将MySQL by Zabbix agent模板联接上去了&#xff0c;但增加的mysql监控项&#xff0c;全部显示为不支持的&#xff0c;这是什么原因&#xff1f; A&#xff1a;这个是自定义脚本的形式&#…

Java中使用Graphics2D实现字符串- 竖直并居中排序显示算法

效果&#xff1a; 代码&#xff1a; public static void drawMyString(Graphics textGraphics, String text) {// 每列显示的汉字数量int columnSize 7;// 文字之间的垂直间距int verticalSpacing 75;// 获取字体渲染上下文FontMetrics fm textGraphics.getFontMetrics();//…

STC15L2K60S2-28I-LQFP44 单片机芯片 STC宏晶

STC15L2K60S2-28I-LQFP44 规格信息&#xff1a; 产品类型STC(宏晶) UART/USART2 额定特性- SPI1 USB Device0 USB Host/OTG0 PWM3 I2C&#xff08;SMBUS/PMBUS&#xff09;0 LCD0 工作电压2.4V ~ 3.6V EEPROM 尺度1KB Ethernet0 A/D8x10bit CAN0 D/A3x10bit CPU…

网站被SmartScreen标记为不安全怎么办?

在互联网时代&#xff0c;网站的安全性和可信度是用户选择是否继续访问的重要因素之一&#xff0c;然而&#xff0c;网站运营者偶尔会发现使用Edge浏览器访问网站时&#xff0c;会出现Microsoft Defender SmartScreen&#xff08;以下简称SmartScreen&#xff09;提示网站不安全…

代理设置方法 ubuntu git

目录 ubuntu设置代理方法 git 中 ubuntu设置代理方法 &#xff08;1&#xff09; .bashrc中写 或者 &#xff08;2&#xff09; 当自己的 虚拟机选择default switch&#xff0c;保持了虚拟机与本机的联通性&#xff08;host模式好像&#xff09;&#xff0c;这时&#xff0…

SAM5916B 法国追梦DREAM 音频DSP芯片

法国追梦/DERAM SAM5504/5704/5716/5808音频DSP芯片,开发板&#xff0c;方案 可用于电子鼓、电子琴、电吉他、效果器、均衡器、啸叫抑制器等电声产品领域 一、全系列芯片&#xff1a; SAM2634 SAM2695 SAM5504B SAM5704B SAM5708B SAM5808B SAM5716B SAM5916B... 二、原厂开发套…

大厂常见算法50题-反转链表

专栏持续更新50道算法题&#xff0c;都是大厂高频算法题&#xff0c;建议关注。 文章目录 解法参考链接题目解法一 双指针解法二 递归解法三 妖魔化的双指针总结 解法参考链接 题目 解法一 双指针 定义两个指针&#xff1a; pre 和 cur。pre 在前 cur 在后。每次让 pre的 nex…

React 19 带来了 JSX 运行时的重要更新

在 React 的发展历程中&#xff0c;JSX 运行时一直扮演着重要的角色。在以前的的版本&#xff0c;JSX 运行时会克隆传入的 props 对象&#xff0c;这背后有着两大原因。 历史原因 React 保留了一些特殊的 prop 名称&#xff0c;如 key 和在 React 19 之前的 ref。这些 prop 并…

【Docker】Docker基本操作

docker 发展历史 https://www.cnblogs.com/rongba/articles/14782624.html Docker概述 Docker是一个开源的应用容器引擎&#xff0c;基于go语言开发并遵循了apache2.0协议开源。 Docker是在Linux容器里运行应用的开源工具&#xff0c;是一种轻量级的“虚拟机”。 Docker 的容…

指针专题(4)【qsort函数的概念和使用】

1.前言 上节我们学习了指针的相关内容&#xff0c;本节我们在有指针的基础的条件下学习一下指针的运用&#xff0c;那么废话不多说&#xff0c;我们正式进入今天的学习 2.回调函数 我们既然已经学习了指针的相关基础&#xff0c;那么我们此时就可以用指针来实现回调函数 而回…

轻松学会微信小程序开发(一)

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

Java常见面试题总结

文章目录 1. 什么是线程和进程?2. 请简要描述线程与进程的关系,区别及优缺点&#xff1f;3. 什么是堆和方法区&#xff1f;4. 并发与并行的区别5. 同步和异步的区别6.为什么要使用多线程? 优点&#xff1f;&#xff08;重要&#xff09;7. 使用多线程可能带来什么问题?8. 如…

javaWeb中的classpath

参考&#xff1a;https://www.cnblogs.com/StarbucksBoy/p/11375475.html 日常开发过程中的项目目录结构 打包后的war包&#xff0c;解压缩后的目录结构 打包前后文件的映射关系如下&#xff1a;

ElasticSearch查询时修改打分

原生的ES打分基于BM25算法&#xff0c;相比于TF-IDF已经有了较大的改进&#xff0c;但是在实际场景中往往最终的排序效果还是需要进行调整。由于直接修改索引的权重往往代价较大&#xff0c;比较经济的方式还是在查询时即时修改得分以实现排序控制。 注&#xff1a;案例测试数据…

MO DOCKER - Docker synopsis - Huge

Docker synopsis website addressDocker series2.1 今日课程介绍2.2 初始docker - 什么是docker website address url address Docker series 2.1 今日课程介绍 2.2 初始docker - 什么是docker 项目部署的问题 大型项目组件较多, 运行环境也较为复杂,部署时会碰到一些问题…

VR MR AR 的区别

VR(Virtual Reality)、MR(Mixed Reality)和AR(Augmented Reality)是三种不同的沉浸式技术,它们各自在交互方式、信息呈现和环境感知方面有着显著的区别。 以下是这三种技术的详细对比: VR (Virtual Reality) 虚拟现实 定义与特点: 完全沉浸:VR技术通过头戴式显示器…

keil创建单片机工程

一、创建工程 打开Keil uVision4&#xff0c;依次选择 Project—>New uVision4 Project&#xff0c;选择工程保存路径及填写工程名称&#xff0c;如下图 然后点“保存”。在Select a CPU Data Base File中选择"STC MCU Database"&#xff0c;点 "OK"&am…

Linux/Usage

Usage Enumeration nmap 首先使用 nmap 默认配置扫描系统端口对外开放情况&#xff0c;发现对外开放了 22 和 80 端口&#xff0c;然后又扫描了这两个端口的详细信息&#xff0c;情况如下 ┌──(kali㉿kali)-[~/vegetable/HTB/Usage] └─$ nmap -sC -sV -p 22,80 -oA nmap…