初学51单片机1602液晶时序图实例分析

news2024/12/24 21:40:49

     上篇博文笔者分享了关于液晶1602基本的工作流程,本篇主要是通过逻辑分析仪来看一下程序使能的电平时序,是否符合产品文档给出 的时序逻辑。 先看一下1602的时序图

认识下时序图中各个标识的含义:

  • Tc信号周期(E Cycle Time)指的是使能引脚E从本次上升沿到下次上升沿的最短时间是400ns,而51单片机因为速度较慢,本案用的晶振是11.0592M因此1个机器周期的时间是1us多,而一条C语言指令肯定是1个或者多个机器周期,所有这个条件天然满足。即 E = 1;这个指令就满足要求了,除非是高速单片机E指令后需要加一点延时时间。
  • tpw脉冲宽度(E Pulse Width)指的是使能周期E高电平的持续时间最短是150ns,同样由于单片机比较慢这个条件是满足的,本案高脉冲的实现方法简单粗暴:
    	LCD1602_E = 0;    //高脉冲
    	LCD1602_E = 1;    //高脉冲
    	LCD1602_E = 0;    //高脉冲

    这个高脉冲时间刚好是1个机器周期即语句LCD1602_E = 1执行时间1us多一点。

  • tR,tF上升沿下/降沿时间(E Rise/fall time)指的是使能引脚E的上升沿时间和下降沿时间,不能超过25ns,这个时间对于51单片机来说也是比较宽裕的,51单片机引脚的上升沿和下降沿时间大概是10~15ns之间。
  • tsp1地址建立时间(Address Setup Time)指的是RS和R/W引脚使能后至少保持30ns,使能引脚E才可以变成高电平,本案的实现方案是:
  • 一般都会在在其后加1句总线操作语句因此这个条件也是天然满足的,即使你不加这句也是天然满足的,因为LCD1602_RW=0要保持1个机器周期即1us。

  • tHD1地址保持时间(address Hold Time)指的是使能引脚E变成低电平后,至少保持10ns之后,RS和R/W才能进行变化,这个条件也是天然满足的。E使能语句本身就要持续1个机器周期。

  • tD(读操作)数据建立时间(Data Output Delay Time)指的是使能引脚E变成高电平后,最多100ns,1602就把数据送出来了,就可以正常去读状态或者数据了

  • tHD2读操作数据保持时间(data hold time)指的是读操作过程中,使能引脚E变成低电平后,至少保持20ns,DB数据总线才可以进行变化,这个条件也是天然满足的。本案读操作只有一个就是读状态:

    void LcdWaitReady()
    {
       unsigned char sta;
    	 
    	
    	LCD1602_DB = 0xFF;
    	LCD1602_RS = 0;
    	LCD1602_RW = 1;
    	do{
    		
    		LCD1602_E = 1;
    		 sta = LCD1602_DB; //读取状态字
     	  LCD1602_E = 0;
    	}while(sta & 0x80);//bit7等于1表示液晶正忙,重复检测直到等于0为止
    
    }

  • tsp2(写操作)数据建立时间(data setup time)指的是DB数据总线准备好后,至少保持40ns,使能引脚E才可以从低到高进行使能变化,这个条件也是天然满足的。

  • tHD2(写操作)数据保持时间(data hold Time) 指的是写操作过程中,要引脚E变成低电平后至少保持10ns,DB数据总线才可以变化。这个条件也是天然满足的本案写指令和数据的过程:

    void LcdWriteDat(unsigned char dat)
    {
      LcdWaitReady();
    	LCD1602_RS = 1;
    	LCD1602_RW = 0;
    	LCD1602_DB = dat;
    //忙状态的时候LCD1602_E就被拉成低电平因此这边无需再加1句了
        LCD1602_E = 1; //高脉冲
    	LCD1602_E = 0; //高脉冲
    }
    
    void LcdWriteCmd(unsigned char cmd)
    {
      LcdWaitReady();
    	LCD1602_RS = 0;
    	LCD1602_RW = 0;
    	LCD1602_DB = cmd;
      //
    	LCD1602_E = 1;    //高脉冲
    	LCD1602_E = 0;    //高脉冲
    
    	
    }

    从结论上来看对于51单片机来说1602LCD液晶很多细节上是可以忽视的它是天然满足,只有在高速单片机上可能要多注意一点,看来速度太快也不都是好事。

