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

news2025/3/28 7:34:36

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;

}

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

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

相关文章

【mysql】唯一性约束unique

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

常见中间件漏洞: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的基本架构沿用…

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;前端采…

涨薪技术|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;手把手教…

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;每行显示 姓名…

【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…

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

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

Simple-BEV的bilinear_sample 作为view_transformer的解析,核心是3D-2D关联点生成

文件路径models/view_transformers 父类 是class BiLinearSample(nn.Module)基于https://github.com/aharley/simple_bev。 函数解析 函数bev_coord_to_feature_coord的功能 将鸟瞰图3D坐标通过多相机&#xff08;针孔/鱼眼&#xff09;内外参投影到图像特征平面&#xff0…

同一个局域网的话 如何访问另一台电脑的ip

在局域网内访问另一台电脑&#xff0c;可以通过以下几种常见的方法来实现&#xff1a; ‌直接通过IP地址访问‌&#xff1a; 首先&#xff0c;确保两台电脑都连接在同一个局域网内。获取目标电脑的IP地址&#xff0c;这可以通过在目标电脑上打开命令提示符&#xff08;Windows系…

基于SpringBoot的名著阅读网站

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

Excel(实战):INDEX函数和MATCH函数、INDEX函数实战题

目录 经典用法两者嵌套查值题目解题分析 INDEX巧妙用法让数组公式&#xff0c;自动填充所有、有数据的行/列INDEX函数和SEQUENCE函数 经典用法两者嵌套查值 题目 根据左表查询这三个人的所有数据 解题分析 INDEX函数的参数&#xff1a;第1个参数是选定查找范围&#xff0c…