有关STM32使用ADC的DMA中断问题

2019-03-23 18:08发布

本人需要调试一个AD功能,就是用单通道连续采样4次AD口(PA0)的数据存入DMA中后,产生一次DMA中断。设计思路是:
1)需要采样时利用软件触发AD的方式,将单通道连续采样的数据通过DMA存到对应数组;
2)在DMA中断里关闭AD,直到下一次需要采样时再打开AD。


但实际调试的时后发现,如果 DMA_InitStructure.DMA_Mode 设置成DMA_Mode_Circular,中断会不停产生。但是如果DMA_MODE设置成DMA_Mode_Normal以后,产生一次中断以后就不再产生中断了。请大家帮我看看是什么原因,代码是在stm32自带ADC1_DMA中的例程基础上增加中断控制处理。


ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;   
       
__IO uint16_t ADCConvertedValue[4];

// 配置PA0口为AD口
void ADC1_GPIO_Config(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;  /* Enable ADC1 and GPIOA clock */
       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA,ENABLE);
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;  
  GPIO_Init(GPIOA, &GPIO_InitStructure);
}


void ADC1_Mode_Config(void)
{
  /* DMA1 channel1 configuration ----------------------------------------------*/
  DMA_DeInit(DMA1_Channel1);
  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADCConvertedValue;        // (uint32_t)&ADCConvertedValue;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  DMA_InitStructure.DMA_BufferSize = 4;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;        //DMA_MemoryInc_Disable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;        // DMA_Mode_Normal
  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 = DISABLE;        //ENABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfChannel = 1;
  ADC_Init(ADC1, &ADC_InitStructure);

  /* ADC1 regular channel14 configuration */
  //ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 1, ADC_SampleTime_55Cycles5);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);

  /* Enable ADC1 DMA */
  ADC_DMACmd(ADC1, ENABLE);

  /* Enable ADC1 */
  ADC_Cmd(ADC1, ENABLE);

  /* Enable ADC1 reset calibration register */   
  ADC_ResetCalibration(ADC1);
  /* Check the end of ADC1 reset calibration register */
  while(ADC_GetResetCalibrationStatus(ADC1));

  /* Start ADC1 calibration */
  ADC_StartCalibration(ADC1);
  /* Check the end of ADC1 calibration */
  while(ADC_GetCalibrationStatus(ADC1));

  /* Start ADC1 Software Conversion */
  //ADC_SoftwareStartConvCmd(ADC1, ENABLE);
       
       
                        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
                        NVIC_InitStructure.NVIC_IRQChannel=DMA1_Channel1_IRQn;
                        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
                        NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
                        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
                        NVIC_Init(&NVIC_InitStructure);

                        DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE); //??DMA??????
}



stm32f10x_it.c里的DMA中断处理:

void DMA1_Channel1_IRQHandler(void)
{
        if(DMA_GetITStatus(DMA1_IT_TC1) != RESET)
        {
                //filter();//ADC????
                ADC_SoftwareStartConvCmd(ADC1, DISABLE);
                DMA_ClearITPendingBit(DMA1_IT_TC1);
        }
}


程序里启动ADC和DMA时同时调用了以下函数:
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
ADC_SoftwareStartConvCmd(ADC1, ENABLE);








此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
8条回答
netlhx
1楼-- · 2019-03-23 22:01
 精彩回答 2  元偷偷看……
netlhx
2楼-- · 2019-03-24 02:49
还有种办法,设立一个长的缓冲区,比如1024,然后4次一下分别读取值

nettlhx 2016/7/1 10:27:04
这种方法可以用CIRCULAR
SoftwareX
3楼-- · 2019-03-24 04:15
netlhx 发表于 2016-7-1 10:23
用单次,然后用一个全局计数器,4次后再清零试试看

这种方法也可以,但是我要弄明白是哪里设置错了,并不要避开这个问题。
SoftwareX
4楼-- · 2019-03-24 07:18
 精彩回答 2  元偷偷看……
Li_Lei
5楼-- · 2019-03-24 10:45
连续AD转换,连续dma,当dam传输完一半时处理数据。
huaiqiao
6楼-- · 2019-03-24 11:58
好像没有看到使能DMA的时钟总线哦,要看看DMA挂在哪个总线下面哦。。。。。

一周热门 更多>