正點原子[第二期]Linux之ARM(MX6U)裸機篇學習筆記-17講 定時器按鍵消抖

前言:

本文是根據嗶哩嗶哩網站上“正點原子[第二期]Linux之ARM(MX6U)裸機篇”視頻的學習筆記,在這里會記錄下正點原子 I.MX6ULL 開發板的配套視頻教程所作的實驗和學習筆記內容。本文大量引用了正點原子教學視頻和鏈接中的內容。

引用:

正點原子IMX6U倉庫 (GuangzhouXingyi) - Gitee.com

《【正點原子】I.MX6U嵌入式Linux驅動開發指南V1.5.2.pdf》

正點原子資料下載中心 — 正點原子資料下載中心 1.0.0 文檔

正文:

本文是 “正點原子[第二期]Linux之ARM(MX6U)裸機篇--第17?講” 的讀書筆記。第17講主要是介紹I.MX6U處理器的EPIT定時器的按鍵消抖。本節將參考正點原子的視頻教程第17講和配套的正點原子開發指南文檔進行學習。

0. 概述

在第15章和第17章實驗都使用到了按鍵,用到按鍵就要處理因為機械結構帶來的抖動問題,也就是按鍵消抖。前面的時延中都是直接使用了延時函數來實現消抖,因為簡單,但是直接使用延時函數來實現消抖會浪費CPU的性能,因為在延時函數里面CPU什么都做不了。如果按鍵使用中斷的話更不能再中斷里面使用延時函數,因為中斷服務函數要快進快出!本章我們學習如何使用定時器來實現按鍵消抖,使用定時器既可以實現按鍵消抖,而且也不會浪費CPU性能,這個也是Linux驅動里面按鍵消抖的做法。

1. 定時器按鍵消抖簡介

按鍵消抖的原理已經在第十五章詳細的講解過了,起始就是在按鍵按下以后延時一段時間再去讀取按鍵值,如果此時按鍵值還有效那就表示這是一次有效的按鍵,中間的延時就是消抖的。

但是這有一個缺點,就是已按時函數會浪費CPU性能,應為延時函數就是空跑。如果按鍵是用中斷方式實現的,那就更不應該在中斷服務函數里使用延時函數,因為中斷服務函數最基本的要求就是快進快出!上一章我們學習了EPIT定時器,定時器設置好定時時間,然后CPU就可以做其他事情去了,定時時間到了以后就會觸發中斷,然后在中斷中做相應的處理即可。

因此,我們可以借助定時器來實現消抖,

  1. 按鍵采用中斷驅動的方式,當按下按鍵觸發按鍵中斷,在按鍵中斷中開啟一個定時器,
  2. 定時周期為10ms,當定時時間到了以后就會觸發定時器中斷
  3. 最后在定時器中斷處理函數中讀取按鍵的值,如果按鍵還是按下的狀態那就表示這是一次有效的按鍵。

定時器按鍵消抖如下圖所示:

在圖19.1.1中的t1~t3這一段時間就是按鍵抖動,是需要消除的。設置按鍵為下降沿觸發,因此會在t1,t2,和t3這三個時刻觸發那件中斷,每次進入中斷處理函數都會重開定時器中斷,所以會在t1,t2,和t3這三個時刻開定時器中斷。但是t1~t2和t2~t3這兩段時間是小于我們設置的定時器中斷周期(也就是消抖時間,比如10ms),所以雖然t1開啟了定時器,但是定時器時間沒有到呢t2時刻就重置了定時器,最終之后t3時刻開啟的定時器能完整的完成整個定時周期并觸發中斷,我們就可以在中斷處理函數里面做按鍵處理了,這就是定時器完成按鍵消抖的原理,Linux里面的按鍵驅動用的就是這個原理!

