全志V3S嵌入式驱动开发(lcd屏幕驱动)

news2024/9/20 1:14:57

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        对于一些设备,人们是希望从屏幕上面获取结果信息的,这样也显得更直观一些。另外,也有一些设备,它本身是需要客户和它不停交互,去一起完成某个功能的,这个时候,我们就要引入电容屏或者电阻屏了。那么,对于v3s来说,如果需要完成lcd屏幕的驱动和显示,需要完成哪些工作呢,这部分今天大家可以一起讨论下。

1、重新编译uboot

        重新编译uboot代码,这部分是最容易被忽视的。驱动之前的几种设备时,大家选用的配置文件一般是LicheePi_Zero_defconfig。但是,如今我们需要驱动lcd屏幕,以480*272的分辨率为例,就要使用LicheePi_Zero_480x272LCD_defconfig这个文件。

make ARCH=arm LicheePi_Zero_480x272LCD_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-

        编译完成之后,直接在ubuntu虚拟机里面把u-boot-sunxi-with-spl.bin烧入到sd卡即可,

sudo dd if=u-boot-sunxi-with-spl.bin of=/dev/sdb bs=1024 seek=8

2、配置dts文件

        这里说的dts文件是指linux的dts文件,不是uboot的dts文件。kernel本身还是4.14.y这个版本。在配置之前,前期因为测试各个驱动所作的修改,最好恢复到和以前一样,然后接下来有两个地方需要重新配置下,一个是sun8i-v3s-licheepi-zero-with-lcd.dtsi这个文件,

/*
 * Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
 *
 * SPDX-License-Identifier: (GPL-2.0+ OR X11)
 */

#include "sun8i-v3s-licheepi-zero.dts"

/ {
/*	backlight: backlight {
		compatible = "pwm-backlight";
		pwms = <&pwm 0 1000000 0>;
		brightness-levels = <0 30 40 50 60 70 100>;
		default-brightness-level = <6>;
	};*/

	panel: panel {
		#address-cells = <1>;
		#size-cells = <0>;

		port@0 {
			reg = <0>;
		/*	backlight = <&backlight>;*/
			#address-cells = <1>;
			#size-cells = <0>;

			panel_input: endpoint@0 {
				reg = <0>;
				remote-endpoint = <&tcon0_out_lcd>;
			};
		};
	};
};

&de {
	status = "okay";
};

/*&pwm {
	pinctrl-names = "default";
	pinctrl-0 = <&pwm0_pins>;
	status = "okay";
};*/

&tcon0 {
	pinctrl-names = "default";
	pinctrl-0 = <&lcd_rgb666_pins_a>;
	status = "okay";
};

&tcon0_out {
	tcon0_out_lcd: endpoint@0 {
		reg = <0>;
		remote-endpoint = <&panel_input>;
	};
};

/delete-node/ &simplefb_lcd;

        另外一个就是sun8i-v3s.dtsi文件,这里修改成60M,主要是为了6分频成10M,保持和uboot中的lcd频率一致,

assigned-clock-rates = <60000000>;

        经过了这两处修改之后,重新编译生成dtb文件,

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-

        编译完成之后,需要注意的是,这次sd卡里面烧入的应该是sun8i-v3s-licheepi-zero-with-480x272-lcd.dtb文件,而不应该是之前的sun8i-v3s-licheepi-zero-dock.dtb。

3、点亮屏幕

        修改了uboot代码,重新烧录了dtb文件,但其实这个时候lcd屏幕依然还没有办法点亮,我们可以看一下电路图,

         这幅图是lcd的原理图。整个信号分成三个部分,第一部分VLED-、VLED+,这个主要是点亮屏幕的背光灯使用的。第二部分D2-D23、CLK、HSYNC、VSYNC、DE,这些都是真正的数据传输信号,其中D2-D23一般就是R、G、B信号。第三部分TP信号,这四个主要是处理触摸屏的,后续遇到了再分析。

        前面我们说过目前为止LCD还没有点亮,说的其实就是VLED-、VLED+还没有信号驱动,它的信号来自于芯片PT4103,

         这个芯片的开关就在EN这个地方,而EN又是友PB2来控制的。之前的文章我们也说过,这个PA、PB...都可以看成是gpio端口,只需要设置对应的通道、方向和数值就可以了,像这样,

