OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3434|回复: 5

关于STM32H743 ADC中断函数的疑问

[复制链接]

4

主题

13

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
267
金钱
267
注册时间
2019-5-16
在线时间
94 小时
发表于 2019-5-27 11:03:24 | 显示全部楼层 |阅读模式
1金钱
现在配置了PWM触发ADC转换,并且开启了DMA中断,使用示波器测量过ADC转换完成时间大约在700ns,所以PWM隔1uS触发一次应该没问题。在DMA中断中进行引脚翻转观察,进中断的周期确实是1uS很正常。
现在的问题在于,当把我需要处理的中断函数放进该DMA中断里,进中断的周期就超过1uS了,我也测量过需要处理的中断函数执行时间,大约只需要500nS。
所以有个疑问,DMA中断不处理完毕,ADC是不是不会开启下一次转换?


最佳答案

查看完整内容[请看2#楼]

你处理不处理DMA中断, ADC都是可以继续采样的 把DMA的模式改为循环, 使能HTIE及TCIE, 每次中断只处理Buffer一半, 这样ADC的采样就可以连续不会断
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2019-5-27 11:03:25 | 显示全部楼层
你处理不处理DMA中断, ADC都是可以继续采样的
把DMA的模式改为循环, 使能HTIE及TCIE, 每次中断只处理Buffer一半, 这样ADC的采样就可以连续不会断
回复

使用道具 举报

4

主题

13

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
267
金钱
267
注册时间
2019-5-16
在线时间
94 小时
 楼主| 发表于 2019-5-28 08:40:37 | 显示全部楼层
edmund1234 发表于 2019-5-27 11:03
你处理不处理DMA中断, ADC都是可以继续采样的
把DMA的模式改为循环, 使能HTIE及TCIE, 每次中断只处理Bu ...

DMA已经是循坏模式了,使用HAL库配置的。HTIE和TCIE还需要配置吗?我把详细代码贴上来吧,正好也给需要PWM+ADC+DMA的人一些参考
回复

使用道具 举报

4

主题

13

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
267
金钱
267
注册时间
2019-5-16
在线时间
94 小时
 楼主| 发表于 2019-5-28 09:10:13 | 显示全部楼层
代码部分如下:采用了双重ADC模式。
一、//ADC引脚配置
static void ADC_GPIO_Mode_Config(void)
{
  
    GPIO_InitTypeDef  GPIO_InitStruct;
    __HAL_RCC_GPIOA_CLK_ENABLE();
    GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;  

   GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;

    /* 配置为模拟输入,不需要上拉电阻 */
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}


二、//时钟+DMA配置
static void ADC_Mode_Config(void)
{
    ADC_ChannelConfTypeDef ADC_Config;

    RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit;  
    /*            配置ADC3时钟源             */
    /*    HSE Frequency(Hz)    = 25000000   */                                             

    RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
    RCC_PeriphClkInit.PLL2.PLL2FRACN = 0;
    RCC_PeriphClkInit.PLL2.PLL2M = 5;
    RCC_PeriphClkInit.PLL2.PLL2N = 160;
    RCC_PeriphClkInit.PLL2.PLL2P = 25;
    RCC_PeriphClkInit.PLL2.PLL2Q = 2;
    RCC_PeriphClkInit.PLL2.PLL2R = 2;
    RCC_PeriphClkInit.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_2;
    RCC_PeriphClkInit.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
    RCC_PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
   HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);  

    /* 使能ADC1、2时钟 */
    __HAL_RCC_ADC12_CLK_ENABLE();
               
   //使能DMA时钟
   __HAL_RCC_DMA1_CLK_ENABLE();
         
         //指向DMA数据流基地址的指针,指定用数据流1
    hdma_adc.Instance = DMA1_Stream1;

     //DMA请求选择
    hdma_adc.Init.Request = DMA_REQUEST_ADC1;

   //传输方向,外设至存储器
    hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY;

   //如果配置为PeriphInc_Enable,使能外设地址自动递增。ADC1数据寄存器地址固定,无需递增使能
    hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE;

   //如果配置为MemInc_Enable,使能存储器地址自动递增功能
    hdma_adc.Init.MemInc = DMA_MINC_DISABLE;

     //外设数据宽度,可选字节(8位)、半字(16位)、字(32位)
   //双重模式时,ADC 的通用规则数据寄存器是32 位有效
    hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;

   //存储器字节宽度,可选字节(8位)、半字(16位)、字(32位)
    hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;

   //DMA传输模式选择,可选一次传输或者循环传输
    hdma_adc.Init.Mode = DMA_CIRCULAR;

        //软件设置数据流的优先级
    hdma_adc.Init.Priority = DMA_PRIORITY_LOW;

        //FIFO 模式使能
    hdma_adc.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
               
    HAL_DMA_Init(&hdma_adc);
               
    HAL_DMA_Init(&hdma_adc);
                       
   //hdma_adc和ADC_Handle.DMA_Handle链接
    __HAL_LINKDMA(&ADC1_Handle,DMA_Handle,hdma_adc);
               
               
    ADC1_Handle.Instance = ADC1;
    HAL_ADC_DeInit(&ADC1_Handle);
       
    //使能Boost模式
    ADC1_Handle.Init.BoostMode = ENABLE;

    //ADC时钟1分频
    ADC1_Handle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
               
    //关闭连续转换模式
    ADC1_Handle.Init.ContinuousConvMode = DISABLE;
               
   //扫描1个通道       
   ADC1_Handle.Init.NbrOfConversion = 1;

    //数据存放在数据寄存器中
    ADC1_Handle.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;

    //关闭不连续转换模式
    ADC1_Handle.Init.DiscontinuousConvMode = DISABLE;
    ADC1_Handle.Init.NbrOfDiscConversion = 0;

   //使能EOC标志位
    ADC1_Handle.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
       
    //T4定时器TRGO事件触发
   ADC1_Handle.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T4_TRGO;
   ADC1_Handle.Init.ExternalTrigConvEdge  = ADC_EXTERNALTRIGCONVEDGE_RISING;
               
    //关闭低功耗自动等待
    ADC1_Handle.Init.LowPowerAutoWait = DISABLE;

    //数据溢出时,覆盖写入
    ADC1_Handle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;

    //不使能过采样模式
    ADC1_Handle.Init.OversamplingMode = DISABLE;

    //分辨率为:16bit
    ADC1_Handle.Init.Resolution = ADC_RESOLUTION_12B;

    //不使能多通道扫描
    ADC1_Handle.Init.ScanConvMode = DISABLE;
               
   //扫描0个通道
    ADC1_Handle.Init.NbrOfConversion = 0;

    //初始化 主ADC1
    HAL_ADC_Init(&ADC1_Handle) ;
               
               
    HAL_ADCEx_Calibration_Start(&ADC1_Handle,ADC_CALIB_OFFSET,ADC_SINGLE_ENDED);
               
  //初始化 从ADC2
   ADC2_Handle.Instance = ADC2;
   HAL_ADC_DeInit(&ADC2_Handle);
               
   ADC2_Handle.Init = ADC1_Handle.Init;
               
    HAL_ADC_Init(&ADC2_Handle);
       
    iHAL_ADCEx_Calibration_Start(&ADC2_Handle,ADC_CALIB_OFFSET,ADC_SINGLE_ENDED);
               
    //使用通道7
    ADC_Config.Channel = ADC_CHANNEL_7;

    //转换顺序为1
    ADC_Config.Rank = ADC_REGULAR_RANK_1 ;

    //采样周期
    ADC_Config.SamplingTime = ADC_SAMPLETIME_16CYCLES_5;

    //不使用差分输入的功能
    ADC_Config.SingleDiff = ADC_SINGLE_ENDED ;
    ADC_Config.OffsetNumber = ADC_OFFSET_NONE;            
    ADC_Config.Offset = 0;  

    //配置ADC1通道
    HAL_ADC_ConfigChannel(&ADC1_Handle, &ADC_Config);

    // 使用通道3
    ADC_Config.Channel = ADC_CHANNEL_3;

   // 转换顺序为2
    ADC_Config.Rank = ADC_REGULAR_RANK_1;

    //配置ADC2通道
    HAL_ADC_ConfigChannel(&ADC2_Handle, &ADC_Config);

   //使能ADC1、2
    ADC_Enable(&ADC1_Handle);

   ADC_Enable(&ADC2_Handle);
               
    //数据格式
    ADC_multimode.DualModeData = ADC_DUALMODEDATAFORMAT_32_10_BITS;

    //双重ADC交替模式
               
    ADC_multimode.Mode = ADC_DUALMODE_INTERL;
               
   //主ADC和从ADC采样间隔3个ADC时钟
    ADC_multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_3CYCLES;
               
   //ADC双重模式配置初始化
   //控制是否使能ADC的DMA请求
    HAL_ADCEx_MultiModeConfigChannel(&ADC1_Handle, &ADC_multimode);
               
    //使能DMA
   HAL_ADCEx_MultiModeStart_DMA(&ADC1_Handle, (uint32_t*)&ADC_ConvertedValue, 1);
}



