STM32
直播中

杨丽

8年用户 1399经验值
私信 关注
[问答]

STM32F302 TIM15触发ADC规则扫描DMA连续传输ADC数据失败的原因?

在测试STM32F302RB的ADC功能的时候遇到了问题:  用tiM15 更新事件作为 TRGO源 触发ADC2转换,DMA2_Channel_1 连续模式传输ADC2的数据,开DMA2_TC1中断,发现只进一次TC中断后就再也不进TC1中断了。 通过后续测试发现如果只用TIM15触发ADC转换,不开DMA 正常, 如果不用TIM15,用软件触发ADC转换,开DMA,正常 。  同时 用TIM15触发ADC、开DMA则出问题。      
        ADC初始化如下:
   ADC_DeInit(ADC2);
    RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div6);                                 //72M/6=12M
    ADC_StructInit( ADC_InitStructure);
   
    ADC_VoltageRegulatorCmd(ADC2, ENABLE);
  delay_us(10);
  ADC_SelectCalibrationMode(ADC2, ADC_CalibrationMode_Single);
  ADC_StartCalibration(ADC2);
  while(ADC_GetCalibrationStatus(ADC2) != RESET );
  calibration_value = ADC_GetCalibrationValue(ADC2);
   
    ADC_CommonInitStructure.ADC_Mode=ADC_Mode_Independent;
    ADC_CommonInitStructure.ADC_Clock=ADC_Clock_AsynClkMode;//ADC_Clock_SynClkModeDiv4;                //ʹÓÃͬ²½Ê±ÖÓ
    ADC_CommonInitStructure.ADC_DMAAccessMode=ADC_DMAAccessMode_1;             //12/10bitDMAģʽʹÄÜ
    ADC_CommonInitStructure.ADC_DMAMode=ADC_DMAMode_Circular;                  //Á¬ÐøÄ£Ê½
    ADC_CommonInitStructure.ADC_TwoSamplingDelay=0;                            //Á½´Î²ÉÑùÑÓʱ
    ADC_CommonInit(ADC2, ADC_CommonInitStructure);
   
    ADC_InitStructure.ADC_ContinuousConvMode=ADC_ContinuousConvMode_Disable;//ADC_ContinuousConvMode_Enable;;
    ADC_InitStructure.ADC_AutoInjMode=ADC_AutoInjec_Disable;
    ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;
  ADC_InitStructure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_14;//ADC_ExternalTrigConvEvent_0;//ADC_ExternalTrigConvEvent_0;   
    ADC_InitStructure.ADC_ExternalTrigEventEdge=ADC_ExternalTrigEventEdge_RisingEdge;//ADC_ExternalTrigEventEdge_None;
    ADC_InitStructure.ADC_NbrOfRegChannel=2;
    ADC_InitStructure.ADC_OverrunMode=ADC_OverrunMode_Disable;
    ADC_InitStructure.ADC_Resolution=ADC_Resolution_12b;
    ADC_Init(ADC2, ADC_InitStructure);
   
    ADC_RegularChannelConfig(ADC2, ADC_Channel_5, 1, ADC_SampleTime_4Cycles5);     
    ADC_RegularChannelConfig(ADC2, ADC_Channel_11, 2, ADC_SampleTime_4Cycles5);   

    DMA_DeInit(DMA2_Channel1);
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)( ADC2->DR);
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADCBuffer;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                    //´ÓÍâÉè¶Á
  DMA_InitStructure.DMA_BufferSize = 2;                                //16
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                       //Á¬Ðø´«Êä
  DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA2_Channel1,  DMA_InitStructure);
   
    DMA_ITConfig(DMA2_Channel1,DMA2_IT_TC1,ENABLE);
    NVIC_InitStructure.NVIC_IRQChannel=DMA2_Channel1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    NVIC_Init( NVIC_InitStructure);
   
    ADC_ITConfig(ADC2,ADC_IT_EOC,ENABLE);
    NVIC_InitStructure.NVIC_IRQChannel=ADC1_2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    NVIC_Init( NVIC_InitStructure);
   
    DMA_Cmd(DMA2_Channel1, ENABLE);
    ADC_DMACmd(ADC2, ENABLE);

    ADC_Cmd(ADC2, ENABLE);
    while(!ADC_GetFlagStatus(ADC2, ADC_FLAG_RDY));
  ADC_StartConversion(ADC2);