然后总结下上篇博文给出一些小结论然后看一下是否需要补充的:

1:在液晶E端是低电平的情况下DB0-DB7都是高电平

2:51单片机IO口默认是高电平,由于本案接了下拉电阻,E端电压最终会被拉成低电平。

3:写指令和写数据是需要高脉冲使能的。

4:液晶更改功能的时候需要先关闭液晶即写指令08H

看下本案用到的程序其实和上篇博文没有什么太大的区别,主要是这篇为了防止产生歧义把整个初始化过程都写出来了,按照规格文件:

上代码:

# include<reg52.h>

# define LCD1602_DB P0
sbit LCD1602_RS = P1^0;
sbit LCD1602_RW = P1^1;
sbit LCD1602_E = P1^5;

void InitLcd1602();
void LcdShowStr(unsigned char x ,unsigned char y, unsigned char* str);

void main()
{
	 unsigned char str[] = "Firewood 2024";
	 unsigned int i =1500;
	 unsigned int j = 500;
	  while(i--);
	LCD1602_RS = 0;
	LCD1602_RW = 0;
	LCD1602_DB = 0x38;
	LCD1602_E = 0;    //高脉冲
	LCD1602_E = 1;    //高脉冲
	LCD1602_E = 0;    //高脉冲
	 while(j--);
	LCD1602_RS = 0;
	LCD1602_RW = 0;
	LCD1602_DB = 0x38;
	LCD1602_E = 0; 
	LCD1602_E = 1;    //高脉冲
	LCD1602_E = 0;    //高脉冲
	j = 500;
	while(j--);
	LCD1602_RS = 0;
	LCD1602_RW = 0;
	LCD1602_DB = 0x38;
	LCD1602_E = 0; 
	LCD1602_E = 1;    //高脉冲
	LCD1602_E = 0;    //高脉冲

	
 
	 InitLcd1602();
	 LcdShowStr(2,0,str);
	 LcdShowStr(0,1,"I love You BeBy");
	 while(1);

}
/*等待液晶准备好 */
void LcdWaitReady()
{
   unsigned char sta;
	 
	
	LCD1602_DB = 0xFF;
	LCD1602_RS = 0;
	LCD1602_RW = 1;
	do{
		
		LCD1602_E = 1;
		 sta = LCD1602_DB; //读取状态字
 	  LCD1602_E = 0;
	}while(sta & 0x80);//bit7等于1表示液晶正忙,重复检测直到等于0为止

}
/*向LCD1602液晶写入一字节命令,cmd为待写入的命令值 */
void LcdWriteCmd(unsigned char cmd)
{
  LcdWaitReady();
	LCD1602_RS = 0;
	LCD1602_RW = 0;
	LCD1602_DB = cmd;
//	LCD1602_E = 0;
	LCD1602_E = 1;    //高脉冲
	LCD1602_E = 0;    //高脉冲

	
}
/*向LCD1602液晶写入一字节数据,dat为待写入数据   */
void LcdWriteDat(unsigned char dat)
{
  LcdWaitReady();
	LCD1602_RS = 1;
	LCD1602_RW = 0;
	LCD1602_DB = dat;
	//LCD1602_E = 0;
	LCD1602_E = 1;
	LCD1602_E = 0;
}
/* 设置显示RAM起始地址,亦即光标位置,(x,y)为对应屏幕上的字符坐标*/
void LcdSetCursor(unsigned char x,unsigned char y)
{
  unsigned char addr;
	if(y == 0)
		addr = 0x00+x;
	else
		addr = 0x40+x;
	LcdWriteCmd(addr|0x80);//0x80 = 1000 0000

}
/*在液晶上显示字符串,(x,y)为对应屏幕上的起始坐标,str为字符串指针 */
void LcdShowStr(unsigned char x,unsigned char y,unsigned char* str)
{
  LcdSetCursor(x,y); //设置其实地址
	while(*str != '\0')
	 {
	   LcdWriteDat(*str++);
	 } 

}

