嵌入式Linux驱动开发(LCD屏幕专题)(三)

news2024/11/30 12:48:09

1. 硬件相关的操作

LCD驱动程序的核心就是:

  • 分配fb_info
  • 设置fb_info
  • 注册fb_info
  • 硬件相关的设置

硬件相关的设置又可以分为3部分:

  • 引脚设置
  • 时钟设置
  • LCD控制器设置

2. 在设备树里指定LCD参数

	framebuffer-mylcd {
			compatible = "100ask,lcd_drv";
	        pinctrl-names = "default";
			pinctrl-0 = <&mylcd_pinctrl>;
			backlight-gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;

            clocks = <&clks IMX6UL_CLK_LCDIF_PIX>,
                     <&clks IMX6UL_CLK_LCDIF_APB>;
            clock-names = "pix", "axi";
            
            display = <&display0>;

			display0: display {
				bits-per-pixel = <24>;
				bus-width = <24>;

				display-timings {
					native-mode = <&timing0>;

					 timing0: timing0_1024x768 {
					 clock-frequency = <50000000>;
					 hactive = <1024>;
					 vactive = <600>;
					 hfront-porch = <160>;
					 hback-porch = <140>;
					 hsync-len = <20>;
					 vback-porch = <20>;
					 vfront-porch = <12>;
					 vsync-len = <3>;

					 hsync-active = <0>;
					 vsync-active = <0>;
					 de-active = <1>;
					 pixelclk-active = <0>;
					 };

				};
			};            
	};

3. 编程

3.1 从设备树获得参数

时序参数、引脚极性等信息,都被保存在一个display_timing结构体里:
在这里插入图片描述

参考内核文件:

  • drivers\video\of_display_timing.c
  • drivers\video\fbdev\mxsfb.c

3.2 使用参数配置LCD控制器

根据芯片手册,一个一个设置寄存器:

  • Framebuffer地址设置
  • Framebuffer中数据格式设置
  • LCD时序参数设置
  • LCD引脚极性设置

4.上机实验

1. 要做的事情

  • 去除内核自带的驱动程序

  • 加入我们编写的驱动程序、设备树文件

  • 重新编译内核、设备树

  • 上机测试:使用编译出来的内核、设备树启动板子

2. 去除内核自带的驱动程序

修改内核文件:drivers/video/fbdev/Makefile,把内核自带驱动程序mxsfb.c对应的那行注释掉,如下:

#obj-$(CONFIG_FB_MXS)             += mxsfb.o

3. 加入新驱动程序、设备树

  • 复制驱动程序:

    • 11_lcd_drv_imx6ull_ok\lcd_drv.c放到内核源码目录drivers/video/fbdev
    • 备份内核自带设备树文件:arch/arm/boot/dts/100ask_imx6ull-14x14.dts
    • 11_lcd_drv_imx6ull_ok\100ask_imx6ull-14x14.dts放到内核源码目录arch/arm/boot/dts/
  • 修改内核文件:

    • 修改:drivers/video/fbdev/Makefile,使用我们提供的lcd_drv.c,如下:
#obj-$(CONFIG_FB_MXS)             += mxsfb.o
obj-$(CONFIG_FB_MXS)             += lcd_drv.o

4. 重新编译内核、设备树

以下命令在Ubuntu中执行。

  • 设置工具链
  export ARCH=arm
  export CROSS_COMPILE=arm-linux-gnueabihf-
  export PATH=$PATH:/home/book/100ask_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin
  • 配置、编译
  book@100ask:~/100ask_imx6ull-sdk$ cd Linux-4.9.88
  book@100ask:~/100ask_imx6ull-sdk/Linux-4.9.88$ make 100ask_imx6ull_defconfig   
  book@100ask:~/100ask_imx6ull-sdk/Linux-4.9.88$ make zImage 
  book@100ask:~/100ask_imx6ull-sdk/Linux-4.9.88$ make dtbs
  • 得到

    • 内核:arch/arm/boot/zImage
    • 设备树文件:arch/arm/boot/dts/100ask_imx6ull-14x14.dtb
  • 复制到NFS目录:

  $ cp arch/arm/boot/zImage ~/nfs_rootfs/
  $ cp arch/arm/boot/dts/100ask_imx6ull-14x14.dtb ~/nfs_rootfs/

