当前位置: 首页 > news >正文

ADC在STM32F1系列的使用详解

目录

1.  ADC简介

2.  逐次逼近型ADC(ADC0809)

3.  ADC框图(STM32)

4.  ADC基本结构

5.  输入通道

6.  转换模式

6.1  单次转换

6.1.1  非扫描模式

6.1.2  扫描模式

6.2  连续转换

6.2.1  非扫描模式

6.2.2  扫描模式

7.  触发控制

8.  转换时间

9.  代码编写

9.1  引脚使能

9.2  预分频器配置

9.3  ADC配置介绍

9.4  ADC相关配置

9.4.1  开启时钟

9.4.2  规组通道配置

9.4.3  ADC初始化

9.4.4  ADC使能

9.4.5  ADC校准

9.5  获取AD转换的值

10.  完整代码


1.  ADC简介

        ADC全称是(Analog-to-Digital Converter)模拟-数字转换器,一般我们把模拟信号(Analog signal) 用A来进行简写,数字信号(digital signal) 用D来表示。主要用于将连续传输的模拟信号转换为数字信号,便于数字系统(如中央处理器CPU、微控制器MCU等)对传输信息进行快速处理和分析。

         模拟信号是指用连续变化的物理量所表达的信息,如温度、湿度、压力、电压、电流等。ADC模块所采集的模拟信号是连续变化的电压或电流信号,其数值在一定范围内连续变化,如下所示:

        在单片机的使用中,我们可以通过ADC的转换将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁。

         ADC采样的实现方式主要有两种:外接采样芯片控制核心内部的采样模块。许多MCU和DSP内部集成了ADC模块。例如,STM32F103C8T6具备一个12位的ADC,1us的转换时间,其电压输出范围在0~3.3V,转换结果范围0~4095(即2^12-1),其ADC资源有ADC1、ADC2,10个外部输入通道。

2.  逐次逼近型ADC(ADC0809)

        我们先来了解一下ADC0809的工作原理。

        首先是通道选择开关,通过通道选择开关,选择(IN0~IN7)其中的一路,输入到这个点进行转换:

        然后是地址锁存和译码,这里你想要选择哪一路,需要将通道号放到(ADDA、ADDB、ADDC)这三个脚上,然后通过ALE给出锁存信号,对应的通道选择开关就会自动拨好了:

        比较器是一个电压比较器,他可以判断两个输入信号电压的大小关系,其中通道选择开关输入的是待测的电压,另一端是DAC(数模转换器)的电压:

        这里待测电压是未知的,但是DAC所出的电压是我们通过数模转换来的,其编码是已知的,我们通过比较器进行比较,当待测电压大于DAC所示电压,我们就调大DAC的值,如果待测电压小于DAC所示电压,我们就调小DAC的值,直到待测电压等于DAC所示电压,这样DAC的输入数据就是待测电压的数据,我们就可以知道待测电压的编码(类似于二分法)。

        得出待测电压的编码通过三态锁存缓冲器进行输出,8位就有8根线,12位就有12根:

3.  ADC框图(STM32)

        STM32F1系列其芯片内部有多达18个通道,可测量16个外部和2个内部信号源:

        通道检测数据进入搭配模拟多路开关,模拟多路开关将数据输出的“模拟至数字转换器”(这里的作用类似于上面介绍的逐次逼近ADC),将转换数据传至数据寄存器,取出结果:

        对于这里,我们可以将注入通道或者规则通道比作饭店上菜的菜单,注入通道的通道相当于菜单上的菜,菜单上有菜(有数据),厨房做菜(注入通道寄存器接受数据),菜单上有多少菜做多少,从上往下一道一道做(数据逐次注入);

        规则通道有16个通道(也就是菜单上能写16个),但是规则通道数据寄存器只有一个,所以每当有新菜,就会将之前的菜划掉,只能保存最后一个数据,这里就需要搭配DMA来使用(作用就是当接收到一个数据之后,将这个数据挪到其他地方去,防止被覆盖):

        这里相当于ADC0809的START信号(开始转换信号),对于STM32的ADC触发ADC开始转换的信号又两种:软件触发硬件触发

        软件触发就是在程序中手动调用一条代码,就可以启动转换。

        硬件触发如下,由于ADC需要经过一个固定时间转换一次,因此我们需要通过定时器进行控制时间,但是若是实时采集数据,会频繁进入定时器,频繁进入中断,而中断又有优先级,若是多处地方需要频繁进入中断,这将会导致程序卡死,不过对于这种需要频繁进入中断,并且中断之进行简单的操作,一般会有硬件的支持:

        这里需要注意一点,ADC最大范围14MHz,如果分频系数选择2或者4分频,最大分别是36MHz和18MHz超范围了,因此只能选择6或者8分频:

