【STM32】在标准库中使用DMA

1.MDA简介

DMA全称Direct Memory Access,直接存储区访问。

DMA传输将数据从一个地址空间复制到另一个地址空间。当CPU初始化这个传输动作,传输动作本身是由DMA控制器来实现和完成的。DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为RAM和IO设备开辟一个直接传输数据的通道,使得CPU的效率大大提高。

STM32F4xx系列的DMA支持外设到存储器传输、存储器到外设传输和存储器到存储器传输三种传输模式。 这里的外设一般指外设的数据寄存器,比如ADC、SPI、I2C、DCMI等等外设的数据寄存器,存储器一般是指片内SRAM、外部存储器、片内Flash等等。

外设到存储器传输就是把外设数据寄存器内容转移到指定的内存空间。比如进行ADC采集时我们可以利用DMA传输把AD转换数据转移到我们定义的存储区中, 这样对于多通道采集、采样频率高、连续输出数据的AD采集是非常高效的处理方法。

存储区到外设传输就是把特定存储区内容转移至外设的数据寄存器中,这种多用于外设的发送通信。

存储器到存储器传输就是把一个指定的存储区内容拷贝到另一个存储区空间。功能类似于C语言内存拷贝函数memcpy, 利用DMA传输可以达到更高的传输效率,特别是DMA传输是不占用CPU的,可以节省很多CPU资源。

1.1外设通道选择

STM32F4xx系列资源丰富,具有两个DMA控制器,同时外设繁多,为实现正常传输,DMA需要通道选择控制。每个DMA控制器具有8个数据流, 每个数据流对应8个外设请求。在实现DMA传输之前,DMA控制器会通过DMA数据流x配置寄存器DMA_SxCR(x为0~7,对应8个DMA数据流)的CHSEL[2:0]位选择对应的通道作为该数据流的目标外设。

外设通道选择要解决的主要问题是决定哪一个外设作为该数据流的源地址或者目标地址。

DMA1各个通道的请求映像

DMA1各个通道的请求映像

DMA2各个通道的请求映像DMA2各个通道的请求映像每个外设请求都占用一个数据流通道,相同外设请求可以占用不同数据流通道。

1.2仲裁器

一个DMA控制器对应8个数据流,数据流包含要传输数据的源地址、目标地址、数据等等信息。如果我们需要同时使用同一个DMA控制器(DMA1或DMA2)多个外设请求时, 那必然需要同时使用多个数据流,那究竟哪一个数据流具有优先传输的权利呢?这就需要仲裁器来管理判断了。

仲裁器管理数据流方法分为两个阶段。第一阶段属于软件阶段,我们在配置数据流时可以通过寄存器设定它的优先级别, 具体配置DMA_SxCR寄存器PL[1:0]位,可以设置为非常高、高、中和低四个级别。第二阶段属于硬件阶段,如果两个或以上数据流软件设置优先级一样, 则他们优先级取决于数据流编号,编号越低越具有优先权,比如数据流2优先级高于数据流3。

1.3FIFO

每个数据流都独立拥有四级32位FIFO(先进先出存储器缓冲区)。DMA传输具有FIFO模式和直接模式。

直接模式在每个外设请求都立即启动对存储器传输。在直接模式下,如果DMA配置为存储器到外设传输那DMA会见一个数据存放在FIFO内, 如果外设启动DMA传输请求就可以马上将数据传输过去。

FIFO用于在源数据传输到目标地址之前临时存放这些数据。可以通过DMA数据流xFIFO控制寄存器DMA_SxFCR的FTH[1:0]位来控制FIFO的阈值, 分别为1/4、1/2、3/4和满。如果数据存储量达到阈值级别时,FIFO内容将传输到目标中。

FIFO对于要求源地址和目标地址数据宽度不同时非常有用,比如源数据是源源不断的字节数据,而目标地址要求输出字宽度的数据, 即在实现数据传输时同时把原来4个8位字节的数据拼凑成一个32位字数据。此时使用FIFO功能先把数据缓存起来,分别根据需要输出数据。

