娇小w搡bbbb搡bbb,《第一次の人妻》,中国成熟妇女毛茸茸,边啃奶头边躁狠狠躁视频免费观看

Linux驅(qū)動入門(七)使用定時器消除按鍵抖動

發(fā)布者:SereneSpirit最新更新時間:2025-01-16 來源: cnblogs關(guān)鍵字:Linux  定時器 手機(jī)看文章 掃描二維碼
隨時隨地手機(jī)看文章

一、為什么要消抖?
二、如何消抖?
三、Linux內(nèi)核定時器
四、源碼
五、測試

本文將在Linux驅(qū)動入門(五)阻塞方式實現(xiàn)按鍵驅(qū)動的基礎(chǔ)上,使用定時器消除按鍵抖動
一、為什么要消抖?
對于沒有做硬件消抖的按鍵,在按下按鍵到電平穩(wěn)定期間,會有一段抖動,此時電平會在高電平低電平不斷地跳動

 

如果我們的按鍵中斷采用下降沿觸發(fā),從圖中可以看出有多段下降沿,那么想必按下一次按鍵,中斷會被觸發(fā)多次,那么我們button_read函數(shù)也會被喚醒多次,這就導(dǎo)致一次按鍵,應(yīng)用層多次返回,這并不是我們想要的效果

二、如何消抖?
軟件消抖的原理非常簡單,只要通過延遲(一般為10ms),等待按鍵穩(wěn)定后,再來檢測按鍵是否被按下

在Linux驅(qū)動中,如果使用在原理打轉(zhuǎn)的方式來實現(xiàn)延時的話,這是非常不可取的,在中斷處理中更是大忌

所以要通過定時器來實現(xiàn)延遲,那具體怎么做呢?

在上面介紹中,我們了解在按鍵按下的時候會觸發(fā)多次按鍵中斷,那么我們可以在按鍵中斷設(shè)置定時器,在定時器的處理函數(shù)中去讀取按鍵狀態(tài)

具體的處理方法是,在每一個下降沿觸發(fā)的中斷處理函數(shù)中,將定時器設(shè)置為10ms后超時,這樣子,將在最后一個下降沿10ms后,定時器超時,再檢測按鍵狀態(tài),達(dá)到消抖的目的,如圖所示

 

三、Linux內(nèi)核定時器
定時器對象

struct timer_list timer;

初始化定時器

void init_timer(struct timer_list * timer);

/* 設(shè)置定時器的處理函數(shù)和傳遞參數(shù) */
timer.function = &xxx_do_timer;
timer.data = (unsigned long)dev;

內(nèi)核提供一個宏定義完成上述功能

setup_timer(timer, fn, data)

注冊定時器

void add_timer(struct timer_list *timer)

刪除定時器

int del_timer(struct timer_list *timer)

修改定時器超時時間

int mod_timer(struct timer_list *timer, unsigned long expires)

內(nèi)核中的jiffies表示時鐘節(jié)拍數(shù),宏定義HZ表示時鐘節(jié)拍的頻率

Linux內(nèi)核的HZ為100,表示1s時鐘跳動100下,所以時鐘周期的10ms

如果要延遲10ms,可以這么做

mod_timer(timer, jiffies + HZ/100);

四、源碼
#include
#include
#include
#include
#include
#include
#include
#include

#include
#include

static dev_t dev_id;
static struct cdev *button_dev;
static struct class *button_class;

/* 定義并初始化一個等待隊列頭 */
static DECLARE_WAIT_QUEUE_HEAD(button_wq_head);
static int button_conditon;
static int button_val;

static struct timer_list timer;

static void timer_fun(unsigned long data)
{
/* 判斷等待隊列中是否有等待元素 */
if(!waitqueue_active(&button_wq_head))
return;

/* 讀取按鍵值 */
button_val = gpio_get_value(S5PV210_GPH0(2));
if(button_val) //按鍵未被按下
return;

/* 喚醒等待隊列 */
button_conditon = 1;
wake_up_interruptible(&button_wq_head);
}

static irqreturn_t button_irq(int irq, void *data)
{
mod_timer(&timer, jiffies+HZ/100);

return IRQ_HANDLED;
}

static int button_open(struct inode *inode, struct file *file)
{
int ret;

ret = request_irq(IRQ_EINT2, button_irq, IRQF_TRIGGER_FALLING, 'button_irq', NULL);

return 0;
}