4.  ADC基本结构

5.  输入通道

6.  转换模式

6.1  单次转换

6.1.1  非扫描模式

        只有第一个序列1的位置有效,在其中选择转换的通道,例如选择通道2,这样ADC就会对通道2进行模数转换,过一会转换完成,将其放到数据寄存器里,将EOC标志位置1,表示转换完成:

6.1.2  扫描模式

        其与非扫描模式不同的是,非扫描模式只使用了序列1,而扫描模式将下面序列使用了起来,在结构体初始化时,需要初始化通道数目:

6.2  连续转换

6.2.1  非扫描模式

        这个和单次转换非扫描模式有些类似,但是不同的是,这个在转换结束后不需要停止,可以直接进行下一次转换,不需要多次触发:

6.2.2  扫描模式

        这个就是在单次转换扫描模式基础上,使其连续触发:

7.  触发控制

ADC1和ADC2用于规则通道的外部触发

触发源类型EXTSEL[2:0]
TIM1_CC1事件来自片上定时器的内部信号000
TIM1_CC2事件001
TIM1_CC3事件010
TIM2_CC2事件011
TIM3_TRGO事件100
TIM4_CC4事件101
EXTI线11/TIM8_TRGO事件外部引脚/来自片上定时器的内部信号110
SWSTART软件控制位111

8.  转换时间

        ADC转换步骤:采样、保持、量化、编码

STM32的ADC的总转换时间为:

T_{CONV}=采样时间+12.5个ADC周期

例如:

当ADCCLK=14MHz,采样时间为1.5个ADC周期

T_{CONV}=1.5+12.5=14个ADC周期=1us

9.  代码编写

9.1  引脚使能

        首先初始化GPIO口:

void AD_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//开启GPIOA的时钟/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);					//将PA0引脚初始化为模拟输入}

9.2  预分频器配置

        然后是RCC预分频器的配置,找到stm32f10x_rcc.h找到:

void RCC_ADCCLKConfig(uint32_t RCC_PCLK2);

        其可以对APB2的72MHz时钟选择2、4、6、8分频,输入到ADCCLK:

/** @defgroup ADC_clock_source * @{*/#define RCC_PCLK2_Div2                   ((uint32_t)0x00000000)
#define RCC_PCLK2_Div4                   ((uint32_t)0x00004000)
#define RCC_PCLK2_Div6                   ((uint32_t)0x00008000)
#define RCC_PCLK2_Div8                   ((uint32_t)0x0000C000)
#define IS_RCC_ADCCLK(ADCCLK) (((ADCCLK) == RCC_PCLK2_Div2) || ((ADCCLK) == RCC_PCLK2_Div4) || \((ADCCLK) == RCC_PCLK2_Div6) || ((ADCCLK) == RCC_PCLK2_Div8))

例如设置成6分频:

	/*设置ADC时钟*/RCC_ADCCLKConfig(RCC_PCLK2_Div6);						//选择时钟6分频,ADCCLK = 72MHz / 6 = 12MHz

9.3  ADC配置介绍

        ADC相关配置存放在stm32f10x_adc相关文件内:

/** @defgroup ADC_Exported_Functions* @{*/void ADC_DeInit(ADC_TypeDef* ADCx);
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);
void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct);
void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState);
void ADC_ResetCalibration(ADC_TypeDef* ADCx);
FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx);
void ADC_StartCalibration(ADC_TypeDef* ADCx);
FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx);
void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx);
void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number);
void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
void ADC_ExternalTrigConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);
uint32_t ADC_GetDualModeConversionValue(void);
void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv);
void ADC_ExternalTrigInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_SoftwareStartInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx);
void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length);
void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset);
uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel);
void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog);
void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold, uint16_t LowThreshold);
void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel);
void ADC_TempSensorVrefintCmd(FunctionalState NewState);
FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT);
void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT);

        方便后续需要使用我们简单介绍一下:

        DeInit恢复缺省配置(恢复默认初始状态),Init初始化,StructInit结构体初始化:

