当前位置: 首页 > article >正文

Linux驱动开发-①platform平台②MISC字符驱动框架③input框架

Linux驱动开发-①platform平台②MISC字符驱动框架③input框架

  • 一,platform
    • 1.1 platform框架(设备树下)
    • 1.2 platform框架(配置设备函数)
  • 二,MISC字符驱动框架
  • 三,input框架

在这里插入图片描述

一,platform

  platform框架是一种管理平台设备(Platform Device)和平台驱动(Platform Driver)的机制,分为总线,驱动和设备,主要用于处理那些不依赖于传统总线(如 PCI、USB、I2C 等)的设备,①SoC(系统芯片)类型,②内部的外设(如 GPIO、定时器、UART 等)。好处:让设备信息和驱动信息分开,提供一个标准化的接口(probe,remove),不用管总线协议,方便驱动开发。其次支持设备树,支持设备的热插拔(驱动在内核配置好后,比如有设备连接上,通过compatible属性,驱动能够自动的控制设备),并且一个驱动能控制多个设备。

1.1 platform框架(设备树下)

  驱动和设备的匹配方式,常用的有两种,一种通过name匹配,一种是利用of类型匹配比较设备的compatible属性和of_match_table表中的所用成员,是否有相同的,有即匹配成功。(在设备树情况下,虽然用不到name,但是还是要在结构体函数里面定义一下name变量,目前不定义会报错)。驱动和设备匹配成功后,probe函数执行,当设备找不到或者卸载后,remove函数执行。

设备树:

     led {compatible = "gpio-leds";pinctrl-0 = <&pinctrl_led>;gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;status = "okay";};

platform驱动框架:


......top函数相关
static int led_probe(struct platform_device *dev)
{.......初始化工作还是要找AAAled节点的return 0;
}
static int led_remove(struct platform_device *dev)
{........return 0;
}const struct of_device_id led_match_table[]={{.compatible = "gpio-leds"},{}
};
struct platform_driver led_platform={.probe = led_probe,.remove = led_remove,.driver = {.name = "led_driver",.of_match_table = led_match_table,},
};static int __init led_init(void)
{return platform_driver_register(&led_platform);
}
static void __exit led_exit(void)
{platform_driver_unregister(&led_platform);
}/*驱动入口*/
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("wyt");

1.2 platform框架(配置设备函数)

  即不使用设备树,直接将设备用.c文件表达出,然后编译出device.ko,和驱动文件一起放到内核中去,这个设备先于驱动,或者后于驱动配置都行,当驱动检测到就会自动运行了,设备函数:

