所以这个问题是一个"续集"这一个:Stm32f4: DMA + ADC Transfer pausing。
同样,我正在尝试实现这样的算法:
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);
}
答案 0 :(得分:1)
我自己找到了解决方案。我以为这是一个DMA问题;然而,它变成了ADC的问题。 ADCx-> CR寄存器中的OVR标志始终在传输过程中被设置为#34;卡住"。因此,我在ADC溢出情况中添加了一个中断并重新启动了DMA& ADC里面。问题现在解决了。