void ADC_DeInit(ADC_TypeDef* ADCx);
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);
void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct);

        用于给ADC上电:

void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);

        用于开启DMA输出信号,如果使用DMA转运数据,需要调用这个:

void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);

        用于中断输出控制:

void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState);

        复位校准,获取复位校准状态:

void ADC_ResetCalibration(ADC_TypeDef* ADCx);
FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx);

        开始校准,获取开始校准状态:

void ADC_StartCalibration(ADC_TypeDef* ADCx);
FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx);

        ADC软件开始转换控制,这个就是用于软件触发的函数:

void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);

         ADC获取软件开始转换状态:

FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx);

        用于间断模式控制,第一个函数表示每隔几个通道间断一次,第二个函数表示启用间断模式:

void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number);
void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);

        用于ADC规则组通道配置,配置选定的ADC常规通道、其在序列器中的对应等级及其采样时间::

void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);

ADCx: 其中x可以是1、2或3,以选择ADC外设。

ADC_Channel: 要配置的ADC通道。

此参数可以是以下值之一:@arg ADC_Channel_0: ADC Channel0 selected@arg ADC_Channel_1: ADC Channel1 selected@arg ADC_Channel_2: ADC Channel2 selected@arg ADC_Channel_3: ADC Channel3 selected@arg ADC_Channel_4: ADC Channel4 selected@arg ADC_Channel_5: ADC Channel5 selected@arg ADC_Channel_6: ADC Channel6 selected@arg ADC_Channel_7: ADC Channel7 selected@arg ADC_Channel_8: ADC Channel8 selected@arg ADC_Channel_9: ADC Channel9 selected@arg ADC_Channel_10: ADC Channel10 selected@arg ADC_Channel_11: ADC Channel11 selected@arg ADC_Channel_12: ADC Channel12 selected@arg ADC_Channel_13: ADC Channel13 selected@arg ADC_Channel_14: ADC Channel14 selected@arg ADC_Channel_15: ADC Channel15 selected@arg ADC_Channel_16: ADC Channel16 selected@arg ADC_Channel_17: ADC Channel17 selected

Rank: 在常规组序列器中的等级。该参数必须在1到16之间。

ADC_SampleTime: 要为所选通道设置的采样时间值。

此参数可以是以下值之一:@arg ADC_SampleTime_1Cycles5: 采样时间等于1.5个周期@arg ADC_SampleTime_7Cycles5: 采样时间等于7.5个周期@arg ADC_SampleTime_13Cycles5: 采样时间等于13.5个周期@arg ADC_SampleTime_28Cycles5: 采样时间等于28.5个周期@arg ADC_SampleTime_41Cycles5: 采样时间等于41.5个周期@arg ADC_SampleTime_55Cycles5: 采样时间等于55.5个周期@arg ADC_SampleTime_71Cycles5: 采样时间等于71.5个周期@arg ADC_SampleTime_239Cycles5: 采样时间等于239.5个周期

        获取AD转换的数据寄存器,读取转换结果:

uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);

        双ADC读取转换结果的函数:

uint32_t ADC_GetDualModeConversionValue(void);

9.4  ADC相关配置

9.4.1  开启时钟

	/*开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);	//开启ADC1的时钟

9.4.2  规组通道配置

	/*规则组通道配置*/ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);		//规则组序列1的位置,配置为通道0

9.4.3  ADC初始化

	/*ADC初始化*/ADC_InitTypeDef ADC_InitStructure;						//定义结构体变量ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;		//模式,选择独立模式,即单独使用ADC1ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	//数据对齐,选择右对齐ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//外部触发,使用软件触发,不需要外部触发ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;		//连续转换,失能,每转换一次规则组序列后停止ADC_InitStructure.ADC_ScanConvMode = DISABLE;			//扫描模式,失能,只转换规则组的序列1这一个位置ADC_InitStructure.ADC_NbrOfChannel = 1;					//通道数,为1,仅在扫描模式下,才需要指定大于1的数,在非扫描模式下,只能是1ADC_Init(ADC1, &ADC_InitStructure);						//将结构体变量交给ADC_Init,配置ADC1

         ADC_InitTypeDef相关参数介绍:

