input子系统的框架和重要数据结构详解

#1024程序员节 | 征文#
在这里插入图片描述
1

往期内容

I2C子系统专栏:

  1. 专栏地址:IIC子系统_憧憬一下的博客-CSDN博客
  2. 具体芯片的IIC控制器驱动程序分析:i2c-imx.c-CSDN博客
    – 末篇,有往期内容观看顺序

总线和设备树专栏:

  1. 专栏地址:总线和设备树_憧憬一下的博客-CSDN博客
  2. 设备树与 Linux 内核设备驱动模型的整合-CSDN博客
    – 末篇,有往期内容观看顺序

1. 回顾字符设备驱动程序

img

1. 确定主设备号

字符设备驱动需要一个主设备号来标识。你可以选择一个静态的设备号,或者使用动态分配的设备号。

#define DEVICE_NAME "my_chrdev"
#define CLASS_NAME  "my_class"
static int major;  // 保存主设备号

可以通过 register_chrdev() 函数静态注册一个设备号,或者通过 alloc_chrdev_region() 动态分配设备号。

2. 创建 file_operations 结构体

file_operations 结构体定义了设备文件操作的函数指针,如打开、读写、控制等。你需要在这里填充相关的操作函数:

static int drv_open(struct inode *inode, struct file *file) {printk(KERN_INFO "Device opened\n");return 0;
}static int drv_release(struct inode *inode, struct file *file) {printk(KERN_INFO "Device closed\n");return 0;
}static ssize_t drv_read(struct file *file, char __user *buf, size_t len, loff_t *offset) {printk(KERN_INFO "Reading from device\n");return 0;  // 返回读取的字节数
}static ssize_t drv_write(struct file *file, const char __user *buf, size_t len, loff_t *offset) {printk(KERN_INFO "Writing to device\n");return len;  // 返回写入的字节数
}static struct file_operations fops = {.open = drv_open,.release = drv_release,.read = drv_read,.write = drv_write,
};

3. 注册 file_operations 结构体

通过 register_chrdev()file_operations 注册到内核中。如果主设备号是动态分配的,需要通过 major 保存分配的设备号。

static int __init my_driver_init(void) {// 动态分配主设备号major = register_chrdev(0, DEVICE_NAME, &fops);if (major < 0) {printk(KERN_ALERT "Failed to register char device\n");return major;}printk(KERN_INFO "Registered char device with major number %d\n", major);// 创建设备类my_class = class_create(THIS_MODULE, CLASS_NAME);if (IS_ERR(my_class)) {unregister_chrdev(major, DEVICE_NAME);printk(KERN_ALERT "Failed to create class\n");return PTR_ERR(my_class);}// 创建设备节点my_device = device_create(my_class, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);if (IS_ERR(my_device)) {class_destroy(my_class);unregister_chrdev(major, DEVICE_NAME);printk(KERN_ALERT "Failed to create device\n");return PTR_ERR(my_device);}return 0;
}

在这里,我们使用 class_create()device_create() 来创建设备类和设备节点,这样用户空间可以通过 /dev/my_chrdev 访问设备。

4. 编写入口函数

入口函数是模块加载时执行的代码,一般用于初始化设备、分配资源等。

static int __init my_driver_init(void) {printk(KERN_INFO "Initializing character device driver\n");// 注册字符设备major = register_chrdev(0, DEVICE_NAME, &fops);if (major < 0) {printk(KERN_ALERT "Failed to register a major number\n");return major;}printk(KERN_INFO "Registered with major number %d\n", major);// 创建类和设备节点my_class = class_create(THIS_MODULE, CLASS_NAME);if (IS_ERR(my_class)) {unregister_chrdev(major, DEVICE_NAME);printk(KERN_ALERT "Failed to register device class\n");return PTR_ERR(my_class);}my_device = device_create(my_class, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);if (IS_ERR(my_device)) {class_destroy(my_class);unregister_chrdev(major, DEVICE_NAME);printk(KERN_ALERT "Failed to create the device\n");return PTR_ERR(my_device);}printk(KERN_INFO "Device class created\n");return 0;
}

