请教大家一个问题,如何利用STM32自带AD和DMA模块测量两路信号的相位差。
现在我有一路基准信号,是用TIM3产生的占空比为50%的5kHz的PWM波,测量该PWM波和外围电路上一个5kHz的正弦波的相位差。
由于我采用了FFT,所以我需要对5kHz的正弦波连续采样1024个点,这里我采用了DMA的方式,DMA的缓冲区设置为1024
程序如下,前面都是配置AD和DMA的,没什么问题,关键在AD转换启动的那一刻,也就是ADC_SoftwareStartConvCmd(ADC1, ENABLE)这里
启动以后,我把那个用于产生PWM波的TIM3中的计数值TIM3->CNT放到一个变量PlusePhase中存储起来,这就是PWM在AD转换开始时的相位,应该是没有问题的吧?
接下来,我对每采集到的1024个点进行FFT(我程序FFT是没有问题的,将AD值导出后,用我MATLAB算的结果和我程序是一致的)测量相位,多次测量发现
该信号的相位和PWM波相位的相位差一直在变化,而我用示波器看,这两路同频率的信号相位差是恒定的,请问这是什么原因呢?
我怀疑是不是ADC_SoftwareStartConvCmd(ADC1, ENABLE)以后,AD采用需要经过一段间隔时间才能进行。如果这段时间是固定的,那相位差还是应该恒定不变,
难道这个间隔一直在变吗?很不解,所以请大家帮帮忙啦...
小弟先行谢过...
/***********************************************************************************************************
AD的配置
***********************************************************************************************************/
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立的转换模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //关闭扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //开启连续转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //ADC外部开关,关闭状态
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //对齐方式,ADC为12位中,右对齐方式
ADC_InitStructure.ADC_NbrOfChannel = 1; //开启通道数,1个
ADC_Init(ADC1, &ADC_InitStructure);
/***********************************************************************************************************
DMA的配置
***********************************************************************************************************/
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //DMA对应的外设基地址
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADCConvertedValueTab; //内存存储基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //DMA的转换模式为SRC模式,由外设搬移到内存
DMA_InitStructure.DMA_BufferSize = 1024; //DMA缓存大小,1个
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //接收一次数据后,设备地址禁止后移
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //接收一次数据后,目标内存地址后移
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //定义外设数据宽度为16位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //DMA搬移数据尺寸,HalfWord就是为16位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //转换模式,循环缓存模式。
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA优先级高
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //M2M模式禁用
/***********************************************************************************************************
AD的校准
***********************************************************************************************************/
ADC_Cmd(ADC1, ENABLE); //开启ADC1
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
/***********************************************************************************************************
AD和DMA的初始化
***********************************************************************************************************/
ADC_RegularChannelConfig(ADC1, Channel, 1, ADC_SampleTime_7Cycles5);
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_DeInit(DMA1_Channel1); //开启DMA1的第一通道
ADC_DMACmd(ADC1, ENABLE);
/***********************************************************************************************************
KEY:软件触发
***********************************************************************************************************/
ADC_SoftwareStartConvCmd(ADC1, ENABLE)
PlusePhase = TIM3->CNT; //方波相位
while(!DMA_GetFlagStatus(DMA1_FLAG_TC1));
ADC_SoftwareStartConvCmd(ADC1, DISABLE);
DMA_ClearFlag(DMA1_FLAG_TC1);
return ADCConvertedValueTab;
|