Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: AT91SAM7S64 + PDC + ADC
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Pasha 111
Всем привет!

Прошу прощения за многобукв, но сразу решил написать, как всё работает.

Делаю тут свой приборчик на базе AT91SAM7S64, который должен оцифровывать аналоговый сигнал с частотой 500 кГц. Но у меня получается только в районе 370 кГц sad.gif

Атмел заявляет, что в её камне АЦП в режиме 8 бит делает 533 кГц. Это при максимальной частоте контроллера АЦП = 8 МГц и времени преобразования = 15 тактов (8000000 / 15 = 533333) (см. 37.9 ADC Characteristics)

Соответственно, хочу ещё и DMA использовать, чтобы всё хорошо было sm.gif

DMA (он же PDC) для АЦП в атмеле так устроен: как обычно, задаёте указатель на массив в один регистр, размер массива - в другой. Дальше запускаете АЦ преобразование. Когда оно завершится, и будет выставлен соответствующий бит в регистре статуса, DMA контроллер сам перепишет полученное значение в массив. Но запускать АЦ преобразование нужно самому, DMA контроллер этого не делает.

Зато у самого АЦП есть замечательная возможность включить внешний триггер запуска АЦ преобразования от сигнала TIOA любого из таймеров Timer Counter. Для этого, как пишут в datasheet'е, нужно TimerCounter выставить в режим Waveform Mode.

Итак, настраиваю АЦП контроллер: включён внешний триггер от TIOA1, разрешение 8 бит, PRESCAL = 2, STARTUP = 19, SHTIM = 15

Код
// Включаем частоту для АЦП
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_ADC;
while((AT91C_BASE_PMC->PMC_PCSR & (1 << AT91C_ID_ADC)) != (1 << AT91C_ID_ADC));
// Сбрасываем АЦП
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST;
// Делитель
uint32 PRESCAL = 2;
// Время запуска
uint32 STARTUP = 19;
// Время преобразования
uint32 SHTIM = 15;
// Настраиваем АЦП
AT91C_BASE_ADC->ADC_MR =
    AT91C_ADC_TRGEN_EN | AT91C_ADC_TRGSEL_TIOA1 |
    AT91C_ADC_LOWRES |
    (PRESCAL << 8) & AT91C_ADC_PRESCAL |
    (STARTUP << 16) & AT91C_ADC_STARTUP |
    (SHTIM << 24) & AT91C_ADC_SHTIM;


Получаю:
ADCClock = MCK / ((PRESCAL + 1) * 2) = 48054857 / ((2 + 1) * 2) = 8009142 Hz (8 MHz)
Startup Time = (STARTUP + 1) * 8 / ADCClock = (19 + 1) * 8 / 8009142 = 19,97 мкс (по документации время запуска спящего канала макс. 20 мкс)
Sample & Hold Time = SHTIM / ADCClock = 15 / 8009142, частота 8009142 / 15 = 533942 Hz
Частота процессора у меня
MCK = PLL / 2 = (18432000 * 73 / 14) / 2 = 48054857 Hz

Включаю нужный канал (как написано в даташите, DMA контроллер переписывает данные только от активных каналов)

Код
AT91C_BASE_ADC->ADC_CHER = AT91C_ADC_CH5;


Настраиваю DMA:

Код
// Буфер
uint8 buf[8192];

// Отключаем приёмник
PDC_ADC->PDC_PTCR = AT91C_PDC_RXTDIS;
// Отключаем передатчик
PDC_ADC->PDC_PTCR = AT91C_PDC_TXTDIS;

// Устанавливаем буфер чтения для PDC
PDC_ADC->PDC_RPR = (uint32)buf;
PDC_ADC->PDC_RCR = sizeof(buf);

// Включаем приёмник
PDC_ADC->PDC_PTCR = AT91C_PDC_RXTEN;


Теперь настраиваю таймер: частота MCK / 2, режим Waveform, способ счёта - пилообразный с автоматическим сбросом значения счётчика при достижении регистра RC, RA Compare Effect on TIOA = set, RC Compare Effect on TIA = clear

Код
// Включаем частоту таймера
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_TC1;
while((AT91C_BASE_PMC->PMC_PCSR & (1 << AT91C_ID_TC1)) != (1 << AT91C_ID_TC1));
// Настраиваем таймер на формирование П-образного сигнала на TIOA
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK |
    AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO |
    AT91C_TC_ACPA_SET | AT91C_TC_ACPC_CLEAR);