關于定時器消毒的原理就介紹到這里,接下來講解如何使用EPIT1來配置按鍵KEY來實現具體的消抖,步驟如下:

  1. 配置按鍵IO中斷
    配置按鍵所使用的IO,因為要使用到中斷驅動按鍵,所以要配置IO的中斷模式。
  2. 初始化消抖用的定時器
    上面已經講的很清楚了,消抖要用定時器來完成,所以需要初始化一個定時器,這是使用上一章講解的EPIT1定時器,也算是對EPIT1定時器的一次鞏固。定時器的定時周期為10ms,也可以根據實際情況調整定時周期。
  3. 編寫中斷處理函數
    需要編寫兩個中斷處理器函數:按鍵對應的GPIO中斷處理函數和EPIT1定時器的中斷處理函數。在按鍵的中斷處理函數中主要用于開啟EPIT1定時器,EPIT1定時器處理函數才是重點,按鍵要做的具體任務都是在定時器EPIT1的中斷處理函數中完成的,比如控制蜂鳴器打開或關閉。

2. 定時器按鍵消抖程序編寫

更具上面分析的定時器按鍵消抖的原理和定時器按鍵消抖實驗的步驟,編寫定時器按鍵消抖程序源碼如下:

bsp/keyfilter/bsp_keyfilter.h

#ifndef __BSP_KEYFILTER_H__
#define __BSP_KEYFILTER_H__#include "imx6u.h"void keyfilter_init(void);
void keyfilter_timer_init(int value);
void keyfilter_timer_stop(void);
void keyfilter_timer_restart(int value);
void keyfilter_timer_irqhandler(IRQn_Type irq, void *userparam);
void gpio1_16_31_irqhandler(IRQn_Type irq, void *userparam);#endif

bsp/keyfilter/bsp_keyfilter.c?

#include "bsp_keyfilter.h"
#include "bsp_beep.h"
#include "bsp_led.h"
#include "bsp_int.h"
#include "bsp_gpio.h"
#include "bsp_epittimer.h"void keyfilter_init(void)
{/* GPIO1_IO18 */gpio_pin_config_t config;/* 1. 初始化IO復用,復用為GPIO1_IO18 */IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0);/* 2. 設置 UART1_CTS_B IO 的電氣特性 */IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0xf080);/* 3. 初始化 GPIO1_IO18 設置為輸入 */config.directioin = kGPIO_DigitalInput;config.intMode = kGPIO_FalllingEdgeInt;gpio_init(GPIO1, 18, &config);/* 啟用GIC IRQ */GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn);/* 注冊IRQ處理函數 */system_irqhandler_register(GPIO1_Combined_16_31_IRQn, gpio1_16_31_irqhandler, NULL);/* EPIT1定時器初始化 */keyfilter_timer_init(66000000/100);/* 啟用gpio中斷 */gpio_int_enable(GPIO1, 18);
}void keyfilter_timer_init(int value){EPIT1->CR = 0;EPIT1->CR = (1 << 24 )| (1 << 3) | (1 << 2) | (1 << 1);EPIT1->LR = value;EPIT1->CMPR = 0;/* 使能GIC EPIT1_IRQn 中斷 */GIC_EnableIRQ(EPIT1_IRQn);/* 注冊中斷處理函數 */system_irqhandler_register(EPIT1_IRQn, keyfilter_timer_irqhandler, NULL);
}void keyfilter_timer_stop(void)
{EPIT1->CR &= ~(1 << 0);
}void keyfilter_timer_restart(int value){EPIT1->CR &= ~(1 << 0);		/* 關閉EPIT1 */EPIT1->LR = value;			/* EPIT1加載值寄存器 */EPIT1->CR |= (1 << 0);		/* 打開EPIT1 */
}void keyfilter_timer_irqhandler(IRQn_Type irq, void *userparam){static int beep_state = 0;if(EPIT1->SR & (1 << 0)){					/* 檢查EPIT1中斷標志 */keyfilter_timer_stop();					/* 關閉EPIT1定時器 */if(gpio_pinread(GPIO1, 18) == 0)		/* 檢查gpio引腳電平值 */{beep_state = !beep_state;			/* 翻轉蜂鳴器 */beep_switch(beep_state);}}/* 清除中斷標志位 */EPIT1->SR |= (1<<0);
}void gpio1_16_31_irqhandler(IRQn_Type irq, void *userparam){if(GPIO1->ISR & (1 << 18)){keyfilter_timer_restart(66000000/100);		/* 重啟EPIT1定時器,定時器周期10ms */}/* 清除中斷標志位 */gpio_int_cleanFlag(GPIO1, 18);
}