FIFO另外一个作用使用于突发(burst)传输。

2.DMA数据配置

DMA配置可能情况

2.1DMA传输模式

DMA2支持全部三种传输模式,而DMA1只有外设到存储器和存储器到外设两种模式。模式选择可以通过DMA_SxCR寄存器的DIR[1:0]位控制, 进而将DMA_SxCR寄存器的EN位置1就可以使能DMA传输。

在DMA_SxCR寄存器的PSIZE[1:0]和MSIZE[1:0]位分别指定外设和存储器数据宽度大小,可以指定为字节(8位)、半字(16位)和字(32位), 我们可以根据实际情况设置。直接模式要求外设和存储器数据宽度大小一样,实际上在这种模式下DMA数据流直接使用PSIZE,MSIZE不被使用。

2.2源地址和目标地址

DMA数据流x外设地址DMA_SxPAR(x为0~7)寄存器用来指定外设地址,它是一个32位数据有效寄存器。 DMA数据流x存储器0地址DMA_SxM0AR(x为0~7) 寄存器和DMA数据流x存储器1地址DMA_SxM1AR(x为0~7)寄存器用来存放存储器地址, 其中DMA_SxM1AR只用于双缓冲模式,DMA_SxM0AR和DMA_SxM1AR都是32位数据有效的。

当选择外设到存储器模式时,即设置DMA_SxCR寄存器的DIR[1:0] 位为“00”,DMA_SxPAR寄存器为外设地址,也是传输的源地址, DMA_SxM0AR寄存器为存储器地址,也是传输的目标地址。对于存储器到存储器传输模式,即设置DIR[1:0]位为“10”时, 采用与外设到存储器模式相同配置。而对于存储器到外设,即设置DIR[1:0]位为“01”时,DMA_SxM0AR寄存器作为为源地址,DMA_SxPAR寄存器作为目标地址。

2.3流控制器

流控制器主要涉及到一个控制DMA传输停止问题。DMA传输在DMA_SxCR寄存器的EN位被置1后就进入准备传输状态,如果有外设请求DMA传输就可以进行数据传输。 很多情况下,我们明确知道传输数据的数目,比如要传1000个或者2000个数据,这样我们就可以在传输之前设置DMA_SxNDTR寄存器为要传输数目值, DMA控制器在传输完这么多数目数据后就可以控制DMA停止传输。

DMA数据流x数据项数DMA_SxNDTR(x为0~7)寄存器用来记录当前仍需要传输数目,它是一个16位数据有效寄存器,即最大值为65535, 这个值在程序设计是非常有用也是需要注意的地方。我们在编程时一般都会明确指定一个传输数量,在完成一次数目传输后DMA_SxNDTR计数值就会自减,当达到零时就说 明传输完成。

如果某些情况下在传输之前我们无法确定数据的数目,那DMA就无法自动控制传输停止了,此时需要外设通过硬件通信向DMA控制器发送停止传输信号。 这里有一个大前提就是外设必须是可以发出这个停止传输信号,只有SDIO才有这个功能,其他外设不具备此功能。

2.4循环模式

循环模式相对应于一次模式。一次模式就是传输一次就停止传输,下一次传输需要手动控制,而循环模式在传输一次后会自动按照相同配置重新传输,周而复始直至被控制停止或传输发生错误。

通过DMA_SxCR寄存器的CIRC位可以使能循环模式。

2.5传输类型

DMA传输类型有单次(Single)传输和突发(Burst)传输。突发传输就是用非常短时间结合非常高数据信号率传输数据,相对正常传输速度, 突发传输就是在传输阶段把速度瞬间提高,实现高速传输,在数据传输完成后恢复正常速度,有点类似达到数据块“秒传”效果。为达到这个效果突发传输过程要占用AHB总线, 保证要求每个数据项在传输过程不被分割,这样一次性把数据全部传输完才释放AHB总线;而单次传输时必须通过AHB的总线仲裁多次控制才传输完成。

