打印

STM32的TIM2触发ADC问题,版主和各位朋友帮忙

[复制链接]
9872|22
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
eagle109|  楼主 | 2011-10-20 21:31 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
我使用TIM2的TIM_TRGOSource_OC2Ref来触发ADC转换,按照我的理解我改变OC2比较寄存器的值就可以控制ADC开始转换的时间,但是实验结果是ADC总在OC2计数器复位后开始。如下图:
沙发
eagle109|  楼主 | 2011-10-20 21:37 | 只看该作者
附上TIM2初始化代码,10KHz,占空比25%,即OC2Ref,我在PA1引脚输出了OC2的波形,好示波器做抓取比较

void Init_T2(void)
{
        TIM_OCInitTypeDef  TIM_OCInitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

        GPIO_InitTypeDef GPIOA_InitStruct;

        GPIOA_InitStruct.GPIO_Pin = GPIO_Pin_1;
        GPIOA_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIOA_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIOA_InitStruct);

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE );

  TIM_DeInit(TIM2);
  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);  
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;       
  TIM_TimeBaseStructure.TIM_Period = (SystemCoreClock / 10000 ) - 1;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

  TIM_OCStructInit(&TIM_OCInitStructure);

  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
  TIM_OCInitStructure.TIM_Pulse = 1800;
  TIM_OC2Init(TIM2, &TIM_OCInitStructure);          

   TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable);
   TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_OC2Ref);
  /* TIM1 counter enable */
  TIM_Cmd(TIM2, ENABLE);

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

}

使用特权

评论回复
板凳
eagle109|  楼主 | 2011-10-20 21:41 | 只看该作者
ADC初始化代码如下,3路AD。使用TIM2的OC2ref触发ADC转换,转换完成后触发DMA中断:
void ADC_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  DMA_InitTypeDef DMA_InitStructure;
  ADC_InitTypeDef  ADC_InitStructure;

  /* Configure PC.00, PC.02 and PC.03 (ADC Channel10, Channel12 and Channel13)*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  /* init ADC clock */
  RCC_ADCCLKConfig(RCC_PCLK2_Div6);        /* 72MHz/6 */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 , ENABLE );

  /* DMA1 channel1 configuration ----------------------------------------------*/
  DMA_DeInit(DMA1_Channel1);
  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  DMA_InitStructure.DMA_BufferSize = 3;
  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 DMA1 channel1 */
  DMA_Cmd(DMA1_Channel1, ENABLE);
  
  /* ADC1 configuration ------------------------------------------------------*/
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfChannel = ADC_NUM;
  ADC_Init(ADC1, &ADC_InitStructure);

  /* ADC1 regular configuration */
  ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_1Cycles5);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 2, ADC_SampleTime_1Cycles5);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 3, ADC_SampleTime_1Cycles5);


   ADC_DMACmd(ADC1 , ENABLE);
   ADC_ExternalTrigConvCmd(ADC1, ENABLE);
  

   ADC_Cmd(ADC1 , ENABLE);   
   ADC_ResetCalibration(ADC1);
   while(ADC_GetResetCalibrationStatus(ADC1)){};
   ADC_StartCalibration(ADC1);
   while(ADC_GetCalibrationStatus(ADC1)){};

   DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
}

使用特权

评论回复
地板
airwill| | 2011-10-21 08:49 | 只看该作者
不能直接提供你的功能,不过你可以让 CC2 输出反相,再变换 CCR2 的值来实现。

使用特权

评论回复
5
bili| | 2011-10-21 09:37 | 只看该作者
楼主你漏掉看规格书里面说的一句话:“When an external trigger is selected for ADC regular or injected conversion, only the rising edge of the signal can start the conversion.” 这里你只要将PWM模式换成PWM2即可。但是波形跟你想要的正好是反向互补。这样你还是控制CCR2就可以控制ADC转换的时刻。波形应该对你意义不大吧!

