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
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.