【linux驱动】定时器的使用

【linux驱动】定时器的使用

文章目录

  • 【linux驱动】定时器的使用
    • 1.介绍
      • 1.1相关名词
      • 1.2配置HZ的方法
    • 2.API
    • 3.示例
    • 4.调试

1.介绍

1.1相关名词

HZ、jiffies、tick

Linux系统启动后,每隔固定周期就会发出timer interrupt(IRQ 0),HZ用来定义每一秒发生多少次timer interrupt;
一般HZ的值并不确定,可以被修改设定;可供修改的值有:100HZ 200HZ 250HZ 300HZ 500HZ 1000HZ;
具体修改方法下面有
Tick是HZ的倒数,意即timer;
也就是发生一次中断的时间;比如HZ是250时,tick为1/250s,也就是4ms;
Jiffies为Linux核心变数(unsigned long)用来记录系统开启以来,发生的timer interrupt的次数;这里需要注意的就是32位的类型会出现溢出导致数据不准确(这个时间好像是30天还是40天,记不住,大概是这个时间);64位的类型就不会出现这个问题,溢出都要几百万年了;其他的倒是不用怎么关注,定时器的使用,程序里面都是套路;下面是一些其他的内容,提供给想了解的同志。

在这里插入图片描述

1.2配置HZ的方法

menuconfig

打开menuconfig配置界面

cd xxx/Linux-xxx.xxx 
make menuconfig

在这里插入图片描述

我的系统默认选择的是100HZ

其他选项:

在这里插入图片描述

.config

cd 到对应linux源码顶层目录下
vi .config

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
在这里插入图片描述

修改后,可以使用下面的命令:
esc 后  :wq!
要是只是看看,就直接esc :q!

2.API

头文件:

#include <linux/timer.h>

对应结构体:

    struct timer_list { struct hlist_node entry; //构成内核链表相关成员unsigned long  expires; //定时器到期时间void   (*function)(struct timer_list *); //定时器处理函数u32			flags; //一般填写为0};

初始化定时器:

方式1void timer_func(struct timer_list *timer){}mytimer.expires = jiffies+HZ;  //# define HZ CONFIG_HZ 定时1stimer_setup(&mytimer, timer_func, 0);方式2/*我的好像是linux版本太低,导致无法使用比较新的API,因此使用下面的方式*/void timer_func(struct timer_list *timer){}
init_timer(&mytimer);
mytimer.expires = jiffies + HZ/50;
mytimer.function = timer_func;  // 设置定时器到期时调用的回调函数还有其他的方式,这里就不一一赘述,有兴趣的可以多多探索

启动定时器:

    void add_timer(struct timer_list *timer)//启动定时器,定时器启动之后只会执行一次,add_timer只能调用一次,//如果第二次调用内核会崩溃int mod_timer(struct timer_list *timer, unsigned long expires)//功能再次启动定时器

删除定时器:

    int del_timer(struct timer_list *timer)//删除定时器

3.示例

key.h

#ifndef __KEY_CTRL_H__
#define __KEY_CTRL_H__#include <linux/timer.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/uaccess.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/timer.h>#define KEY_NAME1 "KEY_USER1"
#define KEY_NAME2 "KEY_USER2"
#define CONSUMER_LABEL1 "user1"
#define CONSUMER_LABEL2 "user2"#define PATH_DTS_KEY_USR1 "/psd_key_irqs/user1"
#define PATH_DTS_KEY_USR2 "/psd_key_irqs/user2"#define KMD_ERR(str) \printk("%s %s line: %d %s \n", __FILE__, __FUNCTION__, __LINE__, str);typedef struct my_key {char *dev_name;struct device_node *key_node;unsigned int key_irq_no;int key_num;int key_status;//led开关状态int Level_state;//电平状态struct timer_list mytimer; // 分配定时器
} key_ctrl_t;/*key1设备树控制的初始化*/
int key1_ctrl_init(key_ctrl_t * key);
/*key2设备树控制的初始化*/
int key2_ctrl_init(key_ctrl_t * key);
/*led设备树控制的卸载处理函数*/
void key_ctrl_exit(key_ctrl_t * key);#endif

