打印
[STM32F0]

关于ADC_DMA采样偶尔会出错的问题咨询

[复制链接]
2290|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tzw51723|  楼主 | 2014-7-14 10:38 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
ADC, DMA, TI, ST, ni
现在有一个问题,ADC采样有时会不准,十几分钟出现1,2次采集数据不准确。以下是我的ADC初始化,帮忙看下有什么问题?
硬件:stm32f030x4 (16k flash,4k ram,5 timer,1 usart)
原理:通过XtBspAdcTimerStart(),启动TIM16,625us中断一次,然后再中断中,启动ADC转换,并打开DMA中断,直到采集完SAMPLE_NUM,停止定时器,表示采用完成,然后再进行ADC数据处理。
补充说明:
1、系统还用到TM14,每1ms产生一次中断;和串口1中断。另外TIM3和TIM17,分别作为PWM时钟和模拟USART时钟。TIM1闲置。
2、NVIC_InitStructure.NVIC_IRQChannelPriority = 0; 所有中断优先级,都设为同级别优先级了。
3、正常数据应该是一个正弦波,而出错数据如下。

我做的一些实验:
1、恒定给一个3.3V的直流信号。数据采集出来都是OK得
2、用信号源,给一个稳定的1.65V的正弦波信号,采集数据还是一样会有时出错。
3、判定是否硬件电平不稳定,用示波器捕捉了很久,没有看到有脉冲信号。
-->之前初步判定是TIM16优先级不够,被打断,导致采样间隔误差造成,采样数据出错。
4、于是我TIM16改为TIM1后,还是偶尔会出现采集出错的问题,根据一些列表,和我用到得中断,我的TIM1在我系统中,除了DMA,已经是优先级最高了。




以下是我的ADC采样相关设置代码,请帮忙看下有什么问题吗?谢谢
//--------------------------------------------------------
void STM_EVAL_ADCConfig(void)
{
ADC_InitTypeDef       ADC_InitStructure;
//ADC_CommonInitTypeDef ADC_CommonInitStructure;
DMA_InitTypeDef       DMA_InitStructure;
GPIO_InitTypeDef      GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable ADC1, and GPIO clocks ****************************************/
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 | RCC_AHBPeriph_GPIOA|RCC_AHBPeriph_GPIOB, ENABLE);     
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
//RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 , ENABLE);
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)adc1Buf;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 2;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;//DMA_Priority_High
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel1, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 ;
GPIO_Init(GPIOB, &GPIO_InitStructure);

  /* Initialize ADC structure */
   ADC_StructInit(&ADC_InitStructure);

ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //连续扫描模式
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Backward;
ADC_Init(ADC1, &ADC_InitStructure);
//ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_T3_CC2);

//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelPriority = 0x00;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);

/*enable transfer complete interrupt------------------*/
//DMA_ITConfig(DMA1_Channel1, DMA1_IT_TC1, ENABLE);
/* ADC3 regular channel7 configuration *************************************/

ADC_ChannelConfig(ADC1, ADC_Channel_7 , ADC_SampleTime_13_5Cycles);
ADC_ChannelConfig(ADC1, ADC_Channel_9 , ADC_SampleTime_13_5Cycles);
//ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);
//ADC_StartOfConversion(ADC1);

}

xt_s32 XtBspAdcTimerStart()
{
xt_s32 ret = 0;
STM_EVAL_Tim16Config();
return ret;
}

xt_s32 XtBspAdcTimerStop()
{
xt_s32 ret = 0;
TIM_ITConfig(TIM16, TIM_IT_Update, DISABLE);
TIM_Cmd(TIM16, DISABLE);
return ret;
}


void TIM16_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;

/* TIM3 clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM16, ENABLE);

/* Enable the TIM16 gloabal Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM16_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}

void STM_EVAL_Tim16Config(void)
{
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
//unsigned int val;
unsigned int psc;
unsigned int arr;
RCC_ClocksTypeDef RCC_Clocks;
RCC_GetClocksFreq(&RCC_Clocks);
TIM16_Config();

//val = RCC_Clocks.PCLK2_Frequency / (50 * 32);
//psc = (val + 49999) / 50000 - 1;
//arr = (val / (psc + 1)) - 1;
arr= RCC_Clocks.PCLK_Frequency/1600-1;
psc=0;

/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = arr;
TIM_TimeBaseStructure.TIM_Prescaler = psc;//;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM16, &TIM_TimeBaseStructure);

/* Prescaler configuration */
TIM_PrescalerConfig(TIM16, psc, TIM_PSCReloadMode_Update);