5. 上机测试

以下命令在开发板中执行。

  • 挂载NFS

    • vmware使用NAT(假设windowsIP为192.168.1.100)

      [root@100ask:~]# mount -t nfs -o nolock,vers=3,port=2049,mountport=9999 
      192.168.1.100:/home/book/nfs_rootfs /mnt
      
    • vmware使用桥接,或者不使用vmware而是直接使用服务器:假设Ubuntu IP为192.168.1.137

      [root@100ask:~]#  mount -t nfs -o nolock,vers=3 192.168.1.137:/home/book/nfs_rootfs /mnt
      
  • 更新单板文件

  [root@100ask:~]# cp /mnt/zImage /boot
  [root@100ask:~]# cp /mnt/100ask_imx6ull-14x14.dtb /boot
  [root@100ask:~]# sync
  • 重启开发板观察现象

    • 如果可以看到企鹅LOGO,就表示正常
    • 如果在终端中可以查看到存在/dev/fb0节点,也表示正常
  • 解决BUG

    • 现象:LCD上没有企鹅LOGO,在终端中执行ls -l /dev/fb0发现没有设备节点

    • 观察内核启动信息,看到:

      [    0.619880] imx6ul-pinctrl 20e0000.iomuxc: pin MX6UL_PAD_GPIO1_IO08 already requested by 2080000.pwm; cannot claim for 21c8000.framebuffer-mylcd
      [    0.619920] imx6ul-pinctrl 20e0000.iomuxc: pin-31 (21c8000.framebuffer-mylcd) status -22
      [    0.619954] imx6ul-pinctrl 20e0000.iomuxc: could not request pin 31 (MX6UL_PAD_GPIO1_IO08) from group mylcd_pingrp  on device 20e0000.iomuxc
      [    0.619985] mylcd 21c8000.framebuffer-mylcd: Error applying setting, reverse things back
      [    0.620070] mylcd: probe of 21c8000.framebuffer-mylcd failed with error -22
      
    • 原因:引脚冲突

      • 设备树中pwm节点、framebuffer-mylcd节点,都使用到的同一个引脚:PAD_GPIO1_IO08
    • 解决方法:修改arch/arm/boot/dts/100ask_imx6ull-14x14.dts,禁止pwm节点,如下:
      在这里插入图片描述

6、代码

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/cpufreq.h>
#include <linux/io.h>
#include <video/display_timing.h>
#include <video/of_display_timing.h>
#include <linux/gpio/consumer.h>
#include <asm/div64.h>
#include <asm/mach/map.h>

