|
Как инициализировать АЦП в режиме непрерывного преобразования |
|
|
|
Jan 31 2013, 15:35
|
Местный
  
Группа: Участник
Сообщений: 245
Регистрация: 15-08-07
Пользователь №: 29 795

|
Чип 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); } Судя по поведению, при попадании в прерывание - выхода от туда нет. Если в инициализации закоментировать разрешение прерывания АЦП или в обработчике его запретить, то остальной софт функционирует В чем косяк?
|
|
|
|
|
Feb 1 2013, 08:00
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(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)? Вот и получается песня про Сусанина "он из лесу вышел, и снова вошёл". Ещё вариант - разрешено более другое прерывание.
|
|
|
|
|
Feb 1 2013, 09:01
|
Местный
  
Группа: Участник
Сообщений: 245
Регистрация: 15-08-07
Пользователь №: 29 795

|
Цитата пока программа ковыряется внутри У меня в настоящий момент в обработчике единственное присваивание, причем код я привел с двухбайтным вариантом, а на самом деле я опрашиваю лишь ADCH. Тактирование ацп - clk / (128 * 13). Так. что для "ногодрыга" в основном коде полторы тысячи тактов с лихвой. Понятное дело - это то, что я ожидаю от проца. А что творится на самом деле, а главное, как и почему - я не понимаю.
|
|
|
|
|
Feb 1 2013, 19:00
|
Участник

Группа: Свой
Сообщений: 71
Регистрация: 28-01-08
Из: Zelenograd
Пользователь №: 34 503

|
В даташите на странице 247 написано:
Код When Auto Triggering is used, the prescaler is reset when the trigger event occurs Насколько я понимаю у вас ADATE в 1, получается надо в прерывании задавать заново prescaler.Да, похоже тут я не прав. Попробуйте сбрасывать запрос прерывания в обработчике записывая 1 в ADIF. Или такой вариант: Изначально прерывание уже выставлено, и при инициализации включается автоматическое преобразование и происходит переход в обработчик прерывания, а prescaler не задаётся (хотя маловероятно). Можно попробовать при инициализации ADCSRA также сбрасывать ADIF, а ADATE задавать в следующей команде.
Сообщение отредактировал doublekey - Feb 1 2013, 19:53
|
|
|
|
|
Feb 1 2013, 22:05
|

Профессионал
    
Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339

|
Цитата Попробуйте сбрасывать запрос прерывания в обработчике записывая 1 в ADIF . Цитата Да, похоже тут я не прав. ещё раз и далее по тексту
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
Feb 2 2013, 07:39
|
Участник

Группа: Свой
Сообщений: 71
Регистрация: 28-01-08
Из: Zelenograd
Пользователь №: 34 503

|
Хм, но вот проверил у себя на плате, инициализирую АЦПшник вот так, и всё работает Код 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); }
|
|
|
|
|
Feb 2 2013, 09:53
|

Профессионал
    
Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339

|
Код ADCSRA = _BV(ADEN); ADCSRA |= _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0) | _BV(ADIE) | _BV(ADATE); ADCSRA |= _BV(ADSC); Охренеть!!! 15(минимум) команд для запуска ADC to SirkoОтключите непрерывное и проверьте что у Вас происходит в прерывании. Сделайте Single Conversion
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
Feb 2 2013, 10:22
|
Участник

Группа: Свой
Сообщений: 71
Регистрация: 28-01-08
Из: Zelenograd
Пользователь №: 34 503

|
Код 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 выставляет до конфигурации АЦП или после.
|
|
|
|
|
Feb 2 2013, 11:45
|
Участник

Группа: Свой
Сообщений: 71
Регистрация: 28-01-08
Из: Zelenograd
Пользователь №: 34 503

|
ILYAUL, так тема про то, что человек написал инициализацию ADCSRA в 2 инструкции, и такой код оказывается неработоспособным, но вы настаиваете, что инициализация должна выполняться именно так. Есть такой момент, что если производить запись в регистры АЦП когда бит ADEN ещё не установлен, не понятно, запишется что-нибудь или нет, ведь блок выключен и enable на регистры не подаётся. Так вот, если выставлять ADEN в ADCSRA в одной команде вместе с остальными битами, то запись в остальные биты может не производиться, поскольку enable ещё не выставлен (ведь он защёлкнется только в этом такте), именно поэтому ADCSRA = _BV(ADEN); вынесено в отдельную команду. И следующей командой может идти запись в остальные биты ADCSRA, поскольку в этом случае блок АЦП гарантированно включен.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|