key.c

#include"key_ctrl.h"
#include <linux/timer.h>void my_timer_callback1(unsigned long para)
{printk("key1 down...\n");
}void my_timer_callback2(unsigned long para)
{printk("key2 down...\n");
}irqreturn_t key1_irq_handle(int irq, void* dev)
{key_ctrl_t *key1 = (key_ctrl_t *)dev;// 启动定时器mod_timer(&key1->mytimer, jiffies + HZ/50);return IRQ_HANDLED;
}irqreturn_t key2_irq_handle(int irq, void* dev)
{key_ctrl_t * key2 = (key_ctrl_t *)dev;// 启动定时器mod_timer(&key2->mytimer, jiffies + HZ/50);return IRQ_HANDLED;
}int key1_ctrl_init(key_ctrl_t * key)
{int ret;key->key_node = of_find_node_by_path(PATH_DTS_KEY_USR1);if(IS_ERR(key->key_node)){KMD_ERR("of_find_node_by_path ERR");ret = -ENODATA;goto exit;}// 2.解析得到软中断号key->key_irq_no = irq_of_parse_and_map(key->key_node, 0);if (key->key_irq_no == 0) {printk("irq_of_parse_and_map error\n");ret = -EAGAIN;goto exit_node;// 资源暂时不可用}init_timer(&key->mytimer);key->mytimer.expires = jiffies + HZ/50;// timer_setup_on_stack(&key->mytimer, my_timer_callback1, 0);key->mytimer.function = my_timer_callback1;  // 设置定时器到期时调用的回调函数add_timer(&key->mytimer);              //将定时器加入到系统定时器链表中ret = request_irq(key->key_irq_no, key1_irq_handle,IRQF_TRIGGER_LOW, KEY_NAME1, key);if (ret) {printk("request_irq key1 error\n");goto exit_irq;}return 0;
exit_irq:free_irq(key->key_irq_no, NULL);
exit_node:of_node_put(key->key_node);
exit:return ret;  // 出错返回
}int key2_ctrl_init(key_ctrl_t * key)
{int ret;key->key_node = of_find_node_by_path(PATH_DTS_KEY_USR2);if(IS_ERR(key->key_node)){KMD_ERR("of_find_node_by_path ERR");ret = -ENODATA;goto exit;}// 2.解析得到软中断号key->key_irq_no = irq_of_parse_and_map(key->key_node, 0);if (key->key_irq_no == 0) {printk("irq_of_parse_and_map error\n");of_node_put(key->key_node); // 清理已获取的节点ret = -EAGAIN;goto exit_node;// 资源暂时不可用}init_timer(&key->mytimer);        key->mytimer.expires = jiffies + HZ/50;// timer_setup(&key->mytimer, my_timer_callback2, 0);key->mytimer.function = my_timer_callback2;  // 设置定时器到期时调用的回调函数add_timer(&key->mytimer);                //将定时器加入到系统定时器链表中ret = request_irq(key->key_irq_no, key2_irq_handle,IRQF_TRIGGER_LOW, KEY_NAME2, key);if (ret) {printk("request_irq key2 error\n");goto exit_irq;}return 0;
exit_irq:free_irq(key->key_irq_no, NULL);
exit_node:of_node_put(key->key_node);
exit:return ret;  // 出错返回
}void key_ctrl_exit(key_ctrl_t * key)
{free_irq(key->key_irq_no,key);if (timer_pending(&key->mytimer)) {del_timer_sync(&key->mytimer);}}MODULE_DESCRIPTION("key_ctrl_driver");
MODULE_LICENSE("GPL");

4.调试

这里的按键防抖需要注意以下几点:首先不加定时器防抖看下,按键硬件是否已经存在防抖机制
其次,使用定时器的时候要确定linux的HZ是多少,确定一次timer irq是多久,再添加防抖代码
再一个就是一般来说,按键抖动会在20ms左右,
最后就是如果HZ是100hz、jiffies+1就是在计数的基础上延时10ms触发自定义的定时器中断函数

over,祝各位定时器使用愉快!

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

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

