F7用DMA传送ADC数据的问题,发现只传送一次后就停止传送

2019-07-20 12:32发布

想法: 开启TIM3中断 每50us进行一次ADC转换 ,转换的数据用DMA发送,当采集到200个数据时,主程序中进行一次处理 我将ADC和DAC接到一次,发现测得的电压示数一直为0,
好像并没有进入到DMA中断中处理,也没有进行DMA传输,这是怎么回事


部分程序如下

ADC部分:

//初始化ADC
//ch: ADC_channels
//通道值 0~16取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
void MY_ADC_Init(void)
{
    ADC1_Handler.Instance=ADC1;
    ADC1_Handler.Init.ClockPrescaler=ADC_CLOCK_SYNC_PCLK_DIV4;  //4分频,ADCCLK=PCLK2/4=108/4=27MHZ
    ADC1_Handler.Init.Resolution=ADC_RESOLUTION_12B;            //12位模式
    ADC1_Handler.Init.DataAlign=ADC_DATAALIGN_RIGHT;            //右对齐
    ADC1_Handler.Init.ScanConvMode=DISABLE;                     //非扫描模式
    ADC1_Handler.Init.EOCSelection=DISABLE;                     //关闭EOC
    ADC1_Handler.Init.ContinuousConvMode=DISABLE;               //关闭连续转换
    ADC1_Handler.Init.NbrOfConversion=1;                        //1个转换在规则序列中 也就是只转换规则序列1
    ADC1_Handler.Init.DiscontinuousConvMode=DISABLE;            //禁止不连续采样模式
    ADC1_Handler.Init.NbrOfDiscConversion=0;                    //不连续采样通道数为0
    ADC1_Handler.Init.ExternalTrigConv=ADC_SOFTWARE_START;      //软件触发
    ADC1_Handler.Init.ExternalTrigConvEdge=ADC_EXTERNALTRIGCONVEDGE_NONE;//使用软件触发
    ADC1_Handler.Init.DMAContinuousRequests=ENABLE;             //开启DMA请求
    HAL_ADC_Init(&ADC1_Handler);                                //初始化  
   
    HAL_ADC_Start_IT(&ADC1_Handler);                            //开启中断
   
}


//ADC底层驱动,引脚配置,时钟使能
//此函数会被HAL_ADC_Init()调用
//hadc:ADC句柄
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
    GPIO_InitTypeDef GPIO_Initure;
    __HAL_RCC_ADC1_CLK_ENABLE();            //使能ADC1时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();   //开启GPIOA时钟

    GPIO_Initure.Pin=GPIO_PIN_5;            //PA5
    GPIO_Initure.Mode=GPIO_MODE_ANALOG;     //模拟
    GPIO_Initure.Pull=GPIO_NOPULL;          //不带上下拉
    HAL_GPIO_Init(GPIOA,&GPIO_Initure);
   
   HAL_NVIC_SetPriority(ADC_IRQn, 3, 3);  
    HAL_NVIC_EnableIRQ(ADC_IRQn);
}

void ADC_IRQHandler(void)
{
    HAL_ADC_IRQHandler(&ADC1_Handler);
}

void HAL_ADC_ErrorCallback(ADC_HandleTypeDef* hadc) //DMA溢出回调函数   好像并没有进入这个中断,实验发现LED0不变
{                                                                                                                        一直为灭。
     HAL_ADC_Stop_DMA(&ADC1_Handler);   //重新初始化DMA
     ADC_Flag=1;                             //FLAG置位,表示已经采集完成,主程序中进行处理,处理完成后再开启DMA
    LED0_Toggle;
}

void Start_Adc(u32 ch)                            //开启ADC的转换,在定时器中断中调用
{
    ADC_ChannelConfTypeDef ADC1_ChanConf;
   
    ADC1_ChanConf.Channel=ch;                                   //通道
    ADC1_ChanConf.Rank=1;                                       //1个序列
    ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES;        //采样时间
    ADC1_ChanConf.Offset=0;                 
    HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf);        //通道配置
    HAL_ADC_Start(&ADC1_Handler);                               //开启ADC转换
}



DMA配置如下