5. 编写出口函数

当卸载驱动时需要释放相关资源,这个过程在出口函数中完成。

static void __exit my_driver_exit(void) {device_destroy(my_class, MKDEV(major, 0));  // 删除设备节点class_unregister(my_class);  // 注销设备类class_destroy(my_class);  // 销毁类unregister_chrdev(major, DEVICE_NAME);  // 注销字符设备printk(KERN_INFO "Character device driver unloaded\n");
}

6. 辅助函数

使用 class_createdevice_create 可以帮助自动创建 /dev 中的设备节点,从而方便用户访问。

  • class_create(THIS_MODULE, CLASS_NAME):创建一个类
  • device_create(my_class, NULL, MKDEV(major, 0), NULL, DEVICE_NAME):在 /dev 中创建设备节点

2. Input子系统框架

img

从图中可以看到,整个 Linux 输入子系统架构可以分为三大层:Input Device 层Input Core 层Input Handler 层

1. Input Device 层(输入设备层)

这个层主要是和硬件直接打交道的地方,如键盘、鼠标、触摸屏、GPIO
键等输入设备。输入设备的驱动程序从硬件中获取数据,并将这些原始数据转换为标准的输入事件,然后上报给核心层(Input Core)。

核心组件:

  • input_dev 结构体:这是设备驱动程序和输入子系统交互的核心结构体。它定义了设备驱动程序如何报告事件,比如按键按下、鼠标移动等。

简要流程: 硬件设备产生输入信号(如按下按键),设备驱动程序通过 input_dev 将这些输入信号传递给 Input Core。

2. Input Core 层(输入核心层)

这个层负责接收来自底层输入设备的事件,并将这些事件分发给上层的处理器(Handler)。它起到桥梁的作用,将底层设备的事件转换为上层可以理解的标准化事件。

核心组件:

  • input.c:是 Input Core 层的主要模块,它提供了 API 和机制来管理输入设备和输入事件。输入核心会将设备上报的事件(如键值、坐标)转交给处理这些事件的 handler

功能概述

  • 接收底层设备上报的输入事件。
  • 将事件转发给合适的 handler 进行处理。

3. Input Handler 层(输入处理层)

这个层负责处理输入核心层转发的输入事件,并向用户空间提供访问接口。在 Linux 中,evdev
是最常用的处理层,负责将输入事件暴露给用户空间。

核心组件:

  • evdev.c:该模块将输入设备的事件通过 /dev/input/eventX 设备节点暴露给用户空间的应用程序,应用程序可以通过 open()read()ioctl() 等系统调用来访问这些事件。

file_operations 结构体evdev_fops 定义了如何处理用户空间对输入设备的访问。这个结构体包括了多个操作函数,比如:

  • .read:读取输入事件。
  • .write:写入数据。
  • .poll:轮询事件。
  • .ioctl:处理设备的控制命令。

4. 用户空间访问

用户空间的应用程序可以通过 /dev/input/eventX 设备节点直接访问输入设备。这些应用程序通过
open()ioctl()poll()read() 等接口访问设备数据,处理输入事件。

举例:

  • tslib:是用于处理触摸屏输入的库。
  • libinput:是一个更高级的输入处理库,用于统一处理键盘、鼠标、触摸屏等设备的输入事件。

Input Device 层:负责将硬件设备的原始输入信号转换为标准事件。

Input Core 层:负责管理输入设备,并将标准事件传递给处理层。

Input Handler 层:将事件暴露给用户空间,用户通过访问 /dev/input/eventX 来读取输入事件。

3. Input子系统重要结构体

内核源码:

  • \Linux-4.9.88\include\linux\input.h📎input.h
  • \Linux-4.9.88\include\uapi\linux\input-event-codes.h📎input-event-codes.h

