首页 文章

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

提问于
浏览
1

所以这个问题有点像这个问题:Stm32f4: DMA + ADC Transfer pausing .

我再次尝试实现这样的算法:

  • 在一个通道上以三重交错模式使用ADC初始化DMA

  • 等待外部中断

  • 暂停DMA传输和ADC

  • 在中断中通过USART从存储器发送缓冲数据

  • 恢复DMA和ADC

  • 退出中断,转到2 .

DMA和ADC暂停并恢复,但有时(在大约16%的中断调用中)恢复失败 - DMA只是从ADC写入第一次测量并停止直到下一次中断,其中DMA和ADC重新启动(因为它们被挂起并且再次恢复) - 好吧,一切都恢复正常,直到下一个这样的错误 .

我试过暂停DMA就像参考手册说的那样:

为了从传输停止点重新启动,软件必须通过写入DMA_SxCR寄存器中的EN位(然后检查它是否为0)来禁用流后读取DMA_SxNDTR寄存器以了解该数字已收集的数据项 . 然后: - 必须更新外设和/或存储器地址以调整地址指针 - 必须使用要传输的剩余数据项更新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 回答

  • 1

    我自己找到了解决方案 . 我以为这是一个DMA问题;然而,它变成了ADC的问题 . 当传输“卡住”时,ADCx-> CR寄存器中的OVR标志始终置位 . 因此,我在ADC溢出情况中添加了一个中断,并重新启动了DMA和ADC . 问题现在解决了 .

相关问题