相关文章

【机器学习】经典目标检测算法:RCNN、Fast RCNN、 Faster RCNN 基本思想和网络结构介绍

文章目录 三者的比较&#xff1a;RCNN、Fast RCNN、 Faster RCNN一、框架的对比1.三者都是二阶算法&#xff0c;网络框架比较&#xff1a;2.三者的优缺点比较&#xff1a; RCNN一、RCNN系列简介二、RCNN算法流程的4个步骤三、RCNN存在的问题四、论文解析补充1.R-CNN提出了两个问…

Odoo17免费开源ERP开发技巧:如何在表单视图中调用JS类

文/Odoo亚太金牌服务开源智造 老杨 在Odoo最新V17新版中&#xff0c;其突出功能之一是能够构建个性化视图&#xff0c;允许用户以独特的方式与数据互动。本文深入探讨了如何使用 JavaScript 类来呈现表单视图来创建自定义视图。通过学习本教程&#xff0c;你将获得关于开发Odo…

放慢音频速度的三个方法 享受慢音乐

如何让音频慢速播放&#xff1f;我们都知道&#xff0c;在观看视频时&#xff0c;我们可以选择快进播放&#xff0c;但是很少有软件支持慢速播放。然而&#xff0c;将音频慢速播放在某些情况下是非常必要的。例如&#xff0c;当我们学习一门新语言时&#xff0c;我们可以将音频…

Pytorch详细应用基础(全)

&#x1f525;博客主页&#xff1a; A_SHOWY&#x1f3a5;系列专栏&#xff1a;力扣刷题总结录 数据结构 云计算 数字图像处理 力扣每日一题_ 1.安装pytorch以及anaconda配置 尽量保持默认的通道&#xff0c;每次写指令把镜像地址写上就行。 defaults优先级是最低的&#…

深度学习神经网络相关记录《二》

如何判断模型是一个好模型&#xff1f; 模型预测效果&#xff0c;也就是模型预测的准确率运算速度&#xff1b;能够处理大量数据、短时间内急速学习、可以实时进行预测&#xff0c;是机器学习的重要优势&#xff1b;可解释性&#xff1b;深度学习已经不太关系这一点了&#xf…

基础:TCP三次握手做了什么,为什么要握手?

1. TCP 三次握手在做些什么 1. 第一次握手 &#xff1a; 1&#xff09;握手作用&#xff1a;客户端发出建立连接请求。 2&#xff09;数据处理&#xff1a;客户端发送连接请求报文段&#xff0c;将SYN位置为1&#xff0c;Sequence Number为x;然后&#xff0c;客户端进入SYN_S…

基于Matlab的视频人面检测识别,Matalb实现

博主简介&#xff1a; 专注、专一于Matlab图像处理学习、交流&#xff0c;matlab图像代码代做/项目合作可以联系&#xff08;QQ:3249726188&#xff09; 个人主页&#xff1a;Matlab_ImagePro-CSDN博客 原则&#xff1a;代码均由本人编写完成&#xff0c;非中介&#xff0c;提供…

分布式(计算机算法)

目录 分布式计算 分布式​编辑 分布式和集群 分布式和集群的应用场景 分布式应用场景 集群应用场景 哪种技术更优、更快、更好呢 性能 稳定性 以下概念来源于百度百科 分布式计算 分布式计算是近年提出的一种新的计算方式。所谓分布式计算就是在两个或多个软件互相共享信息…

【uniapp】uniapp设置改变全局字体大小功能:

文章目录 一、效果&#xff1a;二、文档&#xff1a;三、案例&#xff1a;引用插件&#xff0c;将项目中的字体单位rpx换成rem&#xff0c;结合官网提供的page-meta属性&#xff0c;通过控制根字体大小&#xff0c;达到调节字体大小要求。 一、效果&#xff1a; 二、文档&#…

代码随想录算法训练营第46天 | 完全背包,139.单词拆分

动态规划章节理论基础&#xff1a; https://programmercarl.com/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html 完全背包理论基础&#xff1a; https://programmercarl.com/%E8%83%8C%E5%8C%85%E9%97%AE%E9%A2%98%E7%90%86%E8%AE%BA%E5%9…