img

3.1 Input_dev

truct input_dev 是描述输入设备的核心结构体。它提供了输入设备的详细属性、支持的事件类型、处理事件的回调函数等。在开发输入设备驱动时,开发者需要初始化并注册该结构体,使其能够正确地处理输入事件并将其传递到上层。

\Linux-4.9.88\include\linux\input.h
struct input_dev {const char *name; //输入设备的名称。例如,"USB Keyboard"const char *phys; //输入设备的物理路径。例如,"usb-0000:00:1d.0-1/input0"。const char *uniq; //输入设备的唯一标识符,通常用于区分具有相同类型的多个设备。struct input_id id; //输入设备的硬件 ID,用于标识输入设备的制造商、产品 ID 和版本号。unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];unsigned long evbit[BITS_TO_LONGS(EV_CNT)];//设备支持的事件类型。事件类型定义在 linux/input.h 中,如 EV_KEY 表示按键事件,EV_ABS 表示绝对坐标事件。unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];//设备支持的按键,如键盘按键或鼠标按键。unsigned long relbit[BITS_TO_LONGS(REL_CNT)];//设备支持的相对运动事件,如鼠标的移动。unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];//设备支持的绝对坐标事件,如触摸屏的坐标数据。unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];//设备支持的杂项事件,如扫描码、遥控器信号等。unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];//设备支持的 LED 事件(如键盘指示灯)。unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];//设备支持的声音事件(如蜂鸣器)。unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];//设备支持的力反馈事件(如游戏手柄的振动)。unsigned long swbit[BITS_TO_LONGS(SW_CNT)];//设备支持的开关事件。unsigned int hint_events_per_packet;// 每个数据包的建议事件数,优化设备的事件处理。unsigned int keycodemax;unsigned int keycodesize;//输入设备支持的最大键码数和每个键码的大小。void *keycode;//存储设备支持的键码映射表。int (*setkeycode)(struct input_dev *dev,const struct input_keymap_entry *ke,unsigned int *old_keycode);//设置设备的键码映射。int (*getkeycode)(struct input_dev *dev,struct input_keymap_entry *ke);// 获取设备的键码映射。struct ff_device *ff;//力反馈设备的相关信息。unsigned int repeat_key;//保存最后一个重复的按键值。struct timer_list timer;//用于处理按键重复事件的定时器int rep[REP_CNT];//按键重复相关的参数,主要用于延迟与频率。struct input_mt *mt;//多点触控相关的数据结构。struct input_absinfo *absinfo;//保存绝对坐标相关的信息(如最小值、最大值、分辨率等)。unsigned long key[BITS_TO_LONGS(KEY_CNT)];//保存按键的当前状态unsigned long led[BITS_TO_LONGS(LED_CNT)];//保存 LED 的当前状态unsigned long snd[BITS_TO_LONGS(SND_CNT)];//保存声音设备的当前状态unsigned long sw[BITS_TO_LONGS(SW_CNT)];//保存开关的当前状态。int (*open)(struct input_dev *dev);//打开设备时调用的函数,通常用于初始化设备。void (*close)(struct input_dev *dev);// 关闭设备时调用的函数,通常用于释放资源。int (*flush)(struct input_dev *dev, struct file *file);//刷新设备时调用的函数,通常用于清空缓冲区。int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);//处理输入事件的回调函数struct input_handle __rcu *grab;spinlock_t event_lock;//用于保护输入事件处理的自旋锁。struct mutex mutex;//用于保护设备其他部分的互斥锁。unsigned int users;//记录打开该设备的用户数。bool going_away;//标识设备是否正在被卸载。struct device dev;//内核设备模型中的设备结构体。struct list_head	h_list; // 保存handle链表struct list_head	node;//设备在输入子系统链表中的挂载点。unsigned int num_vals;unsigned int max_vals;//当前设备的输入值数量及其最大值。struct input_value *vals;//保存输入值的数组bool devres_managed;//标识设备是否由资源管理器管理
};