/*初始化1602液晶  */
void InitLcd1602()
{
	
 LcdWriteCmd(0x38);//0x38 = 0011 1000 16*2显示,5*7点阵,8位数据接口

 LcdWriteCmd(0x08);//显示关闭
 LcdWriteCmd(0x01);//清屏

 LcdWriteCmd(0x06);//0x04 = 0000 0100 文字不动,地址自动加1
 LcdWriteCmd(0x0C);//显示器开 ,光标关闭
 		 
}

结果和上篇博文是一样的 


然后先看下逻辑分析仪的输出图

      共11个通道,我们要观察的是这些电平信号,是否是按照程序执行的,并且是符合之前文档给出的时序要求的。这个图被压缩了很多,看不同清楚,这篇博文主要就是一点一点的看完所有的时序信号。

由上图知:前4个通道分别是液晶使能端口E,状态字端口bit7即是P0.7/DB7端口,RS数据指令选择端口,R/W读写选择端口.后续7个就是数据端口即P0端口的低7位。

  • 由上图可以看到2个很短的高脉冲信号,其实是3个第三个和后面的电平信号连在一起,在图上不易看出,而且三个脉冲信号之间的时间间隔是5ms左右,这是符合我们初始化过程的
  • 当然最前面的15ms以及一开始上电电平被下拉电阻拉低的过程没显示出来,笔者采用的是上升沿触发但是不影响分析这个时序图。由于液晶E端口与单片机P1.5端口相连并且接了下拉电阻,因此电平信号最终会被拉成低电平,从上述图看出它确实是低电平信号突然产生了个高脉冲 信号。我们把图放大仔细看一下
  • 这个图就是第一个高脉冲的时序图,我们挨个看一下这个时序图是否符合我们的要求,首先这个高脉冲时间是1us左右,右上角图片放大看一下。这个图对应程序哪个部分呢?
  • 就是上图这个过程,可以看到高脉冲使能语句是LCD1602_E = 1;它的执行时间是1个机器周期鉴于本案用的晶振1个机器周期的时间就是1us符合时序图的结果。
  • 由上图可知在使能高脉冲前就已经使能了RS,RW,以及数据端口。从程序结构来说RS端口是最早发送电平信号,接着是R/W端口,最后是数据端口。
  • 从时序图我们可以看出确实是这样的,并且我们发现即使程序上没有进行“忙”判断,在时序图上bit7确实在总线写入的时候拉低了;看下图RS语句在时序延时了1us(仅指语句执行时间),RW在时序上是延时2us(按理是只延时1us的)才进行总线赋值的LCD1602 = 0x38;而且是在2us后bit7从高电平变成低电平总线才开始赋值。事实上RW该语句是只使能了1us,所谓2us的产生是由于总线在等待BIt7从高电平变成低电平,总线电平的信号才开始发生变化。这是符合文档给出只有在bit7为低电平的时候才允许进行读写使能
  • 上述说法是不对的,“忙”判断结束后bit7和“忙”状态检测就没有关系了,纯粹是因为赋值运算把bit7拉低了,而且这个时间恰好发生在赋值语句执行一半的时候发生,(整个语句要2个机器周期即2us)且bit7这个端口既是忙状态检测也是数据输入输出端口这个要分开,当然这个前端初始化也没有“忙”判断,可能是15ms的延时时间使得无需再忙判断。“忙”判断读出的是液晶给出的电平信息,而这个bit7信号是我们写入程序的电平信号。要区分电平信号的来源。
  • 看一下数据线的输出是否是符合要求的,时序图可知它写入的是X011 1000,而最高位x其实是Bit7的电平,它是低电平0,因此写入的就是0011 1000=0x38;是符合程序以及文档初始化要求的。
  • 这是一个写指令的过程,写执行过程中我们要关注的时序要求是如下
  • tsp1地址建立时间(Address Setup Time)指的是RS和R/W引脚使能后至少保持30ns,使能引脚E才可以变成高电平,其它的时序要求要不不适用,要不是天然满足的,其实从时序图上就可以看出来RS和R/W引脚的持续时间比高脉冲的时间还要长。

    第一个高脉冲分析结束,看下第二个高脉冲:

