Linux按鍵驅動測試

文章目錄

一、設備節點添加

二、創建驅動文件代碼

2.1 核心數據結構

2.2?按鍵值定義

2.3?關鍵函數實現

三、創建測試文件

四、測試


一、設備節點添加

????????首先在設備樹文件中添加pinctrl以及在根目錄下添加設備節點。如下:

//創建按鍵輸入的pinctrlpinctrl_key: keygrp {fsl,pins = <MX6UL_PAD_UART1_CTS_B__GPIO1_IO18 0xF080 /* KEY0 */>;}; 
//創建按鍵節點key {#address-cells = <1>;#size-cells = <1>;compatible = "atkalpha-key";pinctrl-names = "default";pinctrl-0 = <&pinctrl_key>;key-gpio = <&gpio1 18 GPIO_ACTIVE_LOW>; /* KEY0 */status = "okay";};
};

二、創建驅動文件代碼

2.1 核心數據結構

定義結構體,其中包含按鍵驅動所需的信息,使用atomic_t類型保證按鍵值的原子操作。

struct key_dev {dev_t devid;               /* 設備號 */struct cdev cdev;          /* cdev結構體 */struct class *class;       /* 類 */struct device *device;     /* 設備 */int major;                 /* 主設備號 */int minor;                 /* 次設備號 */struct device_node *nd;    /* 設備樹節點 */int key_gpio;              /* 按鍵GPIO編號 */atomic_t keyvalue;         /* 按鍵值 */
};

2.2?按鍵值定義

驅動中定義了兩個按鍵狀態:按下(1)和未按下/無效(0)。

#define KEY0VALUE       1      /* 按鍵值 */
#define INVAKEY         0      /* 無效的按鍵值 */

2.3?關鍵函數實現

首先是GPIO初始化:從設備樹獲取按鍵GPIO信息,并配置為輸入

static int keyio_init(void)
{keydev.nd = of_find_node_by_path("/key");if (keydev.nd == NULL) {return -EINVAL;}keydev.key_gpio = of_get_named_gpio(keydev.nd, "key-gpio", 0);if (keydev.key_gpio < 0) {printk("can't get key0\r\n");return -EINVAL;}printk("key_gpio=%d\r\n", keydev.key_gpio);/* 初始化key所使用的IO */gpio_request(keydev.key_gpio, "key0");   /* 請求IO */gpio_direction_input(keydev.key_gpio);   /* 設置為輸入 */return 0;
}

?按鍵讀取:驅動會阻塞等待按鍵釋放后才返回,進而實現了一次完整按鍵周期的檢測。

static ssize_t key_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{int ret = 0;int value;struct key_dev *dev = filp->private_data;if (gpio_get_value(dev->key_gpio) == 0) {        /* key0按下 */while(!gpio_get_value(dev->key_gpio));       /* 等待按鍵釋放 */atomic_set(&dev->keyvalue, KEY0VALUE);    } else {    atomic_set(&dev->keyvalue, INVAKEY);         /* 無效的按鍵值 */}value = atomic_read(&dev->keyvalue);ret = copy_to_user(buf, &value, sizeof(value));return ret;
}

三、創建測試文件

? ? ? ? 在測試文件中,通過對字符設備文件(/dev/key)進行標準文件操作實現與內核驅動層的交互。程序結構包括四個關鍵函數:信號處理函數sig_handler()、資源清理函數cleanup_resources()、幫助顯示函數show_usage()及主函數main()。在主函數中,程序首先檢查命令行參數格式,注冊SIGINT信號處理確保可通過Ctrl+C優雅退出,然后打開設備文件獲取文件描述符fd,隨后進入核心監測循環,通過read()系統調用讀取按鍵狀態并使用前后狀態比較算法(prev_keyvalue與keyvalue對比)檢測按鍵事件邊緣變化,實時輸出中文提示信息反饋按鍵狀態。