3.2 input_handler

input_handler 作为输入事件的处理器,它的作用在于:

  • 事件的接收与处理:它定义了如何接收和处理来自输入设备的事件,如键盘按键、鼠标移动等。
  • 事件过滤filter 函数可以在事件传递前过滤掉不需要的事件,提高处理效率。
  • 设备匹配与连接:通过 matchconnect 函数,它负责将处理程序与适当的设备连接起来。
  • 事件传递eventevents 回调函数可以在设备产生事件时,将事件传递给上层逻辑,或通过驱动程序接口传递给用户空间应用。

工作流程简述

  1. 设备连接:当一个输入设备注册时,input_handlermatch 函数会被调用,以确定该处理程序是否可以处理这个设备。如果匹配成功,connect 函数被调用来建立连接。
  2. 事件处理:一旦设备产生事件,eventevents 回调会被调用来处理输入事件。根据设备和处理程序的实现,事件可以传递给用户空间或在内核中进一步处理。
  3. 设备断开:当设备断开时,disconnect 函数会被调用,处理程序负责清理与设备连接相关的资源。
\Linux-4.9.88\include\linux\input.h
struct input_handler {void *private;//用于存储处理程序的私有数据。驱动程序可以使用它来保存与特定设备相关的上下文信息。void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);//这是处理单个输入事件的回调函数。事件由 type、code 和 value 表示,分别代表事件类型、事件码和事件的值(如按键按下或松开、移动坐标等)。void (*events)(struct input_handle *handle,const struct input_value *vals, unsigned int count);//处理多个输入事件的回调函数。vals 是一个包含多个事件的数组,count 是事件的数量。这允许处理一组输入事件,提高效率。bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value);//这是一个事件过滤函数。它用于判断某个事件是否应该被传递给上层。如果返回 true,则事件会被过滤掉,不会继续处理;如果返回 false,事件将继续传递。bool (*match)(struct input_handler *handler, struct input_dev *dev);//用于匹配处理程序和输入设备。返回 true 表示当前 handler 可以处理 dev 设备。int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);//当有输入设备与 handler 匹配时调用的回调函数,用于连接设备。返回 0 表示成功连接,其他值表示失败。void (*disconnect)(struct input_handle *handle);//当输入设备断开时调用的回调函数,用于处理设备断开连接后的清理工作。void (*start)(struct input_handle *handle);//在 connect 成功之后调用的回调函数,通常用于初始化某些特定资源或启动设备处理程序。bool legacy_minors;//指示处理程序是否使用了旧的次设备号 (minor number) 机制。这个标志主要用于向后兼容旧的输入设备模型。int minor;//用于存储处理程序关联的次设备号。次设备号帮助区分同一类设备中的不同实例。const char *name;//输入处理程序的名称,用于在内核日志或其他信息输出中标识处理程序。const struct input_device_id *id_table;//这是一个输入设备 ID 表,用于定义处理程序可以匹配的输入设备类型。它通常包含输入设备的厂商 ID、产品 ID 等信息,用于识别设备。struct list_head	h_list;//用于将 input_handler 添加到输入子系统的处理程序列表handle中,和相应的input_dev匹配保存进去struct list_head	node;//用于将 input_handler 添加到设备的处理程序链表中。
};

3.3 input_handle

输入子系统中的一个核心结构体,它用于连接输入设备 (input_dev) 和输入事件处理程序 (input_handler)。当设备和处理程序之间建立连接时,input_handle 负责维护两者之间的关联,确保事件能够从设备传递到合适的处理程序进行处理。

