STM32上实现FFT算法精准测量正弦波信号的幅值、频率和相位差(标准库)

在研究声音、电力或任何形式的波形时,我们常常需要穿过表面看本质。FFT(快速傅里叶变换)就是这样一种强大的工具,它能够揭示隐藏在复杂信号背后的频率成分。本文将带你走进FFT的世界,了解它是如何将时域信号转化为频域信号,如何使用STM32F407微控制器和FFT来分析正弦信号的幅值、频率和相位差。

一、FFT介绍

FFT(快速傅里叶变换)是一种将信号从时域(随时间变化的信号)转换为频域(不同频率成分的信号)的算法。做一个比喻:信号=食材,FFT=刀,频域=切好的食材。时域信号:想象你拿到了一块复杂的食材,比如一只未处理的鱼,里面有骨头、肉、皮等。这就是时域信号,它包含所有部分,但你还不能清楚地看到每个成分。FFT:这就像一把精准的,它能快速地把鱼切成不同的部分:肉、骨头、皮等。FFT就像这把刀,把复杂的信号拆分为不同的频率成分,让我们能够看到信号中隐藏的细节。频域信号:处理后的结果就像分好类的食材——你清楚地看到了鱼的骨头、肉和皮,知道每个部分的大小(幅值)和具体成分(频率)。这样你就可以根据需要进一步处理这些“分好类的食材”。FFT像一把高效的刀,能快速、精准地将复杂的信号“解剖”成简单、清晰的频率部分。其优势在于:

1.实现频域分析:FFT将时域信号转换为频域,使我们能够识别信号中的频率成分。对于复杂信号,时域分析可能难以识别其频率特征,而频域分析(如滤波、频谱分析、数据压缩)则能直观地展现信号的频率内容。

2.提高效率:直接计算离散傅里叶变换(DFT)运算复杂度较高,而FFT通过优化算法显著提升计算效率,适用于单片机中实时数据处理。

FFT广泛应用于音频处理、通信系统、图像处理、医学成像、地震数据分析等领域。在电力信号处理中,FFT可帮助清晰识别信号中的基波和谐波成分,协助检测电网中的频率偏移和谐波干扰问题。

二、时域分析 vs 频域分析


时域:时域是我们通常看到的信号,比如正弦波,随时间波动。用电压表测量交流电压时,指针上下波动就是时域信号的表现。时域分析只能告诉我们信号的瞬时变化,无法揭示信号的频率组成。
  
频域:频域是一种数学上的表示方式,用于分析信号的频率成分。在频域中,任何复杂的时域信号都可以分解为正弦波的叠加,因为正弦波是频域中唯一存在的基本波形。

时域分析:这是你在电压表或示波器上看到的信号波形,它显示信号如何随时间变化。时域分析的主要缺点是无法直接告诉你信号中包含哪些频率成分。

频域分析:通过FFT,我们可以将这些时域信号分解为不同的频率成分,就像把一首歌分解成各个音符。可以帮助我们找到信号中的主要频率,如50Hz的基波和其他高频谐波。

三、FFT的实部和虚部

正弦信号可以用以下数学表达式表示: x(t)=A⋅sin(ωt+θ) 其中:

  • A 是振幅,表示信号的最大值。
  • ω 是角频率,单位为弧度/秒(ω=2πf,其中 f 为频率)。
  • θ是相位角,表示信号的初始偏移。
    x(t)=A⋅sin(ωt+θ) 
    本身是一个实数函数,因为它在任何时间点 t 的值都是实数。这个表达式没有直接包含虚数部分,所以可以说它的“虚部”是0。

FFT 变换后,得到的是复数Re+j⋅Im ,包括实部和虚部:

  • 实部 (Re):与余弦分量相关,决定信号的振幅。
  • 虚部 (Im):与正弦分量相关,影响信号的相位。 

计算幅值和相位:

  • 幅值:表示信号在某频率下的强度,通过以下公式计算:幅值 = sqrt(Re^2 + Im^2)

  • 相位:表示信号相对于参考信号的偏移,通过以下公式计算: 相位 = atan2(Im, Re)