2.6直接模式

默认情况下,DMA工作在直接模式,不使能FIFO阈值级别。

直接模式在每个外设请求都立即启动对存储器传输的单次传输。直接模式要求源地址和目标地址的数据宽度必须一致, 所以只有PSIZE控制,而MSIZE值被忽略。突发传输是基于FIFO的所以直接模式不被支持。另外直接模式不能用于存储器到存储器传输。

在直接模式下,如果DMA配置为存储器到外设传输那DMA会见一个数据存放在FIFO内,如果外设启动DMA传输请求就可以马上将数据传输过去。

2.7双缓冲模式

设置DMA_SxCR寄存器的DBM位为1可启动双缓冲传输模式,并自动激活循环模式。双缓冲不应用与存储器到存储器的传输。双缓冲模式下, 两个存储器地址指针都有效,即DMA_SxM1AR寄存器将被激活使用。开始传输使用DMA_SxM0AR寄存器的地址指针所对应的存储区, 当这个存储区数据传输完DMA控制器会自动切换至DMA_SxM1AR寄存器的地址指针所对应的另一块存储区, 如果这一块也传输完成就再切换至DMA_SxM0AR寄存器的地址指针所对应的存储区,这样循环调用。

当其中一个存储区传输完成时都会把传输完成中断标志TCIF位置1,如果我们使能了DMA_SxCR寄存器的传输完成中断,则可以产生中断信号, 这个对我们编程非常有用。另外一个非常有用的信息是DMA_SxCR寄存器的CT位,当DMA控制器是在访问使用DMA_SxM0AR时CT=0, 此时CPU不能访问DMA_SxM0AR,但可以向DMA_SxM1AR填充或者读取数据;当DMA控制器是在访问使用DMA_SxM1AR时CT=1,此时CPU不能访问DMA_SxM1AR, 但可以向DMA_SxM0AR填充或者读取数据。另外在未使能DMA数据流传输时,可以直接写CT位,改变开始传输的目标存储区。

双缓冲模式应用在需要解码程序的地方是非常有效的。比如MP3格式音频解码播放,MP3是被压缩的文件格式, 我们需要特定的解码库程序来解码文件才能得到可以播放的PCM信号,解码需要一定的实际,按照常规方法是读取一段原始数据到缓冲区, 然后对缓冲区内容进行解码,解码后才输出到音频播放电路,这种流程对CPU运算速度要求高,很容易出现播放不流畅现象。 如果我们使用DMA双缓冲模式传输数据就可以非常好的解决这个问题,达到解码和输出音频数据到音频电路同步进行的效果。

2.8DMA中断

每个DMA数据流可以在发送以下事件时产生中断:

  1. 达到半传输:DMA数据传输达到一半时HTIF标志位被置1, 如果使能HTIE中断控制位将产生达到半传输中断;

  2. 传输完成:DMA数据传输完成时TCIF标志位被置1, 如果使能TCIE中断控制位将产生传输完成中断;

  3. 传输错误:DMA访问总线发生错误或者在双缓冲模式下试图访问“受限”存储器地址寄存器时TEIF标志位被置1, 如果使能TEIE中断控制位将产生传输错误中断;

  4. FIFO错误:发生FIFO下溢或者上溢时FEIF标志位被置1, 如果使能FEIE中断控制位将产生FIFO错误中断;

  5. 直接模式错误:在外设到存储器的直接模式下,因为存储器总线没得到授权,使得先前数据没有完成被传输到存储器空间上, 此时DMEIF标志位被置1,如果使能DMEIE中断控制位将产生直接模式错误中断。

3.DMA_InitTypeDef初始化结构体