工作流程简述

  1. 设备与处理程序连接:当输入设备与输入处理程序匹配成功时,系统会创建并初始化一个 input_handle,用来维持设备和处理程序的关系。
  2. 事件传递:一旦输入设备产生事件,input_handle 会将这些事件从 input_dev 传递给对应的 input_handler 进行处理。
  3. 设备打开/关闭管理input_handle 中的 open 标志位用于记录设备的状态,确保设备只在被打开时接收和处理事件,并且在关闭时停止事件处理。
  4. 设备断开:当输入设备断开连接时,系统会调用 input_handlerdisconnect 函数,并清理 input_handle 中的资源。
\Linux-4.9.88\include\linux\input.h
struct input_handle {void *private;//这个指针用于保存输入处理程序的私有数据(上下文数据)。//输入子系统在连接设备时,可能需要为每个连接的 input_handle 维护独立的数据。int open; // 这个整数值用于表示设备是否已经打开。const char *name;//处理程序的名称,通常用于标识该输入处理程序,可以帮助调试和日志输出时识别当前使用的 input_handle。struct input_dev *dev;//它表示 input_handle 正在处理的输入设备。struct input_handler *handler;//它表示当前 input_handle 所使用的处理程序。struct list_head	d_node;//这个链表节点用于将 input_handle 挂接到输入设备的处理程序链表中。这意味着一个输入设备可以有多个 input_handle 进行事件处理。struct list_head	h_node; //同里
};

3.4 input_event/value

是 Linux 输入子系统中用来描述输入设备事件的核心结构体,它表示从输入设备(如键盘、鼠标、触摸屏等)发送到内核的每个输入事件。

\Linux-4.9.88\include\linux\input.h
struct input_event {struct timeval time; //用来记录事件发生的时间。它包括秒 (tv_sec) 和微秒 (tv_usec) 两个字段,表示该事件的时间戳。__u16 type; // 表示事件的类型。它决定了事件的类别,比如按键事件、相对移动事件、绝对位置事件等。__u16 code;//表示具体的事件代码。其含义依赖于 type 的值。__s32 value;//表示事件的值,其含义取决于 type 和 code 的组合。
};struct input_value { //差不多,用这个比较多好像__u16 type;__u16 code;__s32 value;
};

type:

\Linux-4.9.88\include\uapi\linux\input-event-codes.h
/** Event types*/
#define EV_SYN			0x00
#define EV_KEY			0x01
#define EV_REL			0x02
#define EV_ABS			0x03
#define EV_MSC			0x04
#define EV_SW			0x05
#define EV_LED			0x11
#define EV_SND			0x12
#define EV_REP			0x14
#define EV_FF			0x15
#define EV_PWR			0x16
#define EV_FF_STATUS		0x17
#define EV_MAX			0x1f
#define EV_CNT			(EV_MAX+1)