可以看到第二个高脉冲其他通道没有电平变化,一直保持着之前的电平信号。

  • 使能端E只有一个高脉冲,时间是1us。
  • bit7一直是低电平
  • RS,R/W端口都是低电平。即处在写指令状态
  • 数据端口依然写入0x38,中键那个0的白线不是电平信号线是测试时间线下面那根橙的(要放大看)才是电平线。
  • 它是符合初始化这个过程

然后看一下前端初始化的最后一个高脉冲:


  • 从结果上看它和第二个高脉冲的电平信号相同它是前端初始化的最后一个部分
  • ,可以看出在这个高脉冲后一段时间电平信号发生了很多变化,其实就是1602LCD液晶真正的初始化过程。

在分析后续的时序先看一下接下来的过程可以看到在完成前端初始化,程序正式进入初始化。从程序的执行顺序来说是要执行

LcdWriteCMd(0x38);语句因此进入相关函数

第1句就是“忙”判断函数LcdWaitReady();因此进入相关函数

然后看时序图:

  • 我们接下写的指令,有两个关键的指示电平信号。1是总线写入时的高脉冲,2是“忙”判断的bit7电平信号拉低,
  • 从上图可以看到时序在第一次“忙”判断的时候它的高电平时间是3us即3个机器周期,其实就是如下图红框两句程序语句导致的,E端赋值是1个机器周期,总线读状态是2个机器周期,从时序图看出在执行sta = LCD1602_DB语句的时候bit7就引进被拉成低电平了,但是在while()函数判断的时候并没有通过,又再次执行了do--while()函数里的内容,这次在LCD1602_E = 1:赋值的时候bit7立马就被拉成低电平了,这次才通过了“忙”判断,从这个现象来说:赋值运算只能读取前面语句使能的端口信号,在本句内发生的电平信号变化,它无法即刻读取。这才造成了又进行了一次“忙”判断。

 “忙”判断后进入写指令的函数,我们看下写指令的过程,写入0x38,然后接个高脉冲使能看下图高脉冲使能前:

  • E端是低电平
  • BIt7是低电平
  • RS、R/W都是低电平说明是写指令
  • 数据端口提前写入数据是x011 1000,x是最高位bit7因此写入的指令是0011 1000= 0x38;
  • 然后一个高脉冲使能指令写入成功,即液晶接收0x38指令


接着进行下一次写指令LCDWriteCmd(0x08);看下时序图

从结果上看在下一个高脉冲前它发生了三次忙判断,只有在最后一次“忙”判断才成功。前面两次判断都是高电平,而且这次没有发生上个“忙”判断节点发生的现象。即在读总线状态的时候bit7才拉低。通过下图的时序图看下写入的指令是什么:

  • E端是低电平,为高脉冲准备
  • BIt7是低电平。这个低电平由总线写入语句造成。
  • RS、R/W都是低电平说明是写指令
  • 数据端口提前写入数据是x000 1000,x是最高位bit7因此写入的指令是0000 1000= 0x08;
  • 然后一个高脉冲使能指令写入成功,即液晶接收0x08指令;
  • 而且我们看到PO端口这次是P0.3/DB3端口在写指令的时候即使写入前和写入后的电平都是高电平,它依然会先拉低再很快的拉高,如果放大看它其实有一个80ns的低电平保持时间。

       我们已经看了几个时序图了可以得出一些结论。

  • “忙”判断 后E端在高脉冲来临前一直是低电平的(其实这个不强制要求的只是我们这个程序现象是这个,关于这个问题可以看下我上篇博文的说法)
  • “忙”判断后bit7它就恢复高电平了。
  • “忙”判断结束后,bit7这个端口的电平信号就和“忙”判断没关系了,它的后续电平信号就由写入的指令或者地址决定,后续我们可以看到在写地址的时候bit7是高电平。

 接着下一个指令

 LcdWriteCmd(0x01);//清屏

这是个清屏指令,看时序图:

这次进行了两次“忙”判断才成功,接着看下输入的指令是什么?

  • E端是低电平,为高脉冲准备
  • BIt7是低电平。这个低电平由总线写入语句造成。
  • RS、R/W都是低电平说明是写指令
  • 数据端口提前写入数据是x000 0001,x是最高位bit7因此写入的指令是0000 0000= 0x01;
  • 然后一个高脉冲使能指令写入成功,即液晶接收0x01指令;
  • 这里要看一下液晶是怎么清屏它的具体表现是什么?

