打印
[STM32F0]

STM32F051单片机定时触发ADC采集PWM信号出现问题

[复制链接]
2006|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
各位大神下午好,我在使用STM32F051调试定时器触发ADC时无意间发现一个问题,使用TIM15作为触发,时间为1ms,当采集一个20KHZ的PWM信号时(不要纠结为什么用AD采集,无意间发现的这个问题),然后使用DAC将采集到的量输出,意思就是DAC跟踪ADC,发现DAC输出变为1HZ,但是占空比和PWM信号是一样的,但是使用ADC采集其他电压信号(我认为是变化比较慢的)时DAC跟踪输出是正常的,以下是测量的波形
图1:ADC管脚(PC5)PWM的波形


图2:DAC输出的波形

图3:可以看出DAC输出时每1ms值会变化一次,但是根据PWM信号频率是20KHZ 周期为50us,DAC的输出应该是上下跳动的而不是这种阶梯似的波形


以下为部分初始化代码

void Cfg_Time_TGO(void)
{

    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStruct;
   
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM15, ENABLE);
    TIM_TimeBaseStruct.TIM_ClockDivision            =TIM_CKD_DIV4;
    TIM_TimeBaseStruct.TIM_CounterMode                =TIM_CounterMode_Up;
    TIM_TimeBaseStruct.TIM_Prescaler                  =48-1;   
    TIM_TimeBaseStruct.TIM_Period                    =1000-1;     
    TIM_TimeBaseStruct.TIM_RepetitionCounter        = 0;
    TIM_TimeBaseInit(TIM15, &TIM_TimeBaseStruct);
   
    TIM_SelectOutputTrigger(TIM15,TIM_TRGOSource_Update);
    TIM_ClearFlag(TIM15,TIM_FLAG_Update);
    TIM_Cmd(TIM15, ENABLE);
}


void Cfg_ADC_INss(void)
{
    NVIC_InitTypeDef NVIC_InitStruct;
    GPIO_InitTypeDef GPIO_InitStruct;
    ADC_InitTypeDef  ADC_InitStruct;
    DMA_InitTypeDef  DMA_InitStruct;
   
    ADC_DeInit(ADC1);
    DMA_DeInit(DMA1_Channel1);
   
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);  
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);  
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);  
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
   
    GPIO_InitStruct.GPIO_Pin                         = GPIO_Pin_0|GPIO_Pin_1 ;  //¿ØÖƵçѹ Êä³öµçѹ
    GPIO_InitStruct.GPIO_Mode                     = GPIO_Mode_AN;
    GPIO_InitStruct.GPIO_PuPd                     = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOB, &GPIO_InitStruct);
   
    GPIO_InitStruct.GPIO_Pin                       = GPIO_Pin_5 ;  //¿ØÖƵçѹ Êä³öµçѹ
    GPIO_InitStruct.GPIO_Mode                     = GPIO_Mode_AN;
    GPIO_InitStruct.GPIO_PuPd                     = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOC, &GPIO_InitStruct);
        
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //
  ADC_StructInit(&ADC_InitStruct);

    ADC_InitStruct.ADC_ContinuousConvMode        =DISABLE;
    ADC_InitStruct.ADC_DataAlign                    =ADC_DataAlign_Right;
   
    ADC_InitStruct.ADC_ExternalTrigConvEdge =ADC_ExternalTrigConvEdge_Rising;
    ADC_InitStruct.ADC_ExternalTrigConv         =ADC_ExternalTrigConv_T15_TRGO;
    //ADC_InitStruct.ADC_ExternalTrigConvEdge        =ADC_ExternalTrigConvEdge_None;
    ADC_InitStruct.ADC_Resolution                    =ADC_Resolution_12b;
    ADC_InitStruct.ADC_ScanDirection            =ADC_ScanDirection_Backward;
    ADC_Init(ADC1, &ADC_InitStruct);
   
    ADC_OverrunModeCmd(ADC1,ENABLE);
    ADC_ChannelConfig(ADC1, ADC_Channel_8 , ADC_SampleTime_239_5Cycles);
    ADC_ChannelConfig(ADC1, ADC_Channel_15 , ADC_SampleTime_239_5Cycles);
   
    ADC_GetCalibrationFactor(ADC1);
   
    ADC_Cmd(ADC1, ENABLE);
    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN));
   
    ADC_StartOfConversion(ADC1);
   
    DMA_DeInit(DMA1_Channel1);//Ñ¡ÔñƵµÀ
    DMA_InitStruct.DMA_PeripheralBaseAddr     =(uint32_t)((uint16_t *)ADC1_DR_Address);//ÉèÖÃÍâÉèµØÖ·
    DMA_InitStruct.DMA_MemoryBaseAddr         =(uint32_t)((uint16_t *)ADC_DR);//ÉèÖÃÄÚ´æÓ³Éä
    DMA_InitStruct.DMA_PeripheralBaseAddr     =ADC1_DR_Address;//ÉèÖÃÍâÉèµØÖ·
    DMA_InitStruct.DMA_MemoryBaseAddr         =(uint32_t)&ADC_DR;//ÉèÖÃÄÚ´æÓ³Éä
    DMA_InitStruct.DMA_DIR                     =DMA_DIR_PeripheralSRC;
    DMA_InitStruct.DMA_BufferSize             =2;//»º³åΪ
    DMA_InitStruct.DMA_PeripheralInc         =DMA_PeripheralInc_Disable;//¹ØÍâÉèµØÖ·¼ÆÊý
    DMA_InitStruct.DMA_MemoryInc             =DMA_MemoryInc_Enable;
    DMA_InitStruct.DMA_PeripheralDataSize    =DMA_PeripheralDataSize_HalfWord;
    DMA_InitStruct.DMA_MemoryDataSize         =DMA_MemoryDataSize_HalfWord;//°ë×Ö
    DMA_InitStruct.DMA_Mode                 =DMA_Mode_Circular;//Ñ­»·Ä£Ê½
    DMA_InitStruct.DMA_Priority             =DMA_Priority_High;//¸ßÓÅÏȼ¶
    DMA_InitStruct.DMA_M2M                     =DMA_M2M_Disable;//¹ØÄÚ´æµ½ÄÚ´æ
    DMA_Init(DMA1_Channel1, &DMA_InitStruct);
    DMA_Cmd(DMA1_Channel1, ENABLE);//ƵµÀʹÄÜ
    ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular);//ÅäÖà DMA Ñ­»·Ä£Ê½
    ADC_DMACmd(ADC1, ENABLE);   
   
    DMA_ITConfig (DMA1_Channel1,DMA_IT_TC,ENABLE);
    NVIC_InitStruct.NVIC_IRQChannel=DMA1_Channel1_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPriority=0;
    NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
    NVIC_Init(&NVIC_InitStruct);
}