中断如下: void DMA2_Channel1_IRQHandler(void)
{
    if(DMA_GetITStatus(DMA2_IT_TC1) != RESET)
    {
        DMA_ClearITPendingBit(DMA2_IT_TC1);
    }
}

TIM15初始化如下:
  TIM_DeInit(TIM15);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM15, ENABLE );//TIM1ʱÖÓʹÄÜ
   
   
    PrescalerValue = (uint16_t)( 7200 )- 1;             //Fcnt=1M

  TIM_TimeBaseStructure.TIM_Period = 10000;             //  500usת»»Ò»´Î
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
  TIM_TimeBaseInit(TIM15,  TIM_TimeBaseStructure);
  TIM_PrescalerConfig(TIM15, PrescalerValue, TIM_PSCReloadMode_Immediate);
    TIM_SelectOutputTrigger(TIM15,TIM_TRGOSource_Update);
   
  TIM_ITConfig(TIM15,TIM_IT_Update, ENABLE);
  NVIC_InitStructure.NVIC_IRQChannel = TIM1_BRK_TIM15_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init( NVIC_InitStructure);
  TIM_Cmd(TIM15, ENABLE);
我是使用TIM15 更新作为TRGO事件触发ADC2转换, TIM15 1秒钟更新一次,开 ADC EOC中断的debug的时候
是1秒钟进一次中断,然后使能DMA后就并开DMA中断后就只进一次中断了, 后续我又测试500ms软件触发一次ADC转换,并且开DMA,DMA中断符合预期结果。 然后我同时使用TIM15,DMA则 只进一次DMA中断。  我后续又修改了DMA_BUF_SIZE  改成8,以此来排除ADC初始化的那一次软件使能ADC转换, 就是要发生8次 ADC->EOC 才算一次 DMA_TC,结果还是只有一次DMA中断。




回帖(1)

刘洋

2024-5-6 16:41:00
根据您提供的信息,您在使用STM32F302RB的ADC功能时遇到了问题。您尝试使用TIM15更新事件作为TRGO源触发ADC2转换,并通过DMA2_Channel_1连续模式传输ADC2的数据。但是,您发现在开DMA2_TC1中断后,只进入了一次TC中断,之后就不再进入TC1中断了。您还提到,如果只用TIM15触发ADC转换而不开启DMA,或者不使用TIM15而使用软件触发ADC转换并开启DMA,这两种情况下都是正常的。

为了解决这个问题,我们可以按照以下步骤进行排查:

1. 确保TIM15和ADC2的时钟已经正确配置。检查RCC_ADCCLKConfig和RCC_APB2PeriphClockCmd函数的设置。

2. 检查TIM15的配置,确保更新事件能够正确触发ADC2转换。这包括设置TIM15的时钟源、预分频器、自动重载寄存器等。

3. 检查ADC2的配置,确保它能够正确响应TIM15的触发信号。这包括设置ADC2的触发源为外部事件(TIM15更新事件),以及配置ADC2的采样时间和分辨率等。

4. 检查DMA2_Channel_1的配置,确保它能够正确地从ADC2读取数据并传输到目标内存地址。这包括设置DMA的源地址、目标地址、数据宽度、传输方向等。

5. 检查DMA2_TC1中断的配置,确保中断能够正确触发。这包括设置DMA的中断优先级、中断使能等。

6. 在中断服务程序中,检查是否有任何可能导致中断退出的条件。例如,确保在中断服务程序中没有错误地禁用了DMA或ADC。

7. 使用调试器或仿真器逐步执行代码,观察TIM15、ADC2和DMA2_Channel_1的状态,以便找到可能的问题所在。

8. 如果以上步骤都无法解决问题,可以尝试查阅STM32F302的参考手册,看看是否有关于TIM15触发ADC转换和DMA传输的特定注意事项或限制。

通过以上步骤,您应该能够找到导致问题的原因,并采取相应的措施解决。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分