在如上的源碼中,初始化按鍵KEY0 對應GPIO1_IO18的 IO 復用,IO特性,啟用IO中斷,并注冊GPIO1_IO18的中斷處理函數,在按鍵中斷處理函數中重啟 EPIT1定時器設置定時周期為10ms,當定時周期完成時觸發EPIT1定時器比較事件中斷,在EPIT1定時器中斷里再次檢查gpio引腳的輸入電平如果還是有效說明此次按鍵按下是有效的,此時在EPIT1定時器中斷里翻轉蜂鳴器的鳴叫。

3. 編譯燒寫SD卡驗證實驗結果

譯修改主頻后源碼燒錄SD卡驗證本節的EPIT定時器消抖實驗是否生效。預期燒錄SD卡后正點原子I.MX6ULL ALPHA/Mini 開發板后,按下按鍵蜂鳴器鳴叫,再次按下按鍵蜂鳴器停止鳴叫,多次測試按鍵按下都能翻轉蜂鳴器開關。

我本地驗證的結果是EPIT定時器按鍵消抖實驗結果正常,多次按下按鍵都能正確的翻轉蜂鳴器鳴叫開關。

4. 總結和實驗遇到的問題記錄

4.1 問題1:EPIT定時器消抖實驗程序燒錄SD,發現有時按下并松開按鍵后蜂鳴器只鳴叫一聲就停止,預期應該一直鳴叫。

原因分析如下:

  1. 由于按鍵的機械結構,不僅僅在按鍵按下的瞬間有電平的多次抖動,從而在按鍵按下的瞬間多次在按鍵gpio電平的下降沿觸發GPIO中斷,進而重置EPIT1定時器最終出發EPIT1定時器中斷。
  2. 按鍵的機械結構決定了,在按鍵松開的瞬間也有多次的gpio引腳電平抖動,也會在按鍵松開的瞬間由于抖動在電平的下降沿觸發GPIO中斷,進而重置EPIT1定時器最終出發EPIT1定時器中斷。
  3. 由上分析可知,由于按鍵的機械結構,在按鍵按下的時會有電平抖動從而觸發GPIO中斷;在按鍵松開的時同樣也會有電平抖動從而觸發GPIO中斷;
    所以,必須在EPIT1定時器中斷里再次檢查 GPIO 引腳的電平是否有效,對于本實驗,在按鍵按下的時候EPIT1中斷處理函數讀取到的gpio引腳為低電平證明按鍵按下有效。
    (EPIT1定時中斷處理函數里讀取到gpio引腳為高電平,說明是按鍵松開。)

5. 結束

本文至此結束

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/14209.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/14209.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/14209.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

計算機網絡安全控制技術

1.防火墻技術 防火墻技術是近年來維護網絡安全最重要的手段&#xff0c;但是防火墻不是萬能的&#xff0c;需要配合其他安全措施來協同 2.加密技術 目前加密技術主要有兩大類&#xff1a;對稱加密和非對稱加密 3.用戶識別技術 核心是識別網絡者是否是屬于系統的合法用戶 …

【設計模式深度剖析】【1】【結構型】【代理模式】| 玩游戲打怪、升級為例加深理解