通过 FFT 的实部和虚部,我们可以准确地获取信号的幅值和相位,从而深入理解信号的频率特性,包括基波和谐波的影响。

  • 基波:信号的主要频率成分。例如,电网的基波通常是50Hz或60Hz,它代表了信号的基本频率。

  • 谐波:基波频率的整数倍,例如基波的2倍、3倍频率等。谐波会影响电力设备的正常运行,可能导致设备过热或损坏。

四、如何用STM32进行FFT计算?

让我们一步步看看整个计算流程。

1. 信号采集
首先,我们需要使用STM32的ADC模块来采集模拟信号,比如三相交流电。ADC将模拟信号(如电压或电流)转换为数字信号,供后续处理。

采样数量:FFT的计算通常需要2的整数次幂的采样点数(如1024、2048)。采样点数越多,频率分辨率越高。
  
采样频率:采样频率必须至少是信号频率的两倍(奈奎斯特定理)。例如,分析50Hz的信号时,采样频率应至少为100Hz,但通常使用更高的采样频率,比如10kHz,以保证计算精度。下面的代码是1000Hz的信号的,选用的 采样频率是100000Hz。

2. FFT变换
采集到的时域数据通过FFT算法进行处理,转换为频域信息。ARM-DSP库中有现成的FFT函数,可以简化计算过程。

3. 运算结果:幅值、频率和相位差

幅值:信号的振幅大小,表示每个频率成分的强度。基波的幅值代表主要的电压或电流值。
  
频率:FFT能帮助我们识别信号中的不同频率成分,如电网中的50Hz基波及其他谐波。

相位差:对于三相信号,FFT可以帮助我们分析不同相之间的相位差,揭示它们之间的时间延迟。

4. 处理流程概述

整个处理流程如下:

  • 信号采集:定时器触发ADC采样交流电信号。
  • 采样与ADC转换:STM32的ADC将模拟信号转为数字信号。
  • DMA传输:使用DMA自动传输采样数据到内存。
  • FFT计算:利用FFT将时域数据转换为频域数据。
  • 结果提取:从FFT结果中提取幅值、频率和相位差信息。

五、程序实现

硬件:正点原子探索者 V3 STM32F407 开发板,下面是核心代码,代码中使用了ARM提供的数学库(arm_math.h)来实现FFT算法,以及STM32的标准库库来配置定时器、ADC和DMA。通过这些配置,系统能够高效地采集和处理模拟信号,分析其频谱特性。完整代码请在资源下载。

