Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: ADC для MSP430F1232
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
0xFF
При автоматическом опросе нескольких каналов АDC данные складываю в вектор памтяти. Проблема: данные разных каналов всё время оказываются в разных местах вектора. Я сканирую два канала и их значения всё время находятся в разных местах вектора - то в одной ячейке, то в другой. Подскажите в чём проблема.
rezident
Вы используете DTС? Приведите кусок кода. Думаю что у вас нарушается синхронизация процессов преобразования и "складирования" его результата. Как-то было такое с этим ADC10.
Если правильно помню, то в тот раз выкрутился, похерив конвейерное преобразование и заменив его однократным. Т.е. задавал номер канала, софтверно запускал преобразование и в прерывании считывал результат. В других проектах нужды использования ADC10 и DTC пока не было.
0xFF
void adc_service(void)
{
ADC10CTL0 &= ~ENC; //
while (ADC10CTL1 & BUSY); // Wait if ADC10 core is active
ADC10SA = 0x204; // Data buffer start
ADC10DTC1 = 8;
ADC10CTL0 |= ENC + ADC10SC;
}
void adc_init(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
ADC10CTL1 = INCH_1+ADC10DIV_3 + CONSEQ_3; // Temp Sensor ADC10CLK/4
ADC10AE = 0x03 ;
ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON +MSC;
ADC10DTC0 = ADC10CT;
}
Кстати у меня ещё довольно боьлшой поток по UART от которого приходит прерывание каждые 1мс. Когда я настраивал только один ADC все работало
rezident
Должно быть
Код
while (ADC10CTL1 & ADC10BUSY); // Wait if ADC10 core is active

но не в этом суть. Я не совсем понимаю какой режим преобразования и переносов вы используете или хотите использовать? С одной стороны режим преобразования: повторяющаяся последовательность каналов с софтверным стартом последовательности преобразования, а с другой стороны количество переносов = 8. Почему так? Ведь загружая ADC10SA, вы инициируете новую серию переносов. В то время как преобразований в цепочке только два. Т.е. сбросить/установить ENC и ADC10SC нужно в конце каждой последовательности преобразований, несмотря на то, что установлен бит MSC.
Я понимаю, если бы вы тактировали запуск преобразования таймером, а не программно. Тогда все было бы адекватно. Загрузили ADC10SA, установили ENC и... "сижу курю" пока ADC10IFG колом не встанет после завершения переноса блока. После успей только считать значения из блока памяти, пока они не обновились. Вот и все. И преобразования бы сами преобразовавались и в память сами бы складывались wink.gif
А так (у вас) не совсем понятные (для меня) способы для управления процессом измерения.
Раз запуск софтверный, то не проще ли было в вашем случае просто считывать каждый результат преобразования без использования DTC? Ведь промежуток времени между преобразованиями при ваших установках составляет около 60мкс. Это не так уж и часто ИМХО.
0xFF
Значит вместо while (ADC10CTL1 & ADC10BUSY); (как я понял это только для одноканального режима одиночного преобразования) ставлю while ( ADC10IFG ); - жду когда блок заполнится и затем забираю значнеия?



не использовать DTC не могу т.к. опрашиваю ADC где-то раз в 1 ms и необходимо затем по полученным данным расчитывать среднее значение для других вычислений.

Спасибо за то, что откликнулись на мой вопрос.
rezident
Цитата(0xFF @ Jan 12 2006, 01:03) *
Значит вместо while (ADC10CTL1 & ADC10BUSY); (как я понял это только для одноканального режима одиночного преобразования) ставлю while ( ADC10IFG ); - жду когда блок заполнится и затем забираю значнеия?

Нет. Неверно. ADC10IFG это битовый флаг в регистре ADC10CTL0. Поэтому нужно накладывать битовую маску. Правильно будет наверное так.
Код
while (!(ADC10CTL0&ADC10IFG));

После чтения результатов ADC10IFG нужно программно сбросить.
Код
ADC10CTL0&=~ADC10IFG;

Если бы вы воспользовались прерыванием от ADC10, то ADC10IFG сбрасывался бы самостоятельно при обслуживании вектора перывания ADС10. А так вручную.
Цитата(0xFF @ Jan 12 2006, 01:03) *
не использовать DTC не могу т.к. опрашиваю ADC где-то раз в 1 ms и необходимо затем по полученным данным расчитывать среднее значение для других вычислений.

Еще раз предлагаю вам подумать о том, что нужно
либо использовать режим однократной последовательности каналов (CONSEQ_1), всего два переноса и софтверный запуск,
либо режим повторяющейся последовательности (CONSEQ_3), нужное вам количество переносов, но в качестве источника запуска преобразований использовать какой-либо из выходных сигналов (Out0, Out1 или Out2) таймера TimerA.
Все зависит от того, важны ли вам значения каждого конкретного преобразования или можно считывать любые из этих значений (преобразование будет идти непрерывно пока не заполнится весь блок), но в определенные моменты времени?
0xFF
Сегодня просмотрел примеры использования DTC для ADC от TI

void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
ADC10CTL1 = INCH_1 + CONSEQ_3; // A1/A0, repeat multi channel
ADC10CTL0 = ADC10SHT_2 + MSC + ADC10ON + ADC10IE;
ADC10AE = 0x03; // P2.0,1 ADC option select
ADC10DTC1 = 0x40; // 40 conversions
P1DIR |= 0x01; // Set P1.0 output

for (;;)
{
P1OUT |= 0x01; // Set P1.0 LED on
ADC10CTL0 &= ~ENC;
while (ADC10CTL1 & BUSY); // Wait if ADC10 core is active
ADC10SA = 0x200; // Data buffer start
ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion ready
_BIS_SR(CPUOFF + GIE); // LPM0, ADC10_ISR will force exit
P1OUT &= ~0x01; // Clear P1.0 LED off
}
}

// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR (void)
{
_BIC_SR_IRQ(CPUOFF); // Clear CPUOFF bit from 0(SR)
}

Наверное он мнея м запутал. Большое Вам спасибо, rezident, переписал свою функцию (начальную конфиг. не менял) теперь она выглядит так:

void adc_service(void)
{
Цитата
while (!(ADC10CTL0&ADC10IFG));

ADC10CTL0 &= ~ENC; //
//Забираю данные с вектора
Цитата
ADC10CTL0&=~ADC10IFG;

ADC10SA = 0x204; // Data buffer start
ADC10DTC1 = 8;
ADC10CTL0 |= ENC + ADC10SC;
}
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.