01:2440----点灯大师

news2024/11/18 18:45:02

目录

一:点亮一个LED

1:原理图

2:寄存器

3:2440的框架和启动过程

A:框架

B:启动过程 

4:代码

5:ARM知识补充

6:c语言和汇编的应用

A:代码

B:分析汇编语言

C:内存空间

7:内部机制

二:点亮2个灯

三:流水灯

四:按键控制LED

1:原理图

2:寄存器配置

3:代码


一:点亮一个LED

1:原理图

        当LED输入低电平时出现电压差, LED被点亮  (n的意思是低电平有效)

        LED1 LED2 LED4分别接在 GPF4,5,6的IO口上

2:寄存器

        配置GPFCON寄存器的[9:8]位为0b01-----输出模式 ;  GPFCON--设置串口的模式

         GPFDAT寄存器: 当该端口配置为输入端口时,对应的位为引脚状态。当端口配置为输出端口时,引脚状态与对应的位相同。当端口配置为功能引脚时,将读取未定义值。

        GPF4对应GPFDAT寄存器的第4位, GPF[4]----0低电平/1高电平

        GPFDAT寄存器--设置串口具体输出的内容

3:2440的框架和启动过程

A:框架

注意: CPU----里面有许多寄存器(R0~R15) ; 在CPU里面的寄存器是可以直接访问的.

         GPIO控制器----里面有各种引脚,当然也包括我们今天使用的GPF4引脚;  GPIO控制器里面也有寄存器(GPFCON, GPCDAT),不过这里面的寄存器需要地址访问, 不能向CPU里面的寄存器直接访问.  在芯片手册中有寄存器的地址.

B:启动过程 

大多数的ARM芯片都是从0地址启动的, 当然这也包括我们讲述的2440

NOR启动 : NOR Flash基地址为0 ,  片内RAM的地址为0x4000 0000

        CPU读取出NOR第一个指令(前4个字节),执行

        CPU继续在读取出其他的指令在执行;   一边读取一边执行

Nand启动 : 片内4KARM基地址为0,  NOR启动不可访问

        2440硬件把Nand的前4K内容复制到片内RAM上,  然后CPU从0地址取出第条指令执行

4:代码

/*
*点亮一个LED
*/
.text
.global _start

_start:
/* 配置GPFCON(0X56000050)寄存器的[9:8]位为01--输出模式*/
	ldr r1,=0X56000050
	ldr r0,=0x100
	str r0,[r1]
/*
*配置GPFDAT寄存器为低电平(0x56000054)--输出低电平
*/
	ldr r1,=0x56000054
	ldr r0,=0
	str r0,[r1]
	/*死循环*/
halt:
	b halt
	

        我们采用的是交叉编译的方法---使用window书写汇编代码-----将汇编代码传给虚拟机-----在虚拟机下将传来的汇编代码编译为bin文件-----在将bin文件传给window-------window烧写bin文件给Linux开发板;      我们使用的是GPIO控制器里面的寄存器所以必须使用地址进行访问

5:ARM知识补充

       程序计数器 R15: 寄存器 R15 保存程序计数器(PC),它总是用于特殊的用途。它经常可用于通用寄存器RO~R14 所使用的位置(即在指令编码中 R15 与 RO~R14 的地位一样,只是指令执行的结果不同),因此,可以认为它是一个通用寄存器。但是对于它的使用还有许多与指令相关的限制或特殊情况。这些将在具体的指令描述中介绍。通常,如果 R15 使用的方式超出了这些限制,那么指令将是不可预测的。

        当指令对 R15 的读取没有超过任何对 R15 使用的限制时,读取的值是指令的地址加上 8个字节。由于 ARM 指令总是以字为单位,结果的 Bit[1:0]总是为 0。这种读取 PC 的方式主要用于对附近的指令和数据进行快速、与位置无关的寻址,包括程序中与位置无关的转移。


        当使用 STR或 STM 指令保存 R15 时,出现了上述规则的一个例外。这些指令可将指令地址加 8字节保存(与其它指令读取 R15 一样)或将指令自身地址加 12 字节(将来还可能出现别的数据)。偏移量 8 还是 12(或是其它数值)取决于 ARM 的实现(也就是说,与芯片有关)。对于某个具体的芯片,它是个常量。这样使用 STR 和 STM 指令是不可移植的。


        由于这个例外,最好避免使用 STR 和 STM 指令来保存 R15。如果很难做到,那么应当在程序中使用合适的指令序列来确定当前使用的芯片所使用的偏移量