&#x1f448;?上一篇:創建型設計模式對比 | 下一篇:裝飾器模式&#x1f449;? 目 錄 代理模式定義英文原話直譯如何理解&#xff1f; 3個角色UML類圖1. 抽象主題&#xff08;Subject&#xff09;角色2. 代理類&#xff1a;代理主題&#xff08;Proxy Subject&#xff0…

UE5 OnlineSubsystem Steam創建會話失敗解決方法

連接上Steam但是創建會話失敗 解決方法 在DefaultEngine.ini中加上bInitServerOnClienttrue,這個其實在官方文檔里用注釋給出了&#xff0c;直接取消注釋就行 刪除項目目錄中的Saved、Internmediate、Binaries目錄 右鍵你的項目.uproject選擇Generate Visual Studio project f…

ASP.Net MVC在控制臺添加視圖時沒有模型類并且不能添加視圖

情況如下&#xff1a; 解決方法&#xff1a; 1.查看vs能否創建asp.net mvc項目&#xff0c;這種情況一般是更換了vs打開老項目 2.點擊跳轉至修改安裝選項界面 3.選擇安裝項即可 如果以上都有&#xff1a; 看看你的視圖文件是否存在在項目中 也不能點擊添加&#xff0c;如果…

探索數值分析的奧秘:掌握NumPy與Pandas基礎

新書上架~&#x1f447;全國包郵奧~ python實用小工具開發教程http://pythontoolsteach.com/3 歡迎關注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目錄 一、NumPy&#xff1a;數值計算的效率提升器 二、Pandas&#xff1a;數據處理與分析的利器 …

Linux文本三劍客之sed

set的定義&#xff1a; sed是一種流編輯器&#xff0c;流編輯器會在編輯器處理數據之前基于預先提供的一組規則來編輯數據流。 sed編輯器可以根據命令來處理數據流中的數據&#xff0c;這些命令要么從命令行中輸入&#xff0c;要么存儲在一個命令文本文件中。 sed的執行過程&a…

Nextjs 動態路由獲取參數

目錄 一、創建page目錄下的路由文件 二、通過useRouter來獲取動態參數 先看官方文檔&#xff1a;Routing: Dynamic Routes | Next.js 使用Nextjs13版本參考官方文檔后實現仍有問題&#xff0c;網上的材料大多和官網一致&#xff0c;經過測試后&#xff0c;我找到了這個解決方…

【日記】今天好困(407 字)

正文 4T 硬盤降價了&#xff0c;好心動。雖然只降了 10 塊錢……. 為什么硬盤這么貴啊&#xff01;哼。 柜面上雜事好多。雖然一天到晚見不到幾個客戶&#xff0c;但雜事就是很多。一個頭兩個大。也不知道從哪兒冒出來的這么多事。 芒果干到了&#xff01;還沒去取&#xff0c;…

sql把一個表的某幾列的數據存到另一個表里

一.如何用slq語句把一個表中的某幾個字段的數據插入到另一個新表中&#xff0c;就要用下面這條slq語句&#xff1a; insert into 表名1(字段1,字段2) select 字段1,字段2 from 表名2 這里有一點值得注意的是這2個字段要一一對應&#xff0c;并且按順序。 二.如果另一個表是…

JAVASE之類和對象(1)

路雖遠&#xff0c;行則將至&#xff1b;事雖難&#xff0c;做則必成。 主頁&#xff1a;趨早——Step 專欄&#xff1a;JAVASE gitte&#xff1a;https://gitee.com/good-thg 引言&#xff1a; 這篇文章我們只介紹前半部分&#xff0c;下一篇文章會介紹剩下的部分。 目錄 一、…

LeetCode 面試150

最近準備面試&#xff0c;我以前不愿意面對的 現在保持一顆本心&#xff0c;就是專注于算法思想&#xff0c;語言基礎的磨煉&#xff1b; 不為速成&#xff0c;不急功近利的想要比賽&#xff0c;或者為了面試。 單純的本心&#xff0c;體驗算法帶來的快樂&#xff0c;是一件非常…

