暂停后,stm32f4 DMA并不总是启动

时间:2016-12-13 17:39:25

标签: stm32 dma stm32f4discovery stm32f4

所以这个问题是一个"续集"这一个:Stm32f4: DMA + ADC Transfer pausing

同样,我正在尝试实现这样的算法:

  1. 在一个通道上以三重交错模式使用ADC初始化DMA
  2. 等待外部中断
  3. 暂停DMA传输和ADC
  4. 通过中断
  5. 中的USART从内存中发送缓冲数据
  6. 恢复DMA和ADC
  7. 退出中断,转到2。
  8. DMA和ADC暂停并恢复,但有时(在大约16%的中断调用中)恢复失败 - DMA只是从ADC写入第一次测量并停止直到下一次中断,其中DMA和ADC重新启动(因为它们暂停并再次恢复) - 好吧,一切都恢复正常,直到下一个这样的错误。

    我尝试暂停DMA,就像参考手册所说:

      

    为了从转移停止点重新启动,   软件必须在禁用后读取DMA_SxNDTR寄存器   通过在DMA_SxCR寄存器中写EN位来进行流(然后检查   它是'0')知道已经收集的数据项的数量。   然后:
       - 必须更新外设和/或存储器地址以调整地址指针
       - 必须使用要传输的剩余数据项更新SxNDTR寄存器(禁用流时读取的值)
       - 然后可以重新启用流以从停止的点重新开始传输

    唯一的实际差异在于恢复DMA工作时写入的NDTR值。在我的例子中,它是buffer_size,在RefMan的情况下 - 它是暂停DMA时读取的值。在RefMan案例中,DMA在暂停后永远不会再次启动。就我而言,如上所述,它开始了,但并非总是如此。

    如何防止这种情况发生?

    中断代码目前看起来像这样:

    void EXTI4_IRQHandler(void) {
        uint16_t temp = DMA_GetFlagStatus(DMA2_Stream0, DMA_FLAG_TEIF0);
        if(EXTI_GetITStatus(EXTI_Line4) != RESET) {
            uint16_t fPoint1 = 0;
            uint16_t fPoint2 = 0;
    
            //Some delay using the TIM2
            TIM_SetCounter(TIM2, 0);
            TIM_Cmd(TIM2, ENABLE);
    
            //Measure the first point NDTR
            fPoint1 = DMA2_Stream0->NDTR;
            while(TIM_GetITStatus(TIM2, TIM_IT_Update) != SET) {};
    
            //Measure the second point here.
            fPoint2 = DMA2_Stream0->NDTR;
    
            if(fPoint1 == fPoint2) {
                //The NDTR does not change!
                //If it does not change, it is stuck at buffer_size - 1
            }
    
            //Disable the timer
            TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
            TIM_Cmd(TIM2, DISABLE);
    
            DMA_Cmd(DMA2_Stream0, DISABLE);
            //Wait until the DMA will turn off
            while((DMA2_Stream0->CR & (uint32_t)DMA_SxCR_EN) != 0x00) {};
    
            //Turn off all ADCs
            ADC_Cmd(ADC1, DISABLE);
            ADC_Cmd(ADC2, DISABLE);
            ADC_Cmd(ADC3, DISABLE);
    
            //Send all the data here
    
            //Turn everything back on
    
            //Turn the DMA ON again
            DMA_SetCurrDataCounter(DMA2_Stream0, BUFFERSIZE);
            DMA_Cmd(DMA2_Stream0, ENABLE);
            while((DMA2_Stream0->CR & (uint32_t)DMA_SxCR_EN) == 0x00) {};
    
            //See note @ RefMan (Rev. 12), p. 410
            ADC->CCR &= ~((uint32_t)(0x000000FF));
            ADC->CCR |= ADC_TripleMode_Interl;
    
            ADC_Cmd(ADC1, ENABLE);
            ADC_Cmd(ADC2, ENABLE);
            ADC_Cmd(ADC3, ENABLE);
            while((ADC1->CR2 & (uint32_t)ADC_CR2_ADON) == 0) {};
            while((ADC2->CR2 & (uint32_t)ADC_CR2_ADON) == 0) {};
            while((ADC3->CR2 & (uint32_t)ADC_CR2_ADON) == 0) {};
    
            ADC_SoftwareStartConv(ADC1);
        }
    
        EXTI_ClearITPendingBit(EXTI_Line4);
    }
    

1 个答案:

答案 0 :(得分:1)

我自己找到了解决方案。我以为这是一个DMA问题;然而,它变成了ADC的问题。 ADCx-> CR寄存器中的OVR标志始终在传输过程中被设置为#34;卡住"。因此,我在ADC溢出情况中添加了一个中断并重新启动了DMA& ADC里面。问题现在解决了。