static ssize_t button_read(struct file *file, char __user *data, size_t size, loff_t *loff)
{
int ret;
int val;

/* 睡眠等待 */
button_conditon = 0;
wait_event_interruptible(button_wq_head, button_conditon);
button_conditon = 0;

val = button_val;
ret = copy_to_user(data, &val, sizeof(val));

return sizeof(val);
}

static int button_release(struct inode *inode, struct file *file)
{
free_irq(IRQ_EINT2, NULL);

return 0;
}

static struct file_operations button_fops = {
.owner = THIS_MODULE,
.open = button_open,
.read = button_read,
.release = button_release,
};

static __init int button_init(void)
{
/* 申請設(shè)備號 */
alloc_chrdev_region(&dev_id, 1, 1, 'button');

/* 分配字符設(shè)備 */
button_dev = cdev_alloc();

/* 設(shè)置字符設(shè)備 */
cdev_init(button_dev, &button_fops);

/* 注冊字符設(shè)備 */
cdev_add(button_dev, dev_id, 1);

/* 創(chuàng)建設(shè)備節(jié)點 */
button_class = class_create(THIS_MODULE, 'button'); //創(chuàng)建類
device_create(button_class, NULL, dev_id, NULL, 'button'); //創(chuàng)建設(shè)備節(jié)點

gpio_request(S5PV210_GPH0(2), 'button');

setup_timer(&timer, timer_fun, 0);
add_timer(&timer);

return 0;
}

static __exit void button_exit(void)
{
/* 注銷設(shè)備節(jié)點 */
device_destroy(button_class, dev_id);
class_destroy(button_class);

/* 注銷字符設(shè)備 */
cdev_del(button_dev);
kfree(button_dev);

/* 注銷注冊的設(shè)備號 */
unregister_chrdev_region(dev_id, 1);

gpio_free(S5PV210_GPH0(2));

del_timer(&timer);
}

module_init(button_init);
module_exit(button_exit);

MODULE_LICENSE('GPL');

五、測試
測試應(yīng)用程序

#include
#include
#include
#include
#include

#define BUTTON_DEV '/dev/button'

int main(int argc, char* argv[])
{
int val;

int fd = open(BUTTON_DEV, O_RDONLY);
if(fd < 0)
{
printf('failed to open %sn', BUTTON_DEV);
return -1;
}

while(1)
{
read(fd, &val, sizeof(val));
printf('read returnn');

if(val == 0)
{
printf('button pressn');
}
}


close(fd);

return 0;
}

加載驅(qū)動模塊,執(zhí)行測試應(yīng)用程序

運行效果,只有按鍵按下時,read函數(shù)才會返回,且按鍵按下一次,read只返回一次


關(guān)鍵字:Linux  定時器 引用地址:Linux驅(qū)動入門(七)使用定時器消除按鍵抖動

上一篇:Linux驅(qū)動入門(六)poll機(jī)制實現(xiàn)按鍵驅(qū)動
下一篇:Linux內(nèi)核靜態(tài)映射表的建立過程

推薦閱讀最新更新時間:2025-05-27 12:42

