RK3566(泰山派):GP7101背光驱动

RK3566(泰山派):GP7101背光驱动


文章目录

  • RK3566(泰山派):GP7101背光驱动
  • GP7101背光驱动电路
  • 配置i2c1设备树
  • 创建驱动
  • 编写Makefile
  • gp7101_bl.c驱动
    • 触摸I2C驱动框架。
    • 驱动中的结构体
    • probe函数
    • devm_backlight_device_register函数
  • gp7101_backlight_set函数
    • i2c_write
    • 注释backlight
  • GP7101背光完整驱动代码
  • 编译生效


GP7101背光驱动电路

调试屏幕我们一般会先把背光点亮如果使用的是泰山派的背光电路那直接使用代码里面默认的背光PWM驱动就行,但为了保护屏幕背光我们选择的是扩展板上的板载背光电路给3.1寸屏幕背光供电,扩展板板载背光电路PWM脚是通过GP7101 i2C转PWM芯片实现。所以我们需要编写一个GP7101驱动。
背光选择电路

背光选择电路
GP7101 I2C转PWM电路

硬件3.1寸mipi屏幕背光电路

配置i2c1设备树

从原理图中可知GP7101和触摸共同挂在道I2C下,从数据手册中我们可以得知GP7101的I2C地址是10110000,即0XB0,0xB0是包含了读写位的所以我们实际填写中还需要右移一位最终地址为01011000,即0X58。
在这里插入图片描述


tspi-rk3566-dsi-v10.dtsi中添加GP7101相关设备树驱动,首先引用I2C1并往设备树I2C1节点中添加GP7101子节点并指定I2C地址、最大背光,默认背光等。

/home/paranoid/tspi/android/kernel/arch/arm64/boot/dts/rockchip/tspi-rk3566-dsi-v10.dtsi
&i2c1 {              // 引用名为i2c1的节点  
    status = "okay"; // 状态为"okay",表示此节点是可用和配置正确的  
    GP7101@58 {      // 定义一个子节点,名字为GP7101,地址为58  
        compatible = "gp7101-backlight";   // 该节点与"gp7101-backlight"兼容,  
        reg = <0x58>;                      // GP7101地址0x58  
        max-brightness-levels = <255>;     // 背光亮度的最大级别是255  
        default-brightness-level = <100>;  // 默认的背光亮度级别是100  
    };  
};

在这里插入图片描述

创建驱动

一般背光驱动都放在/kernel/drivers/video/backlight目录下,所以我们在此路径下创建一个my_gp7101_bl目录用来存放Makefile和gp7101_bl.c文件。

cd kernel/drivers/video/backlight
mkdir my_gp7101_bl
cd my_gp7101_bl/
touch Makefile
touch gp7101_bl.c

在这里插入图片描述

编写Makefile

my_gp7101_bl/Makefile中把gp7101_bl.c编译到内核中,当然也可以选择obj-m编译成模块。

/home/paranoid/tspi/android/kernel/drivers/video/backlight/my_gp7101_bl/Makefile
obj-y   += gp7101_bl.o

在这里插入图片描述

要想
my_gp7101_bl下的Makefile生效还需要在上一层目录的Makefile中添加my_gp7101_bl目录,所以我们需要在backlight目录下Makefile中加入:

/home/paranoid/tspi/android/kernel/drivers/video/backlight/Makefile
obj-y += my_gp7101_bl/

在这里插入图片描述

gp7101_bl.c驱动

I2C驱动框架

触摸I2C驱动框架。

#include "linux/stddef.h"
#include <linux/kernel.h>
#include <linux/hrtimer.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/vmalloc.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/timer.h>
#include <linux/input/mt.h>
#include <linux/random.h>

#if 1
#define MY_DEBUG(fmt,arg...)  printk("gp7101_bl:%s %d "fmt"",__FUNCTION__,__LINE__,##arg);
#else
#define MY_DEBUG(fmt,arg...)
#endif

#define BACKLIGHT_NAME

static int gp7101_bl_probe(struct i2c_client *client,
            const struct i2c_device_id *id)
{
    MY_DEBUG("locat");
    return 0;
}

static int gp7101_bl_remove(struct i2c_client *client)
{
    MY_DEBUG("locat");
    return 0;
}