typedef struct
{uint32_t ADC_Mode;                      /*!< 配置ADC以独立模式或双模工作。此参数可以是 @ref ADC_mode 的值。 */FunctionalState ADC_ScanConvMode;       /*!< 指定转换是否在扫描(多通道)或单通道模式下进行。此参数可以设置为 ENABLE 或 DISABLE。 */FunctionalState ADC_ContinuousConvMode; /*!< 指定转换是连续模式还是单次模式进行。此参数可以设置为 ENABLE 或 DISABLE。 */uint32_t ADC_ExternalTrigConv;          /*!< 定义用于启动常规通道的模拟到数字转换的外部触发。此参数可以是 @ref ADC_external_trigger_sources_for_regular_channels_conversion 的值。 */uint32_t ADC_DataAlign;                 /*!< 指定ADC数据对齐方式是左对齐还是右对齐。此参数可以是 @ref ADC_data_align 的值。 */uint8_t ADC_NbrOfChannel;               /*!< 指定将通过序列器转换的ADC通道数量用于常规通道组。此参数的范围必须在1到16之间。 */
} ADC_InitTypeDef;

9.4.4  ADC使能

	/*ADC使能*/ADC_Cmd(ADC1, ENABLE);									//使能ADC1,ADC开始运行

9.4.5  ADC校准

	/*ADC校准*/ADC_ResetCalibration(ADC1);								//固定流程,内部有电路会自动执行校准while (ADC_GetResetCalibrationStatus(ADC1) == SET);ADC_StartCalibration(ADC1);while (ADC_GetCalibrationStatus(ADC1) == SET);

9.5  获取AD转换的值

        我们配置的是单次转换非扫描模式,因此根据下图,编写获取AD转换的值的代码:

uint16_t AD_GetValue(void)
{ADC_SoftwareStartConvCmd(ADC1, ENABLE);					//软件触发AD转换一次while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);	//等待EOC标志位,即等待AD转换结束return ADC_GetConversionValue(ADC1);					//读数据寄存器,得到AD转换的结果
}

10.  完整代码

AD.c代码:

#include "stm32f10x.h"                  // Device header/*** 函    数:AD初始化* 参    数:无* 返 回 值:无*/
void AD_Init(void)
{/*开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);	//开启ADC1的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//开启GPIOA的时钟/*设置ADC时钟*/RCC_ADCCLKConfig(RCC_PCLK2_Div6);						//选择时钟6分频,ADCCLK = 72MHz / 6 = 12MHz/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);					//将PA0引脚初始化为模拟输入/*规则组通道配置*/ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);		//规则组序列1的位置,配置为通道0/*ADC初始化*/ADC_InitTypeDef ADC_InitStructure;						//定义结构体变量ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;		//模式,选择独立模式,即单独使用ADC1ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	//数据对齐,选择右对齐ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//外部触发,使用软件触发,不需要外部触发ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;		//连续转换,失能,每转换一次规则组序列后停止ADC_InitStructure.ADC_ScanConvMode = DISABLE;			//扫描模式,失能,只转换规则组的序列1这一个位置ADC_InitStructure.ADC_NbrOfChannel = 1;					//通道数,为1,仅在扫描模式下,才需要指定大于1的数,在非扫描模式下,只能是1ADC_Init(ADC1, &ADC_InitStructure);						//将结构体变量交给ADC_Init,配置ADC1/*ADC使能*/ADC_Cmd(ADC1, ENABLE);									//使能ADC1,ADC开始运行/*ADC校准*/ADC_ResetCalibration(ADC1);								//固定流程,内部有电路会自动执行校准while (ADC_GetResetCalibrationStatus(ADC1) == SET);ADC_StartCalibration(ADC1);while (ADC_GetCalibrationStatus(ADC1) == SET);
}/*** 函    数:获取AD转换的值* 参    数:无* 返 回 值:AD转换的值,范围:0~4095*/
uint16_t AD_GetValue(void)
{ADC_SoftwareStartConvCmd(ADC1, ENABLE);					//软件触发AD转换一次while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);	//等待EOC标志位,即等待AD转换结束return ADC_GetConversionValue(ADC1);					//读数据寄存器,得到AD转换的结果
}

AD.h代码:

#ifndef __AD_H
#define __AD_Hvoid AD_Init(void);
uint16_t AD_GetValue(void);#endif

