胤幻1988 发表于 2016-3-23 14:26:31

为何STM32F103VET6 ADC采样时间与理论相差太大?


STM32F103VET6 为什么采样要花很长时间,跟理论完全不符合,求助。。。
我是用TIM2的T2_CC2输出PWM作为ADC采样的时钟,并且DMA储存数据,具体如下:
一些外设的配置:
/*******************************************************************************
* 函数名称:USART_Configuration()
* 函数功能:USART 配置
* 入口参数:无
* 出口参数:无
* 返 回 值:无
*******************************************************************************/
void USART_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;

USART_InitStructure.USART_BaudRate = 9600;                                                                                  /* 波特率:9600 */
USART_InitStructure.USART_WordLength = USART_WordLength_8b;                                                /* 数据位:8 */
USART_InitStructure.USART_StopBits = USART_StopBits_1;                                                          /* 停止位:1 */
USART_InitStructure.USART_Parity = USART_Parity_No;                                                                  /* 无校验 */
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;          /* 无硬件握手 */
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;                                    /* 二线模式 */

/* Configure the USART1,3 */
USART_Init(USART1, &USART_InitStructure);
USART_Init(USART3, &USART_InitStructure);

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);                                          /* 允许接收中断 */
//USART_ITConfig(USART1, USART_IT_TC, ENABLE);                                              /* 允许发送完成中断 */
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);                                          /* 允许接收中断 */
//USART_ITConfig(USART3, USART_IT_TC, ENABLE);                                              /* 允许发送完成中断 V1.5 */
      
/* Enable USART1,3 */
USART_Cmd(USART1, ENABLE);
USART_Cmd(USART3, ENABLE);

USART_ClearFlag(USART1,USART_FLAG_TC);
USART_ClearFlag(USART3,USART_FLAG_TC);
}

/*******************************************************************************
* 函数名称:ADC_Configuration()
* 函数功能:ADC 配置
* 入口参数:无
* 出口参数:无
* 返 回 值:无
*******************************************************************************/
void ADC_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;

/* ADC1 configuration ------------------------------------------------------*/
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;                                        /* 独立模式 */
ADC_InitStructure.ADC_ScanConvMode = DISABLE;                                                      /* 不使用扫描模式 */
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;                                        /* 不使用连续转换模式 */
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;      /* 触发模式:T2_CC2 */
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;                              /* 数据右对齐 */
ADC_InitStructure.ADC_NbrOfChannel = 1;                                                                /* 1通道 */
ADC_Init(ADC1, &ADC_InitStructure);

/* ADC1 regular channel2 configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_1Cycles5);

/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);

/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);

/* Enable ADC1 reset calibaration register */   
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));

/* Start ADC1 calibaration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));

/* Start ADC1 Software Conversion */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);

}


/*******************************************************************************
* 函数名称:TIM2_Config()
* 函数功能:定时器2配置 OC2输出ADC CLK
* 入口参数:Prescaler 预分频值
            Period 计数值
* 出口参数:无
* 返 回 值:无
*******************************************************************************/
void TIM2_Config(uint16_t Prescaler,uint16_t Period)
{
uint16_t Pulse;
                                                             /*TIME2 挂载在APB1=SYSCLK/2=72M/2=36M*/
TIM_CtrlPWMOutputs(TIM2, DISABLE);                         /*但APB1的预分频数为2,所以TIM2_Clk=36*2=72M*/
TIM_Cmd(TIM2, DISABLE);

if(Prescaler) Prescaler-=1;
Pulse = Period/2;
if(Period) Period-=1;
                                                             /*中断时间=(TIM_Prescaler+1)*(TIM_Period+1)/TIM_Fre*/
/* Time Base configuration */                              /*本次预分频数为1Tim2Clk=72M*/
TIM_TimeBaseStructure.TIM_Prescaler = Prescaler;         /*时钟预分频数 APB1_Sysclk/(Prescaler+1)*/
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;/*向上计数模式*/
TIM_TimeBaseStructure.TIM_Period = Period;               /*自动重装寄存器的值*/
TIM_TimeBaseStructure.TIM_ClockDivision = 0;               /*采样分频采样分频DIV1不变*/
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

/* Channel 2 Configuration in PWM mode */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;                  
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;         
TIM_OCInitStructure.TIM_Pulse = Pulse;

TIM_OC2Init(TIM2, &TIM_OCInitStructure);

/* TIM2 IT enable */
TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);