使用特权

评论回复
6
eagle109|  楼主 | 2011-10-21 12:23 | 只看该作者
楼上两位,谢谢你们的回答。
“only the rising edge of the signal can start the conversion”
这个就悲剧了,即使改为了PWM2也是一样的,因为PWM2其实只是转换的占空比,上升沿还是在计数器清零的时刻,而不是在CCR2比较成功的时刻。

使用特权

评论回复
7
eagle109|  楼主 | 2011-10-21 12:39 | 只看该作者
我就在想,如果只是上升沿才能触发转换,那么用TIM触发只需要Updata事件就可以了啊,为什么还搞什么TIM1_CC1,TIM1_CC2,TIM1_CC3等事件,不都是一样的吗?

使用特权

评论回复
8
bili| | 2011-10-21 13:04 | 只看该作者
你理解错了吧,TIM2_CC2是TCNT=CCR时候产生的,按照你的配置改成PWM2怎么会是计数器清零的时候出OC2上升沿呢?

使用特权

评论回复
9
eagle109|  楼主 | 2011-10-21 13:15 | 只看该作者
PWM1和PWM2模式就是一个互补输出,但是实际上ST做的做法是占空比取反而已,比如我图上用PWM1模式25%占空比,如果改为PWM2模式,那么就变为75%占空比,如下图:

使用特权

评论回复
10
bili| | 2011-10-21 13:21 | 只看该作者
占空比是75%,但应该是互补才是,你图中的两个波形应该是互补的,而不是相移了270

使用特权

评论回复
11
eagle109|  楼主 | 2011-10-21 13:24 | 只看该作者
没有相移,实际上PWM1和PWM2输出的波形就是这样,即上升沿始终是在起始时刻出现

使用特权

评论回复
12
bili| | 2011-10-21 13:27 | 只看该作者
好吧,相移这只是参考的问题,波形是对的,但是上升沿可不是计数器清零的时候,而是匹配的时候才出的

使用特权

评论回复
13
bili| | 2011-10-21 13:34 | 只看该作者
占空比你可以将你的1800改成5400就变成25%占空比

使用特权

评论回复
14
nongfuxu| | 2011-10-21 16:18 | 只看该作者
airwill的正解. 这也证实了STM32F外设的功能不是一般的强大.

使用特权

评论回复
15
香水城| | 2011-10-21 16:46 | 只看该作者
没有相移,实际上PWM1和PWM2输出的波形就是这样,即上升沿始终是在起始时刻出现
eagle109 发表于 2011-10-21 13:24


PWM1和PWM2输出的波形应该是互补的关系,PWM1是先高再低,PWM2是先低再高。

使用特权

评论回复
16
eagle109|  楼主 | 2011-10-21 19:40 | 只看该作者
谢谢2位,可能是我搞错了,我明天做下实验,把OC1ref和OC2ref分别用PWM1和PWM2输出看看效果

使用特权

评论回复
17
海天一色| | 2011-11-3 08:28 | 只看该作者
我就在想,如果只是上升沿才能触发转换,那么用TIM触发只需要Updata事件就可以了啊,为什么还搞什么TIM1_CC1,TIM1_CC2,TIM1_CC3等事件,不都是一样的吗? ...
eagle109 发表于 2011-10-21 12:39


我也遇到这样的问题,使用TIM2_CC2触发AD转换,但是发现cc2中断和update发生的时刻是一样的

使用特权

评论回复
18
yinyangdianzi| | 2011-11-3 13:22 | 只看该作者
帮不上

使用特权

评论回复
19
zhqs425| | 2011-11-3 13:30 | 只看该作者
谢谢分享喽!!

使用特权

评论回复
20
进程| | 2011-11-27 19:52 | 只看该作者
非常感谢5楼bili的提醒,定时器上溢前后采样时需要设置CCx触发

使用特权

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

本版积分规则

19

主题

57

帖子

1

粉丝