То есть в регистре RC задаю период пилообразного счёта, при этом TIOA при достижении RC (то есть в начале каждого периода) задаётся как низкий уровень, а при достижении RA - становится высоким.

Теперь нужно задать RA, RC, запустить таймер и ждать, когда массив заполнится sm.gif

Хочу, например, 500 кГц, тогда RC = MCK / 2 / 500000 = 48054857 / 2 / 500000 = 48
Тогда RA = RC / 2 = 24, то есть в середине пилы будет выставляться высокий TIOA1 (в этот момент должен происходить запуск преобразования), а в конце - низкий. DMA сделает всё остальное.

Так и делаю:

Код
// Частота АЦ преобразований
uint32 freq = 500000;
// Период таймера, соответствующий 1 периоду преобразования
uint32 period = MCK / 2 / freq;
// Задаём регистры A и C
AT91C_BASE_TC1->TC_RC = period;
AT91C_BASE_TC1->TC_RA = period / 2;
// Запускаем таймер
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;

// Ждём заполнения буфера
while(PDC_ADC->PDC_RCR);

// Смотрим результат
// ....


Так вот изменяя freq опытным путём понял, что максимальная частота составляет где-то 370000. У меня есть опорный сигнал 1 кГц 3.3В, соответственно могу посчитать сколько байт из массива buf должны быть почти 0 (< 10), а сколько почти 255 (>245) при заданной частоте freq. Кодга ставлю freq больше 370000, то в массиве buf получается одно и тоже, как будто freq всё ещё 370000.

Что я делаю не так?

P.S. Пробовал даже разгонять проц до MCK=64 МГц (с изменением PRESCAL с 2 на 3 разумеется, чтобы 8 МГц получить) - всё тоже самое.
RabidRabbit
Цитата(Pasha 111 @ Feb 19 2012, 17:35) *
Итак, настраиваю АЦП контроллер: включён внешний триггер от TIOA1, разрешение 8 бит, PRESCAL = 2, STARTUP = 19, SHTIM = 15

Получаю:
ADCClock = MCK / ((PRESCAL + 1) * 2) = 48054857 / ((2 + 1) * 2) = 8009142 Hz (8 MHz)
Startup Time = (STARTUP + 1) * 8 / ADCClock = (19 + 1) * 8 / 8009142 = 19,97 мкс (по документации время запуска спящего канала макс. 20 мкс)
Sample & Hold Time = SHTIM / ADCClock = 15 / 8009142, частота 8009142 / 15 = 533942 Hz
Частота процессора у меня
MCK = PLL / 2 = (18432000 * 73 / 14) / 2 = 48054857 Hz

В даташите русским по белому написано (для самого скоростного режима):
Corresponds to 15 clock cycles at 8 MHz: 5 clock cycles for track and hold acquisition time and 10 clock cycles for
conversion.

А у Вас только Sample&Hold занимает 15 тактов, + 10 тактов на преобразование, получаем максимальную частоту взятия отсчётов = 8009142/25 = 320365,68.
Pasha 111
RabidRabbit
Действительно, сейчас поигрался с частотой: ограничивается где-то на 312 кГц. Не дотягивает до 320 кГц видимо вот почему:
If a hardware trigger is selected, the start of a conversion is triggered after a delay at each rising edge of the selected signal. Due to asynchronism handling, the delay may vary in a range of 2 MCK clock periods to 1 ADC clock period.
То есть в худшем случае у меня частота АЦ преобразований получается 8009142/(25 + 1) = 308044 Гц

Я изначально SHTIM = 5 и ставил, но у меня сильно искажался сигнал, поэтому решил, что SHTIM - это как раз и есть сумма "5 clock cycles for track and hold acquisition time and 10 clock cycles for conversion.", то есть SHTIM = 15.

Сейчас опять поставил SHTIM = 5. Сигнал меняется так: смещается вверх, а амплитуда уменьшается. В документации написано вот что:
The user can drive ADC input with impedance up to:
Zout <= (SHTIM - 470) * 10 in 8 bit resolution mode
with SHTIM expressed in ns and Zout in ohms.

То есть Zout <= (5 / 8009142 * 1000000000 - 470) * 10 = 1542 Ом