这些宏定义描述了 Linux 输入子系统中不同的 事件类型 (Event Types)。这些类型是用于标识从输入设备(例如键盘、鼠标、触摸屏等)传递到内核的事件类别,每个类别都有不同的意义。struct input_event 结构体中的 type 字段使用这些宏来确定事件的类别。

  1. EV_SYN (0x00)
  • 同步事件,用于标识一组输入事件的结束。例如,多个输入事件会通过 EV_SYN 通知系统完成一个事件序列。这是一个标志位,告诉系统已经处理完一个事件的所有数据。
  • 典型用途:报告鼠标或触摸屏输入后,系统应通过 EV_SYN 告诉用户空间事件已完成。
  1. EV_KEY (0x01)
  • 按键事件,表示设备上的按键或按钮状态的变化。这是键盘、鼠标按钮、游戏控制器按钮等输入设备常用的事件类型。
  • 典型用途:键盘按下某个按键(如 KEY_A)或者鼠标点击时触发。
  1. EV_REL (0x02)
  • 相对坐标事件,用于描述相对于当前坐标的位移量。常用于鼠标等设备,表示相对位置的改变。
  • 典型用途:鼠标移动过程中生成的相对位移数据(REL_X, REL_Y)。
  1. EV_ABS (0x03)
  • 绝对坐标事件,用于描述设备的绝对坐标值。常用于触摸屏、操纵杆等设备,表示其当前位置。
  • 典型用途:触摸屏上的触摸点的 X 和 Y 位置(ABS_X, ABS_Y)。
  1. EV_MSC (0x04)
  • 杂项事件,用于发送某些特定的输入设备数据,例如时间戳或者扫描码等。
  • 典型用途:键盘扫描码事件(MSC_SCAN)。
  1. EV_SW (0x05)
  • 开关事件,用于表示设备上的开关状态。例如,表示设备是否插入、盖子是否关闭等。
  • 典型用途:检测设备状态(如笔记本的盖子是否关闭)。
  1. EV_LED (0x11)
  • LED 事件,用于控制设备上的 LED 指示灯。例如,键盘上的大写锁定指示灯(Caps Lock)、数字锁定指示灯(Num Lock)等。
  • 典型用途:设置或读取键盘上的 LED 状态。
  1. EV_SND (0x12)
  • 声音事件,用于产生音频信号,例如蜂鸣器。
  • 典型用途:系统蜂鸣器发出声音。
  1. EV_REP (0x14)
  • 重复事件,用于控制按键重复行为。例如,按住某个键时,定义按键重复的时间间隔(重复速度和延迟)。
  • 典型用途:按住某个键时产生的重复输入。
  1. EV_FF (0x15)
  • 力反馈事件,用于与具有力反馈功能的设备(如游戏控制器)进行交互,产生物理反馈(震动等)。
  • 典型用途:控制游戏控制器的震动反馈。
  1. EV_PWR (0x16)
  • 电源事件,用于报告或控制设备的电源状态。
  • 典型用途:电源按钮或设备的电源管理事件。
  1. EV_FF_STATUS (0x17)
  • 力反馈状态事件,用于报告力反馈设备的状态。
  • 典型用途:检测力反馈是否成功启动或停止。
  1. EV_MAX (0x1f)
  • 事件类型的最大值,用于定义事件类型的范围。
  1. EV_CNT (EV_MAX + 1)
  • 事件类型的数量(总计 32 种事件类型)。用于计算事件类型的总数。

这些事件类型用于在内核和用户空间之间传递输入设备的事件信息,驱动程序根据事件类型来处理输入设备的数据。例如:

  • 键盘驱动程序会处理 EV_KEY 类型的事件,用于表示按键的按下与松开。
  • 鼠标驱动程序会处理 EV_REL 类型的事件,用于表示鼠标的移动。
  • 触摸屏驱动程序会处理 EV_ABS 类型的事件,用于表示触摸点的坐标。

通过这些事件类型,输入子系统可以统一处理不同输入设备的数据,并通过 /dev/input/eventX 接口传递给用户空间程序。

code:

以type为EV_KEY按键类型例子:

#define KEY_RESERVED		0
#define KEY_ESC			1
#define KEY_1			2
#define KEY_2			3
#define KEY_3			4
#define KEY_4			5
#define KEY_5			6
#define KEY_6			7
#define KEY_7			8
#define KEY_8			9
#define KEY_9			10
.......

以type为EV_ABS绝对位移类型例子:

/** Absolute axes*/
#define ABS_X			0x00 //x方向
#define ABS_Y			0x01 /y方向
#define ABS_Z			0x02
#define ABS_RX			0x03
.......

value:

对于按键,它的 value 可以是 0(表示按键被按下)、1(表示按键被松开)、2(表示长按);

对于触摸屏,它的 value 就是坐标值、压力值。

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

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

相关文章

【人工智能】掌握深度学习中的时间序列预测:深入解析RNN与LSTM的工作原理与应用

深度学习中的循环神经网络&#xff08;RNN&#xff09;和长短时记忆网络&#xff08;LSTM&#xff09;在处理时间序列数据方面具有重要作用。它们能够通过记忆前序信息&#xff0c;捕捉序列数据中的长期依赖性&#xff0c;广泛应用于金融市场预测、自然语言处理、语音识别等领域…

