打印
[应用相关]

STM32使用ADC的DMA中断问题

[复制链接]
1160|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Soraka|  楼主 | 2017-2-16 19:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本人需要调试一个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);
沙发
Garen2| | 2017-2-16 20:00 | 只看该作者
用单次,然后用一个全局计数器,4次后再清零试试看

使用特权

评论回复
板凳
Ryze| | 2017-2-16 20:12 | 只看该作者
设立一个长的缓冲区,比如1024,然后4次一下分别读取值

使用特权

评论回复
地板
Varus| | 2017-2-16 20:47 | 只看该作者
在DMA传输完4次数据以后,如果需要重新采样到DMA,需要对DMA_CNDTRx重新赋值。

使用特权

评论回复
5
Snow7| | 2017-2-16 21:16 | 只看该作者
手册对于这个寄存器的相关操作: “这个寄存器只能在通道不工作(DMA_CCRx的EN=0)时写入。”

使用特权

评论回复
6
android2| | 2017-2-16 21:31 | 只看该作者
连续AD转换,连续dma,当dam传输完一半时处理数据。

使用特权

评论回复
7
xmshao| | 2017-2-16 22:04 | 只看该作者
你DMA配置为NORMAL模式的话,传输一轮结束后产生完成中断,然后DMA就停止了。

如果后面需要再次使用DMA的话,得再次初始化并使能DMA. 否则即使你的ADC循环采集,但并
不会再次触发DMA及DMA完成中断。

DAM配置为CIRCULATE模式就没有上面的问题。

使用特权

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

本版积分规则

178

主题

865

帖子

5

粉丝