day3 ARM

【昨日作业】

.text .global start _start: mov r0,#0 @存放sum mov r1,#1 @存放相加的数值 loop: cmp r1,#100 bhi wh add r0,r0,r1 add r1,r1,#1 b loop wh: b wh .end

【内存读写指令】

通过内存读写指令可以实现向内存中写入指定数据或者读取指定内存地址的数据

c语言内存访问方式是通过指针实现 int a=10; int *p=&a; //从内存中获取a的数值 int b= *p; //向内存中写 *p=100;

关于调试时如何查看内存数据:

关于可用内存查看:

1.单寄存器内存读写指令

将一个寄存器中的数值写入到内存,或者从内存中读取数据放在某一个指定寄存器中

1.1 指令码和功能

1.向内存中写: str{条件码} 目标寄存器,[目标地址]:将目标寄存器的4字节数值写入到目标地址为首地址的空间中 strh{条件码} 目标寄存器,[目标地址]:将目标寄存器的2字节数值写入到目标地址为首地址的空间中 strb{条件码} 目标寄存器,[目标地址]:将目标寄存器的1字节数值写入到目标地址为首地址的空间中 2.从内存中读: ldr{条件码} 目标寄存器,[目标地址]:从目标地址为首地址的空间中读取4字节数据存放在目标寄存器中 ldrh{条件码} 目标寄存器 ,[目标地址]:从目标地址为首地址的空间中读取2字节数据存放在目标寄存器中 ldrb{条件码} 目标寄存器 ,[目标地址]:从目标地址为首地址的空间中读取1字节数据存放在目标寄存器中

1.2 示例

.text .global start _start: mov r0,#0XFFFFFFFE mov r1,#0X40000000 @R1保存内存地址 @将r0的值写入到r1对应的地址空间 str r0,[r1] @从r1对应的地址空间中读取数据保存在r2中 ldr r2,[r1] wh: b wh .end

1.3 单寄存器内存索引方式

前索引方式