主函数代码:

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "AD.h"uint16_t ADValue;			//定义AD值变量
float Voltage;				//定义电压变量int main(void)
{/*模块初始化*/OLED_Init();			//OLED初始化AD_Init();				//AD初始化/*显示静态字符串*/OLED_ShowString(1, 1, "ADValue:");OLED_ShowString(2, 1, "Voltage:0.00V");while (1){ADValue = AD_GetValue();					//获取AD转换的值Voltage = (float)ADValue / 4095 * 3.3;		//将AD值线性变换到0~3.3的范围,表示电压OLED_ShowNum(1, 9, ADValue, 4);				//显示AD值OLED_ShowNum(2, 9, Voltage, 1);				//显示电压值的整数部分OLED_ShowNum(2, 11, (uint16_t)(Voltage * 100) % 100, 2);	//显示电压值的小数部分Delay_ms(100);			//延时100ms,手动增加一些转换的间隔时间}
}

STM32学习笔记_时光の尘的博客-CSDN博客

相关文章:

ADC在STM32F1系列的使用详解

目录 1. ADC简介 2. 逐次逼近型ADC&#xff08;ADC0809&#xff09; 3. ADC框图&#xff08;STM32&#xff09; 4. ADC基本结构 5. 输入通道 6. 转换模式 6.1 单次转换 6.1.1 非扫描模式 6.1.2 扫描模式 6.2 连续转换 6.2.1 非扫描模式 6.2.2 扫描模式…...

网络空间安全之一个WH的超前沿全栈技术深入学习之路(一:渗透测试行业术语扫盲)作者——LJS

欢迎各位彦祖与热巴畅游本人专栏与博客 你的三连是我最大的动力 以下图片仅代表专栏特色 [点击箭头指向的专栏名即可闪现] 专栏跑道一 ➡️网络空间安全——全栈前沿技术持续深入学习 专栏跑道二➡️ 24 Network Security -LJS ​ ​ ​ 专栏跑道三 ➡️ MYSQL REDIS Advanc…...

中间件-概念

什么是中间件&#xff1f; 中间件&#xff08;Middleware&#xff09;是位于 Web 服务器和应用程序之间的组件&#xff0c;它可以处理每个请求和响应。中间件的主要作用是在请求到达应用程序之前或响应返回客户端之前对其进行处理。中间件可以执行各种任务&#xff0c;如日志记…...

vscode离线状态ssh连接不断输入密码登不上:配置commit_id

如题&#xff0c;vscode在一个离线服务器上&#xff0c;通过remote-ssh登录远程服务器&#xff0c;不断弹出密码框&#xff0c;总是进不去&#xff0c;后来了解到主要是不同vscode版本需要下载对应抑制commit-id的vscode-server-linux-x64.tar.gz包。 1&#xff09;vscode, 点…...

Vim使用与进阶

1. Vim 技巧 撤销 U 反撤销 Ctrl U 历史命令 history 2.要在Vim中进行多行缩进&#xff0c;可以按以下步骤操作&#xff1a; 进入Vim编辑器并进入命令模式。使用 v 键或 Shift v 键选择多行需要缩进的文本。按下 > 键进行向右缩进&#xff0c;或按下 < 键进行向左…...

python中frida的安装+frida-server(雷电模拟器)保姆级安装教程

一.安装雷电模拟器 雷电模拟器官网 直接下载安装即可 &#xff08;1&#xff09;打开必要权限 雷电模拟器的设置已完毕 二.安装adb工具 本文以autox.js来实现adb操作 &#xff08;1&#xff09;vscode中下载auto.js插件 &#xff08;2&#xff09;雷电模拟器下载autox.j…...

Java线程安全集合之COW

概述 java.util.concurrent.CopyOnWriteArrayList写时复制顺序表&#xff0c;一种采用写时复制技术&#xff08;COW&#xff09;实现的线程安全的顺序表&#xff0c;可代替java.util.ArrayList用于并发环境中。写时复制&#xff0c;在写入时&#xff0c;会复制顺序表的新副本&…...

智能汽车制造:海康NVR管理平台/工具EasyNVR多品牌NVR管理工具/设备实现无插件视频监控直播方案

一、背景介绍 近年来&#xff0c;随着网络在我国的普及和深化发展&#xff0c;企业的信息化建设不断深入&#xff0c;各行各业都加快了信息网络平台的建设&#xff0c;大多数单位已经或者正在铺设企业内部的计算机局域网。与此同时&#xff0c;网络也成为先进的新兴应用提供了…...

[渗透]前端源码Chrome浏览器修改并运行