typedef struct {
    uint32_t DMA_Channel;             //通道选择
    uint32_t DMA_PeripheralBaseAddr;  //外设地址
    uint32_t DMA_Memory0BaseAddr;     //存储器0地址
    uint32_t DMA_DIR;                 //传输方向
    uint32_t DMA_BufferSize;          //数据数目
    uint32_t DMA_PeripheralInc;       //外设递增
    uint32_t DMA_MemoryInc;           //存储器递增
    uint32_t DMA_PeripheralDataSize;  //外设数据宽度
    uint32_t DMA_MemoryDataSize;      //存储器数据宽度
    uint32_t DMA_Mode;                //模式选择
    uint32_t DMA_Priority;            //优先级
    uint32_t DMA_FIFOMode;            //FIFO模式
    uint32_t DMA_FIFOThreshold;       //FIFO阈值
    uint32_t DMA_MemoryBurst;         //存储器突发传输
    uint32_t DMA_PeripheralBurst;     //外设突发传输
} DMA_InitTypeDef;
  1. DMA_Channel:DMA请求通道选择,可选通道0至通道7,每个外设对应固定的通道, 具体设置值需要查表 DMA1各个通道的请求映像 和表 DMA2各个通道的请求映像 ; 它设定DMA_SxCR寄存器的CHSEL[2:0]位的值。例如,我们使用模拟数字转换器ADC3规则采集4个输入通道的电压数据,查表 DMA2各个通道的请求映像 可知使用通道2。

  2. DMA_PeripheralBaseAddr:外设地址,设定DMA_SxPAR寄存器的值;一般设置为外设的数据寄存器地址, 如果是存储器到存储器模式则设置为其中一个存储区地址。ADC3的数据寄存器ADC_DR地址为((uint32_t)ADC3+0x4C)。

  3. DMA_Memory0BaseAddr:存储器0地址,设定DMA_SxM0AR寄存器值;一般设置为我们自定义存储区的首地址。 我们程序先自定义一个16位无符号整形数组ADC_ConvertedValue[4]用来存放每个通道的ADC值, 所以把数组首地址(直接使用数组名即可)赋值给DMA_Memory0BaseAddr。

  4. DMA_DIR:传输方向选择,可选外设到存储器、存储器到外设以及存储器到存储器。 它设定DMA_SxCR寄存器的DIR[1:0]位的值。ADC采集显然使用外设到存储器模式。

  5. DMA_BufferSize:设定待传输数据数目,初始化设定DMA_SxNDTR寄存器的值。 这里ADC是采集4个通道数据,所以待传输数目也就是4。

  6. DMA_PeripheralInc:如果配置为DMA_PeripheralInc_Enable,使能外设地址自动递增功能,它设定DMA_SxCR寄存器的PINC位的值; 一般外设都是只有一个数据寄存器,所以一般不会使能该位。ADC3的数据寄存器地址是固定并且只有一个所以不使能外设地址递增。

  7. DMA_MemoryInc:如果配置为DMA_MemoryInc_Enable,使能存储器地址自动递增功能,它设定DMA_SxCR寄存器的MINC位的值; 我们自定义的存储区一般都是存放多个数据的,所以使能存储器地址自动递增功能。我们之前已经定义了一个包含4个元素的数字用来存放数据, 使能存储区地址递增功能,自动把每个通道数据存放到对应数组元素内。

  8. DMA_PeripheralDataSize:外设数据宽度,可选字节(8位)、半字(16位)和字(32位),它设定DMA_SxCR寄存器的PSIZE[1:0]位的值。 ADC数据寄存器只有低16位数据有效,使用半字数据宽度。

  9. DMA_MemoryDataSize:存储器数据宽度,可选字节(8位)、半字(16位)和字(32位),它设定DMA_SxCR寄存器的MSIZE[1:0]位的值。 保存ADC转换数据也要使用半字数据宽度,这跟我们定义的数组是相对应的。

  10. DMA_Mode:DMA传输模式选择,可选一次传输或者循环传输,它设定DMA_SxCR寄存器的CIRC位的值。 我们希望ADC采集是持续循环进行的,所以使用循环传输模式。

  11. DMA_Priority:软件设置数据流的优先级,有4个可选优先级分别为非常高、高、中和低,它设定DMA_SxCR寄存器的PL[1:0]位的值。 DMA优先级只有在多个DMA数据流同时使用时才有意义,这里我们设置为非常高优先级就可以了。

  12. DMA_FIFOMode:FIFO模式使能,如果设置为DMA_FIFOMode_Enable表示使能FIFO模式功能; 它设定DMA_SxFCR寄存器的DMDIS位。ADC采集传输使用直接传输模式即可,不需要使用FIFO模式。

  13. DMA_FIFOThreshold:FIFO阈值选择,可选4种状态分别为FIFO容量的1/4、1/2、3/4和满;它设定DMA_SxFCR寄存器的FTH[1:0]位; DMA_FIFOMode设置为DMA_FIFOMode_Disable,那DMA_FIFOThreshold值无效。ADC采集传输不使用FIFO模式,设置改值无效。

  14. DMA_MemoryBurst:存储器突发模式选择,可选单次模式、4节拍的增量突发模式、8节拍的增量突发模式或16节拍的增量突发模式, 它设定DMA_SxCR寄存器的MBURST[1:0]位的值。ADC采集传输是直接模式,要求使用单次模式。

  15. DMA_PeripheralBurst:外设突发模式选择,可选单次模式、4节拍的增量突发模式、8节拍的增量突发模式或16节拍的增量突发模式, 它设定DMA_SxCR寄存器的PBURST[1:0]位的值。ADC采集传输是直接模式,要求使用单次模式。

