15.2linux设备树下的platform驱动编写(程序)_csdn
我尽量讲的更详细,为了关注我的粉丝!!!
修改设备树文件:
这个我们在上一章已经写过了,但是还是带着大家来重写一遍!
1.打开pinctrl-stm32.c 这个文件:
strict 成员变量默认为 true,我们需要将其改为 false。
2.在linux源代码中,打开 stm32mp15-pinctrl.dtsi 文件并进行修改:
同时屏蔽PIO这个端口的其他复用功能。
找到<STM32_PINMUX('I', 0, ANALOG)>, /* LCD_G5 */
和<STM32_PINMUX('I', 0, AF14)>, /* LCD_G5 */
,进行屏蔽。
3.在设备树中创建设备节点,打开stm32mp157d-atk.dts 文件,修改gpioled根节点:
之前的博客也是跟大家按照肌肉记忆来编写程序!一步一步按照思路来编写!
总代码会放在最后。
为了让大家更能明白,可以先对着总代码,进行对我的写代码流程更加详细得当!
放心,我也是一步一步打的代码,不是复制粘贴!!!
我们发现驱动文件不用再写地址映射了,是因为都在设备节点和pinctrl准备好了!跟之前一样申请IO即可,这里和以前的区别就是驱动的分离和分层,可以匹配多个设备!通过platform总线来匹配而已!
1、头文件
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of_gpio.h>
#include <linux/semaphore.h>
#include <linux/timer.h>
#include <linux/irq.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/fs.h>
#include <linux/fcntl.h>
#include <linux/platform_device.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
2、驱动注册和注销
之前讲过就不用过多赘述了!
有了platform注册驱动后,就要编写platform_driver驱动结构体:跟之前的字符驱动注册差不多!
3、编写platform_driver驱动结构体
这里有为重要的就是设备树匹配表。
3.1、编写设备树匹配表
这个之前就讲过:
platform 驱动会通过 of_match_table 来保存兼容性值,也就是表明此驱动兼容哪些设备。
通过 MODULE_DEVICE_TABLE 声明一下 led_of_match 这个设备匹配表。
在编写 of_device_id 的时候最后一个元素一定要为空!也就是 { /* Sentinel */ }
。
compatible 值为“alientek,led”,在设备树中也有这个,会互相匹配:
因此驱动中对应的 probe 函数就会执行!
最后我们也可以在内核驱动文件中./drivers中发现stm32mp1-led这个,在./devices中发现gpioled这个,就说明相互匹配了!
3.2、编写probe和remove函数
相互匹配成功后,就会自动执行这个函数,所以我们在这里放注册字符设备驱动以及GPIO相关设置。
匹配成功后:显示这个
放在probe函数内:
3.2.1、配置led字符设备结构体
3.2.2、注册字符设备驱动
同样编写宏定义:
这个名字在以后的/dev目录下构建。
同理编写注销字符设备驱动:
3.2.3、初始化cdev以及添加cdev
配置cdev设备结构体:
作用:可以执行到/dev:
同样编写字符驱动操作集:
static int led_open(struct inode *inode, struct file *filp){return 0;}static ssize_t led_write(struct file *filp, const char __user *buf,size_t cnt, loff_t *offt){return 0;}static int led_release(struct inode *inode, struct file *filp){return 0;}/*设备操作函数*/static struct file_operations led_fops = {.owner = THIS_MODULE,.open = led_open,.write = led_write,.release = led_release,};
同理需要删除cdev:
3.2.4、配置设备类和设备节点
配置相关设备结构体:
配置设备类:
同理删掉设备类:
配置设备节点:
同理删掉设备节点:
接下来就是跟以前一样的操作,目前注册好了设备节点,就要获取设备树的信息。
3.2.5、获取设备树的信息模块集成
接下来集成模块,进行获取设备树上的信息,并申请IO。
已经注册好了设备节点,目前要配置设备节点的相关信息。
配置设备节点相关信息:
配置设备结构体:
集成模块化:
放在probe函数内:
pdev->dev.of_node
能够指向设备节点(struct device_node
)。
在 Linux 内核里,设备树描述硬件信息,内核解析后会生成设备节点(struct device_node
)。struct platform_device
是表示平台设备的结构体,它包含 struct device
类型的 dev
成员。而 struct device
有 struct device_node *of_node
成员,内核创建设备时会把对应设备树节点的指针赋给 of_node
。所以 pdev->dev.of_node
能指向设备节点。
因为这里没有用到自己定义的LED设备节点:为了更直观看到:
一个意思led.node和pdev->dev.of_node。
配置led-gpio结构体:
配置补充集成模块函数:
同样释放GPIO:
从这里可以看出和以前代码不一样,并没有读取compatible和status属性值。这里可以不用写,简化代码。
为何代码可不读取 compatible
和 status
属性
在 Linux 内核里,当使用平台驱动(platform_driver
)时,内核会自动依据驱动的 of_match_table
来匹配设备树节点的 compatible
属性。
驱动需要支持多种不同的设备,且这些设备的 compatible
属性值不同,就可能需要在 probe
函数里手动读取 compatible
属性,进而依据不同的 compatible
值执行不同的初始化操作。
3.2.6、配置错误信息
同时修改集成模块:
这里发生错误了:
在 C 语言里,goto
语句只能跳转到同一个函数内部定义的标号处。
所以fail_findnode和fail_setoutput还是得跳转定义到led_gpio_init函数中:
4、配置操作集
这个都是以前讲过很多遍了,就不多介绍了,直接贴代码!
5、测试效果
开灯或关灯:
6、总代码
dtsleddriver.c
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of_gpio.h>
#include <linux/semaphore.h>
#include <linux/timer.h>
#include <linux/irq.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/fs.h>
#include <linux/fcntl.h>
#include <linux/platform_device.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>#define LED_CNT 1 /* 设备号长度 */
#define LED_NAME "dtsplatled" /* 设备名字 */
#define LEDOFF 0
#define LEDON 1/*led设备结构体*/
struct led_dev{dev_t devid;//设备号int major;//主设备号int minor;//次设备号struct cdev cdev; /*cdev*/struct class *class; /*设备类*/struct device *device; /*设备节点*/struct device_node *node; /*LED设备节点*/int gpio_led; /*LED灯GPIO标号*/
};
struct led_dev led;//led设备void led_switch(u8 sta)
{if (sta == LEDON )gpio_set_value(led.gpio_led, 0);else if (sta == LEDOFF)gpio_set_value(led.gpio_led, 1);
}static int led_gpio_init(struct device_node *nd)
{int ret;/*1.从设备树中获取GPIO*/led.gpio_led=of_get_named_gpio(nd,"led-gpio",0);if(!gpio_is_valid(led.gpio_led)) {printk(KERN_ERR "leddev: Failed to get led-gpio\n");goto fail_findnode;}/*2.申请使用GPIO*/ret=gpio_request(led.gpio_led,"LED0");if (ret) {printk(KERN_ERR "led: Failed to request led-gpio\n");goto fail_findnode;}/*3.将GPIO设置为输出模式并设置GPIO初始电平状态*/ret=gpio_direction_output(led.gpio_led,1);if (ret < 0) {ret = -EINVAL;goto fail_setoutput;}return 0;
fail_setoutput:gpio_free(led.gpio_led);
fail_findnode:device_destroy(led.class,led.devid);return ret;
}static int led_open(struct inode *inode, struct file *filp)
{return 0;
}static ssize_t led_write(struct file *filp, const char __user *buf,size_t cnt, loff_t *offt)
{int retvalue;unsigned char databuf[1];unsigned char ledstat;retvalue = copy_from_user(databuf, buf, cnt);if(retvalue < 0) {printk("kernel write failed!\r\n");return -EFAULT;}ledstat = databuf[0];if (ledstat == LEDON) {led_switch(LEDON);} else if (ledstat == LEDOFF) {led_switch(LEDOFF);}return 0;
}static int led_release(struct inode *inode, struct file *filp)
{return 0;
}/*设备操作函数*/
static struct file_operations led_fops = {.owner = THIS_MODULE,.open = led_open,.write = led_write,.release = led_release,
};/*platform 驱动的 probe 函数,当驱动与设备匹配以后此函数
就会执行*/
static int led_probe(struct platform_device *pdev)
{int ret=0;printk("led driver and device was matched!\r\n");/*6.初始化LED*/led.node=pdev->dev.of_node;ret=led_gpio_init(pdev->dev.of_node);if(ret < 0){return ret;}/*1.注册字符设备驱动*/led.major=0;if(led.major){//若给定主设备号led.devid=MKDEV(led.major,0);ret=register_chrdev_region(led.devid,LED_CNT,LED_NAME);}else{//若未给定主设备号ret=alloc_chrdev_region(&led.devid,0,LED_CNT,LED_NAME);led.major=MAJOR(led.devid);led.minor=MINOR(led.devid);}if(ret<0){goto fail_devid;}printk("major=%d,minor=%d,NUm=%d,NAME=%s\r\n",led.major,led.minor,LED_CNT,LED_NAME);/*2.初始化cdev*/led.cdev.owner=THIS_MODULE;cdev_init(&led.cdev,&led_fops);/*3.添加cdev*/ret=cdev_add(&led.cdev,led.devid,LED_CNT);if(ret<0){goto fail_cdev;}/*4.创建设备类*/led.class=class_create(THIS_MODULE,LED_NAME);if(IS_ERR(led.class)){ret = PTR_ERR(led.class);goto fail_class;}/*5.创建设备节点*/led.device=device_create(led.class,NULL,led.devid,NULL,LED_NAME);if(IS_ERR(led.device)){ret = PTR_ERR(led.device);goto fail_device;}return 0;
fail_device:class_destroy(led.class);
fail_class:cdev_del(&led.cdev);
fail_cdev:unregister_chrdev_region(led.devid,LED_CNT);
fail_devid:return ret;
}
/*platform 驱动的 remove 函数*/
static int led_remove(struct platform_device *dev)
{/*卸载驱动的时候关闭LED*/gpio_set_value(led.gpio_led,1);/*注销GPIO*/gpio_free(led.gpio_led); /*注销设备节点*/device_destroy(led.class,led.devid);/*注销设备类*/class_destroy(led.class);/*注销字符设备对象*/cdev_del(&led.cdev);/*注销字符设备驱动*/unregister_chrdev_region(led.devid,LED_CNT); return 0;
}/*匹配列表*/
static const struct of_device_id led_of_match[] = {{ .compatible = "alientek,led" },{ /* Sentinel */ }
};MODULE_DEVICE_TABLE(of, led_of_match);/*platform驱动结构体*/
static struct platform_driver led_driver = {.driver = {.name = "stm32mp1-led", /*驱动名字,用于和设备匹配*/.of_match_table = led_of_match, /*设备树匹配表*/},.probe = led_probe,.remove = led_remove,
};/*驱动模块注册*/
static int __init leddriver_init(void)
{return platform_driver_register(&led_driver);
}
/*驱动模块注销*/
static void __exit leddriver_exit(void)
{platform_driver_unregister(&led_driver);
}module_init(leddriver_init);
module_exit(leddriver_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("chensir");
MODULE_INFO(intree,"Y");
ledApp.c
#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"#define LEDOFF 0
#define LEDON 1int main(int argc, char *argv[])
{int fd, retvalue;char *filename;unsigned char databuf[1];if(argc != 3){printf("Error Usage!\r\n");return -1;}filename = argv[1];/* 打开 led 驱动 */fd = open(filename, O_RDWR);if(fd < 0){printf("file %s open failed!\r\n", argv[1]);return -1;}databuf[0] = atoi(argv[2]); /* 要执行的操作:打开或关闭 */retvalue = write(fd, databuf, sizeof(databuf));if(retvalue < 0){printf("LED Control Failed!\r\n");close(fd);return -1;}retvalue = close(fd); /* 关闭文件 */if(retvalue < 0){printf("file %s close failed!\r\n", argv[1]);return -1;}return 0;}
makefile
KERNELDIR := /home/chensir/linux/atk-mp1/linux/my_linux/linux-5.4.31
CURRENT_PATH := $(shell pwd)
obj-m := dtsleddriver.o
build: kernel_modules
kernel_modules:$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
clean:$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean
相关文章:
15.2linux设备树下的platform驱动编写(程序)_csdn
我尽量讲的更详细,为了关注我的粉丝!!! 修改设备树文件: 这个我们在上一章已经写过了,但是还是带着大家来重写一遍! 1.打开pinctrl-stm32.c 这个文件: strict 成员变量默认为 true&…...
Java的Selenium的特殊元素操作与定位之window切换
当你要操作另外一个窗口页面的元素时,一定要注意先切换窗口 切换方式:传入要操作窗口的name或者句柄handle driver.switchTo.window(nameOrHandle); 如何获取到窗口的句柄 driver.getWindowHandle();//获取当前操作窗口的句柄driver.getWindowHandles();//获取测…...
【Rust学习】Rust环境搭建和Rust基础语法
本文专栏:Rust学习 目录 一,Rust环境搭建 1,C环境安装 2,Rust下载 3,Rust安装 4,Rust环境检测 二,创建Rust项目 1,rustc 2,cargo 三,输出到命令行 …...
在windows环境下通过docker-compose脚本自动创建mysql和redis
一、环境版本 在windows环境下通过docker容器运行各种服务,使用的软件版本如下: docker desktop :V4.39.0 【docker的安装环境设置略】 mysql:9.2 redis:7.4.2 二、各配置文件 1.已经解决了字符集和排序规则问题造成…...
【玩泰山派】2、制作buildroot镜像,并烧录
文章目录 前言制作buildroot镜像过程搭建环境(docker版)下载泰山派开发的sdk利用制作的镜像和下载的sdk去启动开发docker容器编译buildroot镜像 参考 前言 泰山派官方提供了不少现成的镜像 但是都买了泰山派了,肯定是想自己编译折腾下&…...
实验二 VLAN 的配置与应用
一、实验目的 1. 熟悉 VLAN 和 PORT VLAN 的原理; 2. 熟悉华为网络模拟器的使用; 3. 掌握网络拓扑图的绘制; 4. 掌握单交换机内 VLAN 的配置。 二、实验设备 PC、华为模拟器 ENSP。 三、实验步骤 知识准备:VLAN 和 PORT V…...
【C/C++算法】蓝桥杯之递归算法(如何编写想出递归写法)
绪论:冲击蓝桥杯一起加油!! 每日激励:“不设限和自我肯定的心态:I can do all things。 — Stephen Curry” 绪论: ———————— 早关注不迷路,话不多说安全带系好,发车啦&am…...
coding ability 展开第九幕(位运算——进阶篇)超详细!!!!
文章目录 前言丢失的数字两整数之和只出现一次的数字II消失的两个数字总结 前言 上一篇博客,我们已经把位运算的基础知识,以及基本运算都掌握啦 上次的习题还是让人意犹未尽,今天我们来尝试一下难一点的题目 位运算熟练起来真的让人觉得做题是…...
Python实现NOA星雀优化算法优化随机森林回归模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档视频讲解),如需数据代码文档视频讲解可以直接到文章最后关注获取。 1.项目背景 在现代数据科学领域,回归分析是解决预测问题的核心工具之一。然而,在面对复…...
蓝桥云客--浓缩咖啡液
4.浓缩咖啡液【算法赛】 - 蓝桥云课 问题描述 蓝桥杯备赛选手小蓝最近刷题刷到犯困,决定靠咖啡续命。他手上有 N 种浓缩咖啡液,浓度分别是 A1%, A2%, …, AN%,每种存货都是无限的。为了提神又不炸脑,小蓝需要按比例混合这…...
异常【C++】
文章目录 异常异常的概念和基本语法异常的三个关键字: 异常抛出和被接收的过程异常的再次抛出再次抛出被非catch(...)捕捉到的异常再次抛出被catch(...)捕捉到的异常 异常规范异常安全异常的优缺点优点缺点总结&#x…...
关于图片分类任务的猜想 | 撰写论文 paper
关于图片分类任务的猜想 | 撰写论文 paper 背景Yolo 是一次巨大的飞跃过滤无关的特征Yolo 的问题 背景 在计算视觉领域,有几个关键的演变。 1)CNN 卷积的出现,这是一个大的创新; 2)从卷积到 AlexNet ,是更…...
路由器和交换机
路由器和交换机分别位于OSI模型和TCP/IP模型的不同网络层次,具体对比如下: 1. 路由器(Router) 所属层级: OSI模型:网络层(第3层)TCP/IP模型:网络互联层(Int…...
jEasyUI 表单验证
jEasyUI 表单验证 引言 jEasyUI 是一款流行的 jQuery UI 扩展库,它提供了丰富的 UI 组件和交互效果,极大地方便了前端开发工作。在 jEasyUI 中,表单验证是一个非常重要的功能,它可以帮助开发者确保用户输入的数据符合预期的格式和规则。本文将详细介绍 jEasyUI 表单验证的…...
PIKE 助力知识库进阶:多模型协作下的精准信息 “捕手”
PIKE(通常指的是字节跳动提出的一种技术)增强检索知识库是一种结合了先进的信息检索技术和知识库管理的系统。它旨在提高知识检索的准确性、效率和召回率,以更好地满足用户对知识的需求。 特点和工作原理 数据增强 :对知识库中…...
使用Ubuntu18恢复群晖nas硬盘数据外接usb
使用Ubuntu18恢复群晖nas硬盘数据外接usb 1. 接入硬盘2.使用Ubuntu183.查看nas硬盘信息3. 挂载nas3.1 挂载损坏nas硬盘(USB)3.2 挂载当前运行的nas 4. 拷贝数据分批传输 5. 新旧数据对比 Synology NAS 出现故障,DS DiskStation损坏,则可以使用计算机和 U…...
Dify票据识别遇到的分支判断不准确问题
已测试这篇文章中 https://zhuanlan.zhihu.com/p/5465385787 使用多分支条件判断使用不同的大模型识别图片内容 发现了细节问题。在使用时若不注意,分支会出现走向不准的问题。 需要关注部分 下方红框处。1,2后不能跟点。否则会出问。除此之外࿰…...
Flutter学习总结之Android渲染对比
一、Android 界面渲染机制(基于原生 View 体系) 1. 核心渲染流程(源码级解析) 三阶段渲染流程(ViewRootImpl驱动): Measure 阶段(measure()): View调用onMea…...
Media streaming mental map
Media streaming is a huge topic with a bunch of scattered technologies, protocols, and formats. You may feel like hearing fragments without seeing the big picture. Let’s build that mental map together — here’s a high-level overview that connects everyt…...
7B斗671B:扩散模型能否颠覆自回归霸权?
模型对决:从7B到671B的意外之战 参数量与性能的反差 DeepSeek V3以6710亿参数稳坐自回归模型的“巨无霸”地位,而70亿参数的Dream 7B却在多项测试中与其不分伯仲。例如,在需要复杂规划的“倒计时任务”中,Dream 7B的解题成功率比…...
WVP-GB28181摄像头管理平台存在弱口令
免责声明:本号提供的网络安全信息仅供参考,不构成专业建议。作者不对任何由于使用本文信息而导致的直接或间接损害承担责任。如涉及侵权,请及时与我联系,我将尽快处理并删除相关内容。 漏洞描述 攻击者可利用漏洞获取当前系统管…...
实验研究:不同物体与落点材质对弹起高度的影响
本研究通过控制变量法,探讨了不同物体(乒乓球和笔)在不同下落高度和落点材质条件下,其弹起高度的变化。实验结果显示,物体类型、下落高度和落点材质均对弹起高度有显著影响。其中,铁碗作为落点材质时&#…...
开源 PDF.js 文件编辑操作
一、PDF.js PDF.js 是 Mozilla 基金会推出的一个使用 HTML5 构建的 PDF 阅读器,它完全使用 JavaScript 编写。作为 Firefox 浏览器的默认 PDF 查看器,PDF.js 具有强大的兼容性和稳定性。它不仅支持 PDF 文件的查看和渲染,还提供了丰富的交互…...
hydra小记(一):深入理解 Hydra:instantiate() 与 get_class() 的区别
hydra小记(一):深入理解 Hydra:instantiate 与 get_class 的区别 深入理解 Hydra:instantiate() 与 get_class() 的区别1. hydra.utils.get_class()2. hydra.utils.instantiate()3. 总结对比 深入理解 Hydra࿱…...
在 macOS 上安装和配置 Aria2 的详细步骤
在 macOS 上安装和配置 Aria2 的详细步骤: 1.安装 Aria2 方式一:使用 Homebrew Homebrew 是 macOS 上的包管理器,可以方便地安装和管理软件包。 • 打开终端。 • 输入以下命令安装 Aria2: brew install aria2• 检查安装是否…...
Linux开发工具——make/makefile
📝前言: 这篇文章我们来讲讲Linux开发工具——make/makefile: 🎬个人简介:努力学习ing 📋个人专栏:Linux 🎀CSDN主页 愚润求学 🌄其他专栏:C学习笔记…...
生信分析服务MR孟德尔随机化单细胞测序转录组数据分析网络药理学
将孟德尔随机化(MR)、单细胞测序、转录组数据分析和网络药理学结合,是当前生物信息学领域的前沿方法,尤其在疾病机制解析、靶点发现和药物研发中展现出巨大潜力。以下从技术逻辑、应用场景和服务流程三个维度展开说明:…...
Sentinel实战(五)、系统保护规则、限流后统一处理及sentinel持久化配置
Spring Cloud Alibaba-Sentinel实战(五)、系统保护规则、限流后统一处理及sentinel持久化配置 一、系统保护规则一)、系统规则支持的模式二)、新增系统规则界面三)、demo测试二、限流后统一处理实操demo三、sentinel持久化配一、系统保护规则 系统保护规则是从应用级别的…...
iPhone XR:一代神机,止步于此
什么样的 iPhone ,才配称为一代神机? 我曾经用过iPhone 4S、iPhone 6S Plus、iPhone 8 Plus,iPhone SE2、iPhone XR、iPhone 13、iPhone 14 Plus、iPhone 15/Pro。 不管硬件再怎么卷,不管囊中是否羞涩,主力机基本没考…...
[C++面试] explicit面试8问 —— 较难,可简单了解即可
Google C规范建议所有单参数构造函数必须加explicit,除非明确需要隐式转换(如std::string从const char*构造)。 1. 隐式转换的实际危害 隐式转换可能导致资源泄漏或逻辑错误(如std::vector<int> v 10;可能被误认为初始化…...
2024-2025 CSS前沿技术全景解析:构建下一代Web界面的核心武器库
前言:CSS的范式革命 当WebAssembly与JavaScript持续争夺开发者注意力时,CSS正在经历一场静默的革命。2024年CSS工作组发布的Level 4/5草案,标志着样式语言正式进入「智能样式」时代。本文将从15个维度深入剖析未来两年最具变革性的CSS新特性…...
flutter row里面怎么统一高度
在 Flutter 中,Row 是一个水平布局的组件,默认情况下,它的子组件的高度是根据每个子组件的内容自动调整的。如果你希望 Row 中的所有子组件具有统一的高度,可以通过以下几种方式实现。 1. 使用 SizedBox 或 Container 设置固定高度…...
pinia-plugin-persist、vuex
pinia-plugin-persist 作用:为 Pinia 状态管理库实现状态持久化,自动将指定的 Pinia store 状态保存到本地存储(如 localStorage 或 sessionStorage),并在应用启动时从本地存储恢复状态。效果:确保应用状态…...
Spring Boot整合MyBatis-Plus实现CRUD操作教程
本文将演示如何在Spring Boot项目中整合MyBatis-Plus框架,快速实现数据库的增删改查操作。相较于原生MyBatis,MyBatis-Plus提供了更简洁的API和自动化功能。 环境准备 JDK 1.8MySQL 5.7Spring Boot 2.7.xMyBatis-Plus 3.5.x 实现步骤 1. 创建项目并添加…...
Vue 3 的响应式原理
Vue 3 的响应式原理可以比喻为“智能监控系统”:当数据变化时,它能自动追踪依赖关系并触发更新。以下是通俗解释和核心机制: 一、核心原理:Proxy 代理 Vue 3 的响应式系统基于 JavaScript 的 Proxy 对象实现(Vue 2 使…...
使用Scrapy官方开发的爬虫部署、运行、管理工具:Scrapyd
一般情况下,爬虫会使用云服务器来运行,这样可以保证爬虫24h不间断运行。但是如何把爬虫放到云服务器上面去呢?有人说用FTP,有人说用Git,有人说用Docker。但是它们都有很多问题。 FTP:使用FTP来上传…...
基于51单片机和8X8点阵屏、独立按键的单人弹球小游戏
目录 系列文章目录前言一、效果展示二、原理分析三、各模块代码1、8X8点阵屏2、独立按键3、定时器04、定时器1 四、主函数总结 系列文章目录 前言 用的是普中A2开发板,用到板上的独立按键、8X8点阵屏。 【单片机】STC89C52RC 【频率】12T11.0592MHz 效果查看/操作…...
群体智能避障革命:RVO算法在Unity中的深度实践与优化
引言:游戏群体移动的挑战与进化 在《全面战争》中万人战场恢弘列阵,在《刺客信条》闹市里人群自然涌动,这些令人惊叹的场景背后,都离不开一个关键技术——群体动态避障。传统路径规划算法(如A*)虽能解决单…...
Java 实现选择排序:[通俗易懂的排序算法系列之一]
引言 大家好!从今天开始,我计划写一个关于常见排序算法的系列文章,旨在用通俗易懂的方式,结合 Java 代码实现,帮助大家理解和掌握这些基础但非常重要的数据结构与算法知识。 排序是计算机科学中最基本的操作之一&…...
动画过渡设置
使用Animator的Trigger参数 步骤 1:打开 Animator 窗口 确保你的 Sprite 对象已添加 Animator 组件。 在 Unity 编辑器顶部菜单栏,选择 Window > Animation > Animator,打开 Animator 窗口。 步骤 2:创建 Trigger 参数 在…...
【项目管理-高项】学习方法 整体概览
相关文档,希望互相学习,共同进步 风123456789~-CSDN博客 1.背景 📝 软考高项,全称 信息系统项目管理师 ,是软考高级资格项目之一。 本考试考三门科目:综合知识(上午)、案例分析(下午…...
HarmonyOS应用开发者高级-编程题-001
题目一:跨设备分布式数据同步 需求描述 开发一个分布式待办事项应用,要求: 手机与平板登录同一华为账号时,自动同步任务列表任一设备修改任务状态(完成/删除),另一设备实时更新任务数据在设备…...
HarmonyOS-ArkUI Ability进阶系列-UIAbility与各类Context
UIAbility及相关类关系 一个模块编译的时候会出一个HAP包, 每一个HAP包在运行时都对应一个AbilityStage。 AbilityStage持有一个AbilityStageContext一个APP, 有时候会有很多个HAP包, 至少一个。 一个APP运行时,对应的是我们的App…...
接口并行执行且流式顺序输出的解决方案
接口并行执行且流式顺序输出的解决方案: import asyncio from aiotas_agi2all_llms_utils.output_answer_from_ask_question_results import (reasoning_model_ask_question, ) import os from aiotas_agi2all_llms_utils.logging_utils import create_logger import uuid fr…...
浅谈AI - DeepSpeed - 单卡慎用!
前言 曾在游戏世界挥洒创意,也曾在前端和后端的浪潮间穿梭,如今,而立的我仰望AI的璀璨星空,心潮澎湃,步履不停!愿你我皆乘风破浪,逐梦星辰! 简介 Deepspeed 的 ZeRO(Ze…...
Java Web从入门到精通:全面探索与实战(一)
目录 引言:开启 Java Web 之旅 一、Java Web 基础概念大揭秘 1.1 什么是 Java Web 1.2 Java Web 的优势剖析 1.3 Java Web 相关核心概念详解 二、搭建 Java Web 开发环境:步步为营 2.1 所需软件大盘点 2.2 软件安装与配置全流程 三…...
5G从专家到小白
文章目录 第五代移动通信技术(5G)简介应用场景 数据传输率带宽频段频段 VS 带宽中低频(6 GHz以下):覆盖范围广、穿透力强高频(24 GHz以上):满足在热点区域提升容量的需求毫米波热点区…...
leetcode111 二叉树的最小深度
相对于 104.二叉树的最大深度 ,本题还也可以使用层序遍历的方式来解决,思路是一样的。 最小深度的定义:从根节点到最近叶子节点的最短路径上的节点数量。 特别注意: 如果一个子树不存在,就不能用它来计算深度&#x…...
算法设计学习10
实验目的及要求: 本查找实验旨在使学生深入了解不同查找算法的原理、性能特征和适用场景,培养其在实际问题中选择和应用查找算法的能力。通过实验,学生将具体实现多种查找算法,并通过性能测试验证其在不同数据集上的表现ÿ…...
数字统计题解
题目理解 题目要求计算所有不大于 N 的非负整数中数字 D 出现的总次数。例如,当 D1 且 N12 时,数字1出现在1、10、11(两次)、12中,共5次。 输入输出分析 输入格式: 两个正整数 D 和 N,其中1≤…...