Python操作MySQL數據庫的工具--sqlalchemy

文章目錄 一、pymysql和sqlalchemy的區別二、sqlalchemy的詳細使用1.安裝庫2.核心思想3.整體思路4.sqlalchemy需要連接數據庫5.使用步驟1.手動提前創建數據庫2.使用代碼創建數據表3.用代碼操作數據表3.1 增加數據3.2 查詢數據3.3 刪除數據3.4 修改數據 一、pymysql和sqlalchemy…

2025秋招深度學習基礎面試題(一)

01. 卷積和BN如何融合提升推理速度 Conv和BN的融合:在網絡的推理階段,可以將BN層的運算融合到Conv層中,減少運算量,加速推理。本質上是修改了卷積核的參數,在不增加Conv層計算量的同時,略去了BN層的計算量。def fuse_conv_bn(conv, bn):std = (bn.running_var + bn.eps).…

數據倉庫、數據中臺、大數據平臺之間的關系

數據行業經常會出現數據倉庫、數據中臺、大數據平臺等概念&#xff0c;容易產生疑問&#xff0c;它們中間是相等&#xff0c;還是包含的關系&#xff1f; 數據中臺和數據倉庫概念的關系 數據中臺概念是包含數據倉庫的&#xff0c;數據倉庫是數據中臺中的一部分&#xff0c;包含…

探索Facebook:數字社交的新時代

Facebook&#xff0c;作為全球最大的社交網絡平臺之一&#xff0c;一直在引領著數字社交的發展潮流。隨著科技的不斷進步和社會的不斷變遷&#xff0c;Facebook也在不斷演進和創新&#xff0c;迎接著數字社交的新時代。本文將探索Facebook在數字社交領域的新發展&#xff0c;以…

Behind the Code:Polkadot 如何重塑 Web3 未來

2024 年 5 月 17 日 Polkadot 生態 Behind the Code 第二季第一集 《創造 Web3 的未來》正式上線。第一集深入探討了 Polkadot 和 Web3 技術在解決數字身份、數據所有權和去中心化治理方面的巨大潛力。 &#x1f50d; 查看完整視頻&#xff1a; https://youtu.be/_gP-M5nUidc?…

抖音視頻怎么去水印保存部分源碼|短視頻爬蟲提取收集下載工具

抖音視頻怎么去水印保存部分源碼|短視頻爬蟲提取收集下載工具 抖音視頻去水印保存部分源碼&#xff1a; 通過使用Python中的requests、re和os等庫&#xff0c;可以編寫如下代碼來實現抖音視頻去水印保存的功能。 短視頻爬蟲提取手機下載工具的使用方法&#xff1a; 該工具主…

BevDet-4d(2): 環境安裝及效果展示

1. 環境安裝 conda create -n bevdet python=3.8 conda activate bevdet ? # 3 虛擬環境bevdet中安裝torch pip install spconv pip install torch==1.10.0+cu113 torchvision==0.11.0+cu113 torchaudio==0.10.0 -f https://download.pytorch.org/whl/torch

【數理統計02】延森Jensen‘s不等式的證明

延森不等式&#xff08;Jensen’s Inequality&#xff09;是凸函數理論中的一個重要結果&#xff0c;廣泛應用于概率論、統計學和優化理論等領域。這個不等式的基本形式是&#xff1a; 對于一個凸函數 f f f和一個隨機變量 X X X&#xff0c;如果 E [ X ] \mathbb{E}[X] E[X]存…

安科瑞為河南省促進分布式光伏發電健康持續發展提供解決方案

1 光伏、儲能運維市場分析 在光伏、儲能行業飛速發展的同時&#xff0c;已建的光伏、風力發電站和儲能系統的監控、運維管理項目的招標也非常多&#xff0c;2023年上半年&#xff0c;光伏電站開發企業運維招標規模28.6GW&#xff0c;同比增長204.3%&#xff0c;上述28.6GW招標…