Для меня такой вариант работы АЦП через DMA с накоплением нескольких выборок по каждому обрабатываемому каналу в группе оказался очень удобен, поэтому в другом проекте еще раз попробовал вникнуть в суть проблемы (все таки ADON сбрасывать не есть гуд), перечитать даташит. Наткнулся в RM0090 на следующую фразу (стр.267):
"If the ADC_SQRx or ADC_JSQR registers are modified during a conversion, the current
conversion is reset and a new start pulse is sent to the ADC to convert the newly chosen
group."
Попробовал - работает.
В прерывании DMA (не обязательно там, главное после передачи ВСЕХ результатов преобразований в память):
void DMA2_Stream4_IRQHandler(void)
{
ADC1->CR2 &= ~ADC_CR2_DMA; // выключаем DMA запросы АЦП
ADC1->SR &= ~(ADC_SR_OVR | ADC_SR_STRT); // сброс флага Overrun и старта преобразования
ADC1->SQR1 &= ~ADC_SQR1_L; // сброс количества последовательных преобразований [сброс указателя канала]
DMA2_Stream4->CR &= ~DMA_SxCR_EN; // деактивация 4-го потока DMA2
if(DMA2->HISR & DMA_HISR_TCIF4) // проверяем прерывание по завершению передачи блока
ADCStop = 1; // получены данные от АЦП
DMA2->HIFCR |= DMA_HIFCR_CTCIF4 | DMA_HIFCR_CHTIF4 | DMA_HIFCR_CTEIF4 | DMA_HIFCR_CDMEIF4 | DMA_HIFCR_CFEIF4;
}
можно там же в прерывании обработать результаты и перезапустить преобразование, мне нужно сделать это в другом месте, для запуска нового преобразования требуется:
// перезапускаем 4-й поток DMA (0 канал)
DMA2_Stream4->NDTR = SAMPL_CHANNEL_ADC * MD_CHANNEL; // объем передаваемого блока
DMA2_Stream4->CR |= DMA_SxCR_EN; // активация 4-го потока DMA2 (как и было 0-ой канал)
//перезапускаем АЦП1 10(PC0)
ADC1->SQR1 |= (uint32_t)(MD_CHANNEL-1 << 20); // 4 регулярных каналов (12-15) [сброс указателя канала]
ADC1->CR2 |= ADC_CR2_DMA; // включаем запросы DMA АЦП
ADC1->CR2 |= ADC_CR2_SWSTART; // запускаем преобразование
Другими словами, не сбрасывая ADON нужно изменить SQR1 или SQR2, при этом преобразование начнется с 1-го выбранного канала в группе, что и требовалось.