struct imx6ull_lcdif {
  volatile unsigned int CTRL;                              
  volatile unsigned int CTRL_SET;                        
  volatile unsigned int CTRL_CLR;                         
  volatile unsigned int CTRL_TOG;                         
  volatile unsigned int CTRL1;                             
  volatile unsigned int CTRL1_SET;                         
  volatile unsigned int CTRL1_CLR;                       
  volatile unsigned int CTRL1_TOG;                       
  volatile unsigned int CTRL2;                            
  volatile unsigned int CTRL2_SET;                       
  volatile unsigned int CTRL2_CLR;                        
  volatile unsigned int CTRL2_TOG;                        
  volatile unsigned int TRANSFER_COUNT;   
       unsigned char RESERVED_0[12];
  volatile unsigned int CUR_BUF;                          
       unsigned char RESERVED_1[12];
  volatile unsigned int NEXT_BUF;                        
       unsigned char RESERVED_2[12];
  volatile unsigned int TIMING;                          
       unsigned char RESERVED_3[12];
  volatile unsigned int VDCTRL0;                         
  volatile unsigned int VDCTRL0_SET;                      
  volatile unsigned int VDCTRL0_CLR;                     
  volatile unsigned int VDCTRL0_TOG;                     
  volatile unsigned int VDCTRL1;                          
       unsigned char RESERVED_4[12];
  volatile unsigned int VDCTRL2;                          
       unsigned char RESERVED_5[12];
  volatile unsigned int VDCTRL3;                          
       unsigned char RESERVED_6[12];
  volatile unsigned int VDCTRL4;                           
       unsigned char RESERVED_7[12];
  volatile unsigned int DVICTRL0;    
  	   unsigned char RESERVED_8[12];
  volatile unsigned int DVICTRL1;                         
       unsigned char RESERVED_9[12];
  volatile unsigned int DVICTRL2;                        
       unsigned char RESERVED_10[12];
  volatile unsigned int DVICTRL3;                        
       unsigned char RESERVED_11[12];
  volatile unsigned int DVICTRL4;                          
       unsigned char RESERVED_12[12];
  volatile unsigned int CSC_COEFF0;  
  	   unsigned char RESERVED_13[12];
  volatile unsigned int CSC_COEFF1;                        
       unsigned char RESERVED_14[12];
  volatile unsigned int CSC_COEFF2;                        
       unsigned char RESERVED_15[12];
  volatile unsigned int CSC_COEFF3;                        
       unsigned char RESERVED_16[12];
  volatile unsigned int CSC_COEFF4;   
  	   unsigned char RESERVED_17[12];
  volatile unsigned int CSC_OFFSET;  
       unsigned char RESERVED_18[12];
  volatile unsigned int CSC_LIMIT;  
       unsigned char RESERVED_19[12];
  volatile unsigned int DATA;                              
       unsigned char RESERVED_20[12];
  volatile unsigned int BM_ERROR_STAT;                     
       unsigned char RESERVED_21[12];
  volatile unsigned int CRC_STAT;                        
       unsigned char RESERVED_22[12];
  volatile  unsigned int STAT;                             
       unsigned char RESERVED_23[76];
  volatile unsigned int THRES;                             
       unsigned char RESERVED_24[12];
  volatile unsigned int AS_CTRL;                           
       unsigned char RESERVED_25[12];
  volatile unsigned int AS_BUF;                            
       unsigned char RESERVED_26[12];
  volatile unsigned int AS_NEXT_BUF;                     
       unsigned char RESERVED_27[12];
  volatile unsigned int AS_CLRKEYLOW;                    
       unsigned char RESERVED_28[12];
  volatile unsigned int AS_CLRKEYHIGH;                   
       unsigned char RESERVED_29[12];
  volatile unsigned int SYNC_DELAY;                      
} ;

struct lcd_regs {
	volatile unsigned int fb_base_phys;
	volatile unsigned int fb_xres;
	volatile unsigned int fb_yres;
	volatile unsigned int fb_bpp;	
};

static struct lcd_regs *mylcd_regs;
static struct fb_info *myfb_info;
static unsigned int pseudo_palette[16];

static struct gpio_desc *bl_gpio;
static struct clk* clk_pix;
static struct clk* clk_axi;

static void lcd_controller_enable(struct imx6ull_lcdif *lcdif)
{
	lcdif->CTRL |= (1<<0);
}