echo 34 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio34/direction
echo 1 > /sys/class/gpio/gpio34/value

        为什么是34,我们讲过,从PA开始,channel = 32 * x + y,其中PB代表x=1,而PB2中的2,则代表y,所以通道是32 * 1 + 2= 34。经过上面的direction和value配置后,屏幕就会被点亮,虽然可能什么内容也没有显示。

4、验证驱动是否加载

        验证lcd驱动是否可以正常运行,可以先查看是否有/dev/fb0这样一个设备节点,如果有,且linux kernel启动正常,一般就代表驱动ok了,没有问题了。如果还不放心,可以输入这个命令,

cat /dev/urandom > /dev/fb0

        执行过程中,如果遇到这样的输出错误打印,可以忽略,因为这是完全正常的,

# cat /dev/urandom > /dev/fb0
cat: write error: No space left on device

        我们再看一眼屏幕,这个时候大概率就可以看到这样的效果了,主要就是一些噪声点显示,

5、自己编写程序验证

        除了用随机点验证之外,我们还可以自己编写程序,直接控制/dev/fb0。下面这些程序都是从网上借鉴而来,主要为了学习使用,再次一并表示感谢。代码中为了适应480*272的lcd屏幕,部分代码做了修改。

        5.1 读取屏幕驱动参数

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>

int main () {

 int fp=0;
 struct fb_var_screeninfo vinfo;
 struct fb_fix_screeninfo finfo;
 fp = open ("/dev/fb0",O_RDWR);


 if (fp < 0){
  printf("Error : Can not open framebuffer device/n");
  exit(1);
 }


 if (ioctl(fp,FBIOGET_FSCREENINFO,&finfo)){
  printf("Error reading fixed information/n");
  exit(2);
 }
 
 if (ioctl(fp,FBIOGET_VSCREENINFO,&vinfo)){
  printf("Error reading variable information/n");
  exit(3);
 }


 printf("The mem is :%d\n",finfo.smem_len);
 printf("The line_length is :%d\n",finfo.line_length);
 printf("The xres is :%d\n",vinfo.xres);
 printf("The yres is :%d\n",vinfo.yres);
 printf("bits_per_pixel is :%d\n",vinfo.bits_per_pixel);
 close (fp);
}

        这个程序比较简单,就是读取了缓存大小、每一行字节数、x宽度、y宽度和每一个像素字节序信息。

        5.2 在/dev/fb0上面绘制一个点

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>

int main () {

 int fp=0;
 struct fb_var_screeninfo vinfo;
 struct fb_fix_screeninfo finfo;
 long screensize=0;
 char *fbp = 0;
 int x = 0, y = 0;
 long location = 0;
 fp = open ("/dev/fb0",O_RDWR);


 if (fp < 0){
  printf("Error : Can not open framebuffer device/n");
  exit(1);
 }


 if (ioctl(fp,FBIOGET_FSCREENINFO,&finfo)){
  printf("Error reading fixed information/n");
  exit(2);
 }
 
 if (ioctl(fp,FBIOGET_VSCREENINFO,&vinfo)){
  printf("Error reading variable information/n");
  exit(3);
 }


 screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
 fbp =(char *) mmap (0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fp,0);
 if ((int) fbp == -1){
     printf ("Error: failed to map framebuffer device to memory./n");
     exit (4);
 }

  x = 100;
  y = 100;
  location = x * (vinfo.bits_per_pixel / 8) + y  *  finfo.line_length;

  *(fbp + location) = 100;  
  *(fbp + location + 1) = 15; 
  *(fbp + location + 2) = 200; 
  *(fbp + location + 3) = 0;  
  munmap (fbp, screensize); 
  close (fp);    
  return 0;
}

        将程序编译后,上传到sd卡运行后,就会看到这样的一个斑点,还是比较好找的,

        5.3 显示图片

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <errno.h>