DMA_HandleTypeDef  ADC1DMA_Handler;      //DMA句柄
//DMAx的各通道配置
//这里的传输形式是固定的,这点要根据不同的情况来修改
//从存储器->外设模式/8位数据宽度/存储器增量模式
//DMA_StreamxMA数据流,DMA1_Stream0~7/DMA2_Stream0~7
//chxMA通道选择,@ref DMA_channel DMA_CHANNEL_0~DMA_CHANNEL_7



void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx,u32 chx)
{
if((u32)DMA_Streamx>(u32)DMA2)//得到当前stream是属于DMA2还是DMA1
{
        __HAL_RCC_DMA2_CLK_ENABLE();//DMA2时钟使能
}else
{
        __HAL_RCC_DMA1_CLK_ENABLE();//DMA1时钟使能
}
   
    __HAL_LINKDMA(&ADC1_Handler,DMA_Handle,ADC1DMA_Handler);    //将DMA与ADC1联系起来(发送DMA)
   
    //Tx DMA配置
    ADC1DMA_Handler.Instance=DMA_Streamx;                              //数据流选择
    ADC1DMA_Handler.Init.Channel=chx;                                       //通道选择
    ADC1DMA_Handler.Init.Direction=DMA_PERIPH_TO_MEMORY;             //外设到存储器
    ADC1DMA_Handler.Init.PeriphInc=DMA_PINC_DISABLE;                 //外设非增量模式
    ADC1DMA_Handler.Init.MemInc=DMA_MINC_ENABLE;                     //存储器增量模式
    ADC1DMA_Handler.Init.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD;    //外设数据长度:16位
    ADC1DMA_Handler.Init.MemDataAlignment=DMA_MDATAALIGN_HALFWORD;       //存储器数据长度:16位
    ADC1DMA_Handler.Init.Mode=DMA_PFCTRL;                                //外设触发模式
    ADC1DMA_Handler.Init.Priority=DMA_PRIORITY_MEDIUM;               //中等优先级
    ADC1DMA_Handler.Init.FIFOMode=DMA_FIFOMODE_DISABLE;              
    ADC1DMA_Handler.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL;      
    ADC1DMA_Handler.Init.MemBurst=DMA_MBURST_SINGLE;                 //存储器突发单次传输
    ADC1DMA_Handler.Init.PeriphBurst=DMA_PBURST_SINGLE;              //外设突发单次传输
   
    HAL_DMA_DeInit(&ADC1DMA_Handler);   
    HAL_DMA_Init(&ADC1DMA_Handler);

__HAL_DMA_ENABLE_IT(&ADC1DMA_Handler,DMA_IT_TC);                  //开启发送完成中断

   HAL_NVIC_SetPriority(DMA2_Stream0_IRQn,1,0);  //接收DMA中断优先级
    HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
}


//DMA2数据流0中断服务函数
void DMA2_Stream0_IRQHandler(void)                  //开启后应该回调ADC溢出中断函数
{
    HAL_DMA_IRQHandler(ADC1_Handler.DMA_Handle);
}


定时器溢出中断:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)   //实现ADC的定时采样
{


if(htim==(&TIM3_Handler))
    {
         
        Start_Adc(ADC_CHANNEL_5);     //每50us开启一次ADC转换,DMA自动传送

    }

}


主程序部分代码)
MYDMA_Config(DMA2_Stream0,DMA_CHANNEL_0); //初始化DMA
    MY_ADC_Init();                  //初始化ADC1
    DAC1_Init();                    //初始化DAC1
TIM3_Init(50-1,108-1);          //50us中断一次

HAL_DAC_SetValue(&DAC1_Handler,DAC_CHANNEL_1,DAC_ALIGN_12B_R,4095);//初始值为3.3V
HAL_ADC_Start_DMA(&ADC1_Handler, (u32*)MYADC_GET, Samp_Times);    //开启第一次DMA传送
while(1)
{
   KeyDriver();
    if(ADC_Flag==1)       //DMA已经传送200个数据
  {
          ADC_Flag=0;
         for(j=0;j<Samp_Times;j++)
           SUM+=MYADC_GET[j];                                                                      //求平均                  
           adcx=SUM/Samp_Times;
           SUM=0;

         HAL_ADC_Start_DMA(&ADC1_Handler, (u32*)MYADC_GET, Samp_Times);                //数据处理完成,重新开启DMA传送
      。。。。。。(之后将adcx值显示在液晶屏上)
  }
}

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。