|
AT91SAM7xxxx, ADC, 2 канала и PDC |
|
|
|
Dec 10 2012, 13:17
|

Профессионал
    
Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980

|
Привет всем. AT91SAM7S256 цифрует стереозвук встроенным АЦП (ADC7-левый, ADC6-правый канал) и далее обрабатывает эти выборки. Выборки сейчас по 512 байт. Сейчас сделано "как в AVR" - запуск АЦП по сигналу TIOA1 ~24kHz, съём данных в прерывании АЦП. Каналы АЦП переключаются в прерывании. Код // Прерывание АЦП - один из каналов завершил преобразование void ADC_IrqHandler(void) { dword status; word wValue; status = ADC_GetStatus(AT91C_BASE_ADC); if ( (status & (1<<ADC_CHANNEL_LEFT) ) !=0 ) { // левый канал закончил преобразование wValue = AT91C_BASE_ADC->ADC_CDR7;
// Включить правый канал ADC_EnableChannel ( AT91C_BASE_ADC, ADC_CHANNEL_RIGHT ); ADC_EnableIt ( AT91C_BASE_ADC, 1 << ADC_CHANNEL_RIGHT ); adcDataLeft [ dataPosLeft ] = wValue >> 2; dataPosLeft ++; if ( dataPosLeft == ADC_DATA_SIZE ) { // останов преобразований StopConversion ( ); conversionDone = 1; } // if } // if if ( (status & (1<<ADC_CHANNEL_RIGHT) ) !=0 ) { // правый канал закончил преобразование // AT91C_BASE_ADC->ADC_CDR6 - регистр канала wValue = AT91C_BASE_ADC->ADC_CDR6;
// Включить левый канал ADC_EnableChannel ( AT91C_BASE_ADC, ADC_CHANNEL_LEFT ); ADC_EnableIt ( AT91C_BASE_ADC, 1 << ADC_CHANNEL_LEFT ); adcDataRight [ dataPosRight ] = wValue >> 2; dataPosRight ++; if ( dataPosRight == ADC_DATA_SIZE ) { // останов преобразований StopConversion ( ); conversionDone = 1; } // if } // if } // ADC_IrqHandler Процесс начинается с левого канала: ADC_EnableChannel ( AT91C_BASE_ADC, ADC_CHANNEL_LEFT ); ADC_EnableIt ( AT91C_BASE_ADC, 1 << ADC_CHANNEL_LEFT ); Это работает нормально. Результирующая частота дискретизации получается, конечно, в 2 раза меньше, но я сейчас не об этом. Я где-то на форумах читал, что если написать ADC_EnableChannel ( AT91C_BASE_ADC, ADC_CHANNEL_LEFT | ADC_CHANNEL_RIGHT ); ADC_EnableIt ( AT91C_BASE_ADC, ( 1 << ADC_CHANNEL_LEFT ) | ( 1 << ADC_CHANNEL_RIGHT ) ); то он будет сам щёлкать каналы по очереди. Попробовал - не работает. Точнее сказать - работает только левый канал - ADC7. Условие для правого канала вообще никогда не срабатывает. Проверял по DBGU. Может я неправильно включаю этот режим... Или чего-то недопонимаю... Вопрос - может ли он сам переключать каналы? Ведь зачем-то в регистрах сделано по битику на канал (а на как в AVR-ах ADMUX=7 и 6 туда уже одновременно не запишешь)? Вопрос особенно актуален, если задействовать PDC. Получать 512 байт сперва с одного, потом 512 с другого, да ещё и с задержками на перепрограммирование ADC/PDC - как-то "некошерно", необходима как можно большая синхронность в оцифровке каналов. А это - только оцифровка каналов по очереди. Не считая установки 2-х независимых АЦП Спасибо. PS. Замечания типа "Омар фигня, лобстер круче", где омар==AT91SAM7, лобстер==STM32 просьба не писать. Я прекрасно знаю, что в STM32 есть 2-3 независимых АЦП и прочие плюшки, но пока интересует исключительно AT91SAM7.
--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса. (с) Мария Эдуарда
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 14)
|
Dec 11 2012, 05:47
|

Местный
  
Группа: Свой
Сообщений: 397
Регистрация: 3-12-09
Из: Россия, Москва
Пользователь №: 54 040

|
Цитата(hd44780 @ Dec 10 2012, 17:17)  Я где-то на форумах читал, что если написать ADC_EnableChannel ( AT91C_BASE_ADC, ADC_CHANNEL_LEFT | ADC_CHANNEL_RIGHT ); ADC_EnableIt ( AT91C_BASE_ADC, ( 1 << ADC_CHANNEL_LEFT ) | ( 1 << ADC_CHANNEL_RIGHT ) ); то он будет сам щёлкать каналы по очереди. Попробовал - не работает. Точнее сказать - работает только левый канал - ADC7. Условие для правого канала вообще никогда не срабатывает. Проверял по DBGU. Может я неправильно включаю этот режим... Или чего-то недопонимаю... DS========== Only one start command is necessary to initiate a conversion sequence on all the channels. The ADC hardware logic automatically performs the conversions on the active channels, then waits for a new request. The Channel Enable (ADC_CHER) and Channel Disable (ADC_CHDR) Registers enable the analog channels to be enabled or disabled independently. If the ADC is used with a PDC, only the transfers of converted data from enabled channels are performed and the resulting data buffers should be interpreted accordingly. DS========== Попробуйте сделать, как в даташите - в регистр ADC_CHER записать два бита для соответствующих каналов, настроить PDC, в регистр ADC_IER записать бит ENDRX и запустить таймер. Руками по регистрам, кстати, гораздо понятнее получается, чем при использовании библиотечных функций (на мой взгляд, конечно).
|
|
|
|
|
Dec 11 2012, 07:32
|