//14byte文件头
typedef struct
{
    char    cfType[2];//文件类型,"BM"(0x4D42)
    int     cfSize;//文件大小(字节)
    int cfReserved;//保留,值为0
    int     cfoffBits;//数据区相对于文件头的偏移量(字节)
}__attribute__((packed)) BITMAPFILEHEADER;
//__attribute__((packed))的作用是告诉编译器取消结构在编译过程中的优化对齐

//40byte信息头
typedef struct
{
    char ciSize[4];//BITMAPFILEHEADER所占的字节数
    int  ciWidth;//宽度
    int  ciHeight;//高度
    char ciPlanes[2];//目标设备的位平面数,值为1
    int  ciBitCount;//每个像素的位数
    char ciCompress[4];//压缩说明
    char ciSizeImage[4];//用字节表示的图像大小,该数据必须是4的倍数
    char ciXPelsPerMeter[4];//目标设备的水平像素数/米
    char ciYPelsPerMeter[4];//目标设备的垂直像素数/米
    char ciClrUsed[4]; //位图使用调色板的颜色数
    char ciClrImportant[4]; //指定重要的颜色数,当该域的值等于颜色数时(或者等于0时),表示所有颜色都一样重要
}__attribute__((packed)) BITMAPINFOHEADER;

typedef struct
{
    unsigned char blue;
    unsigned char green;
    unsigned char red;
    unsigned char reserved;
}__attribute__((packed)) PIXEL;//颜色模式RGB

BITMAPFILEHEADER FileHead;
BITMAPINFOHEADER InfoHead;

static char *fbp = 0;
static int xres = 0;
static int yres = 0;
static int bits_per_pixel = 0;
int width, height;

int show_bmp();
int fbfd = 0;

static void fb_update(struct fb_var_screeninfo *vi)   //将要渲染的图形缓冲区的内容绘制到设备显示屏来
{  
    vi->yoffset = 1;  
    ioctl(fbfd, FBIOPUT_VSCREENINFO, vi);  
    vi->yoffset = 0;  
    ioctl(fbfd, FBIOPUT_VSCREENINFO, vi);  
}  

static int cursor_bitmap_format_convert(char *dst,char *src)
{
    int i ,j ;
    char *psrc = src ;
    char *pdst = dst;
    char *p = psrc;

    /* 由于bmp存储是从后面往前面,所以需要倒序进行转换 */
    pdst += (width * height * 4);
    for(i=0;i<height;i++){
        p = psrc + (i+1) * width * 3;
        for(j=0;j<width;j++){
            pdst -= 4;
            p -= 3;
            pdst[0] = p[0];
            pdst[1] = p[1];
            pdst[2] = p[2];
	        pdst[3] = 0;
        }
    }
    return 0;
}

