Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Тема избитая, но всеже... ацп12 некорректно работает
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
aag
Потребовалось в нужный момент времени по команде произвести измерения напряжений с восьми каналов.

Измерения проходят успешно, но почему-то при первом запуске ацп происходит зацикливание и дальше постоянно происходит прерывание sad.gif Что не так?

Инициализация ацп:
Код
//---------------------------------------------------------------------------
void InitADC()
{
    ADC12CTL0 = ADC12ON | SHT0_4 | MSC; //источник опоры внешний
    ADC12CTL1 = CSTARTADD_0 | SHP | CONSEQ_1;
  
    ADC12MCTL0 = SREF_1 | INCH_0;
    ADC12MCTL1 = SREF_1 | INCH_1;
    ADC12MCTL2 = SREF_1 | INCH_2;
    ADC12MCTL3 = SREF_1 | INCH_3;
    ADC12MCTL4 = SREF_1 | INCH_4;
    ADC12MCTL5 = SREF_1 | INCH_5;
    ADC12MCTL6 = SREF_1 | INCH_6;
    ADC12MCTL7 = SREF_1 | INCH_7 | EOS;
  
    ADC12IE = 0x80; // прерывание от последнего канала
    ADC12CTL0 |= ENC;
}
//---------------------------------------------------------------------------
void ADC_Start()
{
    ADC12CTL0 |= ADC12SC;
}
//---------------------------------------------------------------------------
// Прерывание:
#pragma vector=ADC12_VECTOR
OS_INTERRUPT void ADC12ISR (void)
{
    OS::TISRW ISRW;
  
    ef_adc.SignalISR();
    //тут стоит брейкпоинт, и почему-то после первого запуска ацп
    //постоянно попадаю сюда :(
}
//---------------------------------------------------------------------------
//фрагмент кода, откуда должно запускаться ацп:

...
    ADC_Start();
    ef_adc.Wait(); //ждать окончания преобразования
    
    int SenseA = ADC12MEM0;
    int SenseB = ADC12MEM1;
....


Вопрос то состоит в том, почему ацп не останавливается после первого измерения с восьми каналов? 01.gif
Флаг ADC12SC при этом сбрасывается - проверял.
MrYuran
Ну, мануала под рукой сейчас нет, но вот глянул свои тексты, у меня после преобразования стоит
ADC12CTL0 &= ~(ADC12ON+REFON);
Логично это вставить в обработку прерывания. Опору можно не выключать, у меня просто своя специфика была.
По-моему, есть ещё разные режимы работы АЦП (однократный/непрерывный), но могу и ошибаться.
Дело было давно, сейчас в основном копи-пастю куски старых проектов.
VAI
А что, если Вам в прерывании прочитать ADC12MEM-ы и скопировать из в какой-либо массивчик?
Я делаю так:
Код
#pragma vector=ADC_VECTOR
__interrupt void ADC12_isr( void )
{
unsigned short *adc_mem_ptr;
int a;

  adc_mem_ptr = (unsigned short *)&ADC12MEM0;
  for ( a = 0; a < adc_cnt; a++ )    
    x_adc_t[a] += *adc_mem_ptr++;                // сохраним результаты АЦП во временный массив
}

Я OS не использую, но инициализирую почти так-же:
Код
/* --- adc_ini() ------------------------------------------------------------------------------------------ **
*  Инициализация каналов АЦП
* -------------------------------------------------------------------------------------------------------- */
static void adc_ini( void )
{
  P6SEL = BINARY( 11111111 );
  P6DIR = BINARY( 00000000 );

  ADC12CTL0 = ADC12ON                                             // АЦП включено
            | SHT0_2                                              // время установленияния для ADC12MEM0…ADC12MEM7
            | SHT1_3                                              // время установленияния для ADC12MEM8…ADC12MEM15
            | MSC                                                 // обрабатываем последовательность каналов
            | REFON + REF2_5V                                     // опорное напряжение 2.5В включено
          ;

  ADC12CTL1 = CSTARTADD_0
            | SHP                                                 // Сигнал SAMPCON берется с таймера защёлки.
            | ADC12SSEL_3
            | ADC12DIV_1
            | CONSEQ_1                                            // один цикл измерения последовательности каналов
          ;

  ADC12MCTL0 = INCH_2  + SREF_1;
  ADC12MCTL1 = INCH_0  + SREF_1;
  ADC12MCTL2 = INCH_3  + SREF_1;
  ADC12MCTL3 = INCH_1  + SREF_1;

  ADC12MCTL4 = INCH_4  + SREF_1;
  ADC12MCTL5 = INCH_6  + SREF_1;
  ADC12MCTL6 = INCH_5  + SREF_1;
  ADC12MCTL7 = INCH_7  + SREF_1 + EOS;

// -----------------------------------------------------------------------------------------------------------------
  ADC12IE = 1 << ( adc_cnt - 1 );     // Enable ADC12IFG.x - разрешим прерывание от последнего канала
  Enable_conversions();                    // { ADC12CTL0 |= ENC; }
}

А запуск преобразования делаю по прерыванию от таймера.
Никаких проблем нет, прерывание от АЦП вызывается однократно после каждго запуска преобразования
aag
Хм, а ведь помогло...

Вроде непрерывный или однократный режим измерения по каналам задается двумя младшими битами регистре ADC12CTL1. Но у меня при инициализации указывалось ADC12CTL1 |= CONSEQ_1, а не CONSEQ_3.

Почему же ацп продолжал генерить прерывания, пока не произошло считывание из регистров ADC12MEM0...ADC12MEM7 не знаю sad.gif
но теперь, когда считывание регистров сделал в самом прерывании, все заработало как надо smile.gif
VAI
Цитата
Почему же ацп продолжал генерить прерывания, пока не произошло считывание из регистров ADC12MEM0...ADC12MEM7 не знаю


Наверное по этому:
Цитата
Флаги ADC12IFGx не сбрасываются при доступе к ADC12IV. Биты ADC12IFGx сбрасываются автоматически при доступе к их соответствующим регистрам ADC12MEMx или же могут быть сброшены программно.

http://www.gaw.ru/html.cgi/txt/doc/micros/msp430/arh/17.htm в самом конце...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.