三、//DMA中断配置
static void DMA_NVIC_Config(void)
{
    HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
}

四、//DMA中断服务函数
void DMA1_Stream1_IRQHandler(void)
{
    HAL_DMA_IRQHandler(ADC1_Handle.DMA_Handle);
}



五、//PWM触发源配置
void TIM4_PWM_Init(void)
{
  TIM_MasterConfigTypeDef master_timer_config;


  TIM4_Handler.Instance = TIM4;//定时器4
  TIM4_Handler.Init.Period            = 50-1;//自动重装载值
  TIM4_Handler.Init.Prescaler         = 4-1;//定时器分频
  TIM4_Handler.Init.ClockDivision     = TIM_CLOCKDIVISION_DIV1;
  TIM4_Handler.Init.CounterMode       = TIM_COUNTERMODE_UP;
  TIM4_Handler.Init.RepetitionCounter = 0x0;

  HAL_TIM_Base_Init(&TIM4_Handler);

  /* Timer TRGO selection */
  master_timer_config.MasterOutputTrigger = TIM_TRGO_UPDATE;
  master_timer_config.MasterOutputTrigger2 = TIM_TRGO2_RESET;
  master_timer_config.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

  HAL_TIMEx_MasterConfigSynchronization(&TIM4_Handler, &master_timer_config);


  HAL_TIM_Base_Start(&TIM4_Handler); //使能定时器4和定时器4更新中断:TIM_IT_UPDATE   
}