RSocket vs WebSocket:Spring Boot 3.3 中的两大实时通信利器

RSocket vs WebSocket&#xff1a;Spring Boot 3.3 中的两大实时通信利器 随着现代互联网应用的不断发展&#xff0c;实时通信已经成为许多应用程序不可或缺的功能。无论是社交网络、在线游戏还是数据监控系统&#xff0c;实时通信都能提供快速、无缝的信息交换。而实现实时通…

高精度KEITHLEY2636A参数资料吉时利2636B数字源表

Keithley 2636A吉时利2636B数字源表&#xff0c;200V&#xff0c;1fA/1uV&#xff0c;2 通道&#xff0c;10A 脉冲 Keithley 2636A SourceMeter 是 Keithley 最新 IV 源测量仪器的一部分&#xff0c;可用作台式 IV 表征工具或多通道 IV 测试系统的构建块组件。对于台式使用&am…

STM32通信协议-I2C

目录 一&#xff0c;IC2的协议规则 I2C总线是PHILIPS公司开发的两线式串行总线&#xff0c;I2C总线主要解决了单片机一对多通信的问题 两根通信线&#xff1a;SCL,SDA&#xff0c;同步&#xff0c;半双工通信&#xff0c;支持数据应答机制&#xff0c;支持总线挂载多设备。 …

Python异常检测- 单类支持向量机(One-Class SVM)

系列文章目录 Python异常检测- Isolation Forest&#xff08;孤立森林&#xff09; python异常检测 - 随机离群选择Stochastic Outlier Selection (SOS) python异常检测-局部异常因子&#xff08;LOF&#xff09;算法 Python异常检测- DBSCAN 文章目录 系列文章目录前言一、On…

图像高清化(论文复现)

图像高清化(论文复现) 本文所涉及所有资源均在传知代码平台可获取 文章目录 图像高清化(论文复现)概述算法原理核心逻辑效果演示使用方式概述 本文复现论文 “Zero-Shot” Super-Resolution using Deep Internal Learning[1] 提出的图像超分辨率方法。 图像超分辨率是指从低…

如何从模块内部运行 Pytest

在 Python 中&#xff0c;pytest 是一个强大的测试框架&#xff0c;用于编写和运行测试用例。通常我们会在命令行中运行 pytest&#xff0c;但是有时你可能希望从模块或脚本的内部运行 pytest&#xff0c;比如为了自动化测试或集成到某个工作流程中。 1、问题背景 当你从模块…

Netty无锁化设计之对象池实现

池化技术是比较常见的一种技术&#xff0c;在平时我们已经就接触很多了&#xff0c;比如线程池&#xff0c;数据库连接池等等。当我们要使用一个资源的时候从池中去获取&#xff0c;用完就放回池中以便其他线程可以使用&#xff0c;这样的目的就是为了减少资源开销&#xff0c;…

JMeter 动态参数赋值实践

目录 前言 单线程 用户参数 场景说明 实战结果 配置明细 单线程 CSV Data Set Config 场景说明 实践结果 配置明细 多线程循环单次执行 场景说明 实践结果 配置明细 单线程 控制器 用户自定义变量 用户参数 场景说明 实战结果 配置明细 多并发 多接口 …

AudioSegment 提高音频音量 - python 实现

一些采集的音频声音音量过小可以通过 AudioSegment 实现音量增强。 按照 python 库&#xff1a; pip install AudioSegment 代码具体实现&#xff1a; #-*-coding:utf-8-*- # date:2024-10 # Author: DataBall - XIAN # Function: 音频增加音量import os from pydub import …

Matlab学习01-矩阵

