Ксения (01.05.2017 00:03 - 01:31, просмотров: 431) ответил Idler на Вот как то так (поправил и прокомментировал) (еще 2 раза поправил):
Спасибо за труды! У меня получилось вот что (кое-где отступила от рекомендаций): volatile unsigned char Flag = 0; // мой флаг событий
uint16_t DMAbuf[1024]; // буфер для чтения ADC через DMA
#pragma vector=DMA_CH0_vect
__interrupt void isrDMA0()
{
Flag |= Flag_DMA; // моя маска события
DMA.INTFLAGS |= DMA_CH0TRNIF_bm;
}
C_task main() {
...
// постоянная часть, выполняемая однажды в начале программы до разрешения прерываний:
DMA.CTRL = 0;
DMA.CTRL = DMA_RESET_bm;
while( DMA.CTRL & DMA_RESET_bm);
DMA.CTRL = DMA_ENABLE_bm;
DMA.CH0.REPCNT = 1; // передаем 1 блок (буфер) и затыкаемся
DMA.CH0.CTRLA = DMA_CH_SINGLE_bm | DMA_CH_BURSTLEN_2BYTE_gc; // reload source after every burst, reload dest after every block
DMA.CH0.ADDRCTRL = DMA_CH_SRCRELOAD_BURST_gc | DMA_CH_SRCDIR_INC_gc | DMA_CH_DESTRELOAD_BLOCK_gc | DMA_CH_DESTDIR_INC_gc;
DMA.CH0.TRIGSRC = DMA_CH_TRIGSRC_ADCA_CH0_gc;
DMA.CH0.TRFCNT = 2048; // 1024 samples
DMA.CH0.DESTADDR0 = (uint8_t)DMAbuf;
DMA.CH0.DESTADDR1 = ((uint16_t)DMAbuf) >> 8;
DMA.CH0.DESTADDR2 = 0;
DMA.CH0.SRCADDR0 = (uint8_t)&ADCA.CH0.RES;
DMA.CH0.SRCADDR1 = ((uint16_t)&ADCA.CH0.RES) >> 8;
DMA.CH0.SRCADDR2 = 0;
DMA.CH0.CTRLB = DMA_CH_TRNINTLVL_LO_gc;
...
__enable_interrupt();
...
// этот кусочек работает только при запуске очередного скана
DMA.CH0.CTRLA |= DMA_CH_ENABLE_bm; // запуск
...
}
Вопросы:
1. Я верно поняла или что-то испортила?
2. К строке
DMA.CH0.CTRLB |= DMA_CH_TRNINTLVL_LO_gc;
Почему здесь |=, не = ? Ведь вроде бы раньше DMA.CH0.CTRLB ничего не присваивали. Или там по умолчанию лежит что-то полезное?
3. Достаточно ли этого для разрешения прерывания или надо еще где-то заглушки снимать?
4. "АЦП даже на макс. скорости выдает данные раз в ~160 тактов, ..." - не согласна. Если в даташите указана макс.частота 1 МГц, то ее периолд уже равен 32 такта, поскольку тактовая частота этого МК у меня 32 МГц. А по описанию АЦП получается и того меньше - 16 тактов (4 стадии "приближения" по 4 такта на каждую).
5. В каком регистре можно удостовериться, что канал DMA свое задание выполнил и остановился, если не использовать для этой цели прерывание?
6. Можно ли во время выполнения DMA своего задания выяснить, насколько далеко оно продвинулось? Например, если АЦП запускается внешними синхроимпульсами, которые прекратились раньше срока (когда массив еще не успел заполниться). Вообще-то я могла бы изначально заполнить массив числами hex(FFFF), которых от 12-разрядного АЦП никогда не бывает, а потом просматривать от конца к началу, но как-то это не элегантно.