4.DMA存储器到存储器模式实验

存储器到存储器模式可以实现数据在两个内存的快速拷贝。我们先定义一个静态的源数据,然后使用DMA传输把源数据拷贝到目标地址上,最后对比源数据和目标地址的数据,看看是否传输准确。

#ifndef __BSP_DMA_H
#define __BSP_DMA_H

#ifdef __cplusplus
extern "C"{

#endif

#include "stm32f4xx.h"

/* 相关宏定义,使用存储器到存储器传输必须使用DMA2 */
#define DMA_STREAM               DMA2_Stream0
#define DMA_CHANNEL              DMA_Channel_0
#define DMA_STREAM_CLOCK         RCC_AHB1Periph_DMA2
#define DMA_IT_TCIF              DMA_IT_TCIF0
#define DMA_IT_HTIF              DMA_IT_HTIF0
#define DMA_FLAG_TCIF            DMA_FLAG_TCIF0
#define DMA_FLAG_HTIF            DMA_FLAG_HTIF0
#define DMA_STREAM_IRQn          DMA2_Stream0_IRQn
#define DMA_STREAM_IRQHandler    DMA2_Stream0_IRQHandler

#define BUFFER_SIZE              32

void Init_M2M_DMA(void);
#ifdef __cplusplus
}
#endif

#endif
#include "bsp_dma.h"
#include "stdio.h"
#include "string.h"

/* 定义aSRC_Const_Buffer数组作为DMA传输数据源
const关键字将aSRC_Const_Buffer数组变量定义为常量类型 */
const uint32_t aSRC_Const_Buffer[BUFFER_SIZE]= {
                        0x01020304,0x05060708,0x090A0B0C,0x0D0E0F10,
                        0x11121314,0x15161718,0x191A1B1C,0x1D1E1F20,
                        0x21222324,0x25262728,0x292A2B2C,0x2D2E2F30,
                        0x31323334,0x35363738,0x393A3B3C,0x3D3E3F40,
                        0x41424344,0x45464748,0x494A4B4C,0x4D4E4F50,
                        0x51525354,0x55565758,0x595A5B5C,0x5D5E5F60,
                        0x61626364,0x65666768,0x696A6B6C,0x6D6E6F70,
                        0x71727374,0x75767778,0x797A7B7C,0x7D7E7F80
};
/* 定义DMA传输目标存储器 */
uint32_t aDST_Buffer[BUFFER_SIZE];