这个清屏效果大概持续了1.38ms,在这个过程中E端是周期7.6us的方波,bit7是高电平,RS选择端是低电平,RW选择端是高电平。


接着下一个指令

LcdWriteCmd(0x06);//文字不动,地址自动加1

这个式初始化过程中主要的使能语句,前面的博文笔者说到,如果不照按产品规格书的写法即在使能这个指令前关闭液晶,这句指令就不会起作用。

看下时序图:

由标志的电平信号我们找到了写指令的信号电平的位置,看下写入的指令是什么是否是0x06,

  • E端是低电平,为高脉冲准备
  • BIt7是低电平。这个低电平由总线写入语句造成。
  • RS、R/W都是低电平说明是写指令
  • 数据端口提前写入数据是x000 0011,x是最高位bit7因此写入的指令是0000 0011= 0x06;
  • 然后一个高脉冲使能指令写入成功,即液晶接收0x06指令;确定是0x06位置没有错,也确定了前面的波形是清屏功能造成的。

最后一个初始化指令

LcdWriteCmd(0x0C);//显示器开 ,光标关闭

看下时序图:这次进行了三次“忙”判断看下写入的指令。

  • E端是低电平,为高脉冲准备
  • BIt7是低电平。这个低电平由总线写入语句造成。
  • RS、R/W都是低电平说明是写指令
  • 数据端口提前写入数据是x000 1100,x是最高位bit7因此写入的指令是0000 1100=0x0C;
  • 至此初始化完成。

初始化完成后我们就要开始写入字符信息了,进入该函数。

void LcdShowStr(unsigned char x,unsigned char y,unsigned char* str)
{
  LcdSetCursor(x,y); //设置其实地址
	while(*str != '\0')
	 {
	   LcdWriteDat(*str++);
	 } 

}

从这个函数又发现要进入LcdSetCursor(x,y)函数

void LcdSetCursor(unsigned char x,unsigned char y)
{
  unsigned char addr;
	if(y == 0)
		addr = 0x00+x;
	else
		addr = 0x40+x;
	LcdWriteCmd(addr|0x80);//0x80 = 1000 0000

}

然后发现该函数又要进入我们熟悉的写指令过程,不过这次是写地址了。理下程序

 LcdShowStr(2,0,str);

该句写入的地址是:0x00+2=0x02;0x02+0x80=0x82,这个“或”运算其实就是加法因为不会发生进位。也就是说要写入一个0x82的地址以写指令的方式好的看下时序图。

找到标志的电平信号图像,然后看下写入的是否符合我们之前程序要求的,

  • E端是低电平,为高脉冲准备
  • BIt7是高电平。这个高电平由总线写入语句造成。可以看到写地址和写指令区分开了用这个高低电平
  • RS、R/W都是低电平说明是写指令
  • 数据端口提前写入数据是x000 0010,x是最高位bit7因此写入的指令是1000 0010=0x82;
  • 确实是写入了1个0x82的地址。然后高脉冲使能

在写入这个地址后就要写入数据了看下这个数据写入函数