在2440中R15(pc)的偏移量为8, 注意取决于他对数据的读取方式

x的地址=x的地址+8

        当他在读取地址A指令的时候

        已经在对地址A+4的指令进行译码

        已经在读取地址A+8的指令

分析反汇编的代码:

led_on.elf:     file format elf32-littlearm
Disassembly of section .text:
00000000 <_start>:
   0:	e59f1014 	ldr	r1, [pc, #20]	; 1c <halt+0x4>
   4:	e3a00c01 	mov	r0, #256	; 0x100
   8:	e5810000 	str	r0, [r1]
   c:	e59f100c 	ldr	r1, [pc, #12]	; 20 <halt+0x8>
  10:	e3a00000 	mov	r0, #0
  14:	e5810000 	str	r0, [r1]

00000018 <halt>:
  18:	eafffffe 	b	18 <halt>
  1c:	56000050 	undefined instruction 0x56000050
  20:	56000054 	undefined instruction 0x56000054

由于我们使用的是伪指令;  他是不存在的指令,最会被拆分真正的几条ARM指令;

上面的汇编代码都是由伪指令拆分而来的

优点 : 他可以表示任意值;   

        ARM指令===>32位,但是如果使用MOV的话并不能表示32位, 因为MOV32位中的一些位是用来表示他自己的,剩下的不够32位,  剩下的不够32位也只能表示一些立即数

ldr r1,=0X56000050=====>伪指令

6:c语言和汇编的应用

A:代码

我们需要写一个汇编代码, 给main函数设置内存, 调用main函数

int main()
{
	unsigned int *pGPFCON = (unsigned int *)0x56000050;
	unsigned int *pGPFDAT = (unsigned int *)0x56000054;

	/* 配置GPF4为输出引脚 */
	*pGPFCON = 0x100;
	
	/* 设置GPF4输出0 */
	*pGPFDAT = 0;

	return 0;
}


.text
.global _start

_start:

	/* 设置内存: sp 栈 */
	ldr sp, =4096  /* nand启动 */
//	ldr sp, =0x40000000+4096  /* nor启动 */

	/* 调用main */
	bl main

halt:
	b halt
	
all:
	arm-linux-gcc -c -o led.o led.c
	arm-linux-gcc -c -o start.o start.S
	arm-linux-ld -Ttext 0 start.o led.o -o led.elf
	arm-linux-objcopy -O binary -S led.elf led.bin
	arm-linux-objdump -D led.elf > led.dis
clean:
	rm *.bin *.o *.elf *.dis
	

我们使用makefile来编译, 避免重复多次的编译 

可以看到x.ids文件中的地址和给板子烧录的bin文件地址一致;

B:分析汇编语言

r0~r3寄存器负责----调用者和被调用者的传递参数的问题;

r4~r11寄存器在函数中,可能被使用, 所以在人口中保存他们, 在出口中恢复他们;


led.elf:     file format elf32-littlearm

Disassembly of section .text:

00000000 <_start>:
   0:	e3a0da01 	mov	sp, #4096	; 0x1000
   4:	eb000000 	bl	c <main>

00000008 <halt>:
   8:	eafffffe 	b	8 <halt>

0000000c <main>:
   c:	e1a0c00d 	mov	ip, sp
  10:	e92dd800 	stmdb	sp!, {fp, ip, lr, pc}
  14:	e24cb004 	sub	fp, ip, #4	; 0x4
  18:	e24dd008 	sub	sp, sp, #8	; 0x8
  1c:	e3a03456 	mov	r3, #1442840576	; 0x56000000
  20:	e2833050 	add	r3, r3, #80	; 0x50
  24:	e50b3010 	str	r3, [fp, #-16]
  28:	e3a03456 	mov	r3, #1442840576	; 0x56000000
  2c:	e2833054 	add	r3, r3, #84	; 0x54
  30:	e50b3014 	str	r3, [fp, #-20]
  34:	e51b2010 	ldr	r2, [fp, #-16]
  38:	e3a03c01 	mov	r3, #256	; 0x100
  3c:	e5823000 	str	r3, [r2]
  40:	e51b2014 	ldr	r2, [fp, #-20]
  44:	e3a03000 	mov	r3, #0	; 0x0
  48:	e5823000 	str	r3, [r2]
  4c:	e3a03000 	mov	r3, #0	; 0x0
  50:	e1a00003 	mov	r0, r3
  54:	e24bd00c 	sub	sp, fp, #12	; 0xc
  58:	e89da800 	ldmia	sp, {fp, sp, pc}
Disassembly of section .comment:

00000000 <.comment>:
   0:	43434700 	cmpmi	r3, #0	; 0x0
   4:	4728203a 	undefined
   8:	2029554e 	eorcs	r5, r9, lr, asr #10
   c:	2e342e33 	mrccs	14, 1, r2, cr4, cr3, {1}
  10:	Address 0x10 is out of bounds.

C:内存空间

        内存空间被分为三个部分:代码段(text segment,即程序代码)、数据段(data segment,即变量)和栈段(stack segment)。数据段从下往上增长,而栈从上向下增长图。在这两者之间是空闲的地址空间。栈的增长是随着程序的执行自动进行的,而数据的扩展则需要通过brk 系统调用来显式地完成,brk有一个参数来指定数据段的结束地址,它可比当前值大(表示扩展数据段 ),或是比当前值小(表示缩小数据段 )。当然,这个参数必须小于指针,否则栈和数据段将会重叠,这是不允许的。

7:内部机制

二:点亮2个灯

        上面我们实现了被调用者给调用者传递参数;

        我们这里学习---调用者给被调用者传递参数

int len_on(int num)
{
	/*设置寄存器 点亮LED2*/
	unsigned int* GPFCON = 0x56000050;
	unsigned int* GPFDAT = 0x56000054;
	if (num == 4)
	{
		/*设置输出模式*/
		*GPFCON = 0x100;
	}
	if (num == 5)
	{
		/*设置输出模式*/
		*GPFCON = 0x400;
	}
	/*输出低电平*/
	
	*GPFDAT = 0;
	return 0;
}
void Delay(int n)
{
	while (n--);
}
/*
*点亮一个LED
*/
.text
.global _start

_start:
 /*设置内存: sp栈*/
	 ldr sp,=4096 /*nand启动*/
	 ldr sp,=0x40000000+4096/*nor启动*/

	 mov r0 ,#4
	 bl len_on

	 ldr r0 ,=10000
	 bl Delay

	 mov r0 ,#5
	 bl len_on

halt:
	b halt

led.elf:     file format elf32-littlearm


Disassembly of section .text:

00000000 <_start>:
   0:	e3a0da01 	mov	sp, #4096	; 0x1000
   4:	e59fd018 	ldr	sp, [pc, #24]	; 24 <halt+0x4>
   8:	e3a00004 	mov	r0, #4
   c:	eb000006 	bl	2c <len_on>
  10:	e59f0010 	ldr	r0, [pc, #16]	; 28 <halt+0x8>
  14:	eb000022 	bl	a4 <Delay>
  18:	e3a00005 	mov	r0, #5
  1c:	eb000002 	bl	2c <len_on>

00000020 <halt>:
  20:	eafffffe 	b	20 <halt>
  24:	40001000 	andmi	r1, r0, r0
  28:	00002710 	andeq	r2, r0, r0, lsl r7

0000002c <len_on>:
  2c:	e52db004 	push	{fp}		; (str fp, [sp, #-4]!)
  30:	e28db000 	add	fp, sp, #0
  34:	e24dd014 	sub	sp, sp, #20
  38:	e50b0010 	str	r0, [fp, #-16]
  3c:	e59f3058 	ldr	r3, [pc, #88]	; 9c <len_on+0x70>
  40:	e50b300c 	str	r3, [fp, #-12]
  44:	e59f3054 	ldr	r3, [pc, #84]	; a0 <len_on+0x74>
  48:	e50b3008 	str	r3, [fp, #-8]
  4c:	e51b3010 	ldr	r3, [fp, #-16]
  50:	e3530004 	cmp	r3, #4
  54:	1a000002 	bne	64 <len_on+0x38>
  58:	e51b300c 	ldr	r3, [fp, #-12]
  5c:	e3a02c01 	mov	r2, #256	; 0x100
  60:	e5832000 	str	r2, [r3]
  64:	e51b3010 	ldr	r3, [fp, #-16]
  68:	e3530005 	cmp	r3, #5
  6c:	1a000002 	bne	7c <len_on+0x50>
  70:	e51b300c 	ldr	r3, [fp, #-12]
  74:	e3a02b01 	mov	r2, #1024	; 0x400
  78:	e5832000 	str	r2, [r3]
  7c:	e51b3008 	ldr	r3, [fp, #-8]
  80:	e3a02000 	mov	r2, #0
  84:	e5832000 	str	r2, [r3]
  88:	e3a03000 	mov	r3, #0
  8c:	e1a00003 	mov	r0, r3
  90:	e28bd000 	add	sp, fp, #0
  94:	e8bd0800 	pop	{fp}
  98:	e12fff1e 	bx	lr
  9c:	56000050 	undefined instruction 0x56000050
  a0:	56000054 	undefined instruction 0x56000054

000000a4 <Delay>:
  a4:	e52db004 	push	{fp}		; (str fp, [sp, #-4]!)
  a8:	e28db000 	add	fp, sp, #0
  ac:	e24dd00c 	sub	sp, sp, #12
  b0:	e50b0008 	str	r0, [fp, #-8]
  b4:	e51b3008 	ldr	r3, [fp, #-8]
  b8:	e3530000 	cmp	r3, #0
  bc:	03a03000 	moveq	r3, #0
  c0:	13a03001 	movne	r3, #1
  c4:	e20330ff 	and	r3, r3, #255	; 0xff
  c8:	e51b2008 	ldr	r2, [fp, #-8]
  cc:	e2422001 	sub	r2, r2, #1
  d0:	e50b2008 	str	r2, [fp, #-8]
  d4:	e3530000 	cmp	r3, #0
  d8:	1afffff5 	bne	b4 <Delay+0x10>
  dc:	e28bd000 	add	sp, fp, #0
  e0:	e8bd0800 	pop	{fp}
  e4:	e12fff1e 	bx	lr

Disassembly of section .ARM.attributes:

00000000 <.ARM.attributes>:
   0:	00002541 	andeq	r2, r0, r1, asr #10
   4:	61656100 	cmnvs	r5, r0, lsl #2
   8:	01006962 	tsteq	r0, r2, ror #18
   c:	0000001b 	andeq	r0, r0, fp, lsl r0
  10:	00543405 	subseq	r3, r4, r5, lsl #8
  14:	01080206 	tsteq	r8, r6, lsl #4
  18:	04120109 	ldreq	r0, [r2], #-265	; 0x109
  1c:	01150114 	tsteq	r5, r4, lsl r1
  20:	01180317 	tsteq	r8, r7, lsl r3
  24:	Address 0x00000024 is out of bounds.


Disassembly of section .comment:

00000000 <.comment>:
   0:	3a434347 	bcc	10d0d24 <__bss_end__+0x10c8c3c>
   4:	74632820 	strbtvc	r2, [r3], #-2080	; 0x820
   8:	312d676e 	teqcc	sp, lr, ror #14
   c:	312e362e 	teqcc	lr, lr, lsr #12
  10:	2e342029 	cdpcs	0, 3, cr2, cr4, cr9, {1}
  14:	00332e34 	eorseq	r2, r3, r4, lsr lr

        对于2440他的内部同样存在看门狗, 我们在程序中没有对看门狗进行操作; 所以他在一段时间就会复位. 

三:流水灯


void Delay(int n)
{
	while (n--);
}

int main(void)
{
	int i = 4;
	/*设置寄存器 点亮LED2*/
	volatile unsigned int* GPFCON = (volatile unsigned int*)0x56000050;
	volatile unsigned int* GPFDAT = (volatile unsigned int*)0x56000054;
	/*设置GPF4/5/6位位输出模式*/
	*GPFCON &= ~((3 << 8) | (3 << 10) | (3 << 12)); //3对应0b11 清位
	*GPFCON |= ((1 << 8) | (1 << 10) | (1 << 12)); //置1-设置位输出模式

	/*GPFDAT寄存器配置 */
	*GPFDAT &= ~((1 << 4) | (1 << 5) | (1 << 6)); //清位
	*GPFDAT |= ((1 << 4) | (1 << 5) | (1 << 6)); //把GPFDAT寄存器的4 5 6 位置1--灭灯
	/*led4 0x100 led5 0x400 */
	while (1)
	{	
		if (i == 7)i = 4;
		*GPFDAT &= ~(1 << i);
		Delay(10000);
		*GPFDAT |= (1 << i);
		Delay(10000);
		i++;		
	}
	return 0;
}

/*
*点亮一个LED
*/
.text
.global _start

_start:
/* 关闭看门狗 */
	ldr r0, =0x53000000
	ldr r1, =0
	str r1, [r0]

 /*设置内存: sp栈* 我们判断是nor启动还是nand启动/

	mov r1, #0
	ldr r0, [r1] /* 读出原来的值备份 */
	str r1, [r1] /* 0->[0] */ 
	ldr r2, [r1] /* r2=[0] */
	cmp r1, r2   /* r1==r2? 如果相等表示是NAND启动 */
	ldr sp, =0x40000000+4096 /* 先假设是nor启动 */
	moveq sp, #4096  /* nand启动 */
	streq r0, [r1]   /* 恢复原来的值 */
	

	
	 bl main


halt:
	b halt
	

1:看门狗问题的解决

        看门狗定时器控制(WTCON)寄存器WTCON寄存器允许用户启用/禁用看门狗定时器,选择来自4个不同源的时钟信号,启用/禁用中断,启用/禁用看门狗定时器输出。看门狗定时器用于S3C2440A上电后功能异常重启时恢复;如果不希望控制器重启,则关闭看门狗定时器

我们可以看到当 Reset enable/disable (重新启用/禁用) 设置WTCON寄存器位0时, 2400就会关闭我们的寄存器

2:如何区分是nar启动还是nand启动

        nor启动 : 可以向内存一样读, 但是不能向内存一样写; (如果一定要写的话需要发送一定格式的数据才可以写)

        nand : 可读取写

方法: 分辨是nor/nand启动
     * 写0到0地址, 再读出来
     * 如果得到0, 表示0地址上的内容被修改了, 它对应ram, 这就是nand启动 (nand-- 可读取写)
     * 否则就是nor启动  (只能读)

四:按键控制LED

1:原理图

平时他为高电平,  当按键按下他为低电平;  

2:寄存器配置

GPG3

GPF

按键位输入模式

3:代码



void Delay(int n)
{
	while (n--);
}

#define GPFCON (*((volatile unsigned int*)0x56000050))
#define GPFDAT (*((volatile unsigned int*)0x56000054))
#define GPGCON  (*((volatile unsigned int*)0x56000060))
#define GPGDAT (*((volatile unsigned int*)0x56000064))
int main(void)
{
	
	/*volatile unsigned int* GPFCON = (volatile unsigned int*)0x56000050;
	volatile unsigned int* GPFDAT = (volatile unsigned int*)0x56000054;
	volatile unsigned int* GPGCON = (volatile unsigned int*)0x56000060;
	volatile unsigned int* GPGDAT = (volatile unsigned int*)0x56000064;*/
	/*设置GPF4/5/6位p 位输出模式*/
	GPFCON &= ~((3 << 8) | (3 << 10) | (3 << 12)); //3对应0b11 清位
	GPFCON |= ((1 << 8) | (1 << 10) | (1 << 12)); //置1-设置位输出模式

	
	/*设置GPF0和GPF2按键位输入模式*/
	GPFCON &= ~((3 << 0) | (3 << 4));
	/*GPG3位输入模式*/
	GPGCON &= ~(3 << 6);


	while (1)
	{	
		if (GPFDAT & (1 << 0)) /* s2 --> gpf6 */
		{
			/* 松开 */
			GPFDAT |= (1 << 6);
		}
		else
		{
			/* 按下 */
			GPFDAT &= ~(1 << 6);
		}

		if (GPFDAT & (1 << 2)) /* s3 --> gpf5 */
		{
			/* 松开 */
			GPFDAT |= (1 << 5);
		}
		else
		{
			/* 按下 */
			GPFDAT &= ~(1 << 5);
		}

		if ((GPGDAT & (1 << 3))==0) /* s4 --> gpf4 */
		{
			/* 按下 */
			GPFDAT &= ~(1 << 4);
		}
		else
		{
			/* 松开 */
			GPFDAT |= (1 << 4);	
		}
	}
	return 0;
}
/*
*点亮一个LED
*/
.text
.global _start

_start:
/* 配置GPFCON(0X56000050)寄存器的[9:8]位为01--输出模式*/
	ldr r1,=0X56000050
	ldr r0,=0x100
	str r0,[r1]
/*
*配置GPFDAT寄存器为低电平(0x56000054)--输出低电平
*/
	ldr r1,=0x56000054
	ldr r0,=0
	str r0,[r1]
	/*死循环*/
halt:
	b halt
	
		

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

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

相关文章

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:

错误描述如下所示&#xff1a; 我们将错误拉到最下面如下所示为导致异常的原因&#xff1a; Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type com.example.reviewmybatisplus.Service.UserService available: expec…

基于Mahony互补滤波的IMU数据优化_学习笔记整理

这周自己被安排进行优化软件 IMU 姿态解算项目&#xff0c;之前自己只简单了解四元数&#xff0c;对IMU数据处理从未接触&#xff0c;通过这一周的学习感觉收获颇丰&#xff0c;在今天光棍节之际&#xff0c;&#xff0c;&#xff0c;用大半天的时间对这一周的收获进行整理&…

【蓝桥杯 第十三届省赛Java B组】真题训练(A - F)

目录 A、星期计算 - BigInteger B、山 - 暴力判断 字符串 C、字符统计 - 简单哈希 D、最少刷题数 - 排序 思维 二分 分情况讨论 &#xff08;1&#xff09;&#xff08;错误&#xff09;自写哈希表 &#xff08;2&#xff09;正解 E、求阶乘 - 数学思维 二分 F、…

AI 引擎系列 5 - 以 AI 引擎模型为目标运行 AI 引擎编译器(2022.1 更新)

AI 引擎系列 5 - 以 AI 引擎模型为目标运行 AI 引擎编译器&#xff08;2022.1 更新&#xff09; 简介 在先前的 AI 引擎系列博文中&#xff0c;我们以 x86 模型为目标运行了 AI 引擎编译器&#xff0c;并运行了 X86 仿真器来验证 AI 引擎应用的功能模型。在本文中&#xff0c;…

吴恩达《机器学习》8-1->8-2:非线性假设、神经元和大脑

一、非线性假设 在之前学到的线性回归和逻辑回归中&#xff0c;存在一个缺点&#xff0c;即当特征数量很多时&#xff0c;计算的负荷会变得非常大。考虑一个例子&#xff0c;假设我们使用 &#x1d465;₁, &#x1d465;₂ 的多项式进行预测&#xff0c;这时我们可以很好地应…

汽车制动系统技术分析概要

目录 1.基本功能概述 2. 基本工作原理分析 2.1 Two-Box系统架构(Bosch_IBooster) 2.2 One-Box系统架构(Bosch_IPB) 2.3 ​​​​​​​ABS技术 2.4 TCS技术 2.5 VDC技术 2.6 EPB技术 2.7 小结 3. 该场景应用发展趋势分析 1.基本功能概述 传统汽车的底盘主要由传动系、…

容器网络-Underlay和Overlay

一、主机网络 前面讲了容器内部网络&#xff0c;但是容器最终是要部署在主机上&#xff0c;跨主机间的网络访问又是怎么样的&#xff0c;跨主机网络主要有两种方案。 二、 Underlay 使用现有底层网络&#xff0c;为每一个容器配置可路由的网络IP。也就是说容器网络和主机网络…

视频剪辑助手:轻松实现视频随机分割并提取音频保存

随着社交媒体和视频平台的日益普及&#xff0c;视频制作和分享已成为人们日常生活的一部分。无论是分享个人生活&#xff0c;还是展示才艺&#xff0c;或是推广产品&#xff0c;视频都是一个非常有效的工具。但是&#xff0c;视频制作往往涉及到大量的视频剪辑工作&#xff0c;…

FM3793A-高性能PWM控制芯片 超低成本18W-20W 恒功率PD快充

产品描述&#xff1a; FM3793A是一款应用于离线反激式转换器中的高性能电流模式PWM控制器。在 FM3793A中&#xff0c;PWM开关频率最大为65KHz。在轻载和空载条件下&#xff0c;该FM3793A启动间歇模式从而降低开关频率。FM3793A具有丰富的芯片异常状况保护功能&#xff0c;如欠压…

数据分析实战 | KNN算法——病例自动诊断分析

目录 一、数据及分析对象 二、目的及分析任务 三、方法及工具 四、数据读入 五、数据理解 六、数据准备 七、模型训练 八、模型评价 九、模型调参 十、模型改进 十一、模型预测 一、数据及分析对象 CSV文件——“bc_data.csv” 数据集链接&#xff1a;https://dow…

万物皆数——用matlab求解二阶微分方程

一、背景 毕达哥拉斯的“万物皆数”哲学观点表达了一个理念&#xff0c;即宇宙万物都可以通过数学语言来描述&#xff0c;数是万物的本原。 勾股定理就是毕达哥拉斯提出&#xff0c;因此在西方勾股定理也被叫做毕达哥拉斯定理。 工科类的专业&#xff0c;越到后面越感觉到数学…

永达理简析:利用保险的“财务规划”功能维持退休后生活水平

现代社会环境背景下&#xff0c;“自养自老”已经是一种未来养老趋势&#xff0c;很多人会为自己准备一份长期、比较周全的保障&#xff0c;这样财务规划不仅会分担子女的压力&#xff0c;也让自己有一个长远的保障。在各种财务储蓄工具中&#xff0c;商业保险占据着不可取代的…

聊聊性能测试的左移右移

前面的文章中&#xff0c;分享过我对于测试左移右移的一些思考和实践方法。有同学在后台留言问我&#xff1a;常规的性能测试一般都是在测试阶段集成测试时候才开始介入&#xff0c;很容易测试时间不够&#xff0c;可不可以借鉴测试左移右移的思路&#xff0c;更早的介入和发现…

CKA认证模块②-K8S企业运维和落地实战

CKA认证模块②-K8S企业运维和落地实战 Pod高级实战-Pod生命周期-启动钩子,停止钩子 Pod生命周期完整流程介绍 容器钩子; 容器探测; Pod重启策略; Pod的终止过程; Init容器; 初始化容器最佳实践 初始化容器与主容器区别是? init容器没有readinessProbe… [rootk8s-mast…

经典的测试开发面试题

1、你在测试中发现了一个bug&#xff0c;但是开发经理认为这不是一个bug&#xff0c;你应该怎样解决&#xff1f; 首先&#xff0c;将问题提交到缺陷管理库进行备案。 然后&#xff0c;要获取判断的依据和标准&#xff1a; 根绝需求说明书&#xff0c;产品说明、设计文档等&…

迷雾系统-人物驱散迷雾

使用linerRender,将人物移动数据动态添加进去&#xff0c;同样是特殊层级让FogCamera渲染 EndCapVertices的数量越多&#xff0c;矩形就变为一个椭圆形的形状&#xff0c;更适合圆形视野探索 当拐点的两个点距离太近&#xff0c;LineRender会发生扭曲&#xff0c;解决方案是在…

Redis五种数据类型及命令操作(一)

&#x1f388;个人公众号:&#x1f388; :✨✨✨ 可为编程✨ &#x1f35f;&#x1f35f; &#x1f511;个人信条:&#x1f511; 知足知不足 有为有不为 为与不为皆为可为&#x1f335; &#x1f349;本篇简介:&#x1f349; 本篇记录Redis五种数据类型及命令操作&#xff0c;如…

Java基础-面向对象进阶-多态, 包, final, 权限修饰符,代码块

Java基础-面向对象进阶-多态, 包, final, 权限修饰符,代码块 多态多态的概述多态中调用成员的特点多态的优势和弊端多态练习 包final权限修饰符代码块来源Gitee地址 多态 多态的概述 多态: 对象的多种形态多态的前提 有继承/实现关系有父类引用指向子类对象有方法的重写 多态…

Netty--NIO(Non-blocking IO)基础--三大组件

NIO&#xff08;Non-blocking IO&#xff09;是一种非阻塞的IO模型&#xff0c;它通过引入Channel和Selector的概念&#xff0c;使得一个线程能够管理多个通道&#xff0c;从而提高了IO操作的效率。本文将介绍NIO的三大组件&#xff1a;Channel、Buffer、以及Selector&#xff…

【C++对象模型】构造函数II

构造函数语意学 》》构造函数语意学I—默认构造函数的构造操作《《 》》构造函数语意学II—拷贝构造函数的构造操作《《 》》构造函数语意学III—程序转化语意学《《 拷贝构造函数的构造操作 有三种情况&#xff0c;会以一个object的内容作为另一个class object的初值。 1.…