三菱PLC編程實現(xiàn)讀出時間定時器
三菱PLC(Programmable Logic Controller,可編程邏輯控制器)是一種廣泛應(yīng)用于工業(yè)自動化領(lǐng)域的設(shè)備,它通過編程實現(xiàn)對機(jī)器或生產(chǎn)過程的控制。在許多應(yīng)用中,時間控制是一個重要的功能,而定時器是實現(xiàn)時間控制的關(guān)鍵組件。本文將詳細(xì)介紹如何使用三菱PLC編程實現(xiàn)讀出時間定時器。 1. 定時器的基本概念 定時器是一種用于測量時間間隔的設(shè)備,它可以在PLC程序中實現(xiàn)延時、計時等功能。在三菱PLC中,定時器通常分為兩類:T(基本定時器)和D(數(shù)據(jù)塊定時器)。 1.1 基本定時器(T) 基本定時器是最簡單的定時器類型,它使用一個16位的計數(shù)器來實現(xiàn)定時功能。基本定時器的主要特點如下: 定時范圍:0.1ms到32
[嵌入式]
51單片機(jī)定時器和中斷的介紹
最近在學(xué)習(xí)51單片機(jī),學(xué)到了定時器這塊,由于自己的基礎(chǔ)不太扎實,在這方面花了很多時間,這里通過對定時器和中斷的介紹,用簡易時鐘這個例子來對學(xué)習(xí)的內(nèi)容進(jìn)行加深鞏固,把自己的經(jīng)驗分享給大家,希望對大家能夠有幫助。 一、定時器的功能以及定時器的結(jié)構(gòu) 定時器的功能 其實就是單片機(jī)的內(nèi)部,通過系統(tǒng)時鐘的每一個機(jī)器周期產(chǎn)生一個記數(shù)脈沖,即每一個機(jī)器周期計數(shù)器加一。 比如,這里我的實驗板的晶振是12MHZ,1MHZ信號每個脈沖的持續(xù)時間為1us,如果定時器T0對1MHZ的信號進(jìn)行計數(shù),從0~65536us,當(dāng)達(dá)到最大的65536us的時候,定時器計數(shù)達(dá)到最大值,會溢出,于是產(chǎn)生中斷信號,向中斷系統(tǒng)申請中斷,中斷系統(tǒng)接受中斷請求,執(zhí)行中斷
[單片機(jī)]
51單片機(jī)<font color='red'>定時器</font>和中斷的介紹
STM32單片機(jī)學(xué)習(xí)筆記(9):定時器中斷
項目簡介 利用CubMX生成基于32單片機(jī)的HAl庫工程,然后編寫程序在proteus上仿真驗證。本項目最適合沒有開發(fā)板的同學(xué)學(xué)習(xí),零成本利用仿真軟件率先入門STM32單片機(jī)。本項目利用CubMX創(chuàng)建一個32工程,用以實現(xiàn)定時器中斷控制LED燈的狀態(tài)轉(zhuǎn)換的功能,并在Proteus中進(jìn)行仿真驗證。 硬件模塊 STM32F103R4 LED 軟件工具 CubMX Proteus KEIL 電路連接圖 工作流程 首先,創(chuàng)建一個CubMX工程。這里選擇的是STM32F103R4型號的單片機(jī)。下圖是時鐘樹的設(shè)置,這個根據(jù)自己習(xí)慣設(shè)置就好,這里的時鐘頻率,也就是定時器時鐘頻率是8MHz. 介紹定時器發(fā)生中斷時間的計算方法:
[單片機(jī)]
STM32單片機(jī)學(xué)習(xí)筆記(9):<font color='red'>定時器</font>中斷
詳解STM32定時器捕獲功能
一、STM32定時器捕獲功能 STM32的定時器是支持信號輸入捕獲的,何為輸入捕獲?主要做什么應(yīng)用? 輸入捕獲:通過檢測TIMx_CHx上的邊沿信號,在邊沿信號發(fā)生跳變的時候,將當(dāng)前的定時器的值(TIMx_CNT)存放到對應(yīng)的捕獲比較寄存器里面,完成一次捕獲。輸入捕獲主要應(yīng)用于測量信號的脈寬或頻率。 下圖是定時器原理圖的輸入捕獲框圖部分 第一部分是設(shè)置濾波器,用來對信號進(jìn)行濾波,信號從TI1輸入,通過濾波器,輸出TIF信號,正常情況下信號沒有抖動,TI1F信號等于TI1的輸入信號。 ICF 用來設(shè)置輸入采樣頻率的數(shù)字濾波器的長度,如ICF=0011,會在捕獲上升沿時,以fCK_INT的頻率連續(xù)采樣八次通道1的信號電平,
[單片機(jī)]
詳解STM32<font color='red'>定時器</font>捕獲功能
MSP430學(xué)習(xí)總結(jié)——定時器
一、MSP430定時器是什么? 和STM32類似,MSP430定時器也有定時、輸入捕獲、輸出比較以及產(chǎn)生PWM等功能,下面就來一一介紹這些功能以及怎么去使用。 首先,我們應(yīng)該知道MSP430的定時器模式分為比較模式和捕獲模式,個人理解比較模式就是定時中斷、計時等一些常規(guī)的功能,捕獲模式是PWM輸出,捕獲外部信號,用于測量時間和脈沖數(shù)量等。MSP430默認(rèn)為比較模式。 MSP430的TA1的寄存器如下圖 二、MSP定時器的功能 1. 定時器中斷 定時器中斷就是間隔一定的時間,執(zhí)行一次中斷服務(wù)函數(shù),我們通過一段程序來上手定時器中斷,畢竟例程也是學(xué)習(xí)單片機(jī)的一大工具。 WDTCTL = WDTPW + WDTHOLD
[單片機(jī)]
MSP430學(xué)習(xí)總結(jié)——<font color='red'>定時器</font>
MSP430學(xué)習(xí)筆記(五)--定時器實戰(zhàn)
第一個Demo來自官方例程中的 msp430g2xx3_ta_01 ,該例中Timer_A工作在最典型的定時狀態(tài),按照 50000 個SMCLK周期的時間間隔產(chǎn)生中斷。代碼中SMCLK的頻率為DOC默認(rèn)工作頻率,約為1MHz,每次定時中斷都會翻轉(zhuǎn)P1.0管腳的輸出電平,所以P1.0管腳會出現(xiàn)10Hz左右的方波信號。可接LED1的跳線帽直接觀察現(xiàn)象。 #include msp430.h int main(void) { //關(guān)閉看門狗 WDTCTL = WDTPW + WDTHOLD; // Stop WDT //設(shè)置 P1.0 管腳為輸出 P1DIR |= 0x01; //
[單片機(jī)]
MSP430學(xué)習(xí)筆記(五)--<font color='red'>定時器</font>實戰(zhàn)
Keil MDK STM32系列(八) STM32F4基于HAL的PWM和定時器輸出音頻
方式1: 通過PWM和TIM輸出音頻 機(jī)制 音頻使用一個預(yù)生成的的8bit無符號數(shù)組, 采樣率為8KHz 輸出包含兩部分, 一部分是TIM2產(chǎn)生連續(xù)的PWM, PWM分辨率設(shè)置為256, 正好對應(yīng)8bit PCM采樣 輸出的第二部分是TIM3產(chǎn)生的定時中斷, 中斷的頻率正好是8KHz, 每次中斷都修改一次PWM的占空比 通過調(diào)節(jié)PWM頻率可以調(diào)節(jié)輸出音質(zhì), PWM頻率越高音質(zhì)越好(諧振頻率越遠(yuǎn)離音頻) 通過調(diào)節(jié)PWM分辨率可以調(diào)節(jié)音量, PWM分辨率越高, 音量越低 配置STM32CubeMX 選擇芯片STM32F401CCU6, 創(chuàng)建新項目 系統(tǒng)時鐘 System Core - SYS- Debug: Serial Wi
[單片機(jī)]
STM32H7實現(xiàn)ADC等周期采集(定時器觸發(fā)+DMA傳輸)
定時器輸出的PWM通道設(shè)置的是2s的周期,50%占空比,方便沒有示波器的條件下觀察結(jié)果。 數(shù)據(jù)會2s采集一次,500ms打印一次。 主函數(shù)代碼 u16 buffer ; int main(void) { u16 adcx; //Cache_Enable(); //打開L1-Cache HAL_Init(); //初始化HAL庫 Stm32_Clock_Init(200, 2, 2, 2); //設(shè)置時鐘,400Mhz delay_init(400); //延時初始化 uart_init(115200); //串口初始
[單片機(jī)]
STM32H7實現(xiàn)ADC等周期采集(<font color='red'>定時器</font>觸發(fā)+DMA傳輸)
小廣播
設(shè)計資源 培訓(xùn) 開發(fā)板 精華推薦

最新單片機(jī)文章

 
EEWorld訂閱號

 
EEWorld服務(wù)號

 
汽車開發(fā)圈

 
機(jī)器人開發(fā)圈

電子工程世界版權(quán)所有 京ICP證060456號 京ICP備10001474號-1 電信業(yè)務(wù)審批[2006]字第258號函 京公網(wǎng)安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 青岛市| 贵州省| 新化县| 酉阳| 鄂尔多斯市| 庄浪县| 罗源县| 龙井市| 综艺| 延津县| 承德县| 梨树县| 金华市| 云南省| 南投市| 视频| 普定县| 湘潭市| 监利县| 房产| 北碚区| 浠水县| 金溪县| 涟水县| 溧阳市| 扎兰屯市| 宁城县| 娱乐| 莱州市| 德化县| 张家口市| 航空| 宜春市| 富锦市| 湾仔区| 长寿区| 商河县| 晴隆县| 惠安县| 文昌市| 江川县|