目录 一&#xff0c;矩阵的创建 1&#xff0c;直接输入法创建矩阵 2&#xff0c;利用M文件创建矩阵 3&#xff0c;利用其它文本编辑器创建矩阵 二&#xff0c;矩阵的拼接 1&#xff0c;基本拼接 1&#xff09; 水平方向的拼接 2&#xff09;垂直方向的拼接 3&#xf…

记录:网鼎杯2024赛前热身WEB01

目录扫描&#xff0c;发现上传点&#xff0c;判断可能存在文件上传漏洞&#xff0c;并根据文件后缀判断网站开发语言为php 编写蚁剑一句话木马直接上传 蚁剑连接 这里生成 的flag是随机的&#xff0c;因为烽火台反作弊会随机生成环境&#xff0c;在一顿查找后&#xff0c;在hom…

stm32F103 实现呼吸灯效果

目录 硬件连接 软件实现步骤 初始化系统时钟。 配置 GPIO 引脚。 配置定时器以生成 PWM 信号。 在主循环中调整 PWM 占空比以实现呼吸效果。 示例代码 1. 初始化系统时钟 2. 配置 GPIO 引脚 3. 配置定时器以生成 PWM 信号 4. 在主循环中调整 PWM 占空比以实现呼吸效…

5G RedCap工业路由器赋能电力物联网应用

随着5G轻量化技术应用的推进&#xff0c;5G RedCap旨在提供低功耗、低成本、广覆盖等功能特点赋能电力智能化升级。特别适用于工业物联网、低空经济、车联网、消费电子和轻量级5G的需求。 5G RedCap工业路由器的特点 低功耗&#xff1a;5G RedCap工业路由器通过节能技术&#…

npm run serve 提示异常Cannot read property ‘upgrade‘ of undefined

npm run serve 提示Cannot read property ‘upgrade’ of undefined 一般是proxy的target代理域名问题导致的&#xff0c;如下&#xff1a; 解决方案&#xff1a; proxy: { “/remoteDealerReportApi”: { target: ‘http://demo-.com.cn’, //此域名有问题&#xff0c;会导致…

PTA数据库编程练习合集

10-1 查询重量在[40,65]之间的产品信息 本题目要求编写SQL语句&#xff0c; 检索出product表中所有符合40 < Weight < 65的记录。 提示&#xff1a;请使用SELECT语句作答。 表结构: CREATE TABLE product (Pid varchar(20), --商品编号PName varchar(50), --商品名…

JavaWeb开发7

前后端混合开发 沟通成本高 分工不明确 不便管理 不便维护扩展 前后端分离开发 前端--接口--后端 需求分析--接口定义--前后端并行开发--测试--前后端连调测试 前端开发 模块化 JS、CSS 组件化 UI结构、样式、行为 规范化 目录结构、编码、接口 自动化 构建、部署、…

Git_IDEA集成GitHub

Git_IDEA集成GitHub 设置 GitHub 账号 分享工程到 GitHub push 推送本地库到远程库 pull 拉取远程库到本地库 clone 克隆远程库到本地 设置 GitHub 账号 去 GitHub 账户上设置 token 因为网络原因用账号密码可能登不上&#xff0c;所以选择用口令。 分享工程到 GitHub…

网络安全领域推荐证书介绍及备考指南

在网络安全领域&#xff0c;拥有专业认证不仅可以证明个人的专业能力&#xff0c;还能帮助在实际工作中应用先进的技术和知识。以下是几种热门的网络安全证书介绍及备考指南。 1. OSCP (Offensive Security Certified Professional) 证书简介 OSCP是针对渗透测试领域的入门级…

Matlab 疲劳驾驶检测

课题介绍 该课题为基于眼部和嘴部的疲劳驾驶检测。带有一个人机交互界面GUI&#xff0c;通过输入视频&#xff0c;分帧&#xff0c;定位眼睛和嘴巴&#xff0c;通过眼睛和嘴巴的张合度&#xff0c;来判别是否疲劳。 二、操作步骤 第一步&#xff1a;最好电脑安装的是MATLAB …