void DMA1_Channel1_IRQHandler(void)
{
    DMA_ClearFlag(DMA1_FLAG_TC1);
    dmadone = 1;
}


int main()
{
    Cfg_Time_TGO();
    Cfg_ADC_INss();

    while(1)
   {
         if (dmadone!=0)
         {
             DAC_SetChannel1Data(DAC_Align_12b_R,ADC_DR[1]);
         }
   }
}





新建文件2.BMP (217.76 KB )

新建文件2.BMP
沙发
磁轨炮|  楼主 | 2017-8-4 15:40 | 只看该作者
沉了么。。。。

使用特权

评论回复
板凳
fengfeng的恒| | 2017-8-4 15:42 | 只看该作者
有可能是ADC采样时间太长了,配置一下时钟分频,把采样周期减少试试吧。现在是239.5,感觉太长了。

使用特权

评论回复
地板
磁轨炮|  楼主 | 2017-8-4 15:49 | 只看该作者
fengfeng的恒 发表于 2017-8-4 15:42
有可能是ADC采样时间太长了,配置一下时钟分频,把采样周期减少试试吧。现在是239.5,感觉太长了。 ...

谢谢大神,但是试了下没什么效果

使用特权

评论回复
5
fengfeng的恒| | 2017-8-4 16:16 | 只看该作者
磁轨** 发表于 2017-8-4 15:49
谢谢大神,但是试了下没什么效果

似乎你的代码没有对ADC的时钟进行配置,应该不能超过14Mhz的,至少需要4分频。或者你可以单独试试ADC采集1s,用一个变量计算DMA中断了多少次。这样应该能定位问题了。

使用特权

评论回复
6
磁轨炮|  楼主 | 2017-8-4 17:20 | 只看该作者
fengfeng的恒 发表于 2017-8-4 16:16
似乎你的代码没有对ADC的时钟进行配置,应该不能超过14Mhz的,至少需要4分频。或者你可以单独试试ADC采集 ...

谢谢大神指点,问题解决了,是采样的问题,根据图3,怀疑是采样是第一次采到第一个周期的开始,刚好一个周期是50us,然后采到第二个周期的往后一点点,就积累出1S的时间来了,如果把采样周期改为40us就好很多了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

13

主题

38

帖子

0

粉丝