void LcdWriteDat(unsigned char dat)
{
  LcdWaitReady();
	LCD1602_RS = 1;
	LCD1602_RW = 0;
	LCD1602_DB = dat;
	//LCD1602_E = 0;
	LCD1602_E = 1;
	LCD1602_E = 0;

和写指令区别是RS现在是高电平了,从函数看我们即将写入的是

F这个字符的ASCII码是070 =0x46看时序图

找到关键电平信号点,只进行了1次忙判断,看一下写入的代码是什么?

  • E端是低电平,为高脉冲准备
  • BIt7是低电平。这个低电平由总线写入语句造成。
  • RS是1 ,R/W是0说明是写数据
  • 数据端口提前写入数据是x100 0110,x是最高位bit7因此写入的指令是0100 0110=0x46;
  • 确实是写入了1个0x46的数据。然后高脉冲使能。
  • 后续的写入过程和这个类似就不再赘述

至此本案结束,通过上述的时序图,对1602LCD液晶数据传输应该有些理解了。

  • 可以有一点总结:除了前端初始化过程,一般来说任何操作前都要进行“忙”判断。
  • bit在完成“忙”判断后这个端口的功能后只是用来做为输入输出端口。
  • 作为51单片机来说液晶传输的时序要求是天然满足的。
  • 在写指令、数据的时候最后都需要高脉冲使能。

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

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

相关文章

WEB应用(十六)---反序列化

反序列化的概念 在面向对象编程语言中&#xff0c;就是将对象转化为字节流&#xff0c;这一步是序列化&#xff0c;字节流中包括这个对象的数据和信息&#xff0c;便于传输和存储&#xff0c;是可以在网络中传输的。需要时&#xff0c;通过反序列化从字节流中恢复对象。 类似于…

State-Threads初识

1.项目简介 协程&#xff08;coroutine&#xff09;不是进程或线程&#xff0c;其执行过程更类似于子例程&#xff0c;或者说不带返回值的函数调用。 一个程序可以包含多个协程&#xff0c;可以对比与一个进程包含多个线程。 我们知道多个线程相对独立&#xff0c;有自己的上下…

Dopple Labs 选择 Zilliz Cloud 作为安全高效的向量数据库

一直以来&#xff0c;我都十分赞同采用通用的标准来评估机器学习领域的技术。向量数据库领域也是如此。Zilliz 发布的性能测试对我有着很大的帮助。 ——Sam Butler Dopple.AI 机器学习总监 01.Dopple AI简介 Dopple Labs Inc. 是 Dopple.AI 的原厂&#xff0c;通过提供创新…

我是如何选择适合我的电脑的

当前有什么可以供自己选择 将从便携、性能、价格、游戏、视频剪辑、高性能、接口、屏幕、使用感受等方面考虑(超出普通人范围电脑不考虑) 非苹果&#xff1a; 轻薄笔记本&#xff1a;最便捷办公笔记本&#xff1a;游戏笔记本台式电脑台式游戏电脑台式高性能电脑 苹果&#…

ROM修改进阶教程------修改rom 内置app的几种方法与注意事项 以及运行库中arm64 .rmeabi-v7a与armeabi 区别

在定制rom的过程中。内置app是很多rom爱好者必须的技能之一。但对于初学者来说。会遇到内置的app无效果或者出现运行有bug的情况。内置app需要根据安卓版本的不同略有变化 .在高安卓版本中还需要内置apk的运行库。 通过今天的博文了解; 1-----内置APP的几种方式步骤 2-----视…

OpenHarmony南向开发 SA服务SELinux权限配置一站式傻瓜式教程

Selinux权限配置 OpenHarmony中SELinux使用详解 目录 SELinux简介SELinux概念SELinux模式OH中SELinux使用详解新增SA服务如何配置SELinux权限SELinux简介 SELinux是Security Enhanced Linux 的缩写,也就是安全强化的 Linux,旨在增强传统Linux操作系统的安全性,解决传统Li…

关于使用webflux开发思考

1、目前终于看到有系统使用spring的webflux进行系统开发&#xff0c;主要原因是比如gpt、千问的大模型数据返回都支持流式方式返回&#xff0c;比如和用户对话&#xff0c;可以流式的把数据给用户展示&#xff0c;不用一次性把数据展示到页面上。 webflux还有一个能力就是&…

MongoDB笔记1——MongoDB简介

MongoDB 什么是MongoDB 2007年10月&#xff0c;MongoDB由10gen团队所开发&#xff0c;2009年2月首度推出。 基于分布式文件存储的数据库由C语言编写。旨在为WEB应用提供可拓展的高性能数据存储解决方案。 MongoDB是一个介于关系数据库和非关系数据库&#xff08;NoSQL&…

东芝新小黑移动硬盘数据被格式化如何恢复(2024年8月版)

在数字化时代&#xff0c;数据已成为我们生活和工作中不可或缺的一部分。东芝新小黑移动硬盘&#xff0c;以其便携性和大容量&#xff0c;成为许多用户存储重要数据的首选。然而&#xff0c;当这些宝贵的数据因意外格式化而面临丢失的风险时&#xff0c;我们该如何应对&#xf…

Visionpro二次开发学习笔记7-使用CogToolDisplay控件

CogToolDisplay控件可显示与视觉工具记录相关的图像&#xff0c;图形和其他状态信息。它使用CogRecord和ICogTool接口将图像和图形连接到CogDisplay。 图片清单 控件的CogComboBox列出当前记录及其子记录中的图像和图形。您可以单击列表并选择要显示的图像或图形。如果记录层…

基于springboot3实现单点登录(二):认证服务端搭建

前言 上文我们介绍了oauth2.0的相关理论和流程&#xff0c;本文我们继续实现。 Oauth2协议中有个很重要的概念&#xff0c;叫做”端点“&#xff0c; 以下整理了一些常用的端点及其参考访问路径及使用场景的信息&#xff0c;供参考。 这些端点在oauth2.0协议的整个生命周期…

白嫖不是梦,三分钟搞定一台服务器

在知乎上浏览时&#xff0c;我偶然发现了一个引人入胜的话题。这个话题附带了一张Excel表格的截图&#xff0c;表格设计得非常巧妙。它允许用户输入包括日薪、工作时间、通勤时间、休息时间以及学历等在内的多个变量。通过这些输入&#xff0c;表格能够计算出一个反映工作性价比…

JAVA—正则表达式

关于正则表达式的了解学习&#xff0c;以及用于校验格式&#xff0c;信息查找和替换分割内容。 目录 1.概述 2.书写规则 3.应用案例 4.用于信息查找 5.用于搜索替换&#xff0c;分割内容 1.概述 由一些特定的字符组成&#xff0c;代表一个规则 作用&#xff1a; 1.校验数据…

国外高清风景视频素材无水印哪里找?

哪里可以下载国外高清风景视频素材&#xff1f;有哪些高清海外素材网站&#xff1f;作为一名从业多年的视频剪辑师&#xff0c;今天就来给大家揭秘可以下载国外高清风景视频素材的网站&#xff0c;赶紧进来看看吧&#xff5e; 1. 稻虎网 稻虎网作为国内外知名视频素材网站&a…

【机器学习】 Sigmoid函数:机器学习中的关键激活函数

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 Sigmoid函数&#xff1a;机器学习中的关键激活函数1. 引言2. Sigmoid函数定义3.…

C++day04

1】思维导图 2】完成关系运算符重载&#xff0c;实现成员函数和全局函数的版本。 #include <iostream>using namespace std;class Stu { friend bool operator<(const Stu &L,const Stu &R); private:int age;int id; public:Stu(){}Stu(int age,int id):age…

OD工具-18个实操工具共创会

一、什么是共创会1.1 什么是共创共创&#xff0c;共同创造词组的缩写&#xff0c;字面上来看就是团队为了多个个体一起把以前没有的事物给产生出或者造出来&#xff0c;这明显的是一种典型的人类自主行为。 托德老师有一段描述:共创是一种工作状态&#xff0c;让团队中的每个个…

【时时三省】(C语言基础)操作符3

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 &取地址操作符 示例: 每个内存单元都有自己的编号 编号就成为内存单元的地址&a就是找出a的地址 后面可以加一个int *pa&#xff1d;&a 是可以用来存放地址 pa是用来存放地址的…

SQL进阶技巧:有序数据合并问题之如何按照指定的规则对数据进行合并?【详解collect_list函数有序性保证】

目录 0 问题描述【小红书面试题】 1 数据准备 2 问题分析 3 小结 0 问题描述【小红书】 有如下需求,需要将左边的表变换成右边的表,注意字段内容的顺序及对应内容的一致性。 第一个字段为name,第二个字段为subject,第三个字段为score,变换后要求subject按照语文、数学…

电脑管家软件搬运导致edge、chrome浏览器不可用

最新版本的腾讯电脑管家可以直接搬运软件到其他路径&#xff0c;但是搬运浏览器会造成软件问题&#xff0c;不建议搬运。 浏览器恢复到原路径&#xff0c;可以解决浏览器不可用的问题&#xff1a; 首先到达你的搬运路径下 可以看到软件文件夹&#xff0c;比如Microsoft Edge或…