void Init_M2M_DMA(void)
{
	/* 使能DMA时钟 */
    RCC_AHB1PeriphClockCmd(DMA_STREAM_CLOCK, ENABLE);
	
	 /* 复位初始化DMA数据流 */
    DMA_DeInit(DMA_STREAM);

    /* 确保DMA数据流复位完成 */
    while (DMA_GetCmdStatus(DMA_STREAM) != DISABLE) {
    }
	
	DMA_InitTypeDef  DMA_InitStructure;
	DMA_InitStructure.DMA_BufferSize=BUFFER_SIZE;//一次DMA事务传输的数据个数
	DMA_InitStructure.DMA_Channel=DMA_CHANNEL;
	DMA_InitStructure.DMA_DIR=DMA_DIR_MemoryToMemory;
	DMA_InitStructure.DMA_FIFOMode=DMA_FIFOMode_Disable;
	DMA_InitStructure.DMA_FIFOThreshold=DMA_FIFOThreshold_Full;
	DMA_InitStructure.DMA_Memory0BaseAddr= (uint32_t)aDST_Buffer;
	DMA_InitStructure.DMA_MemoryBurst=DMA_MemoryBurst_Single;
	DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Word;
	DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;
	DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;
	DMA_InitStructure.DMA_PeripheralBaseAddr=(uint32_t)aSRC_Const_Buffer;
	DMA_InitStructure.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;
	DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Word;
	DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Enable;
	DMA_InitStructure.DMA_Priority=DMA_Priority_Low;
	DMA_Init(DMA_STREAM,&DMA_InitStructure);
	
	
	//配置中断控制器并使能中断
	NVIC_InitTypeDef NVIC_InitStruct;
	NVIC_InitStruct.NVIC_IRQChannel=DMA_STREAM_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;
	NVIC_Init(&NVIC_InitStruct);
	DMA_ITConfig(DMA_STREAM,DMA_IT_TCIF|DMA_IT_HTIF,ENABLE);
	
	DMA_ClearITPendingBit(DMA_STREAM,DMA_IT_TCIF|DMA_IT_HTIF);
	
	DMA_Cmd(DMA_STREAM,ENABLE);
}

void DMA_STREAM_IRQHandler(void)
{
	if(SET== DMA_GetFlagStatus(DMA_STREAM,DMA_FLAG_HTIF))
	{
		 printf("half transfer\r\n");
		 DMA_ClearFlag(DMA_STREAM,DMA_FLAG_HTIF);
	}
	else if(SET== DMA_GetFlagStatus(DMA_STREAM,DMA_FLAG_TCIF))
	{
		printf("transfer complete\r\n");
		DMA_ClearFlag(DMA_STREAM,DMA_FLAG_TCIF);
	}
	
//	if(SET==DMA_GetITStatus(DMA_STREAM,DMA_IT_HTIF))
//	{
//		//half transfer complete
//		printf("half transfer\r\n");
//		DMA_ClearITPendingBit(DMA_STREAM,DMA_IT_HTIF);
//		
//	}
//	else if(SET==DMA_GetITStatus(DMA_STREAM,DMA_IT_TCIF))
//	{
//		//transfer complete
//		
//		if(0== memcmp(aSRC_Const_Buffer,aDST_Buffer,BUFFER_SIZE))
//		{
//			printf("transfer complete\r\n");
//		}
//		DMA_ClearITPendingBit(DMA_STREAM,DMA_IT_TCIF);
//	}
}

编程注意事项:

  1. 对于存储器到存储器传输模式,源地址和目标地址的设置, 采用与外设到存储器模式相同配置。也就是源存储器地址当作外设地址。
  2. 我们在中断服务函数中检查ITStatus时发现,没有检测到half transfer的IT标志位,但是可以检测到transfer complete的IT标志位。但是FlagStatus都可以获取到,也不知道是啥问题。
  3. 如果我换为其他的DMA2_STREAM,比如DMA2_Stream1。甚至transfer complete的IT标志位都没有检测到。也不知道是啥原因。
  4. 对于存储器到存储器传输模式,只能选择DMA2。

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

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