int show_bmp(char *path)
{
    int i;
    FILE *fp;
    int rc;
    int line_x, line_y;
    long int location = 0, BytesPerLine = 0;
    char *bmp_buf = NULL;
    char *bmp_buf_dst = NULL;
    char * buf = NULL;
    int flen = 0;
    int ret = -1;
    int total_length = 0;

    printf("into show_bmp function\n");
    if(path == NULL)
    {
        printf("path Error,return\n");
        return -1;
    }
    printf("path = %s\n", path);
    fp = fopen( path, "rb" );
    if(fp == NULL){
        printf("load cursor file open failed\n");
        return -1;
    }

    /* 求解文件长度 */
    fseek(fp,0,SEEK_SET);
    fseek(fp,0,SEEK_END);

    flen = ftell(fp);
    printf("flen is %d\n",flen);

    bmp_buf = (char*)calloc(1,flen - 54);
    if(bmp_buf == NULL){
        printf("load > malloc bmp out of memory!\n");
        return -1;
    }

    /* 再移位到文件头部 */
    fseek(fp,0,SEEK_SET);

    rc = fread(&FileHead, sizeof(BITMAPFILEHEADER),1, fp);
    if ( rc != 1)
    {
        printf("read header error!\n");
        fclose( fp );
        return( -2 );
    }

    //检测是否是bmp图像
    if (memcmp(FileHead.cfType, "BM", 2) != 0)
    {
        printf("it's not a BMP file\n");
        fclose( fp );
        return( -3 );
    }
    rc = fread( (char *)&InfoHead, sizeof(BITMAPINFOHEADER),1, fp );
    if ( rc != 1)
    {
        printf("read infoheader error!\n");
        fclose( fp );
        return( -4 );
    }
    width = InfoHead.ciWidth;
    height = InfoHead.ciHeight;

    printf("FileHead.cfSize =%d byte\n",FileHead.cfSize);
    printf("flen = %d\n", flen);
    printf("width = %d, height = %d\n", width, height);

    total_length = width * height *3;

    printf("total_length = %d\n", total_length);

    //跳转的数据区
    fseek(fp, FileHead.cfoffBits, SEEK_SET);
    printf(" FileHead.cfoffBits = %d\n",  FileHead.cfoffBits);
    printf(" InfoHead.ciBitCount = %d\n",  InfoHead.ciBitCount);    

    //每行字节数
    buf = bmp_buf;
    while ((ret = fread(buf,1,total_length,fp)) >= 0) {
        if (ret == 0) {
            usleep(100);
            continue;
        }
        printf("ret = %d\n", ret);
        buf = ((char*) buf) + ret;
        total_length = total_length - ret;
        if(total_length == 0)
            break;
    }

    ///重新计算,很重要!!
    total_length = width * height *4;
    bmp_buf_dst = (char*)calloc(1,total_length );
    if(bmp_buf_dst == NULL){
        printf("load > malloc bmp out of memory!\n");
        return -1;
    }

    cursor_bitmap_format_convert(bmp_buf_dst, bmp_buf);
    memcpy(fbp,bmp_buf_dst,total_length);

    free(bmp_buf);
    free(bmp_buf_dst);

    fclose(fp);
    printf("show logo return 0\n");
    return 0;
}

int show_picture(int fd, char *path)
{
    struct fb_var_screeninfo vinfo;
    struct fb_fix_screeninfo finfo;
    long int screensize = 0;
    struct fb_bitfield red;
    struct fb_bitfield green;
    struct fb_bitfield blue;

    //打开显示设备
    fbfd = fd;          //open("/dev/graphics/fb0", O_RDWR);
    printf("fbfd = %d\n", fbfd);
    if (fbfd == -1)
    {
        //printf("Error opening frame buffer errno=%d (%s)\n",errno, strerror(errno));
        return -1;
    }

    if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo))
    {
        //printf("Error:reading fixed information.\n");
        return -1;
    }

    if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo))
    {
        //printf("Error: reading variable information.\n");
        return -1;
    }

    //printf("R:%x ;G:%d ;B:%d \n", (int)vinfo.red, vinfo.green, vinfo.blue );
    //printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel );

    xres = vinfo.xres;
    yres = vinfo.yres;
    bits_per_pixel = vinfo.bits_per_pixel;

    //计算屏幕的总大小(字节)
    screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
    printf("screensize=%ld byte\n",screensize);

    //对象映射
    fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
    if (fbp == (char *)-1)
    {
        printf("Error: failed to map framebuffer device to memory.\n");
        return -1;
    }

    printf("sizeof file header=%ld\n", sizeof(BITMAPFILEHEADER));

    //显示图像
    show_bmp(path);

    ///在屏幕上显示多久
    sleep(100);

    fb_update(&vinfo);

    //删除对象映射
    munmap(fbp, screensize);

    return 0;
}

int main()
{
    int fbfd = 0;

    fbfd = open("/dev/fb0", O_RDWR);  
    if (!fbfd)  
    {  
        printf("Error: cannot open framebuffer device.\n");  
        exit(1);  
    } 
    show_picture(fbfd, "./girl.bmp");

    close(fbfd);
}

        代码部分有点长,大家可以先copy下来慢慢看。原作者的代码其实是有点问题的,主要体现在,bmp这幅图片上面一个像素是3个字节来表示的,但是lcd屏幕显示的时候,是四个字节。这四个字节当中,前三个字节是一样的,关键这第四个字节透明度,也需要补充上,不然的话,lcd屏幕本身是没有办法正常显示的。

         因为没有找到符合480*272要求的girl.bmp,这里只能用一朵荷花代替了,大家多多包含以下。