str{条件码} 目标寄存器,[目标地址,#立即数] //将目标寄存器的数据保存在目标地址+8为起始地址的内存中 ldr{条件码} 目标寄存器,[目标地址,#立即数] //从目标地址+8为起始地址的内存中读取数据保存在目标寄存器

后索引方式

str{条件码} 目标寄存器,[目标地址],#立即数 //将目标寄存器的数据保存在目标地址为起始地址的内存中,接着目标地址自加立即数大小 ldr{条件码} 目标寄存器,[目标地址],#立即数 //从目标地址为起始地址的内存中读取数据保存在目标寄存器,接着目标地址自加立即数大小

自动索引方式

str{条件码} 目标寄存器,[目标地址,#立即数]! //将目标寄存器的数据保存在目标地址+立即数为起始地址的内存中,接着目标地址自加立即数大小 ldr{条件码} 目标寄存器,[目标地址,#立即数]! //从目标地址+立即数大小为起始地址的内存中读取数据保存在目标寄存器,接着目标地址自加立即数大小

2.批量寄存器的内存读写方式

将多个寄存器的数据存放在内存中以及从内存中取出数据保存在多个寄存器中

2.1 指令码以及格式

向内存写: stm 目标地址,{目标寄存器列表} 将列表中各个寄存器的数值保存在目标地址对应的地址空间中 从内存中读取 ldm 目标地址,{目标寄存器列表} 从目标地址对应的地址空间中拿数据保存到寄存器列表中各个寄存器中 注意: 1.寄存器列表中每一个寄存器之间用','分隔,如果寄存器列表中寄存器的编号连续,那么可以用-表示一定范围内的 寄存器,比如 {r1-r5} 2.无论寄存器列表中的寄存器表现形式如何,在存取数据时始终是小编号寄存器对应低地址

2.2 示例

.text .global start _start: mov r0,#0X40000000 mov r1,#1 mov r2,#2 mov r3,#3 mov r4,#4 mov r5,#5 @向内存中写 @stm r0,{r2,r1,r4,r3,r5} stm r0,{r1-r5} @从内存中读取数据 ldm r0,{r6-r10} wh: b wh .end

2.3 批量寄存器的地址增长方式

每次向寄存器保存的地址对应的地址空间中写入一个数据,这个寄存器保存的地址会发生相应的增长变化,这就是批量寄存器的地址增长方式

.text  
.global start 
            

_start:
   mov r0,#0X40000000
   mov r1,#1
   mov r2,#2
   mov r3,#3
   mov r4,#4
   mov r5,#5
   @向内存中写
   stm r0!,{r1-r5}
   
wh: 
    b wh  
    
.end 

内存读写命令后加ia后缀

先向r0数值为起始地址的内存空间中保存一个数据,然后r0数值往高地址方向增长

内存读写命令后加ib后缀

先r0数值往高地址方向增长,然后向r0数值为起始地址的内存空间中保存一个数据

内存读写命令后加da后缀

先向r0数值为起始地址的内存空间中保存一个数据,然后r0数值往低地址方向增长

内存读写命令后加db后缀

先r0数值往低地址方向增长,然后向r0数值为起始地址的内存空间中保存一个数据

3.栈内存的读写

栈指针寄存器:SP/R13 保存栈顶的地址

栈:本质上就是一段内存。在内存中选取一段内存作为栈内存,可以用于保存临时数据。

3.1 栈的类型

增栈:每次压栈结束,SP保存的栈顶地址往高地址方向增栈 减栈:每次压栈结束,SP保存的栈顶地址往低地址方向增栈 空栈:压栈结束后,SP保存的栈顶空间中没有有效数据 满栈:压栈结束后,SP保存的栈顶空间中有有效数据 空增栈(EA)/空减栈(ED)/满增栈(FA)/满减栈(FD) 当前ARM处理器使用的是哪种栈?满减栈

3.2 满减栈压栈出栈操作

1. push {寄存器列表}@压栈 pop {寄存器列表}@出栈 2. .text .global start _start: @初始化栈 ldr 

1.
push {寄存器列表}@压栈
pop {寄存器列表}@出栈

2.   
.text  
.global start 
            

_start:
@初始化栈
   ldr SP,=0X40000020
   mov r1,#1
   mov r2,#2
   mov r3,#3
   mov r4,#4
   mov r5,#5
   @压栈
   stmdb sp!,{r1-r5}
   @出栈
   ldmia sp!,{r6-r10}
wh: 
    b wh  
    
.end 
    
 
 3.
 .text  
.global start 
            

_start:
@初始化栈
   ldr SP,=0X40000020
   mov r1,#1
   mov r2,#2
   mov r3,#3
   mov r4,#4
   mov r5,#5
   @压栈
   stmfd sp!,{r1-r5}
   @出栈
   ldmfd sp!,{r6-r10}
wh: 
    b wh  
    
.end 
    

3.3 栈的应用实例---叶子函数调用过程

当我们在主函数中调用一个函数,被调用的这个函数中没有别的函数调用,那么 这个函数就叫做叶子函数

1.
push {寄存器列表}@压栈
pop {寄存器列表}@出栈

2.   
.text  
.global start 
            

_start:
@初始化栈
   ldr SP,=0X40000020
   mov r1,#1
   mov r2,#2
   mov r3,#3
   mov r4,#4
   mov r5,#5
   @压栈
   stmdb sp!,{r1-r5}
   @出栈
   ldmia sp!,{r6-r10}
wh: 
    b wh  
    
.end 
    
 
 3.
 .text  
.global start 
            

_start:
@初始化栈
   ldr SP,=0X40000020
   mov r1,#1
   mov r2,#2
   mov r3,#3
   mov r4,#4
   mov r5,#5
   @压栈
   stmfd sp!,{r1-r5}
   @出栈
   ldmfd sp!,{r6-r10}
wh: 
    b wh  
    
.end 
    

3.4 栈的应用实例---非叶子函数调用过程

当我们在主函数中调用一个函数,被调用的这个函数中存在别的函数调用,那么 这个函数就叫做非叶子函数

            

_start:
@初始化栈
   ldr SP,=0X40000020
   b main
main:
    mov r1,#3
    mov r2,#4
    bl fun1
    add r3,r1,r2
    b main
fun1:
@压栈保护现场
    stmfd sp!,{r1,r2,lr}
    mov r1,#7
    mov r2,#9
    bl fun2
    sub r4,r2,r1
    @出栈恢复现场
    ldmfd sp!,{r1,r2,lr}
    mov pc,lr   @程序返回
fun2:
    stmfd sp!,{r1,r2}
    mov r1,#4
    mov r2,#8
    mul r4,r2,r1
    @出栈恢复现场
    ldmfd sp!,{r1,r2}
    mov pc,lr   @程序返回
    
.end 

【程序状态寄存器传输指令】

指令的作用实现CPSR寄存器数值的读取以及数值的修改

1.指令码以及格式

格式: msr CPSR,第一操作数 将第一操作数的数值写入到CPSR寄存器中 mrs 目标寄存器,CPSR 读取CPSR数值保存到目标寄存器中

2.实例

.text  
.global _start 
            

_start:
    mrs r1,CPSR  @读取CPSR数值
    @切换到USR模式,取消FIQ和IRQ禁止
    msr CPSR,#0x10
    

.end 
    
 注意:user模式是ARM处理器工作模式中唯一的非特权模式,这种模式下无法通过手动修改CPSR数值切换到异常模式,只要发生对应的异常后才可以切换到异常模式

【软中断指令】

swi 中断号
注意:中断号是一个由24位二进制数组成的一个整数,用于区分不同的中断

1.概念

软中断是从软件层次上模拟的硬件中断,原理和硬件中断一样。软中断触发之后CPU进行异常模式的切换(SVC),紧接着执行软中断对应的异常处理程序。

2.软中断指令码以及使用

swi 中断号 注意:中断号是一个由24位二进制数组成的一个整数,用于区分不同的中断

3.异常处理过程分析

3.1 异常模式和异常源的对应关系

5种异常模式对应7种异常源

异常模式

异常源

解释

FIQ

FIQ类型异常源

一些硬件发生了FIQ异常事件进入FIQ模型

IRQ

IRQ类型异常源

一些硬件发生了IRQ异常事件进入IRQ模型

SVC

复位信号

按键复位/上电复位时产生

swi软中断指令

执行swi指令

undef

未定义异常源

译码器在翻译指令时,遇到无法翻译的指令,指令未定义

abort

data abort

取数据发生异常时

prefetch abort

取指令发生异常时

3.2 异常的处理过程分析(面试重点)

***********异常的处理过程********
当一个异常源产生之后CPU会进行一些工作用于程序的跳转以及异常模式的切换,这个过程分为四大步三小步
1.保存发生异常之前的CPSR的值到对应异常模式下的SPSR寄存器中
2.修改CPSR的数值
    2.1 根据实际情况设置FIQ和IRQ中断禁止  CPSR[7:6]
    2.2 修改处理器工作状态为ARM状态  CPSR[5]
    2.3 修改处理器的工作模式为对应的异常模式 CPSR[4:0]
3.保存主程序的返回地址到对应模式下的LR寄存器中
4.修改PC的值到对应异常模式下的异常向量表中

*********处理完异常之后现场的恢复过程*********
1.恢复CPSR寄存器的值为未发生异常之前的状态
2.修改PC的值为未发生异常之前的下一条指令地址   PC=LR

3.3 异常向量

1.异常向量表是内存空间中的一段内存。这段内存占据了32字节。这个内存被平分为8等份,一份是4字节。每一份内存对应一种异常源,有一份保留,在异常向量表内存里存放的是当前异常源对应的异常处理程序的跳转指令。当发生异常之后,CPU会修改PC的值为对应异常源在异常向量中的位置,执行这个位置中的跳转指令,去处理异常处理程序。
2.每一种异常源在异常向量表中的位置是固定,不能随便修改
3.只要设置了异常向量表的基地址,就可以根据不同异常在一场向量表中的位置找到对应异常的跳转指令

4.软中断异常处理实例

.text  
.global _start 
            

_start:
    @初始化异常向量表
    b main
    b .
    b do_swi
    b .
    b .
    b .
    b .
    b .
    
main:
@初始化栈
    mov sp,#0X40000020
    @切换到USER模式
    MSR CPSR,#0X10
    MOV R1,#1
    MOV R2,#2
    @触发软中断
    SWI 1
    add r3,r1,r2
    b main

do_swi:@异常处理
@保护现场
    stmfd sp!,{r1,r2,lr}
    mov r1,#3
    mov r2,#4
    mul r4,r1,r2
    @恢复现场
    ldmfd sp!,{r1,r2,pc}^  @  ^的作用是修改PC的值的同时将SPSR的值赋值给CPSR
.end 
    

【混合编程】

1.混合编程的意义

所谓的混合编程就是c语言资源和汇编资源的相互调用

  • 一般工程会有汇编启动程序,启动程序完成堆栈的相关初始化,完毕之后才跳转到c语言的main函数
  • c语言中几乎不可以直接操作寄存器,但是有些特定场景下需要c中操作寄存器,这时候就需要c语言中嵌套汇编的语法

2.概述

所谓的混合编程就是c语言资源和汇编资源的相互调用

  • 一般工程会有汇编启动程序,启动程序完成堆栈的相关初始化,完毕之后才跳转到c语言的main函数
  • c语言中几乎不可以直接操作寄存器,但是有些特定场景下需要c中操作寄存器,这时候就需要c语言中嵌套汇编的语法

3.汇编调用C语言的函数

将C语言的函数当作汇编的标签使用

*****汇编文件**********
.text    
.global _start  
            
_start: 

    @ 1. 初始化栈指针,C代码运行必须有栈
    ldr sp, =0x40000820
    
    @ 2. 汇编调用c函数 
    @ 2.1 给C的函数传递实参值
    mov r0, #3   @ a = 3
    mov r1, #4   @ b = 4
    mov r2, #5   @ c = 5
    mov r3, #6   @ d = 6
    
    @ 2.2 汇编调用c的函数
    bl add_func
    
    @ 2.3 函数的返回通过r0返回,查看r0寄存器中的值

loop:   
        b loop  

.end

**********c文件********************
// c代码的函数是一个全局的函数
int add_func(int a, int b, int c, int d) 
{
 return (a+b+c+d);
}

4.c语言调用汇编标签

将汇编的标签当作c语言的函数

********起始汇编文件**********
.text    
.globl _start  
            
_start: 

    @ 1. 初始化栈指针,C代码运行必须有栈
    ldr sp, =0x40000820
    
    @ 2. 汇编调用c,跳转到main函数
    b main
.end

********c文件************
// 使用extern对函数进行声明
extern int add_func(int a, int b, int c, int d);

int sum = 0;
int main()
{
 // 在c代码中调用汇编代码
 sum = add_func(1,2,3,4);
 while(1);
 return 0;
}

********汇编文件**********
.text 
.global add_func  @ 将add_func函数声明为全局
    
    add_func:
        add r0, r0, r1
        add r0, r0, r2
        add r0, r0, r3
        mov pc, lr
.end

5.c语言内联汇编

在某一些特定的场景下需要在c语言中直接使用汇编的语法,此时需要内联汇编。内联汇编的实现需要通过asm关键字进行修饰

5.1 格式

asm volatile(
    "汇编指令模板\n\t"     //"\n\t"表示一条指令的结束
    .....
    :输出列表  //指令结果的输出值
    :输入列表  //指令的数据输入
    :破坏列表  //破坏列表指定我们当前可用的寄存器
);

5.2 实例

********汇编启动文件*******
.text    
.globl _start  
            
_start: 

    @ 1. 初始化栈指针,C代码运行必须有栈
    ldr sp, =0x40000820
    
    @ 2. 汇编调用c,跳转到main函数
    b main
.end
    
 
 **********c语言文件***********
 // 内联汇编 
int add_func2(int a, int b, int c, int d)
{
 int sum = 0;
 // 使用汇编实现求和
 asm volatile(  "add r0, r0, r1\n\t"  "add r0, r0, r2\n\t"  "add r0, r0, r3\n\t"  :"=r"(sum)  :"r"(a),"r"(b),"r"(c),"r"(d)  :"memory" );
 return sum;
}
 //"=r"(sum)表示输出从寄存器中放到变量sum中
// "r"(a) 指定输入从变量a中获取放到通用寄存器
 //"memory"声明使用内存

// 使用extern对函数进行声明
extern int add_func(int a, int b, int c, int d);

int sum = 0;
int main()
{
 // 调用内联汇编的函数 
 sum = add_func2(5,6,7,8);
 
 // 在c代码中调用汇编代码
 sum = add_func(1,2,3,4);
 while(1);
 return 0;
}
 *********汇编文件*************
 .text 
.global add_func  @ 将add_func函数声明为全局
    
add_func:
        add r0, r0, r1
        add r0, r0, r2
        add r0, r0, r3
        mov pc, lr
.end
    

【环境安装】

1.在ubuntu中安装交叉编译工具链

交叉开发:PC端编写代码,开发板上运行代码,这种开发方式叫做交叉开发。 本地开发:PC端编写代码,PC端运行代码,这种开发方式叫做本地开发。

安装交叉编译工具链,需要安装兼容32位库,ubuntu一定需要联网
    sudo apt-get install lib32z1
1. 在ubuntu的家目录下创建toolchain目录
    cd ~
    mkdir toolchain

2. 拷贝交叉编译工具链的压缩包到ubuntu的~/toolchain目录下
    交叉编译工具链的压缩包的路径:
        STM32MP157-学生资料\02_开发工具\02.5_ubuntu版本交叉编译工具链\
        gcc-linaro-7.5.0-2019.12-i686_arm-linux-gnueabihf.tar.xz

3. 使用tar命令进行解压缩
    tar -vxf gcc-linaro-7.5.0-2019.12-i686_arm-linux-gnueabihf.tar.xz

4. 解压缩成功之后得到一个gcc-linaro-7.5.0-2019.12-i686_arm-linux-gnueabihf,修改文件加额名字
    mv gcc-linaro-7.5.0-2019.12-i686_arm-linux-gnueabihf gcc-7.5.0

5. 交叉编译工具链的路径为:
    ~/toolchain/gcc-7.5.0/bin

6. 修改PATH环境变量,将交叉编译工具链的路径添加到PATH环境变量中
    /etc/bash.bashrc   --》 对所有的用户都有效
    /etc/profile       --》 对所有的用户都有效
    /etc/environment   --》 对所有的用户都有效
    ~/.bashrc          --》 对当前的用户都有效
    
    修改/etc/bash.bashrc文件,在这个文件的最后一行添加以下内容:
    export PATH=$PATH:/home/ubuntu/toolchain/gcc-7.5.0/bin/
                      修改为自己的交叉编译工具链的路径

7. 使修改后的环境变量立即生效
    source /etc/bash.bashrc

8. 测试是否安装成功 
    arm-linux-gnueabihf-gcc -v   ---> 查看交叉编译工具链的版本号
    
    打印一些结果表示安装成功:
    gcc version 7.5.0 (Linaro GCC 7.5-2019.12) 

9. 安装一个32位软件的兼容库
    9.1 ubuntu必须可以联网
    9.2 配置源 
        打开源的配置文件/etc/apt/sources.list,将https修改为http
    9.3. 更新源
        sudo apt-get update
    9.4 安装lib32z1库
        sudo apt-get install lib32z1

2.安装securetCRT串口工具

1. securetCRT软件包的路径: STM32MP157-学生资料\02_开发工具\02.1_串口工具\securetCRT\scrt-sfx-9.0.0.2430 2. 安装步骤参考《SCRT804安装说明文档.docx》安装文档。

3.M4开发环境搭建

3.1 安装PACK包


【1】安装pack包

参考路径:D:\STM32MP157-学生资料\STM32MP157-学生资料\03_M4资料\03-软件工具\MDK Keil

参考文档:keil安装教程.docx

【2】成功现象

3.2 安装STM32CubMX软件


参考路径:D:\STM32MP157-学生资料\03_M4资料\03-软件工具\STM32CubeMx

参考文档:安装stm32cubeMX软件教程.docx

【1】安装jre-8u271-windows-x64.exe,以管理员身份运行,不能出现中文路径

【2】安装SetupSTM32CubeMX-6.3.0-Win.exe,以管理员身份运行,不能出现中文路径

【3】导入STM32MP1包(可以先不做)

1、打开cubmx软件

2.点击”Help--->manager Embedded software packages”,弹出如下图工作框

【4】导入en.STM32Cube_FW_MP1_V1.4.0_v1.4.0.zip,这个包不需要解压

【5】安装成功的现象

3.3 安装ST-LINK驱动


参考路径:D:\STM32MP157-学生资料\03_M4资料\03-软件工具\ST LINK驱动及教程

参考文档:STLink驱动的安装和固件升级教程.docx

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

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

相关文章

MySQL最新2023年面试题及答案,汇总版(3)【MySQL最新2023年面试题及答案,汇总版-第三十三刊】

文章目录 MySQL最新2023年面试题及答案,汇总版(3)01、隔离级别与锁的关系?02、SQL 约束有哪几种呢?03、如何优化子查询?04、什么是前缀索引?05、MySQL5.6和MySQL5.7对索引做了哪些优化?06、MySQL有关权限的…

Linux学习第34天:Linux LCD 驱动实验(一):星星之火可以燎原

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 LCD显示屏是由一个一个的像素点构成的。当你能控制一个像素点的亮暗及颜色变化的时候,你就能让LCD显示瓶显示五颜六色的整幅图案。甚至可以让LCD屏幕…

Spring-Security前后端分离权限认证

前后端分离 一般来说,我们用SpringSecurity默认的话是前后端整在一起的,比如thymeleaf或者Freemarker,SpringSecurity还自带login登录页,还让你配置登出页,错误页。 但是现在前后端分离才是正道,前后端分离的话,那就…

Django快速入门(一)

Django三板斧 1. 基本使用 三板斧: HttpResponse,render,redirect from django.shortcuts import HttpResponse,render,redirect# 一. 返回字符串类型的数据 return HttpResponse(字符串) # 二. 返回HTML文件 # 1. 动态HTML页面: return render(request,login.html) def ab…

极智开发 | CUDA线程模型与全局索引计算方式

欢迎关注我的公众号 [极智视界],获取我的更多经验分享 大家好,我是极智视界,本文分享一下 CUDA线程全局索引计算方式。 邀您加入我的知识星球「极智视界」,星球内有超多好玩的项目实战源码和资源下载,链接:https://t.zsxq.com/0aiNxERDq CUDA 线程全局索引的计算,是很容…

图文加多个测试带你彻底搞懂Netty ChannelPipeline的执行顺序(附源码)

这里是weihubeats,觉得文章不错可以关注公众号小奏技术,文章首发。拒绝营销号,拒绝标题党 netty version 4.1.65.Final ChannelPipeline 是什么 Pipeline,管道、流水线,类似于责任链模式。基本上我们使用Netty开发程序需要编写…

Apache RocketMQ - 概述

2022年,RocketMQ 5.0的正式版发布,相比于4.0版本而言,架构走向云原生化,并且覆盖了更多的业务场景。 如何从互联网时代演进到云时代? 1. 消息队列演进史 操作系统、数据库、中间件是基础软件的三驾马车,…

Sketch是什么软件,如何收费和获得免费版

Sketch软件为设计师构建了一个优秀的本地Mac应用程序。Sketch是整个设计过程的平台,通过基于Web的工具共享工作,获取反馈,测试原型,并将其移交给任何浏览器。Sketch软件的定价根据不同的许可类型和订阅计划而变化。本文从Sketch软…

18. 深度学习 - 从零理解神经网络

文章目录 本文目标预测趋势与关系波士顿房价预测 Hi, 你好。我是茶桁。 我们终于又开启新的篇章了,从今天这节课开始,我们会花几节课来理解一下深度学习的相关知识,了解神经网络,多层神经网络相关知识。并且,我们会尝…

网络安全自学手册

想自学网络安全(黑客技术)首先你得了解什么是网络安全!什么是黑客! 网络安全可以基于攻击和防御视角来分类,我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术,而“蓝队”、“安全运营”、“安全…

No module named ‘importlib.metadata‘

解决办法 参考博客 https://wenku.csdn.net/answer/45a1563cc02e9592dd1d1d28fe7b88e7 pip install importlib_metadata

使用U盘安装ubuntu22操作教程

U盘启动 将烧录好的U盘,插上待安装系统的电脑 服务器在开机之后长按【ESC键】进入BIOS选项中,选择对应的U盘启动 如下图,在界面中“USB”选项就是我的U盘,第一启动项选择U盘启动,其他启动项不动,选择后按F…

③【操作表数据】MySQL添加数据、修改数据、删除数据

个人简介:Java领域新星创作者;阿里云技术博主、星级博主、专家博主;正在Java学习的路上摸爬滚打,记录学习的过程~ 个人主页:.29.的博客 学习社区:进去逛一逛~ MySQL添加数据、修改数据、删除数据 &#x1f…

让旗下产品受到更多用户认可,GNC健安喜登陆中国国际进口博览会

11月5日-10日,第六届中国国际进口博览会(以下简称“中国进博会”)在上海国家会展中心正式起航。自2018年首次举办以来,中国进博会受到了无数参展企业的推崇,无数制造商、采购商的追捧。随着参会企业的逐年增长&#xf…

辐射骚扰整改思路及方法:对共模电流的影响?|深圳比创达电子EMC

某产品首次EMC测试时,辐射、静电、浪涌均失败。本篇文章就“原理探究:对共模电流的影响”问题进行详细讨论。 现在来研究左侧的磁场分布情况。分别对两根导线使用右手螺旋定则可以发现,两根导线的磁场均为顺时针方向,即磁场是互相…

Java后端开发——JDBC入门实验

JDBC(Java Database Connectivity)是Java编程语言中用于与数据库建立连接并进行数据库操作的API(应用程序编程接口)。JDBC允许开发人员连接到数据库,执行各种操作(如插入、更新、删除和查询数据&#xff09…

代码随想录 Day38 完全背包问题 LeetCode T70 爬楼梯 T322 零钱兑换 T279 完全平方数

前言 在今天的题目开始之前,让我们来回顾一下之前的知识,动规五部曲 1.确定dp数组含义 2.确定dp数组的递推公式 3.初始化dp数组 4.确定遍历顺序 5.打印dp数组来排错 tips: 1.当求取物品有限的时候用0-1背包,求取物品无限的时候用完全背包 结果是排列还是组合也有说法,当结果是组…

如何选择最适合的知识付费小程序开发工具?

在选择适合的知识付费小程序开发工具时,需要考虑开发者的技能水平、项目需求、平台兼容性以及用户体验。下面将介绍一些常用的开发工具,并提供一些选择工具的考虑因素。 1. 微信小程序开发工具 微信小程序是知识付费小程序的一个常见平台,…

生活污水处理一体化处理设备有哪些

生活污水处理一体化处理设备有多种类型,包括但不限于以下几种: 鼓风机:提供曝气系统所需的气流。潜水污水提升泵:将污水从低处提升到高处。旋转式滚筒筛分机:对污水中的悬浮物进行分离和筛选。回旋式格栅:…

LVS NAT 模式

1.3.2. LVS DR 模式 模式(局域网改写 (局域网改写 mac 地址) ①.客户端将请求发往前端的负载均衡器,请求报文源地址是 CIP,目标地址为 VIP。 ②.负载均衡器收到报文后,发现请求的是在规则里面存在的地址&am…