狂奔的企鹅 发表于 2015-4-14 18:29:55

关于定时器TIM3 触发 ADC1 采样的一点困惑

本帖最后由 狂奔的企鹅 于 2015-4-15 14:36 编辑

我用的是STM32F4-DISCOVERY (探索板)

下面是我写的配置文件,分别是 adc 的配置文件和 tim的配置文件,其中 tim_gpio_config的配置文件,那部分是 为了检测是否有30KHZ方波产生。

波形产生没有错误,我用示波器测了一下,是 30KHZ的方波。
而ADC配置部分也用软件启动试过也没有问题,唯一有问题的就是 tim 触发 adc 这部分..

我是通过TIM_Cmd(TIM3, ENABLE); 启动AD转换的。然后在一个循环里不断读取 EOC标志位来 存贮 ADC 转换值的。

会滴举个手,指点下我。谢谢!

void adc_config(void)
{
    GPIO_InitTypeDef      GPIO_InitStructure;
    ADC_CommonInitTypeDef ADC_CommonInitStructure;
    ADC_InitTypeDef       ADC_InitStructure;
   
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); // APB2 时钟84MHZ

    /* Configure ADC1 Channel15 pin as analog input pc5******************************/
    /* Configure ADC1 Channel11 pin as analog input pc1******************************/
   
    GPIO_InitStructure.GPIO_Pin =GPIO_Pin_1 | GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    /* ADC Common Init **********************************************************/
    //
    ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; //独立模式
    ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; // 84MHZ / 2 = 42MHZ;
    ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;
    ADC_CommonInit(&ADC_CommonInitStructure);

    /* ADC1 Init ****************************************************************/
    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
    ADC_InitStructure.ADC_ScanConvMode = ENABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
   
    // 通过上升沿触发
    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
   
    // 通过 定时器的TRGO 信号来启动 ADC1
    ADC_InitStructure.ADC_ExternalTrigConv =ADC_ExternalTrigConv_T3_TRGO;

    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfConversion = 2;
    ADC_Init(ADC1, &ADC_InitStructure);
   
   
    /* ADC1 regular channel11,15 configuration *************************************/
    ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 2, ADC_SampleTime_144Cycles);   
    ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_144Cycles);
   
    ADC_Cmd(ADC1, ENABLE);
   
    // 在每个通道转换结束后 产生标志位EOC
    ADC_EOCOnEachRegularChannelCmd(ADC1,ENABLE);   
}


// 检测是否波形是否正确
void GPIO_TIM_Config(void)
{   
    GPIO_InitTypeDefGPIO_InitStructure;

    /* Enable the GPIOC Clock */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);

/* Configure the GPIO_6 pin */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
   
    // 打开GPIOC_6 的引脚复用功能 TIM3_CH1
    GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_TIM3);
   
}
// 计数器 60khz的工作频率
const u16 PrescalerValue = (u16)((168000000 / 2) /60000) - 1;
void TIM1_Config(void)
{
    TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;
    TIM_OCInitTypeDef         TIM_OCInitStructure;
   
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);

    /* Time base configuration */
    // 计数到1,从0到1,计数两次,两次后计数溢出 产生更新事件。更新事件的频率是30KHZ
    TIM_TimeBaseStructure.TIM_Period = 1;
   
    TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue; // 计数器 60khz的工作频率
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
   
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
   
    /* Prescaler configuration1MHZ 的计时工作频率*/
    //TIM_PrescalerConfig(TIM3, PrescalerValue, TIM_PSCReloadMode_Immediate);
   
    /* Output Compare Timing Mode configuration: Channel2 */
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // 使用 PWM 技术检测是否能输出 30KHZ的波
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 1; // 占空比为 25%
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //高电平为有效电平
   
    TIM_OC1Init(TIM3, &TIM_OCInitStructure);
    // 预载寄存器使能
    TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
    /* TIM1 enable counter */
    TIM_ARRPreloadConfig(TIM3, ENABLE);
    // 选择事件作为外部触发 --- > ADC1
    TIM_SelectOutputTrigger(TIM3,TIM_TRGOSource_Update);
   
}






发表于 2015-4-15 09:30:01

先配置TIM,然后配置ADC,在TIM中断里面判断EOC,读取数据存放到指定的缓冲区中。

狂奔的企鹅 发表于 2015-4-15 10:09:44

安 发表于 2015-4-15 09:30
先配置TIM,然后配置ADC,在TIM中断里面判断EOC,读取数据存放到指定的缓冲区中。 ...

这样不就失去了通过 TIM 3的更新事件触发 ADC 采样 的优越性了嘛,还有 adc_config的配置那块的 // 通过 定时器的TRGO 信号来启动 ADC1
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;

已经修改为 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO; 还是不行吖,
不知道阁下有啥好的建议?

狂奔的企鹅 发表于 2015-4-15 10:32:12

试了一下,发下 ADC 根本就没有被启动。

发表于 2015-4-15 10:51:26

楼主为什么要用TIM来触发采集AD呢?想实现什么样的功能?

拼命三郎 发表于 2015-4-15 13:21:09

狂奔的企鹅 发表于 2015-4-15 14:35:23

安 发表于 2015-4-15 10:51
楼主为什么要用TIM来触发采集AD呢?想实现什么样的功能?

我想采集20K个点来实现电压量的采集。因为要求采样频率必须固定,所以想通过定时器采样。

发表于 2015-4-15 16:37:23

哦。楼主可以开启AD中断,中断实时转换数据放入到指定的变量中,当TIM中断产生时,直接取值就可以了。

狂奔的企鹅 发表于 2015-4-15 17:55:14

安 发表于 2015-4-15 16:37
哦。楼主可以开启AD中断,中断实时转换数据放入到指定的变量中,当TIM中断产生时,直接取值就可以了。 ...

EN, thanks, 我已经试过了在TIM中断里面通过软件开启 adc 了,这样是可以,但是方法没有 通过TIM的trgo事件触发 ADC 转换 优越,而且精度 比不上 trgo触发 。毕竟 进入中断要 出栈入栈。

hjl2832 发表于 2015-4-16 13:19:23

我记得ADC转換在第一次使能时,只是把ADC从休眠模式唤醒,需要再次使能才开使转换数据的。
页: [1] 2
查看完整版本: 关于定时器TIM3 触发 ADC1 采样的一点困惑