相关文章

seq2seq+Attention机制原理介绍

一、Seq2seq的局限性 Seq2seq(序列到序列)模型我们在前面讲了它的原理,是一种广泛用于处理序列转换任务的深度学习架构,特别是在机器翻译、文本摘要、对话生成等应用中。然而,尽管seq2seq模型在某些领域取得了显著的成…

使用 Python2.7 抓取 systrace 文件

为了排查安卓终端系统底层问题,需要抓取终端的systrace文件分析,下面是操作步骤: 1、安装python 2.7 2、打开cmd执行命令安装python包:pip install pypiwin32 3、解压six-1.16.0.tar.gz,进入目录用命令安装six&#xf…

《UDS协议从入门到精通》系列——图解0x84:安全数据传输

《UDS协议从入门到精通》系列——图解0x84:安全数据传输 一、简介二、数据包格式2.1 服务请求格式2.2 服务响应格式2.2.1 肯定响应2.2.2 否定响应 Tip📌:本文描述中但凡涉及到其他UDS服务的,均提供专栏内文章链接跳转方式以便快速…

Stable Diffusion最强功能—— 图片背景完美替换

今天分享 Stable Diffusion 图片背景完美替换 功能,通过 Stable Diffusion 图生图重绘蒙版进行背景图的二次重绘。 在广告产品图、头像背景替换、图片后期处理等场景下用到的都很频繁。 整体步骤: 通过 removebg 插件实现图片主体蒙版的抠图 结合图生…

提升研发效能的67个技术点丨IDCF

在当今快速变化的市场环境中,企业要想保持竞争力,就必须不断提高研发效率。高效的研发不仅能够帮助企业快速响应市场需求,还能降低成本、提高产品质量。本文让我们一起来看一下,作为微软18年MVP的技术大咖徐磊老师,梳理…

HTML CSS 基础复习笔记 - 列表使用

用于自己复习 自定义列表 示例代码 <!DOCTYPE html> <html> <head><title>Definition List Example</title> </head> <body><h1>古诗</h1><dl><dt>静夜思</dt><dd>床前明月光&#xff0c;疑…

使用dot来画流程图

Dot是一种图形描述语言&#xff0c;属于Graphviz软件的一部分。Graphviz是一个用于可视化图形&#xff08;图表、网络图等&#xff09;的开源工具集。使用Dot语言&#xff0c;你可以创建并描述节点和边&#xff0c;从而生成图形。以下是如何使用Dot语言画图的基本步骤&#xff…

修复 OpenSSH 爆出极其严重的安全漏洞!

最近几天OpenSSH爆出了一个高危漏洞&#xff1a;CVE-2024-6387&#xff0c;影响到了很多的Linux服务器系统。明月第一时间给所有的代维客户服务器进行了排查和漏洞修复&#xff0c;因此耽搁了一些时间。直到今天才算抽出空来给大家分享一下。严格上来说这个漏洞的危险性还是极高…

Beyond Compare 解锁版下载及安装教程 (文件和文件夹比较工具)

前言 Beyond Compare 是一款功能强大的文件和文件夹比较工具。它支持文件夹比较、文件夹合并与同步、文本比较、表格比较、图片比较、16进制比较、注册表比较、版本比较等多种功能。通过 Beyond Compare&#xff0c;您可以轻松调查文件和文件夹之间的不同之处&#xff0c;并使…

MySQL篇-SQL优化实战-减少子查询

回顾 上一篇了解了分析SQL使用的explain&#xff0c;可以点击查看MySQL篇-SQL优化实战了解我在写sql的注意事项还有explain的说明&#xff0c;这次拿一段生产使用的sql进行优化说明。从14s优化到2.6s 待优化的SQL SELECT DISTINCTswpe.tag_number,hca.ACCOUNT_NAME customer…