У меня сигнал проходит через резистор на 15 кОм (делитель стоит), наверное поэтому у меня сигнал и искажался. Сейчас попробую поменять.
Pasha 111
... похоже сгорели операционники, так что исследование переносится на завтра sm.gif
Pasha 111
Поставил резистор на 330 (Ом) вместо 15 кОм, поставил SHTIM = 5, поменял операционники - всё заработало sm.gif

Но на 533 кГц всё равно не работает.

Как писал выше, в datasheet'е написано, что может быть задержка до 1 такта АЦП между триггером (от таймера) и началом преобразования. Но если эта задержка возникает, то при следующем триггере от таймера АЦ преобразование ещё не завершится, и следующее АЦ преобразование запустится только от следующего триггера. То есть если настроить таймер на выдачу сигналов с частотой, чуть превышающей частоту АЦ преобразований, то последяя упадёт ровно в 2 раза (реально время преобразования останется тоже, но запускаться будет через раз). Так у меня и происходит.

Если взять самый плохой случай, что каждый раз будет задержка в 1 такт АЦП, то максимальная частота тогда будет такой:
8009142 / 16 = 500571 Гц

Но на этой частоте почему-то тоже не работает. Плавно снижая частоту всё стабильно заработало только на 470 кГц. Но эта цифра уж очень подозрительно совпадает вот с этой:
8009142 / 17 = 471126 Гц

То есть АЦП тратит все 17 тактов на преобразования, включая задержку. Значит ещё 1 такт АЦП на что-то уходит. В чём может быть дело? Разгон проца до MCK = 64MHz не помогает. Или это особенность проца, или я что-то не так делаю.
RabidRabbit
Цитата(Pasha 111 @ Feb 21 2012, 13:28) *
То есть АЦП тратит все 17 тактов на преобразования, включая задержку. Значит ещё 1 такт АЦП на что-то уходит. В чём может быть дело? Разгон проца до MCK = 64MHz не помогает. Или это особенность проца, или я что-то не так делаю.

Вроде никаких лишних тактов, период таймера у Вас RC / (MCK / 2) = 48 / (MCK / 2) = 96 / MCK, время преобразования 15 / (MCK / 6) = 90 / MCK - разница как раз в один такт частоты тактирования АЦП. Как вариант, можно попробовать уменьшить SHTIM до 4, т.к. по-моему лучше, чтобы тактовая частота АЦП была кратна частоте выборок (таймера), тогда задержка запуска преобразования будет фиксированной (во времени) величиной...
Pasha 111
RabidRabbit
Так в том то и дело, что с учётом задержки в 1 такт АЦП, как написано в даташите, с момента прихода сигнала триггера от таймера до окончания преобразования проходит 16 / (MCK / 6) = 96 / MCK времени, а не 90 / MCK. Понятно, что преобразование само идёт 90 / MCK, но задежка всегда идёт перед преобразованием, поэтому период таймера тоже должен быть не меньше, чем 96 / MCK.

Таймер, если его настроить на 500 кГц, генерирует сигналы триггера с частотой RC / (MCK / 2) = 48 / (MCK / 2) = 96 / MCK, то есть время (задержка + АЦ преобразование) здесь точно совпадает с периодом подачи сигналов начала преобразования.

Мне как-то кажется, что не могут они прям так ровно совпадать. Просто когда я настраиваю процессор вышеизложенным способом, у меня сигнал начинает мериться то с частотой 500 кГц, то с частотой 250 кГц, причём скорость измерения быстро переключается, как будто какой-то сдвиг по фазе происходит между таймером и АЦП. Т.е. какое-то количество миллисекунд держится скорость 500 кГц, потом опять 250 и т.д.

Видимо, когда приходит триггер от таймера, АЦП как раз заканчивает преобразование и занят, поэтому срабатывает только от каждого 2-го триггера (поэтому нужно ждать ещё 1 такт АЦП - довод в сторону подтверждения минимального периода равного 17 / MCK и максимальной частоты 470 кГц). Или же DMA в это время занимает шину данных и контроллер АЦП для копирования полученного значения из его регистра в буфер.

Попробую поиграть попозже с регистром RC, но мне кажется, что 470 кГц - предел. В любом случае это лучше, чем те 320 кГц, с которых начал sm.gif

Проверил ещё раз, работает при RC = 51, ставлю RC = 50 - уже не работает.
RC / (MCK / 2) = 51 / (MCK / 2) = 102 / MCK, соответственно 471126 измерений в секунду. Так что 17 тактов АЦП ждать всё-таки надо.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.