关于使能ADC1 使用DMA1 CH1 只能进一次中断的问题

各位大佬 

       代码目的  TIM4_CC4作为触发单元  周期性的触发ADC1进行转换   ADC1在触发DMA1 把ADC1获得的三个通道的数据送到一个数组中,传送完成后触发中断。

       目前的进度和遇到的问题  

       1.TM4_CC4周期性的触发ADC1进行转换  这一步已完成(开了ADC中断,测试了下ADC中断周期和TM4_CC4中断周期同步)

       2.ADC1触发DMA1_CH1传输数据 并触发中断(此步也完成 发送的三个通道adc数据也准确)

       3.虽然DMA1_CH1能进中断  但只能进一次  具体代码如下:

      

       TM4初始化

        

TIM4->CTLR1=1<<7;            //使能自动重装载

TIM4->CTLR2=7<<4;            //比较通道4作为触发输出

TIM4->DMAINTENR=1<<8;        //允许比较4中断

TIM4->PSC=4800;              //预分频值

TIM4->ATRLR=400;             //20ms


TIM4->CTLR1|=1<<0;           //开启定时器

TIM4->CCER=1<<12;            //开启使能CC4输出

TIM4->CHCTLR2=6<<12;         //翻转REF4

TIM4->CH4CVR=200;

TIM4->DMAINTENR=1<<4;        //允许比较4中断

       ADC初始化

        

    GPIO_InitTypeDef GPIO_InitStructure={0};

    ADC_InitTypeDef  ADC_InitStructure={0};


    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1 , ENABLE ); //使能GPIOA时钟和ADC

    RCC_ADCCLKConfig(RCC_PCLK2_Div8); //设置ADC时钟分频为6分频


    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_5|GPIO_Pin_7;   //

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //GPIO模式为模拟输入

    GPIO_Init(GPIOA, &GPIO_InitStructure);


    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  //配置ADC为独立模式

    ADC_InitStructure.ADC_ScanConvMode = ENABLE;        //多通道模式下开启扫描模式

    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;  //设置开启连续转换模式

    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T4_CC4; //由T4_CC4触发

    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //设置ADC数据右对齐

    ADC_InitStructure.ADC_NbrOfChannel = 3;                //规则转换的ADC通道的数目

    ADC_Init(ADC1, &ADC_InitStructure);                    //根据ADC_InitStructure中指定的参数初始化ADC1寄存器

 

    ADC1->CTLR1|=1<<5;   //开启ADC转换结束中断

    ADC1->CTLR2|=1<<20;    //开启外部触发功能

    ADC_Cmd(ADC1, ENABLE);      //使能ADC1


    ADC_ResetCalibration(ADC1); //重置ADC1校准寄存器。


    while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束


    ADC_StartCalibration(ADC1); //开启AD校准


    while(ADC_GetCalibrationStatus(ADC1));      //等待校准结束


    ADC_BufferCmd(ADC1, DISABLE); //disable buffer  


   DMA初始化

   

DMA_InitTypeDef DMA_InitStructure={0};

    RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE ); //使能开启DMA时钟


    DMA_DeInit(DMA1_Channel1); //复位DMA控制器


    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->RDATAR;  //配置外设地址为ADC数据寄存器地址

    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC_ConvertedValue; //配置存储器地址为读取ADC值地址

    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;             //配置数据源为外设,即DMA传输方式为外设到存储器

    DMA_InitStructure.DMA_BufferSize = 3;                      //设置DMA数据缓冲区大小,此处设置为length

    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//设置DMA外设递增模式关闭

    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;         //设置DMA存储器递增模式开启

    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //设置外设数据大小为半字,即两个字节

    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;         //设置存储器数据大小为半字,即两个字节

    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;         //设置DMA模式为正常模式

    DMA_InitStructure.DMA_Priority = DMA_Priority_High; //设置DMA传输通道优先级为高,当使用一 DMA通道时,优先级设置不影响

    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;        //因为此DMA传输方式为外设到存储器,因此禁用存储器到存储器传输方式

    DMA_Init( DMA1_Channel1, &DMA_InitStructure );      //初始化DMA



    DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);  //使能DMA传输完成中断

DMA_Cmd(DMA1_Channel1 , ENABLE);  //使能DMA


中断配置部分

 

//NVIC->IENR[0]|=1<<27;          //开启DMA中断

  NVIC->IENR[1]|=1<<2;         //开启ADC 34号中断                     DMA_CH1中断号  27   ADC1_2中断号 34

  //NVIC->IENR[1]|=1<<14;        //允许TIM4中断


DMA中断处理部分

 

if(DMA_GetITStatus(DMA1_IT_TC1))

       {

           //printf("\r\n Enter DMA Interrupt \r\n");


 

          DMA_ClearITPendingBit(DMA1_IT_TC1); //清除全部中断标志

   

       }


你好 你的DMA是单次模式


如果是循环模式  就会一直循环进入中断  而需求是adc触发dma只需要传输一次


搞定了? 主要是需要重置DMA的CNTR寄存器? 当DMA传输结束后 此寄存器为0??

DMA根据此寄存器的值来判断是否传输结束? 以下是中断处理的代码

#define DMA1_CNTR1 (*(uint32_t *) 0x4002000C)? //在sdk中没找到具体的寄存器定义 所以自己定义了一个

void DMA1_Channel1_IRQHandler(void)

{

?if(DMA_GetITStatus(DMA1_IT_TC1))

? {

? ? DMA_ClearITPendingBit(DMA1_IT_TC1);? ? ?//清除全部中断标志0

? ? DMA1_CNTR1=3;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //关键? 必须重置? 否则只能传输一次

? ?TIM3->CTLR1|=1<<0;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//重启定时器3? 原因为程序利用TIM3 产生单次TROG 触发ADC3个通道的规则转换? ADC转换后在触发DMA传输? 所以需要重启TIM3

?

? }

}



只有登录才能回复,可以选择微信账号登录