文章目录 简述本项目所使用的代码[Fir](https://so.csdn.net/so/search?qFir&spm1001.2101.3001.7020) Cloud 完整项目 原始页面修改源码本地运行前端源码修改页面布局修改请求接口 本项目请求方式 简述 好久之前&#xff0c;就已经看到&#xff0c;_无论什么样的加密&am…...

SAP揭秘者-怎么查看SAP 版本及S4 HANA的版本

文章摘要&#xff1a; 在给客户实施SAP项目或部署SAP服务器及SAP跟外部系统集成时&#xff0c;经常客户或第三方软件公司会问SAP版本或SAP HANA的版本。那么到底怎么来看这个SAP的版本呢&#xff1f;这个问题其实很多SAP模块顾问都不知道怎么看&#xff0c;你可以想象一下&…...

UE4 材质学习笔记13(格斯特纳波)

一.格斯特纳波 要让水面动起来&#xff0c;必须要保证平面有足够的三角面。我们可以在材质里的细节面板打开曲面细分&#xff0c;可以分裂三角面且使之数量更多&#xff0c;选择“扁平曲面细分&#xff0c;其作用是切割我的三角面&#xff0c;然后给我做一大堆三角面出来。 这…...

简述 C# 二维数据集合 List 的创建、遍历、修改、输出

简述 C# 二维数据集合 List 的创建、遍历、修改、输出 1、为什么要使用列表 List2、引入命名空间3、声明一维列表 List4、声明创建一个二维列表 List&#xff0c;数据类型 int5、 简单访问元素6、遍历二维列表&#xff0c;控制台输出7、遍历二维列表&#xff0c;修改数据&#…...

ps2024 一键安装教程 永久使用!

下载后&#xff0c;直接解压打开exe文件就能安装了 下载: https://pan.baidu.com/s/1uDSug00prwRw5igF0N-Xhw?pwd8888 【软件名称】:ps2024 【软件大小】:4.7g 【软件版本】:25.12.0.806 【软件简介】:Photoshop&#xff0c;简称“PS”&#xff0c;是由美国Adobe公司推出…...

ScrollView 真机微信小程序无法隐藏滚动条

问题描述 根据官方文档&#xff0c;使用:show-scrollbar"false"&#xff0c;隐藏滚动条无效 解决方法 添加一段样式在 scroll-view 上或者父级节点上下 ::-webkit-scrollbar {width: 0;height: 0;color: transparent;display: none;} eg. .inforDetails_app {p…...

【日志】编辑器开发——修复根据Excel表格数据生成Json文件和配置表代码报错

2024.10.15 又是蕉绿且摆烂的一天&#xff0c;不仅需要克制网瘾&#xff0c;还要努力学习&#xff0c;不然真的会被抛弃啊。但是我还是不想卷&#xff0c;给我的时间大概还有半年&#xff0c;突然好奇半年时间到底能学点什么或者做点什么。 【力扣刷题】 暂无 【数据结构】 …...

C#线性查找算法

前言 线性查找算法是一种简单的查找算法&#xff0c;用于在一个数组或列表中查找一个特定的元素。它从数组的第一个元素开始&#xff0c;逐个检查每个元素&#xff0c;直到找到所需的元素或搜索完整个数组。线性查找的时间复杂度为O(n)&#xff0c;其中n是数组中的元素数量。 …...

GPT+Python)近红外光谱数据分析与定性/定量建模技巧

2022年11月30日&#xff0c;可能将成为一个改变人类历史的日子——美国人工智能开发机构OpenAI推出了聊天机器人ChatGPT3.5&#xff0c;将人工智能的发展推向了一个新的高度。2023年4月&#xff0c;更强版本的ChatGPT4.0上线&#xff0c;文本、语音、图像等多模态交互方式使其在…...

Spark动态资源释放机制 详解

Apache Spark 是一个分布式数据处理框架&#xff0c;其动态资源分配&#xff08;或称为动态资源释放&#xff09;机制&#xff0c;是为了更高效地利用集群资源&#xff0c;尤其是在执行具有不同工作负载的作业时。Spark 的动态资源释放机制允许它根据作业的需求自动分配和释放集…...

基于径向基神经网络(RBF)的构网型VSG自适应惯量控制MATLAB仿真模型

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 模型简介 逆变器虚拟同步发电机控制和核心控制参数就是虚拟惯量与虚拟阻尼&#xff0c;目前的文献中已有众多论文对VSG的虚拟参数展开了研究&#xff0c;但是百分之90都是采用构造函数的方法&#xff0c;使用…...