ELFK简介

&#x1f468;‍&#x1f393;博主简介 &#x1f3c5;CSDN博客专家   &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01…

K8S学习教程(二):在 PetaExpress KubeSphere容器平台部署高可用 Redis 集群

前言 Redis 是在开发过程中经常用到的缓存中间件&#xff0c;为了考虑在生产环境中稳定性和高可用&#xff0c;Redis通常采用集群模式的部署方式。 在制定Redis集群的部署策略时&#xff0c;常规部署在虚拟机上的方式配置繁琐并且需要手动重启节点&#xff0c;相较之下&#…

java基础:方法

一、方法 1、Java方法是语句的集合&#xff0c;它们在一起执行一个功能。 方法是解决一类问题的步骤的有序集合方法包含于类或对象中方法在程序中被创建&#xff0c;在其他地方被引用 2、设计方法的原则&#xff1a;方法的本意是功能块&#xff0c;就是实现某个功能的语句块…

layui+jsp项目中实现table单元格嵌入下拉选择框功能,下拉选择框可手动输入内容或选择默认值,修改后数据正常回显。

需求 table列表中的数据实现下拉框修改数据&#xff0c;当默认的下拉框不符合要求时&#xff0c;可手动输入内容保存。内容修改后表格显示修改后的值同时表格不刷新。 实现 layui框架下拉框组件只能选择存在的数据&#xff0c;不支持将输入的内容显示在input中的功能&#x…

什么牌子的无线领夹麦克风好,一篇了解哪种领夹麦性价比高

随着5G技术的广泛应用&#xff0c;短视频平台迎来了前所未有的发展机遇&#xff0c;几乎每个地方都有人在记录生活&#xff0c;分享故事。在这样的背景下&#xff0c;户外直播和视频创作的需求急剧增长&#xff0c;然而&#xff0c;户外的复杂声场仅靠普通手机的录音功能实在难…

计算机网络之局域网

目录 1.局域网的基本概念 2.LAN的特性 3.局域网特点 4.拓扑结构 5.传输媒体的选择 6.传输媒体 7.传输技术 8.传输技术距离问题 9.LAN的逻辑结构 10.局域网工作原理 上篇文章内容&#xff1a;OSI七层体系结构 1.局域网的基本概念 局域网 是将分散在有限地 理范围内&…

Robust Test-Time Adaptation in Dynamic Scenarios--论文阅读

论文笔记 资料 1.代码地址 https://github.com/BIT-DA/RoTTA 2.论文地址 https://arxiv.org/abs/2303.13899 3.数据集地址 coming soon 1论文摘要的翻译 测试时间自适应(TTA)旨在使预先7训练的模型适用于仅具有未标记测试数据流的测试分布。大多数以前的TTA方法已经在…

SQL Server特性

一、创建表 在sql server中使用create table来创建新表。 create table Customers( id int primary key identity(1,1), name varchar(5) ) 该表名为Customers其中包含了2个字段&#xff0c;分别为id&#xff08;主键&#xff09;以及name。 1、数据类型 整数类型&#xff…

NAT地址转换实验,实验超简单

实验拓扑 实验目的 将内网区域&#xff08;灰色区域&#xff09;的地址转换为172.16.1.0 实验过程 配置静态NAT&#xff08;基于接口的静态NAT&#xff09; R1配置 <Huawei>sys Enter system view, return user view with CtrlZ. [Huawei]sysname R1 [R1]un in en I…

探索 Apache Paimon 在阿里智能引擎的应用场景

摘要&#xff1a;本文整理自Apache Yarn && Flink Contributor&#xff0c;阿里巴巴智能引擎事业部技术专家王伟骏&#xff08;鸿历&#xff09;老师在 5月16日 Streaming Lakehouse Meetup Online 上的分享。内容主要分为以下三个部分&#xff1a; 一、 阿里智能引擎…