6、题外话

        看过VGA和LCD通讯协议的同学应该都知道,屏幕中的图像,是需要定时刷新才有专业的效果,这中间就包括了数据刷新、行同步、场同步,此外频率越高,分辨率越高,耗电也越大,这都是显而易见的。使用者只需要把数据写到ddr buffer里面,刷新的事情,其实都是gpu或者ip驱动后台帮助我们默默完成的。

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

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

相关文章

阿里云OSS实现图片上传(后端接口)

文章目录 1、阿里云oss服务开通2、java操作阿里云oss&#xff0c;上传文件到阿里云oss1. 创建操作阿里云oss许可证2. 安装SDK3.修改配置文件4.创建常量类&#xff0c;读取配置文件中的内容5、OssController6、OssService7、OssServiceImpl8、改进1. 多次上传相同名称文件&#…

Segment Anything学习小结

论文地址&#xff1a;Segment Anything 项目地址&#xff1a;https://github.com/facebookresearch/segment-anything 在线Demo&#xff1a; https://segment-anything.com/demo 前言 近日&#xff0c;MetaAI团队开源了一个用于分割的10亿个masks&#xff0c;1100w张图片数…

测试新手如何晋升为月入过万的软件测试工程师?“我“的测试之路不简单...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 测试工程师这个岗…

记一次binlog恢复Mysql某张表数据的过程

1、备份数据库&#xff0c;非常重要 2、要用户不能操作&#xff08;如果不能停止&#xff0c;可以新建一个库&#xff0c;所有的binlog执行操作在新库执行&#xff09;。 3、登录服务器&#xff1b; 4、获取Mysql数据路径 cat /etc/my.cnf.d/mysql-server.cnf5、进入当前目录…

【SpinalHDL快速入门】4.2、基本类型之Bits

文章目录 1.1、描述1.2、声明1.3、运算符1.3.1、逻辑运算&#xff08;Logic&#xff09;1.3.2、比较&#xff08;Comparison&#xff09;1.3.3、类型转换&#xff08;Type cast&#xff09;1.3.4、部分赋值/提取操作符&#xff08;Bit extraction&#xff09;1.3.5、杂项&#…

Redis的使用规范小建议

Redis 核心技术与实战 笔记 作者&#xff1a; 蒋德钧 毕竟&#xff0c;高性能和节省内存&#xff0c;是我们的两个目标&#xff0c;只有规范地使用Redis&#xff0c;才能真正实现这两个目标。如果说之前的内容教会了你怎么用&#xff0c;那么今天的内容&#xff0c;就是帮助你用…

ChatGPT的学习过程【分析ChatGPT原理】+如何高效使用GPT

ChatGPT的学习过程【分析ChatGPT原理】如何高效使用GPT 此处借鉴&#xff1a;台湾大学李宏毅老师的讲解 资料&#xff1a;pan.baidu.com/s/1Jk1phne3ArfOERYNTPL12Q?pwd1111 GPTGenerative Pre-trained Transformer生成式预训练转换模型 ChatGPT共有四个学习阶段 学习文字接龙…

Java性能权威指南-总结7

Java性能权威指南-总结7 垃圾收集算法理解Throughput收集器堆大小的自适应调整和静态调整理解CMS收集器 垃圾收集算法 理解Throughput收集器 Throughput收集器有两个基本的操作&#xff1b;其一是回收新生代的垃圾&#xff0c;其二是回收老年代的垃圾。 下图展示了堆在新生代…

Python配置MySQL数据库使用

创建配置文件 config.ini [MySQL] host 172.xxx.xxx.xxx port 3306 user root password ****** db bgp_routing charset utf8创建读取配置文件 readConfig.py import configparser from pathlib import Pathclass ReadConfig():def __init__(self):configDir Path.cwd…

【学习日记2023.6.6】之 Linux环境下部署Java项目

