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

news/2024/10/11 7:27:03/

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.ppmy.cn/news/1443505.html

相关文章

【Unity动画系统】详解Root Motion动画在Unity中的应用(二)

Root Motion遇到Blend Tree 如果Root Motion动画片段的速度是1.8&#xff0c;那么阈值就要设置为1.8&#xff0c;那么在代码中的参数就可以直接反映出Root Motion的最终移动速度。 Compute Thresholds&#xff1a;根据Root Motion中某些数值自动计算这里的阈值。 Velocity X/…

linux运行jar

安装Java环境 下载Java安装包 首先&#xff0c;需要从Oracle官网或其他可信渠道下载适用于Linux系统的Java安装包。根据系统架构&#xff08;32位或64位&#xff09;选择合适的安装包。 安装Java 下载完成后&#xff0c;通过终端进入安装包所在目录&#xff0c;使用tar命令…

【前端热门框架【vue框架】】——条件渲染和列表渲染的学习的秒杀方式

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;程序员-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;v…

每天一个数据分析题(二百九十九)

用于描述各个维度项的表现水平与标准维度项的表现水平之间的差异程度的是哪种指标计算方法&#xff1f; A. 标准比 B. 均比 C. 目标比 D. 基准比 题目来源于CDA模拟题库 点击此处获取答案 cda数据分析考试&#xff1a;点击进入

【自然语言处理】InstructGPT、GPT-4 概述

InstructGPT官方论文地址&#xff1a;https://arxiv.org/pdf/2203.02155.pdf GPT-4 Technical Report&#xff1a;https://arxiv.org/pdf/2303.08774.pdf GPT-4&#xff1a;GPT-4 目录 1 InstructGPT 2 GPT-4 1 InstructGPT 在了解ChatGPT之前&#xff0c;我们先看看Instr…

c++的策略模式,就是多态

一、定义&#xff1a; 策略模式定义了一系列的算法&#xff0c;并将每一个算法封装起来&#xff0c;而且使它们还可以相互替换。 策略模式让算法独立于使用它的客户而独立变化。 二&#xff0c;核心 抽象策略&#xff08;抽象基类&#xff09;&#xff08;Strategy&#xff09…

sql将日期区间拆分为多行

将日期区间拆分为多行 将二维表格中的开始时间结束间用sql拆分成多行连续的时间 源数据 start_dateend_date2023-12-012023-12-03 结果 biz_datestart_dateend_date2023-01-012023-12-012023-12-032023-01-022023-12-012023-12-032023-01-032023-12-012023-12-03 代码 S…

GO语言核心30讲 进阶技术

原站地址&#xff1a;Go语言核心36讲_Golang_Go语言-极客时间 一、数组和切片 1. 两者最大的不同&#xff1a;数组的长度是固定的&#xff0c;而切片的长度是可变的。 2. 可以把切片看成是对数组的一层封装&#xff0c;因为每个切片的底层数据结构中&#xff0c;一定会包含一…