你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

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

[复制链接]
胤幻1988 提问时间:2016-3-23 14:26 /

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 */                              /*本次预分频数为1  Tim2Clk=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[i].T1,TAB_TIM_TIME[i].T2);

                        Delay_ms(My_DELAYTIME[i]);

                        /* 采样并计算有效值 */
                    
                        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[k];
                                        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[j]=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[3]={{1,19175},{1,1340},{1,268}};                  /* 采样定时器时间系数 分别对70HZ,2000HZ,5000HZ进行采样 */
uint16_t My_DELAYTIME[3]={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求解??
收藏 评论0 发布时间:2016-3-23 14:26

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版