IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32MP157 | 使用 Linux 内核定时器消抖 -> 正文阅读

[嵌入式]STM32MP157 | 使用 Linux 内核定时器消抖

一、定时器简介

(1)什么是定时器(timer)

定时器实际上就是Soc当中的一个内部外设。

  1. 定时器有什么用

(1)定时器可以让SoC在执行主程序的同时,可以(通过定时器)具有计时功能,到了一定时间(计时结束)后,定时器会产生中断提醒CPU,CPU会去处理中断并执行定时器的ISR。从而去执行预先设定好的事件。

(2)定时器就好像是CPU的一个秘书一样,这个秘书专门管帮CPU来计时,并到时间后提醒CPU要做某件事情。所以CPU有了定时器之后,只需要预先把自己XX时间之后必须要做的事情绑定到定时器中断ISR即可,到了时间之后定时器就会以中断的方式提醒CPU来处理这个事情。

二、定时器的相关api

1.定时器的值加1代表走多长时间?

定时器的频率可以通过make menuconfig选配,选配后的值保存在内核顶层目录下的.config

CONFIG_HZ=100 开发板 =====> 10ms

CONFIG_HZ=250 ubuntu =====> 4ms

2.当前的时间如何获取?

jiffies: 内核时钟节拍数,从内核启动这一刻起,这个值一直在增加。

#include <linux/timer.h>

1.分配对象
    struct timer_list {
        struct hlist_node	entry; //构成内核链表
        unsigned long		expires; //定时时间
        void			(*function)(struct timer_list *);//定时器处理函数
        unsigned long		data; //向定时器处理函数传递的参数
        u32			flags;        //0
    };
	
   struct timer_list mytimer;
2.对象初始化
    mytimer.expires = jiffies+HZ;
	timer_setup(&mytimer, 定时器处理函数, 0);

3.注册
    void add_timer(struct timer_list *timer);
	//注册并启动定时器,只会启动一次 (一个定时器对象只能注册一次,但可以启动很多次)

	int mod_timer(struct timer_list *timer, unsigned long expires);
	//再次启动定时器
4.注销
    int del_timer(struct timer_list * timer);
	//注销定时器

三、 添加设备树的节点

1. 添加设备树

//在stm32mp175a-fsmp1a.dts中添加如下节点:

myirqs{
    interrupt-parent = <&gpiof>;                                                           
    interrupts = <9 0>,<7 0>,<8 0>;
    keys = <&gpiof 9 0>,<&gpiof 7 0>,<&gpiof 8 0>;   //gpiod_to_irq
};  

2. 重新编译设备树

make dtbs

重启开发板

安装驱动

四. 编写按键消抖驱动

1.先写个模块

#include <linux/init.h>
#include <linux/module.h>

static int __init timer_key_init(void)
{
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    return 0;
}
static void __exit timer_key_exit(void)
{
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    return 0;
}
module_init(timer_key_init);
module_exit(timer_key_exit);
MODULE_LICENSE("GPL");

2. 写个Makefile编译一下:

ifeq ($(arch),arm)
KERNELDIR :=/home/linux/linux-5.10.61
CROSS_COMPILE ?=arm-linux-gnueabihf-
else 
KERNELDIR :=/lib/modules/$(shell uname -r)/build
CROSS_COMPILE ?=
endif 

modname ?=
PWD :=$(shell pwd)

CC :=$(CROSS_COMPILE)gcc

all:
	make -C $(KERNELDIR) M=$(PWD) modules
	# $(CC) test.c -o test
clean:
	make -C $(KERNELDIR) M=$(PWD) clean
	# rm test

install:
	cp *.ko ~/nfs/rootfs/
	# cp test ~/nfs/rootfs/

help:
	echo "make arch = arm or x86 modname= dirvers file name"

obj-m:=$(modname).o
linux@ubuntu:~/linu/driver/csdn/timer$ make arch=arm modname=timer

3. 再写定时器驱动框架

#include <linux/init.h>
#include <linux/module.h>

struct timer_list mytimer;

void timer_handle(struct timer_list *timer)
{

}

static int __init timer_key_init(void)
{
    int ret, i;
    // 0.初始化定时器
    mytimer.expires = jiffies + 1;
    timer_setup(&mytimer, timer_handle, 0);
    add_timer(&mytimer);
    
    return 0;
}
static void __exit timer_key_exit(void)
{

}
module_init(timer_key_init);
module_exit(timer_key_exit);
MODULE_LICENSE("GPL");

4.加入中断子系统

#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/of_irq.h>
#include <linux/of.h>
#include <linux/of_gpio.h>

struct timer_list mytimer;
struct device_node *node;
unsigned int irqno[3];
const char *irqname[] = {"key1", "key2", "key3"};
int gpiono[3];
void timer_handle(struct timer_list *timer)
{
    if (gpio_get_value(gpiono[0]) == 0)
    {
        printk("key1 ..............\n");
    }
    if (gpio_get_value(gpiono[1]) == 0)
    {
        printk("key2 ..............\n");
    }
    if (gpio_get_value(gpiono[2]) == 0)
    {
        printk("key3 ..............\n");
    }
}
irqreturn_t key_irq_handle(int irq, void *dev)
{
    //启动定时器
    mod_timer(&mytimer, jiffies + 1);
    return IRQ_HANDLED;
}
static int __init timer_key_init(void)
{
    int ret, i;
    // 0.初始化定时器
    mytimer.expires = jiffies + 1;
    timer_setup(&mytimer, timer_handle, 0);
    add_timer(&mytimer);

    // 1.获取节点
    node = of_find_node_by_path("/myirqs");
    if (node == NULL)
    {
        printk("find node error\n");
        return -EAGAIN;
    }

    for (i = 0; i < ARRAY_SIZE(irqno); i++)
    {
        // 2.获取gpio号
        gpiono[i] = of_get_named_gpio(node, "keys", i);
        if (gpiono[i] < 0)
        {
            printk("get gpio number error\n");
            return gpiono[i];
        }
        // 3.映射软中断号
        irqno[i] = irq_of_parse_and_map(node, i);
        if (!irqno[i])
        {
            printk("get irq number error\n");
            return -EAGAIN;
        }

        // 4.注册中断
        ret = request_irq(irqno[i], key_irq_handle,IRQF_TRIGGER_FALLING, irqname[i], (void *)i);
        if (ret)
        {
            printk("request irq error\n");
            return ret;
        }
    }

    return 0;
}
static void __exit timer_key_exit(void)
{
    int i = 0;
    for (i = 0; i < ARRAY_SIZE(irqno); i++)
    {
        free_irq(irqno[i], (void *)i);
    }
    del_timer(&mytimer);
}
module_init(timer_key_init);
module_exit(timer_key_exit);
MODULE_LICENSE("GPL");

四、测试驱动模块

1.加载驱动,查看驱动,并测试

在这里插入图片描述

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-09-15 02:09:57  更:2022-09-15 02:12:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 22:56:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码