#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"
#include "signal.h"/* 定義按鍵值 */
#define KEY0VALUE	1
#define INVAKEY		0/* 全局變量 */
static int fd = -1;        /* 文件描述符 */
static int running = 1;    /* 程序運行標志 *//** @description		: 信號處理函數* @param - signum 	: 信號編號* @return 			: 無*/
void sig_handler(int signum)
{if (signum == SIGINT) {printf("\n程序接收到中斷信號,正在退出...\n");running = 0;}
}/** @description		: 釋放資源* @param - filename: 設備文件名* @return 			: 無*/
void cleanup_resources(const char *filename)
{if (fd >= 0) {if (close(fd) < 0) {printf("文件 %s 關閉失敗!\n", filename);} else {printf("已關閉設備文件 %s\n", filename);}}
}/** @description		: 顯示使用幫助* @param - name 	: 程序名* @return 			: 無*/
void show_usage(const char *name)
{printf("使用方法: %s <設備文件>\n", name);printf("示例: %s /dev/key\n", name);
}/** @description		: main主程序* @param - argc 	: argv數組元素個數* @param - argv 	: 具體參數* @return 			: 0 成功;其他 失敗*/
int main(int argc, char *argv[])
{char *filename;int keyvalue;int prev_keyvalue = INVAKEY;/* 參數檢查 */if (argc != 2) {printf("參數錯誤!\n");show_usage(argv[0]);return -1;}filename = argv[1];/* 注冊信號處理函數,捕獲Ctrl+C */signal(SIGINT, sig_handler);/* 打開按鍵設備 */fd = open(filename, O_RDWR);if (fd < 0) {printf("無法打開設備文件 %s!\n", filename);return -1;}printf("按鍵測試程序已啟動\n");printf("按下按鍵進行測試,按 Ctrl+C 退出程序\n");/* 循環讀取按鍵值數據 */while (running) {if (read(fd, &keyvalue, sizeof(keyvalue)) < 0) {printf("讀取按鍵數據失敗\n");break;}/* 按鍵狀態變化檢測 */if (keyvalue == KEY0VALUE && prev_keyvalue != KEY0VALUE) {printf("按鍵被按下,鍵值 = %d\n", keyvalue);} else if (keyvalue == INVAKEY && prev_keyvalue == KEY0VALUE) {printf("按鍵已釋放\n");}prev_keyvalue = keyvalue;usleep(50000);  /* 短暫延時,降低CPU占用 */}/* 清理資源 */cleanup_resources(filename);printf("程序已退出\n");return 0;
}

四、測試

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

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

相關文章

5000元可以運行32B大模型的筆記本

5000元可以運行32B 大模型的筆記本 榮耀筆記本 X14 Plus 銳龍版 R7-8845HS -32G -1T 模型名稱 模型大小 tokens/s qwq-32b-q4 19GB 2.4 Qwen2.5-Coder-14B- Q8 16GB 4 DeepSeek-R1-Distill-Qwen-7B-Q8 8GB 8.1 DeepSeek-R1-Distill-Llama-8B-Q4 5GB 11.7

arm設備樹基礎知識

文章目錄 前言dts片段通用屬性介紹地址大小中斷phandlecompatible mmc節點介紹 前言 arm開發&#xff0c;早晚要了解設備樹 dts片段 interrupt-parent <0x8005>; model "linux,dummy-virt"; #size-cells <0x02>; #address-cells <0x02>; co…

【C++ 核心知識點面試攻略:從基礎到實戰(上位機開發視角)】

一、命名空間&#xff08;Namespace&#xff09;相關問題 問題1&#xff1a;C引入命名空間的核心目的是什么&#xff1f;如何通過命名空間解決命名沖突&#xff1f; 答案&#xff1a; C引入命名空間的核心目的是 避免全局作用域中的命名沖突&#xff0c;通過將變量、函數、類…

線性代數與數據學習

The Functions of Deep Learning (essay from SIAM News, December 2018) Deep Learning and Neural Nets

phpstorm用php連接數據庫報錯

項目場景&#xff1a; phpstorm用php連接數據庫 問題描述 用php使用mysql_connect 的時候報錯了&#xff0c;沒有這個函數 原因分析&#xff1a; php解釋器問題&#xff0c;后來查資料得知mysql_connct只適用于php5.5以下解釋器。一開始用的7&#xff0c;改成5.3以后還是報…

51c大模型~合集122

我自己的原文哦~ https://blog.51cto.com/whaosoft/13877107 #PHYBench 北大物院200人合作&#xff0c;金牌得主超50人&#xff01;PHYBench&#xff1a;大模型究竟能不能真的懂物理&#xff1f; 本項目由北京大學物理學院朱華星老師、曹慶宏副院長統籌指導。基準設計、…

單片機 + 圖像處理芯片 + TFT彩屏 觸摸滑動條控件

觸摸滑動條控件使用說明 一、項目概述 本項目基于單片機和RA8889/RA6809圖形處理芯片的TFT觸摸屏滑動條控件。該控件支持水平和垂直滑動條&#xff0c;可自定義外觀和行為&#xff0c;并支持回調函數進行值變化通知。 硬件平臺&#xff1a;51/ARM均可(測試時使用STC8H8K64U單…

linux離線安裝zsh

下載zsh 下載倉庫后解壓 下載地址&#xff1a;https://github.com/zsh-users/zsh 離線安裝 安裝方法見INSTALL文件 ./configure --prefix[/usr/local] make make install

機器學習中的數據轉換:關鍵步驟與最佳實踐