#include "tim_adc_dma_fft.h"
#include "usart.h"
#include "arm_math.h"   
#include "delay.h" /*通过ADC采集模拟信号,然后使用DMA将采集的数据传输到内存中,接着通过FFT算法分析信号的频谱,最后通过串口输出信号的基波和谐波的频率、幅值和相位差等信息*/
#define sampledot  4096
#define FFT_LENGTH		4096		//4096点FFT
#define fft_arr 10     // 用于计算FFT采样频率的系数             
#define fft_psc 84       // 用于计算FFT采样频率的系数            const u32  fft_sample_freq=84000000/(fft_arr*fft_psc);  // 计算FFT采样频率float fft_inputbuf[FFT_LENGTH*2];	 // FFT输入数组,用于存放复数
float fft_outputbuf[FFT_LENGTH];	 // FFT输出数组,存放幅值
arm_cfft_radix4_instance_f32 scfft;   // FFT实例结构体u32 sampledata[sampledot]={0};//用于存放ADC采样数据的数组,高16位保存adc2 pa5, 低16位保存adc1 pa6float phase_difference=0; // 用于存放相位差的变量
float freamp[50];//用于存放各次谐波频率和幅值的数组// 定时器3初始化函数
void Tim3_Init(u16 arr,u16 psc)
{TIM_TimeBaseInitTypeDef   TIM_TimeBaseInitstruct;          RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);          TIM_TimeBaseInitstruct.TIM_Period=arr;   TIM_TimeBaseInitstruct.TIM_Prescaler=psc;TIM_TimeBaseInitstruct.TIM_CounterMode=TIM_CounterMode_Up;TIM_TimeBaseInitstruct.TIM_ClockDivision=TIM_CKD_DIV1;TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitstruct);//TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);     TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update);	TIM_Cmd(TIM3,DISABLE);
}
// ADC初始化函数
void Adc_Init()
{GPIO_InitTypeDef  GPIO_InitStructure;ADC_CommonInitTypeDef ADC_CommonInitStructure;ADC_InitTypeDef       ADC_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_5;  //adc 1和2 的通道GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;GPIO_Init(GPIOA, &GPIO_InitStructure);RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,ENABLE);	RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,DISABLE);RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC2,ENABLE);	RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC2,DISABLE); //重置ADC_CommonInitStructure.ADC_Mode = ADC_DualMode_InjecSimult;ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_2;ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInit(&ADC_CommonInitStructure);ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;ADC_InitStructure.ADC_ScanConvMode = DISABLE;	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	ADC_InitStructure.ADC_NbrOfConversion =1;  //通道数ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_T3_TRGO;ADC_Init(ADC1, &ADC_InitStructure);ADC_Init(ADC2, &ADC_InitStructure);ADC_RegularChannelConfig(ADC2, ADC_Channel_5, 1, ADC_SampleTime_3Cycles);ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_3Cycles);ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE); //多路转化完后触发dmaADC_DMACmd(ADC1, ENABLE); ADC_Cmd(ADC1, ENABLE);ADC_Cmd(ADC2, ENABLE);
}// DMA初始化函数,用于ADC数据的采集
void Dma_ADC_Init()
{DMA_InitTypeDef  DMA_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);DMA_DeInit(DMA2_Stream0);DMA_InitStructure.DMA_BufferSize= sampledot;DMA_InitStructure.DMA_Channel=DMA_Channel_0; DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralToMemory;	DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;         DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;	DMA_InitStructure.DMA_Memory0BaseAddr= (uint32_t)&sampledata ;//要存入的值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_Circular;DMA_InitStructure.DMA_PeripheralBaseAddr=(uint32_t)0x40012308; //adc地址DMA_InitStructure.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Word;DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;DMA_InitStructure.DMA_Priority=DMA_Priority_High;DMA_Init(DMA2_Stream0, &DMA_InitStructure);DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);DMA_Cmd(DMA2_Stream0, ENABLE);NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;  //DMA2_Stream0中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;  //抢占优先级1NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;        //子优先级1NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能NVIC_Init(&NVIC_InitStructure);
}// 数据初始化函数,用于初始化ADC、DMA、串口和定时器
void Data_Init()
{u32 idex;float temp;	Adc_Init();Dma_ADC_Init();uart_init(115200);arm_cfft_radix4_init_f32(&scfft,FFT_LENGTH,0,1);//初始化scfft结构体,设定FFT相关参数     //FFT_LENGTH 4096Tim3_Init(fft_arr-1,fft_psc-1);
}// DMA中断服务函数,用于处理ADC数据采集完成后的操作
void DMA2_Stream0_IRQHandler(void)  
{u32 idex;	//用于将采集到的数据赋值给fft_inputbuf[2*idex]的计数	float bias_voltage2,HZ2,amplitude2,phase2,bias_voltage1,HZ1,amplitude1,phase1;u8 temp[40];int i;u16   freamplen; // freamp长度的一半if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0))  //判断DMA传输完成中断  {TIM_Cmd(TIM3,DISABLE);//关闭时钟,进行计算			//adc2 pa5for(idex=0;idex<sampledot;idex++) //高16位fft,adc2 fft1 //sampledot==4096{			fft_inputbuf[2*idex]=(u16)(sampledata[idex]>>16)*(3.3/4096);    //生成输入信号实部fft_inputbuf[2*idex+1]=0;//虚部全部为0}arm_cfft_radix4_f32(&scfft,fft_inputbuf);  //fft运算arm_cmplx_mag_f32(fft_inputbuf,fft_outputbuf,FFT_LENGTH);	//把运算结果复数求模得幅值	freamplen=fft_getpeak(fft_inputbuf,fft_outputbuf+1,freamp,FFT_LENGTH/2,10,5,0.2);//寻找基波和谐波	bias_voltage2=fft_outputbuf[0]/FFT_LENGTH;//直流 HZ2=freamp[0];//频率amplitude2=freamp[1];//幅度phase2=freamp[2];//相位freamp[0]=0;freamp[1]=0;freamp[2]=0;//adc1 pa6for(idex=0;idex<sampledot;idex++) //低16位fft ,adc1 fft2{fft_inputbuf[2*idex]=(u16)(sampledata[idex])*(3.3/4096);    //生成输入信号实部fft_inputbuf[2*idex+1]=0;//虚部全部为0	,}	arm_cfft_radix4_f32(&scfft,fft_inputbuf);  //fft运算arm_cmplx_mag_f32(fft_inputbuf,fft_outputbuf,FFT_LENGTH);	//把运算结果复数求模得幅值freamplen=fft_getpeak(fft_inputbuf,fft_outputbuf+1,freamp,FFT_LENGTH/2,10,5,0.2); //寻找基波和谐波	bias_voltage1=fft_outputbuf[0]/FFT_LENGTH;//偏置电压      HZ1=freamp[0];//频率amplitude1=freamp[1];//幅度phase1=freamp[2];//相位freamp[0]=0;freamp[1]=0;freamp[2]=0;phase_difference=phase2-phase1;if(phase_difference>180) phase_difference=phase_difference-180;if(phase_difference<-180) phase_difference=phase_difference+180;printf("\r\n");    //fft采样频率printf("fft_sample_freq:%d\r\n",fft_sample_freq);    //fft采样频率 		printf("bias_voltage1:%.2f\r\n",bias_voltage1); //偏置电压 printf("bias_voltage2:%.2f\r\n",bias_voltage2); //偏置电压printf("HZ1:%.2f\r\n",HZ1);   //频率printf("HZ2:%.2f\r\n",HZ2);//频率printf("amplitude1:%.2f\r\n",amplitude1); //幅值 printf("amplitude2:%.2f\r\n",amplitude2);//幅值  printf("phase_difference:%.2f\r\n",phase_difference);//相位差        DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);}	
}// 获取FFT峰值
int fft_getpeak(float *inputx,float *input,float *output,u16 inlen,u8 x,u8 N,float y) //  intlen 输入数组长度,x寻找长度
{                                                                           int i,i2;u32 idex;  //不同于上一个函数中的,因为他们在不同的函数中被定义float datas;float sum;int outlen=0;for(i=0;i<inlen-x;i+=x){arm_max_f32(input+i,x,&datas,&idex);   if( (input[i+idex]>=input[i+idex+1])&&(input[i+idex]>=input[i+idex-1])&&( (2*datas)/FFT_LENGTH )>y)   {sum=0;   for(i2=i+idex-N;i2<i+idex+N;i2++)   {sum+=input[i2];          }        if(1.5*sum/(2*N)<datas)       {                                                                                             output[3*outlen+2] = atan2(inputx[2*(i+idex+1)+1],inputx[2*(i+idex+1)])*180/3.1415926f;	//计算相位		   output[3*outlen+1] = 1.0*(2*datas)/FFT_LENGTH;   //计算幅度output[3*outlen] = 1.0*fft_sample_freq*(i+idex+1)/FFT_LENGTH;//计算频率outlen++;				   }                                                                                               else continue;			   }else continue;}return outlen;}
  1. 定时器初始化 (Tim3_Init): 配置定时器3,用于控制ADC的采样频率。

  2. ADC初始化 (Adc_Init): 配置两个ADC(ADC1和ADC2),用于采集模拟信号。ADC1和ADC2分别连接到不同的通道,采集不同的模拟信号。

  3. DMA初始化 (Dma_ADC_Init): 配置DMA,用于将ADC采集的数据直接传输到内存中,减少CPU的负担。

  4. 数据初始化 (Data_Init): 调用上述初始化函数,完成系统的基本配置。

  5. FFT峰值获取函数 (fft_getpeak): 该函数用于在FFT结果中寻找峰值,这些峰值代表了信号中的基波(主要频率成分)。下面是核心中的核心。

    		arm_cfft_radix4_f32(&scfft,fft_inputbuf);  //fft运算arm_cmplx_mag_f32(fft_inputbuf,fft_outputbuf,FFT_LENGTH);	//把运算结果复数求模得幅值freamplen=fft_getpeak(fft_inputbuf,fft_outputbuf+1,freamp,FFT_LENGTH/2,10,5,0.2); //寻找基波和谐波

  6. DMA中断服务函数 (DMA2_Stream0_IRQHandler): 当DMA传输完成时,该函数会被调用。它负责执行FFT算法,计算信号的偏置电压、频率、幅度、相位的相关信息并用串口1打印。 
     

六、现象

1.信号发生器输入信号源。
信号1:1000Hz的信号的,幅度1V,偏置电压0.5V,相位0°;

信号2:1000Hz的信号的,幅度1.2V,偏置电压0.6V,相位50°;

2.串口收到测量结果与输入信号源的实际接近。

七、总结

FFT(快速傅里叶变换)是一种强大的技术,它允许我们将信号从时域转换到频域,从而深入分析其频率成分。这种转换揭示了信号隐藏的频率特性,为我们提供了一个全新的视角来观察和理解信号的行为。

通过上述介绍,我们探讨了如何使用STM32微控制器执行FFT计算,以提取信号的幅值、频率和相位。
希望这些内容能够为大家提供有价值的参考和指导。在实际应用中,理解和运用FFT的原理和技巧,将有助于我们更有效地处理和分析各种复杂的信号。

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

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

相关文章

如何将Excel表格嵌入Web网页在线预览、编辑并保存到自己服务器上?

猿大师办公助手作为一款专业级的网页编辑Office方案&#xff0c;不仅可以把微软Office、金山WPS和永中Office的Word文档内嵌到浏览器网页中实现在线预览、编辑保存等操作&#xff0c;还可以把微软Office、金山WPS和永中Office的Excel表格实现网页中在线预览、编辑并保存到服务器…

python中ocr图片文字识别样例(二)

一、说明 本次解决图片相关出现中文乱码问题&#xff0c;属于上篇文章的优化&#xff0c;前提条件依赖上篇文章的包&#xff0c;当然ocr的具体应用场景很多&#xff0c;根据自身需求进行调整 二、具体实现 2.1 代码实现&#xff1a; # -*- coding: utf-8 -*- import easyoc…

3.《DevOps》系列K8S部署CICD流水线之部署MetalLB负载均衡器和Helm部署Ingress-Nginx

架构 服务器IP服务名称硬件配置192.168.1.100k8s-master8核、16G、120G192.168.1.101k8s-node18核、16G、120G192.168.1.102k8s-node28核、16G、120G192.168.1.103nfs2核、4G、500G操作系统:Rocky9.3 后续通过K8S部署GitLab、Harbor、Jenkins 为什么使用MetalLB 当使用云平…

在vue中:style 的几种使用方式

在日常开发中:style的使用也是比较常见的&#xff1a; 亲测有效 1.最通用的写法 <p :style"{fontFamily:arr.conFontFamily,color:arr.conFontColor,backgroundColor:arr.conBgColor}">{{con.title}}</p> 2.三元表达式 <a :style"{height:…

如何快速连接超2100家国内外快递物流公司、实现查询结果翻译为中/英文?

近年来&#xff0c;中国企业正不断加快“出海”步伐&#xff0c;“中企出海”也成为了2024年最重要的投资主题之一。 百递云API开放平台深刻理解这一趋势&#xff1a;在我们的客户群体中&#xff0c;既有贸易规模增长超数倍的跨境电商&#xff0c;还有国际业务越来越成为增长新…

ADB 安装教程:如何在 Windows、macOS 和 Linux 上安装 Android Debug Bridge

目录 一、ADB 介绍 二、Windows 系统安装 ADB 1. 下载 ADB 2. 解压文件 3. 验证 ADB 安装 4. 配置环境变量 5. 验证全局 ADB 使用 三、macOS 系统安装 ADB 1. 下载 ADB 2. 解压文件 3. 配置环境变量 4. 验证 ADB 安装 四、Linux 系统安装 ADB 1. 使用包管理器安装…

C++初阶学习——探索STL奥秘——模拟实现list类

1、基本框架 list 由三个类构建而成: 节点类:每个节点必须的三部分(指向前一个节点的指针、指向后一个节点的指针、当前节点存储的数据) 迭代器类:此时的迭代器为双向迭代器&#xff0c;比较特殊&#xff0c;需要对其进行封装&#xff0c;如 it并非使迭代器单纯向后移动&…

Python气象辐射光谱能量平衡模型

&#x1f3af;要点 根据温室模型&#xff0c;计算不同情景下辐射通量和评估能量平衡&#xff0c;构建复杂温室模型计算计算和绘图大气、海洋、陆地表面和海冰复合模型数据建立简单能量平衡情景模型&#xff0c;并根据模型计算释放温度和时滞&#xff0c;计算并绘制地面辐射和吸…

【QT】系统-下

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;QT 目录 &#x1f449;&#x1f3fb;QTheadrun() &#x1f449;&#x1f3fb;QMutex&#x1f449;&#x1f3fb;QWaitCondition&#x1f449;&#x1f3fb;Q…

洛汗2游戏辅助攻略:VMOS云手机带你体会游戏新体验!自动搬砖辅助攻略!

在《洛汗2》游戏中&#xff0c;使用VMOS云手机能极大地提升你的游戏体验。VMOS云手机提供《洛汗2》专属定制版的云手机&#xff0c;内置游戏安装包&#xff0c;玩家不需要再次下载安装游戏&#xff0c;这大大简化了游戏的启动过程。最棒的是&#xff0c;它支持免费的辅助工具运…

音乐项目,总结

今天的写的思路都挺简单的但是比较繁琐&#xff0c;这个查找&#xff0c;传文件的话可以了&#xff0c;但是没有用分片传送&#xff0c;然后在写音乐播放的处理&#xff0c;<歌单&#xff0c;二级评论&#xff0c;歌曲歌词滚轮播放>三个还没有实现&#xff0c;时间挺紧张…

Kafka3.8.0+Centos7.9的安装参考

Kafka3.8.0Centos7.9的安装参考 环境准备 操作系统版本&#xff1a;centos7.9 用户/密码&#xff1a;root/1qazXSW 主机名 IP地址 安装软件 下载地址 k1 192.168.207.131 jdk1.8zookeeper3.9.2kafka_2.13-3.8.0efak-web-3.0.1 1&#xff09; Java Downloads | Oracle …

Java代码调用https(SSL证书验证问题)

Java代码调用https接口SSL证书验证问题 现有一个https接口&#xff0c;如下 Test public void test1() {String url "https://iservericloudhx.yndk.cn:32613/iserver/services/map-mongodb-C_YGYX_530000_2022/wms111/C_YGYX_530000_2022";RestTemplate restTemp…

Docker 里面按照ifconfig

1. 进入Docker 容器内部 docker exec -it xxx bash2. 安装 net-tools iputils-ping apt-get update && apt-get install -y net-tools apt-get update && apt-get install -y iputils-ping 3. 执行ifconfig 执行ping

[Linux]Vi和Vim编辑器

Vi和Vim编辑器 Linux系统会内置vi文本编辑器, 类似于windows中的记事本 Vim具有程序编辑的能力, 可以看作是Vi的增强版本, 可以进行语法检查, 代码补全,代码编译和错误调整等功能 Vi和Vim的模式 快速入门 使用vim开发一个Hello.java程序 通过Xshell连接Linux系统命令行输入…

【Qt | QAction】Qt 的 QAction 类介绍

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

【Taro】初识 Taro

笔记来源&#xff1a;编程导航。 概述 Taro 官方文档&#xff1a;https://taro-docs.jd.com/docs/ &#xff08;跨端开发框架&#xff09; Taro 官方框架兼容的组件库&#xff1a; taro-ui&#xff1a;https://taro-ui.jd.com/#/ &#xff08;最推荐&#xff0c;兼容性最好&…

7.搭建个人金融数据库之快速获取股票列表和基本信息!

前边我们提过&#xff0c;免费的数据一般来自于爬虫&#xff0c;获取难度和维护成本都比较高&#xff0c;其实不太适合小白用户。所以非必要情况下&#xff0c;我们尽量不用这种方式来获取数据。 我自己用的比较多的是tushare&#xff0c;一般来说有它也就够了&#xff0c;大…

Python自动化-操作Excel

在数据处理和报表生成过程中&#xff0c;Excel是一个经常使用的工具。Python中的openpyxl库可以让您通过编程方式读取、写入和操作Excel文件&#xff0c;从而实现自动化的数据处理和报表生成。本文将介绍openpyxl库的基本用法和常见操作&#xff0c;帮助您快速上手使用Python处…

猿大师办公助手在线编辑Office为什么要在客户端电脑安装插件微软Office或金山WPS?

猿大师办公助手作为一款专业级的网页编辑Office方案&#xff0c;与在线云文档方案&#xff08;飞书、腾讯文档等&#xff09;不同&#xff0c;需要在客户端电脑安装猿大师办公助手插件及微软Office或者金山WPS软件&#xff0c;很多客户不理解为什么要这么麻烦&#xff0c;能否客…