static int lcd_controller_init(struct imx6ull_lcdif *lcdif, struct display_timing *dt, int lcd_bpp, int fb_bpp, unsigned int fb_phy)
{
	int lcd_data_bus_width;
	int fb_width;
	int vsync_pol = 0;
	int hsync_pol = 0;
	int de_pol = 0;
	int clk_pol = 0;

	if (dt->flags & DISPLAY_FLAGS_HSYNC_HIGH)
		hsync_pol = 1;
	if (dt->flags & DISPLAY_FLAGS_VSYNC_HIGH)
		vsync_pol = 1;
	if (dt->flags & DISPLAY_FLAGS_DE_HIGH)
		de_pol = 1;
	if (dt->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
		clk_pol = 1;
	
	if (lcd_bpp == 24)
		lcd_data_bus_width = 0x3;
	else if (lcd_bpp == 18)
		lcd_data_bus_width = 0x2;
	else if (lcd_bpp == 8)
		lcd_data_bus_width = 0x1;
	else if (lcd_bpp == 16)
		lcd_data_bus_width = 0x0;
	else
		return -1;

	if (fb_bpp == 24 || fb_bpp == 32)
		fb_width = 0x3;
	else if (fb_bpp == 18)
		fb_width = 0x2;
	else if (fb_bpp == 8)
		fb_width = 0x1;
	else if (fb_bpp == 16)
		fb_width = 0x0;
	else
		return -1;

	/* 
     * 初始化LCD控制器的CTRL寄存器
     * [19]       :  1      : DOTCLK和DVI modes需要设置为1 
     * [17]       :  1      : 设置为1工作在DOTCLK模式
     * [15:14]    : 00      : 输入数据不交换(小端模式)默认就为0,不需设置
     * [13:12]    : 00      : CSC数据不交换(小端模式)默认就为0,不需设置
     * [11:10]    : 11		: 数据总线为24bit
     * [9:8]    根据显示屏资源文件bpp来设置:8位0x1 , 16位0x0 ,24位0x3
     * [5]        :  1      : 设置elcdif工作在主机模式
     * [1]        :  0      : 24位数据均是有效数据,默认就为0,不需设置
	 */	
	lcdif->CTRL = (0<<30) | (0<<29) | (0<<28) | (1<<19) | (1<<17) | (lcd_data_bus_width << 10) |\
	              (fb_width << 8) | (1<<5);

	/*
	* 设置ELCDIF的寄存器CTRL1
	* 根据bpp设置,bpp为24或32才设置
	* [19:16]  : 111  :表示ARGB传输格式模式下,传输24位无压缩数据,A通道不用传输)
	*/	  
	if(fb_bpp == 24 || fb_bpp == 32)
	{	  
		  lcdif->CTRL1 &= ~(0xf << 16); 
		  lcdif->CTRL1 |=  (0x7 << 16); 
	}
	else
		lcdif->CTRL1 |= (0xf << 16); 
	  
	/*
	* 设置ELCDIF的寄存器TRANSFER_COUNT寄存器
	* [31:16]  : 垂直方向上的像素个数  
	* [15:0]   : 水平方向上的像素个数
	*/
	lcdif->TRANSFER_COUNT  = (dt->vactive.typ << 16) | (dt->hactive.typ << 0);

	/*
	* 设置ELCDIF的VDCTRL0寄存器
	* [29] 0 : VSYNC输出  ,默认为0,无需设置
	* [28] 1 : 在DOTCLK模式下,设置1硬件会产生使能ENABLE输出
	* [27] 0 : VSYNC低电平有效	,根据屏幕配置文件将其设置为0
	* [26] 0 : HSYNC低电平有效 , 根据屏幕配置文件将其设置为0
	* [25] 1 : DOTCLK下降沿有效 ,根据屏幕配置文件将其设置为1
	* [24] 1 : ENABLE信号高电平有效,根据屏幕配置文件将其设置为1
	* [21] 1 : 帧同步周期单位,DOTCLK mode设置为1
	* [20] 1 : 帧同步脉冲宽度单位,DOTCLK mode设置为1
	* [17:0] :  vysnc脉冲宽度 
	*/
	  lcdif->VDCTRL0 = (1 << 28)|( vsync_pol << 27)\
					  |( hsync_pol << 26)\
					  |( clk_pol << 25)\
					  |( de_pol << 24)\
					  |(1 << 21)|(1 << 20)|( dt->vsync_len.typ << 0);
	/*
	* 设置ELCDIF的VDCTRL1寄存器
	* 设置垂直方向的总周期:上黑框tvb+垂直同步脉冲tvp+垂直有效高度yres+下黑框tvf
	*/	  
	lcdif->VDCTRL1 = dt->vback_porch.typ + dt->vsync_len.typ + dt->vactive.typ + dt->vfront_porch.typ;  

	/*
	* 设置ELCDIF的VDCTRL2寄存器
	* [18:31]  : 水平同步信号脉冲宽度
	* [17: 0]   : 水平方向总周期
	* 设置水平方向的总周期:左黑框thb+水平同步脉冲thp+水平有效高度xres+右黑框thf
	*/ 
	lcdif->VDCTRL2 = (dt->hsync_len.typ << 18) | (dt->hback_porch.typ + dt->hsync_len.typ + dt->hactive.typ + dt->hfront_porch.typ);
	/*
	* 设置ELCDIF的VDCTRL3寄存器
	* [27:16] :水平方向上的等待时钟数 =thb + thp
	* [15:0]  : 垂直方向上的等待时钟数 = tvb + tvp
	*/ 
	lcdif->VDCTRL3 = ((dt->hback_porch.typ + dt->hsync_len.typ) << 16) | (dt->vback_porch.typ + dt->vsync_len.typ);
	/*
	* 设置ELCDIF的VDCTRL4寄存器
	* [18]	   使用VSHYNC、HSYNC、DOTCLK模式此为置1
	* [17:0]  : 水平方向的宽度
	*/ 
	lcdif->VDCTRL4 = (1<<18) | (dt->hactive.typ);
	/*
	* 设置ELCDIF的CUR_BUF和NEXT_BUF寄存器
	* CUR_BUF	 :	当前显存地址
	* NEXT_BUF :	下一帧显存地址
	* 方便运算,都设置为同一个显存地址
	*/ 
	lcdif->CUR_BUF  =  fb_phy;
	lcdif->NEXT_BUF =  fb_phy;
	return 0;
}


/* from pxafb.c */
static inline unsigned int chan_to_field(unsigned int chan,
					 struct fb_bitfield *bf)
{
	chan &= 0xffff;
	chan >>= 16 - bf->length;
	return chan << bf->offset;
}

static int mylcd_setcolreg(unsigned regno,
			       unsigned red, unsigned green, unsigned blue,
			       unsigned transp, struct fb_info *info)
{
	unsigned int val;

	/* dprintk("setcol: regno=%d, rgb=%d,%d,%d\n",
		   regno, red, green, blue); */

	switch (info->fix.visual) {
	case FB_VISUAL_TRUECOLOR:
		/* true-colour, use pseudo-palette */

		if (regno < 16) {
			u32 *pal = info->pseudo_palette;
			val  = chan_to_field(red,   &info->var.red);
			val |= chan_to_field(green, &info->var.green);
			val |= chan_to_field(blue,  &info->var.blue);
			pal[regno] = val;
		}
		break;

	default:
		return 1;	/* unknown type */
	}

	return 0;
}

static struct fb_ops myfb_ops = {
	.owner		= THIS_MODULE,
	.fb_setcolreg	= mylcd_setcolreg,
	.fb_fillrect	= cfb_fillrect,
	.fb_copyarea	= cfb_copyarea,
	.fb_imageblit	= cfb_imageblit,
};

static int mylcd_probe(struct platform_device *pdev)
{
	struct device_node *display_np;
	dma_addr_t phy_addr;
	int ret;
	int width;
	int bits_per_pixel;
	struct display_timings *timings = NULL;
	struct display_timing *dt = NULL;
	struct imx6ull_lcdif *lcdif;
	struct resource *res;

	display_np = of_parse_phandle(pdev->dev.of_node, "display", 0);

	/* get common info */
	ret = of_property_read_u32(display_np, "bus-width", &width);
	ret = of_property_read_u32(display_np, "bits-per-pixel",
				   &bits_per_pixel);

    /* get timming */
	timings = of_get_display_timings(display_np);
	dt = timings->timings[timings->native_mode];

	/* get gpio from device tree */
	bl_gpio = gpiod_get(&pdev->dev, "backlight", 0);

	/* config bl_gpio as output */
	gpiod_direction_output(bl_gpio, 1);

	/* set val: gpiod_set_value(bl_gpio, status); */

	/* get clk from device tree */
	clk_pix = devm_clk_get(&pdev->dev, "pix");
	clk_axi = devm_clk_get(&pdev->dev, "axi");

	/* set clk rate */
	clk_set_rate(clk_pix, dt->pixelclock.typ);

	/* enable clk */
	clk_prepare_enable(clk_pix);
	clk_prepare_enable(clk_axi);
	
	/* 1.1 分配fb_info */
	myfb_info = framebuffer_alloc(0, NULL);

	/* 1.2 设置fb_info */
	/* a. var : LCD分辨率、颜色格式 */
	myfb_info->var.xres_virtual = myfb_info->var.xres = dt->hactive.typ;
	myfb_info->var.yres_virtual = myfb_info->var.yres = dt->vactive.typ;
	
	myfb_info->var.bits_per_pixel = 16;  /* rgb565 */
	myfb_info->var.red.offset = 11;
	myfb_info->var.red.length = 5;

	myfb_info->var.green.offset = 5;
	myfb_info->var.green.length = 6;

	myfb_info->var.blue.offset = 0;
	myfb_info->var.blue.length = 5;
	

	/* b. fix */
	strcpy(myfb_info->fix.id, "100ask_lcd");
	myfb_info->fix.smem_len = myfb_info->var.xres * myfb_info->var.yres * myfb_info->var.bits_per_pixel / 8;
	if (myfb_info->var.bits_per_pixel == 24)
		myfb_info->fix.smem_len = myfb_info->var.xres * myfb_info->var.yres * 4;

	/* fb的虚拟地址 */
	myfb_info->screen_base = dma_alloc_wc(NULL, myfb_info->fix.smem_len, &phy_addr,
					 GFP_KERNEL);
	myfb_info->fix.smem_start = phy_addr;  /* fb的物理地址 */
	
	myfb_info->fix.type = FB_TYPE_PACKED_PIXELS;
	myfb_info->fix.visual = FB_VISUAL_TRUECOLOR;

	myfb_info->fix.line_length = myfb_info->var.xres * myfb_info->var.bits_per_pixel / 8;
	if (myfb_info->var.bits_per_pixel == 24)
		myfb_info->fix.line_length = myfb_info->var.xres * 4;
	

	/* c. fbops */
	myfb_info->fbops = &myfb_ops;
	myfb_info->pseudo_palette = pseudo_palette;

	/* 1.3 注册fb_info */
	register_framebuffer(myfb_info);

	/* 1.4 硬件操作 */
	//lcdif = ioremap(0x021C8000, sizeof(*lcdif));
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	lcdif = devm_ioremap_resource(&pdev->dev, res);
	lcd_controller_init(lcdif, dt, bits_per_pixel, 16, phy_addr);
	lcd_controller_enable(lcdif);
	gpiod_set_value(bl_gpio, 1); 

	return 0;
}

static int mylcd_remove(struct platform_device *pdev)
{
	/* 反过来操作 */
	/* 2.1 反注册fb_info */
	unregister_framebuffer(myfb_info);

	/* 2.2 释放fb_info */
	framebuffer_release(myfb_info);
	
	iounmap(mylcd_regs);

	return 0;
}

static const struct of_device_id mylcd_of_match[] = {
	{ .compatible = "100ask,lcd_drv", },
	{ },
};
MODULE_DEVICE_TABLE(of, simplefb_of_match);

static struct platform_driver mylcd_driver = {
	.driver = {
		.name = "mylcd",
		.of_match_table = mylcd_of_match,
	},
	.probe = mylcd_probe,
	.remove = mylcd_remove,
};

static int __init lcd_drv_init(void)
{
	int ret;

	ret = platform_driver_register(&mylcd_driver);
	if (ret)
		return ret;

	return 0;
}

/* 2. 出口 */
static void __exit lcd_drv_exit(void)
{
	platform_driver_unregister(&mylcd_driver);
}

module_init(lcd_drv_init);
module_exit(lcd_drv_exit);
MODULE_LICENSE("GPL");

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

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

相关文章

E. Nastya and Potions

Problem - E - Codeforces 思路&#xff1a;想到用图论前驱图了&#xff0c;但是因为考虑可能有环的存在&#xff0c;但是其实题干中说明了不能通过一种或几种混合得到自己&#xff0c;所以就保证了不存在环&#xff0c;那就能用拓扑结构的性质做&#xff0c;用记忆化搜索就可以…

DHCP的interface(接口),global(全局)配置以及DHCP relay(中继),DHCP snooping,DHCP option

目录 1.DHCP的接口&#xff08;interface&#xff09;配置 2.DHCP的全局&#xff08;global&#xff09;配置 3.dhcp relay 4.dhcp snooping 5.option 这里有一个简单的拓扑图 交换机配置命令如下 The device is running!<Huawei> <Huawei>sys Enter system …

go语言基本操作---五

error接口的使用 Go语言引入了一个关于错误处理的标准模式&#xff0c;即error接口&#xff0c;它是Go语言内建的接口类型 type error interface {Error() string }package mainimport ("errors""fmt" )type Student struct {name stringid int }func …

【 XXL-JOB】 XXL-JOB任务分片

文章目录 前言xxl-job 分片广播任务的详细教程创建任务编写任务代码分片参数设置执行任务查看任务执行结果示例1示例2 总结 前言 xxl-job 是一个分布式任务调度平台&#xff0c;支持定时任务和分片任务。其中&#xff0c;分片任务可以将一个大任务拆分成多个小任务&#xff0c…

用vagrant快速创建linux虚拟机

参考B站&#xff1a;https://www.bilibili.com/video/BV1np4y1C7Yf 1、下载VirtualBox 2、下载vagrant 3、vagrant官网下载.box文件 官网&#xff1a;https://app.vagrantup.com/boxes/search 例如要下载这个centos/7 点进去&#xff0c;点击下载 下载后放到一个指定目录…

qt作业day2

//widget.cpp#include "widget.h" #include "ui_widget.h"void Widget::usr_login() {if("admin" this->edit_acc->text()){if("123456" this->edit_psd->text()){speech->say("登录成功");emit jump_sig1…

latex修改公式的默认编号

文章目录 问题描述省流出错演示没有载入amsmath包载入amsmath包 总结 问题描述 有时想自己定义公式的编号&#xff0c;不想用默认的编号(1) (2)…&#xff0c;我们应该怎么做呢&#xff1f; 只需看本文一分钟就能解决。 省流 开头载入amsmath包&#xff0c;然后在公式后面加…

【C4bp】

--- --- # 2% of all animal proteins contain FN3 repeat # Humans in protein body of 1/3 constitutes Collagen

最小可用产品MVP,投石问路

最小可用产品MVP【安志强趣讲281期】 MVP(Minimum Viable Product) 趣讲大白话&#xff1a;投是问路 **************************** 最小可用产品MVP可以是如下形式&#xff1a; 1、简陋产品 2、贵宾式MVP&#xff1a;为少量客户全力周到服务&#xff0c;获得市场反馈 3、静态页…

数字 IC 设计职位经典笔/面试题(四)

共100道经典笔试、面试题目&#xff08;文末可全领&#xff09; 画出 CMOS 电路的晶体管级电路图,实现 YA*BC(DE).&#xff1f; 画出 YABC 的 CMOS 电路图&#xff0c;画出 YABCD 的 CMOS 电路图。 利用与非门和或非门实现 YABC(DE)((AB’)(CD)’(CE)’)’ 三个两输入与非门&a…

2023高教社杯数学建模A题思路分析 - 定日镜场的优化设计

# 1 赛题 A 题 定日镜场的优化设计 构建以新能源为主体的新型电力系统&#xff0c; 是我国实现“碳达峰”“碳中和”目标的一项重要 措施。塔式太阳能光热发电是一种低碳环保的新型清洁能源技术[1]。 定日镜是塔式太阳能光热发电站(以下简称塔式电站)收集太阳能的基本组件&…

物理层-数据链路层-网络层-传输层-会话层-表示层-应用层

Go网络编程 网络协议 从应用的角度出发&#xff0c;协议可理解为“规则”&#xff0c;是数据传输和数据的解释的规则。假设&#xff0c;A、B双方欲传输文件。规定&#xff1a; 第一次&#xff0c;传输文件名&#xff0c;接收方接收到文件名&#xff0c;应答OK给传输方&…

DC/DC开关电源学习笔记(四)开关电源电路主要器件及技术动态

(四)开关电源电路主要器件及技术动态 1.半导体器件2.变压器3.电容器4.功率二极管5.其他常用元件5.1 电阻5.2 电容5.3 电感5.4 变压器5.5 二极管5.6 整流桥5.7 稳压管5.8 绝缘栅-双极性晶体管1.半导体器件 功率半导体器件仍然是电力电子技术发展的龙头, 电力电子技术的进步必…

【数据库事务日志碎片原理分析与方案】-分析篇

前言:说都数据库的事务日志&#xff0c;可以说我们是再熟悉不过的了。一般而言&#xff0c;我们都没有必 要去关心事务日志中的虚拟日志文件的个数。这里提到的“虚拟日志文件”的概念&#xff0c;我们 后面会进行专门的讲述。很多的时候&#xff0c;我们在建立数据库的时候&am…

Android开发重大新闻,安卓手机将不能无视风险安装APP

工信部发文要求所有的APP必须在2024年前完成入网备案。否则它将不再支持网络接入&#xff0c;简单来说这一个决定可以说是封杀了所有的盗版色情擦边APP&#xff1b;之后这些软件将无法再联网使用这么说安卓也终于迎来了绿色上网自由。 用户的利与弊 备案要求会让手机上的“流氓…

大数据课程L2——网站流量项目的算法分析数据处理

文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 了解网站流量项目的算法分析; ⚪ 了解网站流量项目的数据处理; 一、项目的算法分析 1. 概述 网站流量统计是改进网站服务的重要手段之一,通过获取用户在网站的行为,可以分析出哪些内…

【办公类-19-03】办公中的思考——Python批量制作word单元格照片和文字(小照片系列)

背景需求&#xff1a; 工会老师求助&#xff1a;如何在word里面插入4*8的框 我一听&#xff0c;这又是要手动反复黏贴“文本框”“照片”“文字”的节奏哦 我问&#xff1a;你要做几个人&#xff1f;超过20个&#xff0c;我写个程序批量插图 工会老师&#xff1a;大约十几个人…

2023最新pytorch安装教程,简单易懂,面向初学者(Anaconda+GPU)

一、前言 目前是2023.1.27,鉴于本人安装过程中踩得坑&#xff0c;安装之前我先给即将安装pytorch的各位提个醒&#xff0c;有以下几点需要注意 1.判断自己电脑是否有GPU 注意这点很重要&#xff0c;本教程面向有NVIDA显卡的电脑&#xff0c;如果你的电脑没有GPU或者使用AMD显…

2020年09月 C/C++(二级)真题解析#中国电子学会#全国青少年软件编程等级考试

C/C编程&#xff08;1~8级&#xff09;全部真题・点这里 第1题&#xff1a;循环数 若一个n位的数字串满足下述条件&#xff0c;则称其是循环数&#xff08;cyclic&#xff09;&#xff1a;将这个数字串视为整数&#xff08;可能带有前导0&#xff09;&#xff0c;并用任意一个 …

Simulink|用于光伏系统最大功率点跟踪(MPPT)的极值寻道控制(ESC)【采用极值寻道控制算法求解非线性函数的最大/最小点】

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…