关于定时器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);
}
先配置TIM,然后配置ADC,在TIM中断里面判断EOC,读取数据存放到指定的缓冲区中。 安 发表于 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; 还是不行吖,
不知道阁下有啥好的建议? 试了一下,发下 ADC 根本就没有被启动。 楼主为什么要用TIM来触发采集AD呢?想实现什么样的功能? 安 发表于 2015-4-15 10:51
楼主为什么要用TIM来触发采集AD呢?想实现什么样的功能?
我想采集20K个点来实现电压量的采集。因为要求采样频率必须固定,所以想通过定时器采样。 哦。楼主可以开启AD中断,中断实时转换数据放入到指定的变量中,当TIM中断产生时,直接取值就可以了。 安 发表于 2015-4-15 16:37
哦。楼主可以开启AD中断,中断实时转换数据放入到指定的变量中,当TIM中断产生时,直接取值就可以了。 ...
EN, thanks, 我已经试过了在TIM中断里面通过软件开启 adc 了,这样是可以,但是方法没有 通过TIM的trgo事件触发 ADC 转换 优越,而且精度 比不上 trgo触发 。毕竟 进入中断要 出栈入栈。 我记得ADC转換在第一次使能时,只是把ADC从休眠模式唤醒,需要再次使能才开使转换数据的。
见
页:
[1]
2