機器學習中的數據轉換&#xff1a;關鍵步驟與最佳實踐 摘要 &#xff1a;在機器學習領域&#xff0c;數據是模型的核心&#xff0c;而數據的轉換是構建高效、準確模型的關鍵步驟之一。本文深入探討了機器學習中數據轉換的重要性、常見的數據類型及其轉換方法&#xff0c;以及在…

TDR阻抗會爬坡? 別擔心,不是你的錯,你只是不夠了解TDR!

在背板系統或任何長走線設計里&#xff0c;你大概都碰過這畫面&#xff1a; TDR 曲線一開始乖乖在 92 Ω&#xff0c;但越往末端、阻抗越爬越高&#xff0c;來到最高 97 Ω&#xff0c;心里瞬間涼半截 &#x1f612; &#xff0c;「難不成... 板廠又翻車了嗎&#xff1f;」 然…

在另外一臺可以科學下載的電腦用ollama下載模型后,怎么導入到另外一臺服務器的ollama使用

環境&#xff1a; Win10專業版 Ubuntu20.04 問題描述&#xff1a; 在另外一臺可以科學下載的電腦用ollama下載模型后&#xff0c;怎么導入到另外一臺服務器的ollama使用&#xff0c;原電腦win10上的ollama下載的模型,復制到ubuntu20.04的ollama上推理 解決方案&#xff1a;…

Ethan獨立開發產品日報 | 2025-04-27

1. CreateWise AI 旨在提升你工作效率的AI播客編輯器 人工智能播客編輯器&#xff0c;讓你的播客制作速度提升10倍&#xff01;它可以自動去除口頭語和沉默&#xff0c;生成節目筆記和精彩片段&#xff0c;還能一鍵制作適合社交媒體分享的短視頻——所有這些功能都只需一次點…

解決 shadui組件庫Popover 點擊后會消失

react用了shadui組件庫 <Popover><PopoverTrigger><div className"text-operation-item" onClick{props.callback}><img src{props.imgSrc} width{20} height{20} /></div></PopoverTrigger><PopoverContent className"…

SVC電氣設備作用

SVC&#xff08;Static Var Compensator&#xff0c;靜止無功補償器&#xff09;是一種基于電力電子技術的動態無功補償裝置&#xff0c;屬于靈活交流輸電系統&#xff08;FACTS&#xff09;的核心設備之一。它通過快速調節電網中的無功功率&#xff0c;改善電能質量、穩定系統…

黑馬點評商戶查詢緩存--緩存更新策略

ShopTypeServiceImpl類 代碼 package com.hmdp.service.impl;import cn.hutool.json.JSONUtil; import com.hmdp.dto.Result; import com.hmdp.entity.ShopType; import com.hmdp.mapper.ShopTypeMapper; import com.hmdp.service.IShopTypeService; import com.baomidou.myba…

C 語言函數指針與指針函數詳解

一、引言 在 C 語言的編程世界中&#xff0c;函數指針和指針函數是兩個既強大又容易混淆的概念。它們為 C 語言帶來了更高的靈活性和可擴展性&#xff0c;廣泛應用于回調函數、動態鏈接庫、狀態機等多種場景。深入理解和掌握函數指針與指針函數&#xff0c;對于提升 C 語言編程…

HTML5 新特性詳解:語義化標簽、表單與音視頻嵌入

前言 HTML5作為當前Web開發的核心技術&#xff0c;為開發者提供了更強大、更語義化的工具集。本文將深入探討HTML5的三大核心特性&#xff1a;語義化標簽、增強的表單功能以及原生的音視頻支持&#xff0c;幫助開發者構建更現代化、更易維護的網頁應用。 一、HTML5語義化標簽…

利用HandlerMethodArgumentResolver和注解解析封裝用戶信息和Http參數

獲取用戶身份信息詳情注解 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/*** 獲取用戶身份信息詳情注解*/ Retention(RetentionPolicy.RUNTIME) Tar…

OpenCV 圖形API(52)顏色空間轉換-----將 NV12 格式的圖像數據轉換為 RGB 格式的圖像

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 將圖像從 NV12 (YUV420p) 色彩空間轉換為 RGB。該函數將輸入圖像從 NV12 色彩空間轉換到 RGB。Y、U 和 V 通道值的常規范圍是 0 到 255。 輸出圖…

哈工大李治軍《操作系統》進程同步與信號量筆記

1.什么是信號量&#xff1f; 定義&#xff1a;記錄一些信息&#xff08;即量&#xff09;&#xff0c;并根據這個信息決定睡眠還是喚醒&#xff08;即信號&#xff09;。睡眠和喚醒只是一個信號&#xff08;相當于0和1&#xff09;。 2.問題&#xff1a;一種資源的數量是8&am…