全网最全的幻兽帕鲁服务器搭建教程——阿里云保姆级教程

玩转幻兽帕鲁服务器&#xff0c;阿里云推出新手0基础一键部署幻兽帕鲁服务器教程&#xff0c;傻瓜式一键部署&#xff0c;3分钟即可成功创建一台Palworld专属服务器&#xff0c;成本仅需26元&#xff0c;阿里云服务器网aliyunfuwuqi.com分享2024年新版基于阿里云搭建幻兽帕鲁服…

DVWA靶场-SQL InjectionSQL注入

SQL Injection&#xff08;SQL注入&#xff09;概念 就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串&#xff0c;最终达到欺骗服务器执行恶意的SQL命令。具体来说&#xff0c;它是利用现有应用程序&#xff0c;将&#xff08;恶意&#xff09;的SQL命令注…

YOLOv2学习

YOLOv2学习 Anchor boxes 和 bounding boxes 的区别锚框&#xff08;Anchor Boxes&#xff09;边界框&#xff08;Bounding Boxes&#xff09;锚框与边界框的区别 摘要引言数据集组合方法&#xff08;Dataset Combination Method&#xff09;联合训练算法&#xff08;Joint Tra…

Python AI 之PhotoMaker 安装总结

PhotoMaker 官方文档 PhotoMaker GitHub 地址:https://github.com/TencentARC/PhotoMaker PhotoMaker Windows 安装 温馨提示&#xff1a;PhotoMaker 官网github 版本为通用版本&#xff0c;如果是Windows系统安装PhotoMarker 需要使用截图下的版本&#xff1a; 第一步&am…

nvm安装和使用保姆级教程(详细)

一、 nvm是什么 &#xff1a; nvm全英文也叫node.js version management&#xff0c;是一个nodejs的版本管理工具。nvm和npm都是node.js版本管理工具&#xff0c;为了解决node.js各种版本存在不兼容现象可以通过它可以安装和切换不同版本的node.js。 二、卸载之前安装的node: …

【Spring MVC】Spring MVC拦截器(Interceptor)

目录 一、拦截器介绍 二、拦截器 Interceptor 定义 2.1 HandlerInterceptor接口 2.2 Spring MVC中提供的一些HandlerInterceptor接口实现类 1、AsyncHandlerInterceptor 2、WebRequestInterceptor 3、MappedInterceptor 4、ConversionServiceExposingInterceptor 三、拦…

creator-webview加载优化

title: creator-webview加载优化 categories: Cocos2dx tags: [cocos2dx, creator, webview, 优化, 加载, 性能] date: 2024-03-02 13:17:20 comments: false mathjax: true toc: true creator-webview加载优化 前篇 Android WebView shouldInterceptRequest - https://www.ji…

Linux——动静态库的制作及使用与动态库原理

目录 一、静态库 1.静态库的制作 2.静态库的使用 加载静态库方法一&#xff1a;安装头文件与库文件 加载静态库方法二&#xff1a;指定文件目录 二、动态库 1.动态库的制作 2.动态库的使用 方法一&#xff1a;安装到系统中 方法二&#xff1a;软链接 方法三&…

新火种AI|英伟达GTC大会在即,它能否撑住场面,为AI缔造下一个高度?

作者&#xff1a;小岩 编辑&#xff1a;彩云 英伟达不完全属于AI行业&#xff0c;但神奇的是&#xff0c;整个AI领域都有着英伟达的传说。因为几乎所有的AI巨头都需要英伟达的芯片来提供算力支持。 也正因此&#xff0c;纵使AI赛道人来人往&#xff0c;此起彼伏&#xff0c;…

Session会话绑定

1.需求原因 用户的请求,登录的请求,经过负载均衡后落到后面的web服务器上,登录的状态/信息也会记录在web服务器上,就会导致不通的web服务器上,登录状态不统一,造成用户频繁需要登录 2.目标&#xff1a;如何实现会话保持/会话共享 方案一&#xff1a;登录状态写入cookie中.(wor…