/* TIM2 counter enable */
TIM_Cmd(TIM2, ENABLE);

/* Main Output Enable */
TIM_CtrlPWMOutputs(TIM2, ENABLE);
}


/*******************************************************************************
* 函数名称:DMA_Configuration()
* 函数功能:DMA 配置
* 入口参数:无
* 出口参数:无
* 返 回 值:无
*******************************************************************************/
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;

/* DMA1 channel1 configuration ----------------------------------------------*/
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_ConvertedValue;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 100;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);

/* Enable DMA channel1 */
DMA_Cmd(DMA1_Channel1, ENABLE);

}

放在WHILE中的处理函数:
            for(i=0;i<3;i++)
                {
                        /* 控制信号源和交叉开关 */
                        /*复位初始状态*/
                        SET_ON_SELECT_Reset();                      /*SET_ON端复位*/
                        Delay_ms(2);
                                                
                        SET_ON_SELECT_SWITCH('A',i);                /*准备状态*/
                        Delay_ms(2);

                        SET_ON_SELECT_SWITCH('B',i);                /*执行状态*/
                        
                        /* 采样 */
                        /* 采样速率设置 */
                        TIM2_Config(TAB_TIM_TIME.T1,TAB_TIM_TIME.T2);

                        Delay_ms(My_DELAYTIME);

                        /* 采样并计算有效值 */
                  
                        for(j=0;j<4;j++)
                        {
                              AD1_CH2_Value=0;
                              for(k=0;k<50;k++)
                              {
                                        while(!ADC_Flag);
                                        ADC_Flag=0;
                                        CH2_Value_Temp=ADC_ConvertedValue;
                                        CH2_Value_Temp-=2048;
                                        AD1_CH2_Value+=(CH2_Value_Temp*CH2_Value_Temp);
                              }

                              AD1_CH2_Value/=50;
                              AD1_CH2_Value=sqrt(AD1_CH2_Value);

                              AD1_CH2_Temp=AD1_CH2_Value;
                        }
               
                  
               }            


这一段代码耗时间非常长。。。

定义了一个采样标志:ADC_Flag
它是在TIM2中断里面复位的:
/*******************************************************************************
* 函数名称:TIM2_IRQHandler()
* 函数功能:TIM2中断处理,更新ADC采样标志
* 入口参数:无
* 出口参数:无
* 返 回 值:无
*******************************************************************************/
void TIM2_IRQHandler(void)
{
      if(TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET){
                TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
                ADC_Flag=1;
      }
}


其他定义的常量:
STRUCT_TIM_DATA   TAB_TIM_TIME={{1,19175},{1,1340},{1,268}};                  /* 采样定时器时间系数 分别对70HZ,2000HZ,5000HZ进行采样 */
uint16_t My_DELAYTIME={20,10,10};                                                                  /* 延时时间 单位:mS   当波形产生后,要延时一段时间才能稳定*/
我的采样思路是这样的:每种频率的正弦波,每个周期采50个点。。譬如70HZ来说:每个点采样的时间为:1/70/50s..则可以算出TIM2的配置:
中断时间=(TIM_Prescaler+1)*(TIM_Period+1)/TIM_Fre    设定采样频率未分频为1则
1/70/50=1*TIM_Period/72M
得出
TIM_Period=20571;
但为了绝对在1个周期以内 TIM_Period取稍小的值 19175;
那么问题来了:实际上采样10个70HZ周期的最长时间也就是1/70*10=0.143S,但为什么实际上用用时远远不止呢?大概有600ms求解??
页: [1]
查看完整版本: 为何STM32F103VET6 ADC采样时间与理论相差太大?