TIM_SetAutoreload(TIM16, arr);

/* TIM Interrupts enable */
TIM_ITConfig(TIM16, TIM_IT_Update, ENABLE);

/* TIM2 enable counter */
TIM_Cmd(TIM16, ENABLE);
}

//-------------stm32f0xx_it.c--------------------
void TIM16_IRQHandler(void)
{
//__disable_irq();
if(TIM_GetITStatus(TIM16, TIM_IT_Update) == SET) {
dmaFlag = 1;
ADC_StartOfConversion(ADC1);
DMA_ITConfig(DMA1_Channel1, DMA1_IT_TC1, ENABLE);
TIM_ClearITPendingBit(TIM16, TIM_IT_Update);
}
//__enable_irq();
}

void DMA1_Channel1_IRQHandler    (void)
{
unsigned char  i;
//__disable_irq();
if(DMA_GetITStatus(DMA1_IT_TC1) == SET) {
DMA_ITConfig(DMA1_Channel1, DMA1_IT_TC1, DISABLE);
if (dmaFlag == 1)
{
for(i=0;i<CHANNLE;i++)
{
ad_cvs.buf[i][ad_cvs.sample]=adc1Buf[i];//(adc1Buf[i]>>4) & 0xfff;
}
ad_cvs.sample++;
if(ad_cvs.sample>=SAMPLE_NUM)
{
XtBspAdcTimerStop();
}
dmaFlag = 0;
}
DMA_ClearITPendingBit(DMA1_IT_TC1);
}
//__enable_irq();
}




--------------------------------------------------------------------------------
沙发
tzw51723|  楼主 | 2014-7-14 10:48 | 只看该作者
定时中断,开启ADC转换和DMA中断,读出ADC数据,有时出错,会是什么问题???请大家帮忙看下,谢谢。

使用特权

评论回复
板凳
金融小数| | 2014-7-14 11:13 | 只看该作者
私下认为:建议你不要使用DMA。

使用特权

评论回复
地板
tzw51723|  楼主 | 2014-7-14 11:22 | 只看该作者
我准备去掉DMA,试一下。有谁使用过F0 ADC+DMA的呢?也可以参考试一下

使用特权

评论回复
5
金融小数| | 2014-7-14 11:26 | 只看该作者
私下认为:建议你不要使用DMA。

使用特权

评论回复
6
金融小数| | 2014-7-14 11:26 | 只看该作者
私下认为:建议你不要使用DMA。

使用特权

评论回复
7
mmuuss586| | 2014-7-14 12:39 | 只看该作者
先做下软件滤波看看;
也有可能你信号本身就不稳定,输入信号接到电源或基准测试下;

使用特权

评论回复
8
tzw51723|  楼主 | 2014-7-14 13:51 | 只看该作者
软件滤波已做,但是治标不治本,还是会出错。
我也怀疑过,信号不稳定问题,可是我用信号发生器模拟测试,也会出错。
输入信号接到电源,数据采集时OK的,也就是直流信号是OK的,交流采集会出错。
基准电压是参考电源,用示波器捕捉中断,也没有出现抖动。

使用特权

评论回复
9
tzw51723|  楼主 | 2014-7-14 13:53 | 只看该作者
mmuuss586 发表于 2014-7-14 12:39
先做下软件滤波看看;
也有可能你信号本身就不稳定,输入信号接到电源或基准测试下; ...

软件滤波已做,但是治标不治本,还是会出错。
我也怀疑过,信号不稳定问题,可是我用信号发生器模拟测试,也会出错。
输入信号接到电源,数据采集时OK的,也就是直流信号是OK的,交流采集会出错。
基准电压是参考电源,用示波器捕捉中断,也没有出现抖动。

使用特权

评论回复
10
DerekHui| | 2014-7-15 14:12 | 只看该作者
tzw51723 发表于 2014-7-14 13:53
软件滤波已做,但是治标不治本,还是会出错。
我也怀疑过,信号不稳定问题,可是我用信号发生器模拟测试 ...

ADC初始化要先于DMA

使用特权

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

本版积分规则

5

主题

14

帖子

0

粉丝