打印
[应用相关]

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

[复制链接]
1496|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Stannis|  楼主 | 2016-11-12 20:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
调试一个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);
沙发
Rangar| | 2016-11-12 20:49 | 只看该作者
用单次,然后用一个全局计数器,4次后再清零试试看

使用特权

评论回复
板凳
Thor9| | 2016-11-12 21:01 | 只看该作者
还有种办法,设立一个长的缓冲区,比如1024,然后4次一下分别读取值

nettlhx 2016/7/1 10:27:04
这种方法可以用CIRCULAR

使用特权

评论回复
地板
Rollo| | 2016-11-12 21:12 | 只看该作者
连续AD转换,连续dma,当dam传输完一半时处理数据。

使用特权

评论回复
5
Bjorn| | 2016-11-12 21:45 | 只看该作者
好像没有看到使能DMA的时钟总线哦,要看看DMA挂在哪个总线下面

使用特权

评论回复
6
Thorald| | 2016-11-12 21:57 | 只看该作者
楼上看得仔细!是有这问题,上面代码忘记写了

使用特权

评论回复
7
Soraka| | 2016-11-12 22:06 | 只看该作者
基本要对所有的外设,都有相似或者相同的写法

使用特权

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

本版积分规则

176

主题

721

帖子

1

粉丝