#include <linux/module.h>
#include<linux/kernel.h>
#include<linux/init.h>
#include<linux/fs.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/types.h>
#include<linux/cdev.h>
#include<linux/platform_device.h>
#define CCM_CCGR1_BASE          (0X020C406C)
#define SW_MUX_GPIO1_IO03_BASE   (0X020E0068)
#define SW_PAD_GPIO1_IO03_BASE   (0X020E02F4)
#define GPIO1_DR_BASE            (0X0209C000)
#define GPIO1_GDIR_BASE          (0X0209C004)
#define CELL                      0X04
static void  leddevice_release(struct device *dev)//这个函数定义完有用不? 试试
{printk("release \r\n");
}
static struct resource leddevice_resource[]={[0]={.start = CCM_CCGR1_BASE,.end = CCM_CCGR1_BASE + CELL -1,.flags = IORESOURCE_MEM,},[1]={.start = SW_MUX_GPIO1_IO03_BASE,.end = SW_MUX_GPIO1_IO03_BASE + CELL -1,.flags = IORESOURCE_MEM,},[2]={.start = SW_PAD_GPIO1_IO03_BASE,.end = SW_PAD_GPIO1_IO03_BASE + CELL -1,.flags = IORESOURCE_MEM,},[3]={.start = GPIO1_DR_BASE,.end = GPIO1_DR_BASE + CELL -1,.flags = IORESOURCE_MEM,},[4]={.start = GPIO1_GDIR_BASE,.end = GPIO1_GDIR_BASE + CELL -1,.flags = IORESOURCE_MEM,},};
static struct platform_device leddevice ={.name = "LED",.id = -1,//此设备无ID.dev = {.release = leddevice_release,},.num_resources = ARRAY_SIZE(leddevice_resource),.resource = leddevice_resource,
};static int __init leddevice_init(void)
{return  platform_device_register(&leddevice);
}static void  __exit leddevice_exit(void)
{platform_device_unregister(&leddevice);
}module_init(leddevice_init);
module_exit(leddevice_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("wyt");

总体驱动函数:

#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/cdev.h>
#include <linux/kdev_t.h>
#include <linux/device.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/fs.h>  // 包含 register_chrdev_region 的定义
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/slab.h>
#include <linux/semaphore.h>
#include<linux/platform_device.h>#define LED_NAME "pgled"
#define LED_ON 0
#define LED_OFF 1
/*虚拟地址指针*/
static void __iomem  *CCM_CCGR1;
static void __iomem  *SW_MUX_GPIO1_IO03;
static void __iomem  *SW_PAD_GPIO1_IO03;
static void __iomem  *GPIO1_DR;
static void __iomem  *GPIO1_GDIR;struct led_dev{struct class *class;struct device *device;struct device_node *nd;struct cdev cdev;dev_t led_hao;int major;//主设备号int minor;//次设备号int led_gpio;//led的gpio   
};
struct led_dev led;
static int pgled_open(struct inode *innode,struct file *filp)
{filp->private_data = &led;//将led结构体数据设为私有数据return 0;
}
static int pgled_release(struct inode *innode,struct file *filp)
{   return 0;
}
static ssize_t pgled_read(struct file *filp, char __user *buf,size_t cnt,loff_t *offt)
{return 0;
}
static void led_choice(unsigned char in)
{static int register_led = 0;if(in==0)//turn on led{/*控制亮*/register_led = readl(GPIO1_DR); register_led &=~(1<<3);writel(register_led,GPIO1_DR); }else if(in==1){register_led = readl(GPIO1_DR); register_led |=(1<<3);writel(register_led,GPIO1_DR);}
}
static ssize_t pgled_write(struct file *filp, const char __user *buf,size_t cnt,loff_t *offt)
{int ret;unsigned char databuf[1];unsigned char let_status;ret = copy_from_user(databuf,buf,cnt);let_status = databuf[0];if(let_status == 0){led_choice(LED_ON);//开灯}else if(let_status == 1) {led_choice(LED_OFF);//关灯}return 0;
}
static struct file_operations pgled_fops={.owner=THIS_MODULE,.read=pgled_read,.write=pgled_write,.open=pgled_open,.release=pgled_release,
};
static int led_probe(struct platform_device *led_device)
{int i=0,ret = 0;int register_result = 0;struct resource *led_gpio[5] ={0};//数组里面放五个指针for(i=0;i<5;i++){led_gpio[i]= platform_get_resource(led_device,IORESOURCE_MEM,i);//从设备中获取寄存器地址if(led_gpio[i] == NULL) {printk("get resource error \r\n");return -1;}}printk("platform probe true\r\n");/*1.将物理地址*_BASE和虚拟地址联系起来*/CCM_CCGR1 = ioremap(led_gpio[0]->start,resource_size(led_gpio[0]));//右边是实际物理地址,左边是虚拟地址 映射地址长度4(字节),因为32位寄存器SW_MUX_GPIO1_IO03 = ioremap(led_gpio[1]->start,resource_size(led_gpio[0]));SW_PAD_GPIO1_IO03 = ioremap(led_gpio[2]->start,resource_size(led_gpio[0]));GPIO1_DR = ioremap(led_gpio[3]->start,resource_size(led_gpio[0]));GPIO1_GDIR = ioremap(led_gpio[4]->start,resource_size(led_gpio[0]));/*2.初始化*//*2.1 时钟初始化*/register_result = readl(CCM_CCGR1);register_result |=(3<<26);writel(register_result,CCM_CCGR1);/*2.2复用初始化*/writel(5,SW_MUX_GPIO1_IO03);/*2.3电器属性初始化*/writel(0x10b0,SW_PAD_GPIO1_IO03);/*2.4设置为输出模式*/register_result = readl(GPIO1_GDIR);   register_result |= (1<<3);writel(register_result,GPIO1_GDIR);/*2.5控制亮*/register_result = readl(GPIO1_DR); register_result &=~(1<<3);writel(register_result,GPIO1_DR);/*注册*//*1.设备号*/if(led.major){led.led_hao = MKDEV(led.major,0);register_chrdev_region(led.led_hao, 1, LED_NAME);//主动注册}else{alloc_chrdev_region(&led.led_hao, 0, 1, LED_NAME);//自动注册}printk("major = %d,minor = %d",MAJOR(led.led_hao),MINOR(led.led_hao));/*2.注册函数*/led.cdev.owner = THIS_MODULE;cdev_init(&led.cdev,&pgled_fops);cdev_add(&led.cdev,led.led_hao,1);/*3.节点申请*/ led.class = class_create(THIS_MODULE,LED_NAME);led.device = device_create(led.class, NULL,led.led_hao, NULL,LED_NAME);return 0;
}static int led_remove(struct platform_device *led_device)
{int register_result = 0;/*控制灭*/register_result = readl(GPIO1_DR); register_result |=(1<<3);writel(register_result,GPIO1_DR); /*取消虚拟地址映射*/iounmap(CCM_CCGR1);iounmap(SW_MUX_GPIO1_IO03);iounmap(SW_PAD_GPIO1_IO03);iounmap(GPIO1_DR);iounmap(GPIO1_GDIR);printk("exit in linux\r\n");gpio_free(led.led_gpio);cdev_del(&led.cdev);//先删除设备unregister_chrdev_region(led.led_hao,1);//删除设备号device_destroy(led.class,led.led_hao);//先删除和设备关系class_destroy(led.class);//再删除类return 0;
}
const struct of_device_id	led_of_match[]={{.compatible = "alpha-gpiokey"},{ /*sentinel*/ },
};
static struct platform_driver scoop_driver = {.probe		= led_probe,.remove		= led_remove,.driver		= {.name	= "LED",//1.无设备树,匹配名字.of_match_table = led_of_match,//2.有设备树,直接利用设备树中compatible属性},
};
static int __init pgled_init(void)
{ return platform_driver_register(&scoop_driver);
}
static void  __exit pgled_exit(void)
{platform_driver_unregister(&scoop_driver);  
}/*驱动入口和出口*/
module_init(pgled_init);
module_exit(pgled_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("wyt");

二,MISC字符驱动框架

  MISC字符驱动框架目的就是为了让字符设备少占用点主设备号,让字符设备的主设备号为10,不同的字符设备用的次设备号不同。适合简单的字符设备,不适合归类到标准框架(input,tty),功能单一,无复杂子系统支持的设备。注册函数和注销函数为int misc_register(struct miscdevice * misc) 和int misc_deregister(struct miscdevice *misc) ,这俩函数省去了这些函数的操作,1 cdev_del(); /* 删除 cdev */ 2 unregister_chrdev_region(); /* 注销设备号 */ 3 device_destroy(); /* 删除设备 */ 4 class_destroy(); /* 删除类 */
驱动实现:

#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/cdev.h>
#include <linux/kdev_t.h>
#include <linux/device.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/fs.h>  // 包含 register_chrdev_region 的定义
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/slab.h>
#include <linux/semaphore.h>
#include<linux/platform_device.h>
#include<linux/miscdevice.h>struct beep_dev{struct device_node *beep_nd;int beep_gpio;//led的gpio   
};
struct  beep_dev beepdev;
static int beep_open (struct inode *node, struct file *filp)
{// filp->private_data = &beep_misc;return 0;
};
static int beep_release (struct inode *node, struct file *filp)
{return 0;
};
static ssize_t beep_write (struct file *filp, const char __user *buf, size_t count ,  loff_t *ppos)
{int ret =0;unsigned char result = 0;ret = __copy_from_user(&result,buf,count);if(ret<0){printk("__copy_from_user error !!\r\n");return -1;}gpio_set_value(beepdev.beep_gpio,result);//开关return 0;
};
const struct file_operations beep_fops  ={.owner = THIS_MODULE,.write = beep_write,.open = beep_open,.release = beep_release,
};static struct miscdevice beep_misc = {.minor = MISC_DYNAMIC_MINOR,.name = "beep_driver",.fops = &beep_fops,
};static int beep_probe(struct platform_device *dev)
{int ret = 0;ret =  misc_register(&beep_misc);if(ret<0){printk("misc_register error !!\r\n");return -1;}beepdev.beep_nd = of_find_node_by_path("/BEEP");if (!beepdev.beep_nd) {printk("of_find_node_by_path error !!\r\n");return -ENODEV;}printk("of_find_node_by_path yes !!\r\n");beepdev.beep_gpio = of_get_named_gpio(beepdev.beep_nd,"beep-gpio",0);if (beepdev.beep_gpio < 0) {printk("of_get_named_gpio error !!\r\n");return -1;}ret = gpio_request(beepdev.beep_gpio,"beep-aaa");if(ret<0){printk("gpio requst error !\r\n");}ret = gpio_direction_output(beepdev.beep_gpio,1);if(ret < 0){ gpio_free(beepdev.beep_gpio);printk("gpio_direction_output error! \r\n");return -1;}printk("probe yes !!\r\n");return 0;
}
static int beep_remove(struct platform_device *dev)
{int ret = 0;gpio_free(beepdev.beep_gpio);ret =  misc_deregister(&beep_misc);if(ret<0){printk("misc_register error !!\r\n");return -1;}return 0;
}
const struct of_device_id beep_match_table[]={{.compatible = "atkalpha-beep"},{}
};
struct platform_driver beep_platform={.probe = beep_probe,.remove = beep_remove,.driver = {.name = "beep_driver",.of_match_table = beep_match_table,},
};static int __init beep_init(void)
{return platform_driver_register(&beep_platform);
}
static void __exit beep_exit(void)
{platform_driver_unregister(&beep_platform);
}/*驱动入口*/
module_init(beep_init);
module_exit(beep_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("wyt");

三,input框架

  input框架适用于输入的子系统,针对一类设备而创建的框架,比如按键、键盘、鼠标、触摸屏,和这个misc感觉上也差不多,input适用的更多,能省去创建主设备号次设备号和节点的创建工作(主设备号已经定了,子系统的所有设备主设备号都为 13)。具体实现:这个input通过他特定的函数input_event,将数据从驱动中传出去,应用程序再定义一个特定的结构体(好巧名字也叫input_event),把通过read函数将数据读给用户层。
  步骤包括:①定义一个input_dev类型结构体变量a,用input_allocate_device申请出这个结构体定义的值a②初始化这个a,主要包括初始化事件类型(evbit,比如按键类型,led类型等)和事件值(keybit,比如把按键键值设置为5),③利用注册函数注册,④卸载时候,先注销unregister再free释放a。
  input采用的阻塞方式,这个它的子系统框架已经创建好了,所有输入设备通过 /dev/input/eventX 提供统一接口。
驱动:

/*3.24中断和定时器下input框架*/
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/cdev.h>
#include <linux/kdev_t.h>
#include <linux/device.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/fs.h>  
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/slab.h>
#include <linux/semaphore.h>
#include<linux/platform_device.h>
#include<linux/input.h>
#include<linux/interrupt.h>
#include <linux/timer.h>  
/*设备结构体*/
struct key_dev{struct device_node *key_node;int key_gpio;struct input_dev *key_input;struct timer_list timer;
};
/*中断结构体*/
struct irq_key{int irq;unsigned char key_irq_name[10];irqreturn_t (*handler)(int,void *);
};
struct key_dev key;
struct irq_key key_irq;/*中断处理函数*/
static irqreturn_t key_irq_handler(int irq,void *dev)
{key.timer.data = (unsigned long)dev;mod_timer(&key.timer,jiffies+msecs_to_jiffies(15));return IRQ_HANDLED;
}static void key_timer_function(unsigned long arg)
{static int key_retsult = 0;struct key_dev *key_timer_dev =(struct key_dev *)arg;key_retsult = gpio_get_value(key_timer_dev->key_gpio);if(key_retsult == 0)//按下{input_event(key.key_input, EV_KEY, KEY_8, 1);input_sync(key.key_input);}else {  //松开input_event(key.key_input, EV_KEY, KEY_8, 0);input_sync(key.key_input);}}static int __init key_init(void)
{int ret = 0;printk("00000000000\r\n");/*get node*/key.key_node = of_find_node_by_path("/key");if(key.key_node==NULL)//未注册成功{ret = -1;}key.key_gpio = of_get_named_gpio(key.key_node,"key-gpio",0);ret = gpio_request(key.key_gpio,"key_gpio");if(ret<0){printk("gpio requst error !\r\n");}ret = gpio_direction_input(key.key_gpio);//设置输入if(ret < 0){ printk(" gpio_direction_input error!\r\n");ret = -1;goto gpio_error;}printk("111111111111111\r\n");/*irq init*/key_irq.irq = gpio_to_irq(key.key_gpio);strncpy( key_irq.key_irq_name, "key_irq_0", sizeof(key_irq.key_irq_name));key_irq.handler = key_irq_handler;ret = request_irq(key_irq.irq,key_irq.handler,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,key_irq.key_irq_name,&key);if(ret < 0)//未注册成功{ret = -1;goto irq_error;}printk("2222222222222\r\n");/*input  init*/key.key_input = input_allocate_device();//申请key_input__set_bit(EV_KEY,key.key_input->evbit);//设置按键事件__set_bit(EV_REP,key.key_input->evbit);//设置重复事件 __set_bit(KEY_8,key.key_input->keybit);//设置按键值ret = input_register_device(key.key_input);if(ret < 0)//未注册成功{ret = -1;goto ragister_error;}printk("33333333333\r\n");/*timer init */init_timer(&key.timer);key.timer.function = key_timer_function;printk("6666666666666\r\n");return 0;ragister_error:input_free_device(key.key_input);
irq_error:free_irq(key_irq.irq,&key);
gpio_error:gpio_free(key.key_gpio);return ret;
}
static void __exit key_exit(void)
{del_timer_sync(&key.timer);gpio_free(key.key_gpio);free_irq(key_irq.irq,&key);/*input框架注销处理*/input_unregister_device(key.key_input);input_free_device(key.key_input);
}
/*in out*/
module_init(key_init);
module_exit(key_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("wyt");

应用程序:

#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "sys/ioctl.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"
#include <poll.h>
#include <sys/select.h>
#include <sys/time.h>
#include <signal.h>
#include <fcntl.h>
#include <linux/input.h>static struct input_event key_input;
int main(unsigned char argc,unsigned char *argv[])
{int rel = 0,fd = 0;unsigned char *filename;filename = argv[1];printf("111\r\n");fd = open(filename,O_RDWR);if(fd<0) printf("open file error\r\n");while(1){printf("get in !\r\n");rel =  read(fd,&key_input,sizeof(key_input));if(rel>0){switch (key_input.type){case EV_KEY:if(key_input.value==1){printf("按键按下\r\n"); }else  printf("按键释放\r\n"); break;default:break;}}else {printf("读取 error \r\n"); }}   rel = close(fd);if(rel<0) printf("close in  APP error\r\n");return 0;}

相关文章:

Linux驱动开发-①platform平台②MISC字符驱动框架③input框架

Linux驱动开发-①platform平台②MISC字符驱动框架③input框架 一&#xff0c;platform1.1 platform框架&#xff08;设备树下&#xff09;1.2 platform框架&#xff08;配置设备函数&#xff09; 二&#xff0c;MISC字符驱动框架三&#xff0c;input框架 一&#xff0c;platfor…...

【mysql】唯一性约束unique

文章目录 唯一性约束 1. 作用2. 关键字3. 特点4. 添加唯一约束5. 关于复合唯一约束 唯一性约束 1. 作用 用来限制某个字段/某列的值不能重复。 2. 关键字 UNIQUE3. 特点 同一个表可以有多个唯一约束。唯一约束可以是某一个列的值唯一&#xff0c;也可以多个列组合的值唯…...

pytest的测试报告allure

1、安装jdk,安装allure、下载allure,配置环境变量 1.1、下载地址:https://repo.maven.apache.org/maven2/io/qameta/allure/allurecommandline 找到最新版本下载即可 【下载zip包】解压到任意目录,建议目录不要在C盘 不要太深 最好不要有中文;进入allure解压后的目录,找到…...

常见中间件漏洞:Jboss篇

CVE-2015-7501 环境搭建 cd vulhub-master/jboss/JMXInvokerServlet-deserialization docker-compose up -d 过程 访问网址&#xff0c;存在页面说明接口存在且存在反序列化漏洞 http://8.130.17.222:8080/invoker/JMXInvokerServlet 2.下载 ysoserial ⼯具进⾏漏洞利⽤…...

2025年优化算法:龙卷风优化算法(Tornado optimizer with Coriolis force,TOC)

龙卷风优化算法&#xff08;Tornado optimizer with Coriolis force&#xff09;是发表在中科院二区期刊“ARTIFICIAL INTELLIGENCE REVIEW”&#xff08;IF&#xff1a;11.7&#xff09;的2025年智能优化算法 01.引言 当自然界的狂暴之力&#xff0c;化身数字世界的智慧引擎&…...

3.24-3 接口测试断言

一.postman 断言 1.断言再test中 #状态码是否等于200 tests["Status code is 200"] responseCode.code 200; #断言响应时间小于200ms tests["Response time is less than 200ms"] responseTime < 200; #断言响应体包含内容 tests["Body…...

DeepSeek面试——模型架构和主要创新点

本文将介绍DeepSeek的模型架构多头潜在注意力&#xff08;MLA&#xff09;技术&#xff0c;混合专家&#xff08;MoE&#xff09;架构&#xff0c; 无辅助损失负载均衡技术&#xff0c;多Token 预测&#xff08;MTP&#xff09;策略。 一、模型架构 DeepSeek-R1的基本架构沿用…...

【PostgreSQL】pg各版本选用取舍逻辑与docker安装postgres:15

企业常用 PostgreSQL 版本推荐 1. PostgreSQL 14&#xff08;最常见&#xff0c;稳定&#xff09; 目前许多企业仍在使用 PostgreSQL 14&#xff0c;因为它在性能、并发处理、JSON 支持等方面做了较多优化&#xff0c;同时又非常稳定。官方支持时间&#xff1a;2026 年 11 月…...

Python----计算机视觉处理(Opencv:图像亮度变换)

一、图像亮度变换 亮度调整&#xff1a;图像像素强度整体变高或者变低。 对比度调整&#xff1a;图像暗处像素强度变低&#xff0c;图像亮处像素强度变高&#xff0c;从而拉大中间某个区域范围的显示精 度。 A&#xff1a;原图 …...

无人机动平衡-如何在螺旋桨上添加或移除材料

平衡无人机螺旋桨是一项精细的工作&#xff0c;直接影响飞行稳定性和组件寿命。不同的方法适用于不同的情况&#xff0c;螺旋桨的材料和尺寸以及所需调整的幅度都会影响选择的方法。 本文将深入探讨添加如胶水和胶带等材料的方法&#xff0c;以及通过打磨和修剪来移除质量的方…...

基于python的租房网站-房屋出租租赁系统(python+django+vue)源码+运行步骤

该项目是基于python/django/vue开发的房屋租赁系统/租房平台&#xff0c;作为本学期的课程作业作品。欢迎大家提出宝贵建议。给师弟开发的课程作业&#xff0c;技术学习可以留言哦 功能介绍 平台采用B/S结构&#xff0c;后端采用主流的PythonDjango进行开发&#xff0c;前端采…...

C++ 的 if-constexpr

1 if-constexpr 语法 1.1 基本语法 ​ if-constexpr 语法是 C 17 引入的新语法特性&#xff0c;也被称为常量 if 表达式或静态 if&#xff08;static if&#xff09;。引入这个语言特性的目的是将 C 在编译期计算和求值的能力进一步扩展&#xff0c;更方便地实现编译期的分支…...

涨薪技术|k8s设计原理

01k8s介绍 Kubernetes 是一个可移植、可扩展的开源平台&#xff0c;用于管理容器化 工作负载和服务&#xff0c;有助于实现声明性配置和自动化。它有一个庞大、快速增长的生态系统。Kubernetes 服务、支持和工具广泛可用。Kubernetes 这个名字起源于希腊语&#xff0c;意思是舵…...

基于FPGA的16QAM+帧同步系统verilog开发,包含testbench,高斯信道,误码统计,可设置SNR

目录 1.算法仿真效果 2.算法涉及理论知识概要 2.1 16QAM调制解调原理 2.2 帧同步 3.Verilog核心程序 4.完整算法代码文件获得 1.算法仿真效果 vivado2019.2仿真结果如下&#xff08;完整代码运行后无水印&#xff09;&#xff1a; 设置SNR12db 将FPGA数据导入到MATLAB显…...

QuecPython 外设接口之GPIO应用指南

基础知识 了解GPIO基础知识更有益于我们使用它。 框图 GPIO&#xff08;通用输入输出&#xff09;是指一种通用的数字输入/输出接口&#xff0c;用于与外部电子元件或设备进行通信。它通常存在于微处理器、微控制器和其他嵌入式系统中。 物理电路结构如下图所示&#xff1a…...

Spring Boot 整合 Nacos 注册中心终极指南

在微服务架构中&#xff0c;配置管理和动态路由是核心需求。Nacos 作为阿里巴巴开源的动态服务发现、配置管理和服务管理平台&#xff0c;能够帮助开发者实现配置热更新、多环境共享配置以及动态路由管理。本文将结合 Spring Boot 和 Spring Cloud Gateway&#xff0c;手把手教…...

清晰易懂的 Maven 彻底卸载与清理教程

一、Windows 系统卸载 Maven 步骤 1&#xff1a;删除 Maven 安装目录 找到 Maven 的安装路径&#xff08;默认可能为 C:\Program Files\apache-maven-3.x.x 或自定义路径&#xff09;。直接删除整个 Maven 文件夹&#xff08;如 apache-maven-3.x.x&#xff09;。 步骤 2&am…...

光流 | 基于KLT算法的人脸检测与跟踪原理及公式,算法改进,matlab代码

===================================================== github:https://github.com/MichaelBeechan CSDN:https://blog.csdn.net/u011344545 ===================================================== 人脸检测与跟踪 一、KLT算法原理与分析1. 核心思想2. 数学模型二、人脸…...

Spring MVC请求与响应全解析:从参数绑定到异常处理

文章目录 一、请求映射的艺术&#xff1a;RequestMapping深度解析1. 多级路径配置2. 六大核心属性3. RESTful风格实践 二、参数绑定黑科技1. 智能绑定机制基础类型绑定对象嵌套绑定集合类型绑定 2. 参数处理三剑客 三、响应处理全攻略1. 视图跳转三种模式2. JSON交互实践 四、文…...

用免费的github的key调用gpt实现一个简单的rag自动打分评测系统,不用任何框架

1.环境准备 !pip install pymupdf numpy openai 2.导入依赖 import fitz import os import numpy as np import json from openai import OpenAI 3.pdf提取文本 def extract_text_from_pdf(pdf_path):"""从 PDF 文件中提取文本内容。参数:pdf_path (str): …...

SQLServer列转行操作及union all用法

1.创建测试表及数据sql如下 create table ScoresTable( Name varchar(50), ChineseScore int, MathScore int ) insert into ScoresTable values(小张,90,95) insert into ScoresTable values(小王,98,99) 2.表中查询结果如下 3.现需列转行显示&#xff0c;每行显示 姓名…...

深度学习框架PyTorch——从入门到精通(6.2)自动微分机制

本节自动微分机制是上一节自动微分的扩展内容 自动微分是如何记录运算历史的保存张量 非可微函数的梯度在本地设置禁用梯度计算设置requires_grad梯度模式&#xff08;Grad Modes&#xff09;默认模式&#xff08;梯度模式&#xff09;无梯度模式推理模式评估模式&#xff08;n…...

Java面试10个“隐藏考点”

1. Java模块化系统&#xff08;JPMS&#xff09;的requires transitive作用 问题&#xff1a;如何在模块化项目中传递依赖&#xff1f; 解析&#xff1a; ​**requires transitive**&#xff1a;声明模块的依赖可被下游模块隐式继承。​示例&#xff1a;模块A依赖模块B并添加…...

【GL010】C++

1.C中的const关键字有哪些用法&#xff1f; 1.修饰变量&#xff1a;表示变量的值不可修改。 const int a 10; 2.修饰指针&#xff1a; const int* p&#xff1a; // 指针指向的内容不可修改。 int* const p&#xff1a; // 指针本身不可修改。 const int* const…...

(Arxiv-2025)MagicDistillation:用于大规模人像少步合成的弱到强视频蒸馏

MagicDistillation&#xff1a;用于大规模人像少步合成的弱到强视频蒸馏 paper是HKUST发布在Arxiv 2025的工作 paper title&#xff1a;MagicDistillation: Weak-to-Strong Video Distillation for Large-Scale Portrait Few-Step Synthesis Project page&#xff1a;地址 Abst…...

Linux paste命令

目录 一. 简介二. 基本语法三. 小案例 一. 简介 paste 命令用于合并多个文件的行&#xff0c;按列方式输出&#xff0c;默认以制表符&#xff08;Tab&#xff09;分隔。 ⏹基本语法 paste [选项] 文件1 文件2 ...二. 基本语法 <()的方式模拟文件流paste命令将2个文件流粘…...

大模型金融企业场景落地应用

一、商业银行体系 1. 江苏银行 企业背景&#xff1a;江苏银行是总部位于江苏南京的全国性股份制商业银行&#xff0c;在城商行中资产规模位居前列&#xff0c;积极拥抱金融科技&#xff0c;将数字化转型作为核心战略之一。近年来&#xff0c;江苏银行持续加大在人工智能、大数…...

Excel(进阶篇):powerquery详解、PowerQuery的各种用法,逆透视表格、双行表头如何制作透视表、不规则数据如何制作数据透视表

目录 PowerQuery工具基础修改现有数据理规则PowerQuery抓取数据的两种方式多文件合并透视不同表结构多表追加数据透视追加与合并整理横向表格:逆透视 数据用拆分工具整理数据算账龄 不等步长值组合合并文件夹中所有文件PowerQuery处理CSV文件双行表头、带合并单元格如何做数据…...

神经网络解决非线性二分类

这份 Python 代码实现了一个简单的神经网络&#xff0c;用于解决复杂的非线性二分类问题。具体步骤包含生成数据集、定义神经网络模型、训练模型、测试模型以及可视化决策边界。 依赖库说明 python import numpy as np import matplotlib.pyplot as plt from sklearn.datase…...

CentOS 8.2 上安装 JDK 17 和 Nginx

AI越来越火了&#xff0c;我们想要不被淘汰就得主动拥抱。推荐一个人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;最重要的屌图甚多&#xff0c;忍不住分享一下给大家。点击跳转到网站 一、安装 JDK 17 1. 使用 dnf 安装&#xff08;推荐&#xff09…...