static const struct of_device_id gp7101_bl_of_match[] = {
    { .compatible = BACKLIGHT_NAME, },
    { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, gp7101_bl_of_match);

static struct i2c_driver gp7101_bl_driver = {
    .probe      = gp7101_bl_probe,
    .remove     = gp7101_bl_remove,
    .driver = {
        .name     = BACKLIGHT_NAME,
     .of_match_table = of_match_ptr(gp7101_bl_of_match),
    },
};

static int __init my_init(void)
{
    MY_DEBUG("locat");
    return i2c_add_driver(&gp7101_bl_driver);
}

static void __exit my_exit(void)
{
    MY_DEBUG("locat");
    i2c_del_driver(&gp7101_bl_driver);
}

module_init(my_init);
module_exit(my_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("My touch driver");
MODULE_AUTHOR("KuLiT");

驱动中的结构体

因为驱动过程中会有很多参数,我们不可能创建全局变量去保存他们,在linux驱动中一般都是通过创建一个结构体来保存驱动相关的参数,所以这里我创建一个gp7101_backlight_data结构体。

/* 背光控制器设备数据结构 */
struct gp7101_backlight_data {
    /* 指向一个i2c_client结构体的指针*/
    struct i2c_client *client;
    /*......其他成员后面有用到再添加........*/
};

probe函数

当驱动中of_match_table = of_match_ptr(gp7101_bl_of_match)和设备树匹配成功以后会执行探针函数,探针函数中我们会去初始化驱动。

// gp7101_bl_probe - 探测函数,当I2C总线上的设备与驱动匹配时会被调用
static int gp7101_bl_probe(struct i2c_client *client,
            const struct i2c_device_id *id)
{
    struct backlight_device *bl; // backlight_device结构用于表示背光设备
    struct gp7101_backlight_data *data; // 自定义的背光数据结构
    struct backlight_properties props; // 背光设备的属性
    struct device_node *np = client->dev.of_node; // 设备树中的节点

    MY_DEBUG("locat"); // 打印调试信息

    // 为背光数据结构动态分配内存
    data = devm_kzalloc(&client->dev, sizeof(struct gp7101_backlight_data), GFP_KERNEL);
    if (data == NULL){
        dev_err(&client->dev, "Alloc GFP_KERNEL memory failed."); // 内存分配失败,打印错误信息
        return -ENOMEM; // 返回内存分配错误码
    } 

    // 初始化背光属性结构
    memset(&props, 0, sizeof(props));
    props.type = BACKLIGHT_RAW; // 设置背光类型为原始类型
    props.max_brightness = 255; // 设置最大亮度为255

    // 从设备树中读取最大亮度级别
    of_property_read_u32(np, "max-brightness-levels", &props.max_brightness);

    // 从设备树中读取默认亮度级别
    of_property_read_u32(np, "default-brightness-level", &props.brightness);

    // 确保亮度值在有效范围内
    if(props.max_brightness>255 || props.max_brightness<0){
        props.max_brightness = 255;
    }
    if(props.brightness>props.max_brightness || props.brightness<0){
        props.brightness = props.max_brightness;
    }

    // 注册背光设备
    bl = devm_backlight_device_register(&client->dev, "backlight", &client->dev, data, &gp7101_backlight_ops,&props);
    if (IS_ERR(bl)) {
        dev_err(&client->dev, "failed to register backlight device\n"); // 注册失败,打印错误信息
        return PTR_ERR(bl); // 返回错误码
    }
    data->client = client; // 保存i2c_client指针
    i2c_set_clientdata(client, data); // 设置i2c_client的客户端数据

    MY_DEBUG("max_brightness:%d brightness:%d",props.max_brightness, props.brightness); // 打印最大亮度和当前亮度
    backlight_update_status(bl); // 更新背光设备的状态

    return 0; // 返回成功
}

devm_backlight_device_register函数

devm_backlight_device_register这个函数非常重要,他是 Linux 内核中用于动态注册背光设备的一个函数。前缀带devm的一般都会在设备被销毁时自动释放相关资源,无需手动调用 backlight_device_unregister。这个函数的主要作用是创建并注册一个 backlight_device 实例,这个实例代表了系统中的一个背光设备。背光设备通常用于控制显示屏的亮度。函数原型如下:

struct backlight_device *devm_backlight_device_register(
    struct device *dev, const char *name, struct device *parent,
    void *devdata, const struct backlight_ops *ops,
    const struct backlight_properties *props);

参数说明:

  • dev:指向父设备的指针,通常是一个 struct i2c_client 或 struct platform_device。
  • name:背光设备的名称。
  • parent:背光设备的父设备,通常与 dev 参数相同。
  • devdata:私有数据,会被传递给背光操作函数。
  • ops:指向 backlight_ops 结构的指针,这个结构定义了背光设备的行为,包括设置亮度、获取亮度等操作。
  • props:指向 backlight_properties 结构的指针,这个结构包含了背光设备的属性,如最大亮度、当前亮度等。
    gp7101_backlight_ops结构体ops参数非常重要,因为我们就是通过这个参数指向的结构成员中的函数去实现获取背光更新背光的。函数的原型如下:
struct backlight_ops {
    unsigned int options;

#define BL_CORE_SUSPENDRESUME   (1 << 0)

    /* Notify the backlight driver some property has changed */
    int (*update_status)(struct backlight_device *);
    /* Return the current backlight brightness (accounting for power,
       fb_blank etc.) */
    int (*get_brightness)(struct backlight_device *);
    /* Check if given framebuffer device is the one bound to this backlight;
       return 0 if not, !=0 if it is. If NULL, backlight always matches the fb. */
    int (*check_fb)(struct backlight_device *, struct fb_info *);
};

通过backlight_ops定义了一个名为gp7101_backlight_ops的backlight_ops结构体实例,并且只初始化了.update_status成员,它指向了一个名为
gp7101_backlight_set的函数,这个函数负责更新背光设备的亮度状态。

static struct backlight_ops gp7101_backlight_ops = {
    .update_status = gp7101_backlight_set,
};

gp7101_backlight_set函数

这就是我们更新背光的核心函数了,每次背光被改动的时候系统都会回调这个函数,在函数中我们通过I2C1去写GP7101实现修改背光。GP7101两种操作方法第一种是8位PWM,第二种是16位数PWM,刚好我们背光是从0~255所以,我们就选择8位PWM,八位PWM模式需要写寄存器0x03。
在这里插入图片描述

/* I2C 背光控制器寄存器定义 */
#define BACKLIGHT_REG_CTRL_8  0x03  
#define BACKLIGHT_REG_CTRL_16 0x02
/* 设置背光亮度 */
static int gp7101_backlight_set(struct backlight_device *bl)
{
    struct gp7101_backlight_data *data = bl_get_data(bl);  // 获取背光数据结构指针
    struct i2c_client *client = data->client;  // 获取I2C设备指针
    u8 addr[1] = {BACKLIGHT_REG_CTRL_8};  // 定义I2C地址数组
    u8 buf[1] = {bl->props.brightness};  // 定义数据缓冲区,用于存储背光亮度值

    MY_DEBUG("pwm:%d", bl->props.brightness);  // 输出背光亮度值

    // 将背光亮度值写入设备
    i2c_write(client, addr, sizeof(addr), buf, sizeof(buf));

    return 0;  // 返回成功
}

i2c_write

触摸驱动I2C写函数。

s32 i2c_write(struct i2c_client *client, u8 *addr, u8 addr_len, u8 *buf, s32 len)
{
    struct i2c_msg msg; // 定义i2c消息结构,用于传输数据
    s32 ret = -1; // 初始化返回值为-1,表示失败
    u8 *temp_buf; // 定义临时缓冲区指针

    msg.flags = !I2C_M_RD; // 标志位,表示写操作
    msg.addr = client->addr; // 设备地址
    msg.len = len + addr_len; // 写入数据的总长度(地址长度+数据长度)

    // 分配临时缓冲区
    temp_buf = kzalloc(msg.len, GFP_KERNEL);
    if (!temp_buf) {
        goto error; // 如果分配失败,跳转到错误处理
    }

    // 装填地址到临时缓冲区
    memcpy(temp_buf, addr, addr_len);
    // 装填数据到临时缓冲区(紧随地址之后)
    memcpy(temp_buf + addr_len, buf, len);
    msg.buf = temp_buf; // 设置消息的缓冲区为临时缓冲区

    // 发送消息并写入数据
    ret = i2c_transfer(client->adapter, &msg, 1);
    if (ret == 1) {
        kfree(temp_buf); // 释放临时缓冲区
        return 0; // 如果消息成功传输,返回0表示成功
    }

error:
    // 如果写入失败,打印错误信息
    if (addr_len == 2) {
        MY_DEBUG("I2C Write: 0x%04X, %d bytes failed, errcode: %d! Process reset.", (((u16)(addr[0] << 8)) | addr[1]), len, ret);
    } else {
        MY_DEBUG("I2C Write: 0x%02X, %d bytes failed, errcode: %d! Process reset.", addr[0], len, ret);
    }
    if (temp_buf) {
        kfree(temp_buf); // 释放临时缓冲区
    }
    return -1; // 返回-1表示失败
}

注释backlight

因为我们之前的背光驱动也是用的"backlight"节点,为了不去修改上层我们自己写的驱动也是用的"backlight"节点所以两个节点会冲突,所以我们在tspi-rk3566-dsi-v10.dtsi中把之前的屏蔽掉留下我们自己写的驱动。屏蔽原有背光设备树节点。

/ {
    
    /*backlight: backlight {
        compatible = "pwm-backlight";
        pwms = <&pwm5 0 25000 0>;
        brightness-levels = <
              0  20  20  21  21  22  22  23
             23  24  24  25  25  26  26  27
             27  28  28  29  29  30  30  31
             31  32  32  33  33  34  34  35
             35  36  36  37  37  38  38  39
             40  41  42  43  44  45  46  47
             48  49  50  51  52  53  54  55
             56  57  58  59  60  61  62  63
             64  65  66  67  68  69  70  71
             72  73  74  75  76  77  78  79
             80  81  82  83  84  85  86  87
             88  89  90  91  92  93  94  95
             96  97  98  99 100 101 102 103
            104 105 106 107 108 109 110 111
            112 113 114 115 116 117 118 119
            120 121 122 123 124 125 126 127
            128 129 130 131 132 133 134 135
            136 137 138 139 140 141 142 143
            144 145 146 147 148 149 150 151
            152 153 154 155 156 157 158 159
            160 161 162 163 164 165 166 167
            168 169 170 171 172 173 174 175
            176 177 178 179 180 181 182 183
            184 185 186 187 188 189 190 191
            192 193 194 195 196 197 198 199
            200 201 202 203 204 205 206 207
            208 209 210 211 212 213 214 215
            216 217 218 219 220 221 222 223
            224 225 226 227 228 229 230 231
            232 233 234 235 236 237 238 239
            240 241 242 243 244 245 246 247
            248 249 250 251 252 253 254 255
        >;
        default-brightness-level = <255>;
    };*/
};

在这里插入图片描述

在dsi1中也需要屏蔽掉否则找不到引用节点编译时候会报错。

&dsi1 {
    status = "okay";
    rockchip,lane-rate = <1000>;
    dsi1_panel: panel@0 {
        /*省略*/
        // backlight = <&backlight>;
        /*省略*/
    }}

在这里插入图片描述

GP7101背光完整驱动代码

#include "linux/stddef.h"
#include <linux/kernel.h>
#include <linux/hrtimer.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/vmalloc.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/timer.h>
#include <linux/input/mt.h>
#include <linux/random.h>
#include <linux/backlight.h>

#if 1
#define MY_DEBUG(fmt,arg...)  printk("gp7101_bl:%s %d "fmt"",__FUNCTION__,__LINE__,##arg);
#else
#define MY_DEBUG(fmt,arg...)
#endif

#define BACKLIGHT_NAME "gp7101-backlight"

/* I2C 背光控制器寄存器定义 */
#define BACKLIGHT_REG_CTRL_8  0x03  
#define BACKLIGHT_REG_CTRL_16 0x02

/* 背光控制器设备数据结构 */
struct gp7101_backlight_data {
    struct i2c_client *client;
    
};

s32 i2c_read(struct i2c_client *client,u8 *addr,u8 addr_len, u8 *buf, s32 len)
{
    struct i2c_msg msgs[2];
    s32 ret=-1;
    msgs[0].flags = !I2C_M_RD;
    msgs[0].addr  = client->addr;
    msgs[0].len   = addr_len;
    msgs[0].buf   = &addr[0];
    msgs[1].flags = I2C_M_RD;
    msgs[1].addr  = client->addr;
    msgs[1].len   = len;
    msgs[1].buf   = &buf[0];

    ret = i2c_transfer(client->adapter, msgs, 2);
    if(ret == 2)return 0;

    if(addr_len == 2){
        MY_DEBUG("I2C Read: 0x%04X, %d bytes failed, errcode: %d! Process reset.", (((u16)(addr[0] << 8)) | addr[1]), len, ret);
    }else {
        MY_DEBUG("I2C Read: 0x%02X, %d bytes failed, errcode: %d! Process reset.", addr[0], len, ret);
    }
    
    return -1;
}

s32 i2c_write(struct i2c_client *client, u8 *addr, u8 addr_len, u8 *buf,s32 len)
{
    struct i2c_msg msg;
    s32 ret = -1;
    u8 *temp_buf;

    msg.flags = !I2C_M_RD;
    msg.addr  = client->addr;
    msg.len   = len+addr_len;

    temp_buf= kzalloc(msg.len, GFP_KERNEL);
    if (!temp_buf){
        goto error;
    }
    
    // 装填地址
    memcpy(temp_buf, addr, addr_len);
    // 装填数据
    memcpy(temp_buf + addr_len, buf, len);
    msg.buf = temp_buf;

    ret = i2c_transfer(client->adapter, &msg, 1);
    if (ret == 1) {
        kfree(temp_buf);
        return 0;
    }

error:
    if(addr_len == 2){
        MY_DEBUG("I2C Read: 0x%04X, %d bytes failed, errcode: %d! Process reset.", (((u16)(addr[0] << 8)) | addr[1]), len, ret);
    }else {
        MY_DEBUG("I2C Read: 0x%02X, %d bytes failed, errcode: %d! Process reset.", addr[0], len, ret);
    }
    if (temp_buf)
        kfree(temp_buf);
    return -1;
}

/* 设置背光亮度 */
static int gp7101_backlight_set(struct backlight_device *bl)
{
    struct gp7101_backlight_data *data = bl_get_data(bl);
    struct i2c_client *client = data->client;
    u8 addr[1] = {BACKLIGHT_REG_CTRL_8};
    u8 buf[1] = {bl->props.brightness}; 

    MY_DEBUG("pwm:%d", bl->props.brightness);

    i2c_write(client, addr, sizeof(addr), buf, sizeof(buf));

    return 0;
}

/* 背光设备操作函数 */
static struct backlight_ops gp7101_backlight_ops = {
    .update_status = gp7101_backlight_set,
};

static int gp7101_bl_probe(struct i2c_client *client,
            const struct i2c_device_id *id)
{
    struct backlight_device *bl;
    struct gp7101_backlight_data *data;
    struct backlight_properties props;
    struct device_node *np = client->dev.of_node;

    MY_DEBUG("locat");

    data = devm_kzalloc(&client->dev, sizeof(struct gp7101_backlight_data), GFP_KERNEL);
    if (data == NULL){
        dev_err(&client->dev, "Alloc GFP_KERNEL memory failed.");
        return -ENOMEM;
    } 

    memset(&props, 0, sizeof(props));
    props.type = BACKLIGHT_RAW;
    props.max_brightness = 255; 

    of_property_read_u32(np, "max-brightness-levels",
                &props.max_brightness);

    of_property_read_u32(np, "default-brightness-level", 
                &props.brightness);

    if(props.max_brightness>255 || props.max_brightness<0){
        props.max_brightness = 255;
    }
    if(props.brightness>props.max_brightness || props.brightness<0){
        props.brightness = props.max_brightness;
    }
    /* 初始化背光设备 */
    bl = devm_backlight_device_register(&client->dev, "backlight", &client->dev, data, &gp7101_backlight_ops,&props);
    if (IS_ERR(bl)) {
        dev_err(&client->dev, "failed to register backlight device\n");
        return PTR_ERR(bl);
    }
    data->client = client;
    i2c_set_clientdata(client, data);

    MY_DEBUG("max_brightness:%d brightness:%d",props.max_brightness, props.brightness);
    backlight_update_status(bl);

    return 0;
}

static int gp7101_bl_remove(struct i2c_client *client)
{
    MY_DEBUG("locat");
    return 0;
}

static const struct of_device_id gp7101_bl_of_match[] = {
    { .compatible = BACKLIGHT_NAME, },
    { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, gp7101_bl_of_match);


static struct i2c_driver gp7101_bl_driver = {
    .probe      = gp7101_bl_probe,
    .remove     = gp7101_bl_remove,
    .driver = {
        .name     = BACKLIGHT_NAME,
     .of_match_table = of_match_ptr(gp7101_bl_of_match),
    },
};

static int __init my_init(void)
{
    MY_DEBUG("locat");
    return i2c_add_driver(&gp7101_bl_driver);
}

static void __exit my_exit(void)
{
    MY_DEBUG("locat");
    i2c_del_driver(&gp7101_bl_driver);
}

module_init(my_init);
module_exit(my_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("My touch driver");
MODULE_AUTHOR("KuLiT");

编译生效

cd u-boot && ./make.sh rk3566 && cd ../kernel && make distclean && make ARCH=arm64 tspi_defconfig rk356x_evb.config android-11.config && make ARCH=arm64 tspi-rk3566-user-v10.img -j16 && cd .. && source build/envsetup.sh && lunch rk3566_tspi-userdebug && make installclean -j16 && make -j16 && ./mkimage.sh

在这里插入图片描述

./build.sh -u

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

探索数据结构:堆的具体实现与应用

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;数据结构与算法 贝蒂的主页&#xff1a;Betty’s blog 1. 堆的概念 堆(Heap)是计算机科学中一类特殊的数据结构。堆通常是一个…

SpringBoot项目的项目部署全过程

一、前端 安装nginx 1.将提前准备好的nginx的安装包上传到Linux中/opt目录下(我用的是Xftp) 2.解压 2.1:在xshell中解压该文件: tar -zxvf nginx-1.20.1.tar.gz 2.2:进入解压后的目录 cd nginx-1.20.1/ 2.3:安装需要的依赖 yum -y install zlib zlib-devel openssl openssl-de…

Keil编程不同驱动文件引用同一个常量的处理方法

基础不牢&#xff0c;地动山摇&#xff0c;最近单片机编程又遇到一个基础问题。 我在头文件中定义了一个常量同时给两个驱动文件使用&#xff0c;封装的时候编译没问题&#xff0c;但是在main函数中引用驱动函数的时候就出现了重定义的问题&#xff0c;如下如所示。 解决方法很…

8.基于鱼鹰优化算法(OOA)优化VMD参数(OOA-VMD)

代码原理 鱼鹰优化算法&#xff08;Osprey Optimization Algorithm, OOA&#xff09;是一种基于仿生学原理的启发式优化算法&#xff0c;它模拟了鱼鹰觅食的行为&#xff0c;通过调整搜索空间中的个体位置来优化目标函数。 鱼鹰优化算法可参考&#xff1a;鱼鹰优化算法(Ospre…

Network Compression

听课&#xff08;李宏毅老师的&#xff09;笔记&#xff0c;方便梳理框架&#xff0c;以作复习之用。本节课主要讲了Network Compression&#xff0c;包括为什么要压缩&#xff0c;压缩的主要手段&#xff08;pruning,knowledge distillation,parameter quantization,architect…

C# 下载安装,使用OfficeOpenXml

下载安装OfficeOpenXml模块 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Reflection.Emit; using System.Text; using System.Text.RegularEx…

【大道至简】官方兼容到android13+的获取系统屏幕高度, statusbar,navBar

android在屏幕高度和app高度&#xff0c;statusbar, navigationbar的高度处理上&#xff0c;迭代了好多版本。 android11&#xff0c; android12都有新的api和过时的api标记。 涉及的api类似如下&#xff1a; windowManager&#xff0c;defaultDisplay, Context.display, Deco…

uniapp开发安卓app使用文字转语音技术

在 UniApp 开发安卓应用时&#xff0c;要实现文字转语音&#xff08;Text-to-Speech, TTS&#xff09;技术&#xff0c;你可以利用 UniApp 的跨平台能力结合原生模块或第三方服务来实现。以下是一些建议的步骤和方法&#xff1a; 1. 使用 UniApp 原生模块&#xff08;如果支持…

怎么得到所有大写字母/小写字母组成的字符串

有时候&#xff0c;可能需要获取a~z、A~Z组成的26个字母的字符串&#xff0c;这篇文章介绍一种简单的方法。 只需要几句简单到不能再简单的代码&#xff01;你不会还在傻傻地一个个字母敲吧~ /*** author heyunlin* version 1.0*/ public class Example {/*** 小写字母*/priv…

通信指挥类装备(多链路聚合设备)-应急通信指挥解决方案

现场通信指挥系统是一种功能全面的便携式音视频融合指挥通信平台&#xff0c;可实现现场应急救援指挥、多种通信手段融合、现场通信组网等功能&#xff0c;是现场指挥系统的延伸。 多链路聚合设备&#xff0c;是一款通信指挥类装备&#xff0c;具有 4G/5G&#xff0c;专网&…

ResNeXt

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊# 前言 前言 前面已经学习了resnet家族已经inception卷积网络&#xff0c;还简单了解了SE注意力机制&#xff0c;今天学习resnet和inception的组合ResNeXt。 …

Nodejs笔记2

模块化 模块化初体验 模块暴露数据 导入模块 fs 写绝对路径 require写相对路径不会受到影响 ./../不能省略 js 和json文件后缀可以省略 如果存在 命名相同的js和json文件&#xff0c;优先导入js文件 导入文件夹时的情况 require导入模块的基本流程 commonJS模块…

Nginx的正向代理与反向代理

你好呀&#xff0c;我是赵兴晨&#xff0c;文科程序员。 今天&#xff0c;我们将一起了解什么是Nginx的正向代理&#xff1f;什么是Nginx的反向代理&#xff1f;并实际动手实践。 以下内容都是满满的干货&#xff0c;绝对不容错过。我建议先收藏这篇文章&#xff0c;然后找一…

前端CSS3基础1(新增长度单位,盒子模型,背景,边框,文本属性,渐变,字体,2D变换,3D变换)

前端CSS3基础1&#xff08;新增长度单位&#xff0c;盒子模型&#xff0c;背景&#xff0c;边框&#xff0c;文本属性&#xff0c;渐变&#xff0c;字体&#xff0c;2D变换&#xff0c;3D变换&#xff09; CSS3 新增长度单位CSS3 新增盒子模型相关属性box-sizing怪异盒模型box-…

【计算机毕业设计】基于SSM+Vue的线上旅行信息管理系统【源码+lw+部署文档+讲解】

目录 1 绪论 1.1 研究背景 1.2 设计原则 1.3 论文组织结构 2 系统关键技术 2.1JSP技术 2.2 JAVA技术 2.3 B/S结构 2.4 MYSQL数据库 3 系统分析 3.1 可行性分析 3.1.1 技术可行性 3.1.2 操作可行性 3.1.3 经济可行性 3.1.4 法律可行性 3.2系统功能分析 3.2.1管理员功能分析 3.2.…

HTML常用标签-表单标签

表单标签 1 表单标签2 表单项标签2.1 单行文本框2.2 密码框2.3 单选框2.4 复选框2.5 下拉框2.6 按钮2.7 隐藏域2.8 多行文本框2.9 文件标签 1 表单标签 表单标签,可以实现让用户在界面上输入各种信息并提交的一种标签. 是向服务端发送数据主要的方式之一 form标签,表单标签,其内…

景源畅信:抖音小店比较冷门的品类分享?

在抖音小店的世界里&#xff0c;热门品类总是吸引着众多商家和消费者的目光。然而&#xff0c;就像星空中的繁星&#xff0c;虽不那么耀眼却依然存在的冷门品类同样值得我们关注。它们或许不似服装、美妆那样日进斗金&#xff0c;但正是这些小众市场的存在&#xff0c;为平台带…

搜索引擎的设计与实现(三)

目录 5 系统详细实现 5.1实现环境配置 5.2功能实现 5.2.1 建立索引 5.2.2 文件搜索实现 5.2.3 数据库的连接配置 5.2.4 数据库搜索实现 5.2.5 后台数据编辑实现 前面内容请移步 搜索引擎的设计与实现&#xff08;二&#xff09; 免费源代码&毕业设计论文 搜索…

ARM基于DWT实现硬件延时(GD32)

软件延时的缺点 软件延时的精度差&#xff0c;受系统主频影响&#xff0c;调教困难 硬件延时 DWT数据跟踪监视点单元硬件延时 硬件延时实现代码 delay.c #include <stdint.h> #include "gd32f30x.h"/** *****************************************************…

搜索引擎的设计与实现(四)

目录 6 系统测试 6.1测试重要性 6.2测试用例 结 论 参 考 文 献 前面内容请移步 搜索引擎的设计与实现&#xff08;三&#xff09; 免费源代码&毕业设计论文 搜索引擎的设计与实现 6 系统测试 6.1测试重要性 该项目是在本地服务器上进行运行和调试&#xff0c;…