Профессионал
    
Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980

|
Цитата(RabidRabbit @ Dec 11 2012, 07:47)  Попробуйте сделать, как в даташите - в регистр ADC_CHER записать два бита для соответствующих каналов, настроить PDC, в регистр ADC_IER записать бит ENDRX и запустить таймер. Руками по регистрам, кстати, гораздо понятнее получается, чем при использовании библиотечных функций (на мой взгляд, конечно). Спасибо. ADC_CHER я так и писал по задумке. Но недосмотрел реализацию той функции. В итоге бред получался  . Про END_RX понятно, сделаю. Но ещё надо курить, как с PDC работать. Я с ним дел ещё не имел ...
--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса. (с) Мария Эдуарда
|
|
|
|
|
Dec 12 2012, 07:03
|

Профессионал
    
Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980

|
Цитата(RabidRabbit @ Dec 12 2012, 08:25)  Я думаю, с PDC разберётесь с полпинка, там всё просто и логично. Надеюсь  . Цитата(RabidRabbit @ Dec 12 2012, 08:25)  На всякий случай - для ADC счётчики в PDC считают не байты, а "отсчёты", если ADC в 10-битном режиме, то в счётчики надо заряжать количество 16-битных слов в буфере. Да, спасибо. Я в курсе. До этого у меня были 10-битовые отсчёты, но в прерывании я всё равно клал в буферы байты, сдвигая считанное 10-бит значение на 2 бита вправо. Вчера перевёл АЦП в 8-битный режим, убрал эти сдвиги - работает. Пока без PDC.
--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса. (с) Мария Эдуарда
|
|
|
|
|
Dec 12 2012, 09:40
|

Участник

Группа: Участник
Сообщений: 46
Регистрация: 29-10-10
Пользователь №: 60 513

|
Цитата Так вот, если вы будете перезаряжать PDC слишком долго и АЦП успеет сделать преобразование, у вас один отсчет потеряется и все остальнвые будут лежать в буфере со сдвигом, т.е левый и правый каналы перепутаются хотелось бы уточнить: в похожей ситуации я настраиваю PDC на работу с несколькими каналами, подсовываю ему буфер и включаю прерывания End of Receive Buffer и Receive Buffer Full. Я правильно понимаю, что когда прерывание срабатывает, я должен успеть: передать PDC новый буфер до того, как пройдет хотя бы одно преобразование (чтобы нумерация каналов не сбилась) обработать данные из буфера до того, как АЦП успеет заполнить следующий (чтобы данные не затерлись) ? upd: понял что я не прав. PDC подсовывается адреса двух буферов, RPR - куда читать сейчас, RNPR - куда читать когда закончится первый буфер. По прерыванию End of Receive Buffer мне нужно снова указывать буфер RNPR? Немного запутался, можно ли поподробнее рассказать про случай, который я процитировал вначале. У меня имеется уже готовая чужая программа, в которой периодически проявляются проблемы перепутывания каналов АЦП, читаемых через PDC. upd: пока никто не отвечает, кажется у меня очередное просветление: если программа чтения АЦП укажет при запуске два буфера RPR/RNPR и по прерыванию ENDRX будет своевременно их "перезаряжать" - все будет отлично. Если же программа затупит и в какой-то момент ни одного буфера не будет задано - все что в это время оцифровывает АЦП потеряется. При использовании нескольких каналов соответственно может потеряться часть из них, и нумерация собьется. Верно?
Сообщение отредактировал Jack_of_Shadows - Dec 12 2012, 12:55
|
|
|
|
|
Dec 12 2012, 15:51
|

Местный
  
Группа: Свой
Сообщений: 397
Регистрация: 3-12-09
Из: Россия, Москва
Пользователь №: 54 040

|
Цитата(Сергей Борщ @ Dec 12 2012, 11:24)  Когда будете работать с PDC обратите внимание на такой момент - у вас АЦП стартует от таймера и отсчеты выдает независимо от того - успели вы перезарядить PDC на новый буфер или нет. Так вот, если вы будете перезаряжать PDC слишком долго и АЦП успеет сделать преобразование, у вас один отсчет потеряется и все остальнвые будут лежать в буфере со сдвигом, т.е левый и правый каналы перепутаются. Отследить такую ситуацию можно по флагу RXBUFF. К сожалению ни циклических пересылок, ни цепочек буферов в PDC SAM7 не предусмотрено. Как же так?  Я думал, что тяжело не успеть обновить два регистра PDC за время, пока отработает половина буфера (а это будет одно преобразование только в случае если размер буфера == 1, что странно), ну если только программа совсем повиснет...
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|