六、//最终初始化
void ADC_Init(void)
{

    ADC_GPIO_Mode_Config();

    ADC_Mode_Config();
    DMA_NVIC_Config();

    HAL_ADC_Start(&ADC1_Handle);
    HAL_ADC_Start(&ADC2_Handle);
}


七、//ADC回调函数
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
       /* 获取结果 */

        ADC_ConvertedValue=HAL_ADCEx_MultiModeGetValue(AdcHandle);

       
        ADC_ConvertedValueLocal[0] = (uint16_t)ADC_ConvertedValue;
        ADC_ConvertedValueLocal[1] = (uint16_t)((ADC_ConvertedValue&0xFFFF0000)>>16);
        TEST_PIN_Toggle;
        //需要增加的中断处理函数
}


现在的问题是,在第七段中,我不添加那段需要中断处理的函数,用示波器观察TSET_PIN的翻转,是500KHz;
但是我添加了中断处理函数(测量过这段函数执行大约820ns),TSET_PIN的翻转频率就变成了300KHz多一点。
即使我把这段中断处理函数缩减到400ns,TEST_PIN的翻转频率也只提高到425KHz。




回复

使用道具 举报

4

主题

13

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
267
金钱
267
注册时间
2019-5-16
在线时间
94 小时
 楼主| 发表于 2019-5-29 10:45:07 | 显示全部楼层
没人知道答案么?
回复

使用道具 举报

1

主题

18

帖子

0

精华

新手上路

积分
40
金钱
40
注册时间
2019-7-28
在线时间
8 小时
发表于 2019-9-2 18:09:15 | 显示全部楼层
我也正在调试DMA发送完成后中断,没有成功。根本就进不了中断
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-16 10:26

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表