Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как инициализировать АЦП в режиме непрерывного преобразования
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
Sirko
Чип Mega48
Инициализирую вот так:
Код
ADCSRA =
    _BV(ADEN)      // Разрешить работу АЦП
  | _BV(ADIE)     // Разрешить прерывания
  | _BV(ADSC)     // Запустить преобразование (первое, дальше автоматом)
  | _BV(ADATE)    // Непрерывные последовательные преобразования, одно за другим.
  | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0);     // Делитель частоты на 128
    
ADMUX =
    _BV(REFS0)     // Опорное напряжение AVCC 5V
  | _BV(ADLAR)     // Выравнивание по левому краю
  |  5;            //   Сигнал на вход идет с пятого канала АЦП

ISR(ADC_vect){//-------------------------------------------------------------------------------------
   u16 q = ADCW;
//  ADCSRA &=~_BV(ADIE);
}


Судя по поведению, при попадании в прерывание - выхода от туда нет.
Если в инициализации закоментировать разрешение прерывания АЦП или в обработчике его запретить, то остальной софт функционирует

В чем косяк?
arttab
есть бит в регистре управления ацп включающий автозапуск ацп
Sirko
Бит то есть, но при его задействовании нет выхода из прерывания. В том то и суть вопроса.
ILYAUL
Цитата(Sirko @ Feb 1 2013, 10:32) *
нет выхода из прерывания.

Да он то есть, только проц постоянно обрабатывает только прерывание. Выже ему практически ни начто другое время не оставляете.
Sirko
Дык вопрос то о том, как "это" ему дать.
Понятное дело, что я что то делаю не так.

Судя из строк "ADIF is cleared by hardware when executing the corresponding interrupt handling vector. " флаг должен сброситься при входе в прерывание, но что-то, где-то не стыкуется.
xemul
Цитата(Sirko @ Feb 1 2013, 11:36) *
Понятное дело, что я что то делаю не так.

Угу - включив непрерывное преобразование, пытаетесь работать по прерываниям АЦП. Если Ваша программа в обработчике прерывания проводит время, соизмеримое или большее времени преобразования (программисты иногда вставляют в ISR что-нить вроде delay_ms() или printf()), то ...
Такая комбинация может иметь смысл, н-р, при низкой скорости тактирования АЦП и считывании результата преобразования по ещё более редкому прерыванию таймера, если время запуска преобразования не важно.
Цитата
Судя из строк "ADIF is cleared by hardware when executing the corresponding interrupt handling vector. " флаг должен сброситься при входе в прерывание, но что-то, где-то не стыкуется.

А где написано, что ADIF не может быть установлен, пока программа ковыряется внутри ISR(ADC_vect)? Вот и получается песня про Сусанина "он из лесу вышел, и снова вошёл".

Ещё вариант - разрешено более другое прерывание.
ILYAUL
Так всё и происходит , только при выходе он успевает сделать одну - две команды основного цикла и снова туда -> в обработчик прерывания. Так доходчивее?
Sirko
Цитата
пока программа ковыряется внутри

У меня в настоящий момент в обработчике единственное присваивание, причем код я привел с двухбайтным вариантом, а на самом деле я опрашиваю лишь ADCH.
Тактирование ацп - clk / (128 * 13). Так. что для "ногодрыга" в основном коде полторы тысячи тактов с лихвой.

Понятное дело - это то, что я ожидаю от проца. А что творится на самом деле, а главное, как и почему - я не понимаю.
doublekey
В даташите на странице 247 написано:
Код
When Auto Triggering is used, the prescaler is reset when the trigger event occurs

Насколько я понимаю у вас ADATE в 1, получается надо в прерывании задавать заново prescaler.

Да, похоже тут я не прав.
Попробуйте сбрасывать запрос прерывания в обработчике записывая 1 в ADIF.
Или такой вариант:
Изначально прерывание уже выставлено, и при инициализации включается автоматическое преобразование и происходит переход в обработчик прерывания, а prescaler не задаётся (хотя маловероятно).
Можно попробовать при инициализации ADCSRA также сбрасывать ADIF, а ADATE задавать в следующей команде.
ILYAUL
Цитата
Попробуйте сбрасывать запрос прерывания в обработчике записывая 1 в ADIF
.
Цитата
Да, похоже тут я не прав.
ещё раз и далее по тексту
doublekey
Хм, но вот проверил у себя на плате, инициализирую АЦПшник вот так, и всё работает
Код
void
adc_init (void)
{
  // Включаем блок АЦП.
  ADCSRA = _BV(ADEN);
  // Выбираем внутренний источник опорного напряжения.
  // Выравнивание результата по правой границе.
  // В качестве входа используется ADC0.
  ADMUX = _BV(REFS0) | _BV(REFS1);
  // Выбираем предделитель частоты.
  // Разрешаем прерывание от АЦП.
  // Включаем режим автоматического преобразования.
  ADCSRA |= _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0) | _BV(ADIE) | _BV(ADATE);
  // Запускаем преобразование.
  ADCSRA |= _BV(ADSC);
}
ILYAUL
Код
ADCSRA = _BV(ADEN);
ADCSRA |= _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0) | _BV(ADIE) | _BV(ADATE);
ADCSRA |= _BV(ADSC);

Охренеть!!! 15(минимум) команд для запуска ADC

to Sirko

Отключите непрерывное и проверьте что у Вас происходит в прерывании. Сделайте Single Conversion
doublekey
Код
   e:    80 e8           ldi    r24, 0x80; 128
  10:    86 b9           out    0x06, r24; 6
  12:    80 ec           ldi    r24, 0xC0; 192
  14:    87 b9           out    0x07, r24; 7
  16:    86 b1           in    r24, 0x06; 6
  18:    8f 62           ori    r24, 0x2F; 47
  1a:    86 b9           out    0x06, r24; 6
  1c:    36 9a           sbi    0x06, 6; 6

Команд всего 8, с учётом загрузки ADMUX, без загрузки - 6. Есть подозрение, что может быть косяк с выставлением ADSC одновременно с конфигурацией остальных битов в ADCSRA.
Ещё интересно, бит I в SREG выставляет до конфигурации АЦП или после.
ILYAUL
А должно быть -2
doublekey
ILYAUL, так тема про то, что человек написал инициализацию ADCSRA в 2 инструкции, и такой код оказывается неработоспособным, но вы настаиваете, что инициализация должна выполняться именно так.
Есть такой момент, что если производить запись в регистры АЦП когда бит ADEN ещё не установлен, не понятно, запишется что-нибудь или нет, ведь блок выключен и enable на регистры не подаётся. Так вот, если выставлять ADEN в ADCSRA в одной команде вместе с остальными битами, то запись в остальные биты может не производиться, поскольку enable ещё не выставлен (ведь он защёлкнется только в этом такте), именно поэтому ADCSRA = _BV(ADEN); вынесено в отдельную команду. И следующей командой может идти запись в остальные биты ADCSRA, поскольку в этом случае блок АЦП гарантированно включен.
ILYAUL
Код
ADCSRA = (1<<ADEN)|(1<<ADSC)|(0<<ADATE)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
Вот и вся инициализация и всегда работает. У него дело не в инициализации.
Sirko
Цитата
У него дело не в инициализации.


Как оказалось, так и есть.
Случаянно обратил внимание на то, что одна и та же прошивка могла стартовать, могла и не стартовать.
Генератор внутренний. К плате тоже претензий нет.
Кода - две с половиной строки.


Природа болезни осталась под вопросом.
Вылечилось радикально - заменой микрухи.

Спасибо за дискуссию.
Простите за головоломку.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.