文章目录 5. 项目部署5.1 手动部署项目5.2 基于Shell脚本自动部署5.2.1 介绍5.2.2 推送代码到远程5.2.3 Git操作5.2.4 Maven安装5.2.5 Shell脚本准备5.2.6 Linux权限5.2.7 授权并执行脚本5.2.8 设置静态IP 5. 项目部署 开发的项目绝大部分情况下都需要部署在Linux系统中。下面通…

springboot+vue多维的知识分类管理系统

随着国内市场经济这几十年来的蓬勃发展&#xff0c;突然遇到了从国外传入国内的互联网技术&#xff0c;互联网产业从开始的群众不信任&#xff0c;到现在的离不开&#xff0c;中间经历了很多挫折。本次开发的多维分类的知识管理系统有管理员和用户两个角色。管理员可以管理用户…

Dozzle-解决通过命令方式查看Docker 日志的神器

对于程序员们来说&#xff0c;Docker 一定是不陌生了。Docker 为我们的工作带来的巨大的便利&#xff0c;你可以使用它快速部署和扩展应用程序&#xff0c;并保证隔离性和可移植性&#xff0c;使应用程序在容器内独立运行&#xff0c;而且可以轻松地在不同的主机和操作系统上移…

bpmn是什么?bpmn.js的简单使用

文章目录 一、bpmn.js是什么&#xff1f;二、使用步骤1.引入bpmn2.使用bpmn3.引入bpmn-左侧工具栏4.引入bpmn-左侧工具栏5.引入bpmn数据导出6.数据导出为svg格式7.监听modeler并绑定事件7.监听element点击……8.自定义左侧工具栏图标9.自定义左侧工具栏完整效果 总结 一、bpmn.…

推动体系建设 助推融合发展|2023 开放原子全球开源峰会软件物料清单(SBOM)分论坛即将启幕

软件物料清单对于普通人而言可能很陌生&#xff0c;而对于从业者而言&#xff0c;软件物料清单是以 “开源” 为核心&#xff0c;通过有效识别和记录软件组成成分及相互依赖关系&#xff0c;保障软件全生命周期各环节要素的可控制、可预测、可管理。 由开放原子开源基金会主办…

云原生Docker网络管理和数据卷

Docker网络 Docker 网络实现原理 Docker使用Linux桥接&#xff0c;在宿主机虚拟一个Docker容器网桥(docker0)&#xff0c; Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址&#xff0c;称为Container-IP&#xff0c; 同时Docker网桥是每个容器的默认网关。 …

案例26:基于Springboot校园社团管理系统开题报告

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

那些你可能遇到的 Linux 命令?什么,你还不知道?赶紧收藏?完善中!

文章目录 一. Linux 进程1. 通过进程名查找进程号1.1 ps aux & ps -ef&#xff1a;diff1.2 ps aux & ps -aux&#xff1a;什么&#xff1f;它们不一样&#xff1f;1.3 grep & awk&#xff1a;取出进程号、取出进程号并 Kill 2. 通过进程号查看进程信息&#xff1a;…

视频理解学习笔记(四)

视频理解学习笔记&#xff08;四&#xff09; 3D CNNC3DI3DNon-local算子 &#xff08;Self-attention替换掉LSTM&#xff09;R (2 1) DSlowFast Video TransformerTimeSformer 总结Reference 3D CNN 双流的缺点&#xff1a;光流抽取太慢——tvl one算法&#xff0c;0.06s抽取…

什么是浅拷贝和深拷贝

javascript 中有不同的方法来复制对象,那么我们怎样才能正确地复制一个对象呢?&#xff0c;本文来介绍一下浅拷贝和深拷贝。 一、什么是浅拷贝(Shallow Copy) 浅拷贝是创建一个新对象&#xff0c;这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型&#xff0c;拷…

遗传算法在数学建模中的应用及MATLAB实现

2023年9月数学建模国赛期间提供ABCDE题思路加Matlab代码,专栏链接(赛前一个月恢复源码199,欢迎大家订阅):http://t.csdn.cn/Um9Zd 目录 遗传算法基本概念 遗传算法原理 MATLAB实现 1. 使用ga求解遗传算法问题 数学建模案例&#xff1a;旅行商问题&#xff08;TSP&#xf…