简单汇编教程9 字符串与字符串指令

目录 字符串的指令 movs 字符串传送 lods, stos使用 cmpsb的使用 SCASB的使用 字符串你很熟悉了&#xff0c;我们定义了无数次了&#xff01; %macro ANNOUNCE_STRING 2%1 db %2%1_LEN equ $ - %1 %endmacro 当然&#xff0c;我们现在来学习一个比较新的定义方式&#xf…...

Taro构建的H5页面路由切换返回上一页存在白屏页面过渡

目录 项目背景&#xff1a;Taro与Hybrid开发问题描述&#xff1a;白屏现象可能的原因包括&#xff1a; 解决方案解决后的效果图 其他优化方案可参考&#xff1a; 项目背景&#xff1a;Taro与Hybrid开发 项目使用Taro框架同时开发微信小程序和H5页面&#xff0c;其中H5页面被嵌…...

【学习笔记】网络设备(华为交换机)基础知识 9 —— 堆叠配置

提示&#xff1a;学习华为交换机堆叠配置&#xff0c;含堆叠的概念、功能、角色、ID和优先级&#xff1b;堆叠的建立过程以及注意事项&#xff1b;包含堆叠的配置命令&#xff0c;以及堆叠的配置案例 一、前期准备 1.已经可以正常访问交换机的命令行接口 Console口本地访问教…...

jeston编译配置cuda加速版opencv

1.源码下载连接 opencv&#xff1a;Releases - OpenCV opencv-contrib&#xff1a; https://github.com/opencv/opencv_contrib 建议不要下最新版本 一般我会下4.5.4 // 4.5.6 // 4.6.0 opencv和opencv-contrib版本要对齐 将下好的opencv和opencv-contrib解压 将opencv-c…...

ApacheShiro反序列化 550 721漏洞

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理个漏洞被称为 Shiro550 是因为在Apache Shiro的GitHub问题跟踪器中&#xff0c;该漏洞最初被标记为第550个问题,721漏洞名称也是由此而来 Shiro-550 CVE-2016-4437 Shiro反序列化Docker复现 …...

Github + 自定义域名搭建个人静态站点

Github 自定义域名搭建个人静态站点 使用 Github 部署一个自己的免费站点给你的站点添加上自定义域名 本文基于腾讯云基于二级域名, 作用于 Github 实现自定义域名站点 使用 Github 部署一个自己的免费站点 首先你得有一个 Github 账号, 没有就去注册一个,网上有教程,本文跳…...

使用OpenCV进行视频边缘检测:案例Python版江南style

1. 引言 本文将演示如何使用OpenCV库对视频中的每一帧进行边缘检测&#xff0c;并将结果保存为新的视频文件。边缘检测是一种图像处理技术&#xff0c;它可以帮助我们识别出图像中不同区域之间的边界。在计算机视觉领域&#xff0c;这项技术有着广泛的应用&#xff0c;比如物体…...

DataWhale10月动手实践——Bot应用开发task04学习笔记

一、图像流 1. 什么是图像流&#xff1f; 图像流是一种直观的图像处理流程工具&#xff0c;用户可以灵活组合各类图像处理模块。该系统将不同的图像处理工具模块化&#xff0c;并通过可视化界面&#xff0c;将这些模块以拖拽方式组合&#xff0c;构建完整的处理流程。用户可以…...

关于 IntelliJ IDEA 2024 安装使用

补丁文件...

React是如何工作的?

从编写组件到最后屏幕生成界面&#xff0c;如上图所示&#xff0c;我们现在需要知道的就是后面几步是如何运行的。 概述 这张图解释了 React 渲染过程的几个阶段&#xff1a; 渲染触发&#xff1a;通过更新某处的状态来触发渲染。渲染阶段&#xff1a;React 调用组件函数&…...

llama.cpp 去掉打印,只显示推理结果

llama.cpp 去掉打印&#xff0c;只显示推理结果 1 llama.cpp/common/log.h #define LOG_INF(...) LOG_TMPL(GGML_LOG_LEVEL_INFO, 0, __VA_ARGS__) #define LOG_WRN(...) LOG_TMPL(GGML_LOG_LEVEL_WARN, 0, __VA_ARGS__) #define LOG_ERR(…...