|
|
  |
Снова АЦП |
|
|
|
Sep 21 2009, 17:53
|

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

|
ATmega164P. Отладчик AVRdragon и Studio Проблема в следующем ,при прогоне программы с подключённым макетом АЦП ведёт себя как ему и положено , но стоит запрограмировать микросхему и запустить в автономке АЦП просыпается только по прерыванию от таймера , в моем случае через секунду. FUSES выставлены - проблем я с ними не вижу. Ниже привожу код , может всё таки что-то упустил. Конечно многое отсёк оставив только относящееся к АЦП. HELP Код *********************** ; * * ; * * ; * ATMega 164P * ; * * ; ***********************
.include "C:\Program Files\Atmel\AVR Tools\AvrAssembler2\Appnotes\m164pdef.inc"
.DEVICE ATmega164P
.org ADCCaddr jmp ADC3 ; ADC Conversion Complete
; ***************************** ; * * ; * Initialization АЦП * ; * * ; * * ; *****************************
ldi temp,(1<<REFS0)|(1<<ADLAR) sts ADMUX,temp ; Внешнее напряжение AVcc, выравнивание влево ldi temp,(1<<ADC0D) ; Отключение цифрового контакта от sts DIDR0,temp ; PORTA pin0 clr temp sts ADCSRB,temp ldi temp,(1<<ADEN)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(0<<ADPS0) sts ADCSRA,temp ; |(0<<ADSC) Преобразование отключено ; АЦП вкл. Прерывание разрешено . Делитель на 64 = 187,5 Кгц частота ; преобразования
; ***************************** ; * * ; * Подпрограмма обнаружения * ; * * ; * * ; *****************************
TIM2COMPB: cli push temp push count in temp,SREG push temp ldi Cnt0,Low(255); Инициализация счётчика преобразований clr rab ; Очиска рабочих регистров clr mean0 clr mean1 clr ZH clr ZL cbi PORTB,0 ADC1:
ldi temp,(1<<SE)|(1<<SM0) ; Настройка режима "сна" out SMCR,temp ; Запись SMCR sei sleep ; Преобразование dec Cnt0 ; brne ADC1 ; Если не равно 255 - преобразование ldi count,$08 ; Начинаем процедуру вычисления среднего ADC5: lsr mean1 ; 255=2 в степени 8 ror mean0 ; сдвигаем регистры в право 8 раз dec count brne ADC5 ; Конец процедуры вычисления среднего ldi temp,(0<<SE)|(1<<SM0); Выход из режима "сна" out SMCR,temp pop temp out SREG,temp pop count pop temp sbi PORTB,0 sei rjmp CHECK
; ***************************** ; * * ; * Вычисление среднего ; * * ; *****************************
ADC3: cli ldi temp,(0<<SE)|(1<<SM0) ; Выход из режима "сна" out SMCR,temp ; Запись SMCR lds rab,ADCH ; Считывание только старшего регистра clr temp add mean0,rab ; Вычисление среднего adc mean1,temp ; Вычисление среднего ret
; ***************************** ; * * ; * Таблица значений для ADC * ; *****************************
tabADC: .db $00,$01,$4A,$4B,$4C,$95,$96,$97 .db $B4,$B5,$B6,$7E,$7F,$80,$FE,$FF Пояснения TIM2COMPB: это прерывание от таймера по которому и запускается АЦП- убрано за ненадобностью
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
Sep 22 2009, 00:15
|
Местный
  
Группа: Свой
Сообщений: 256
Регистрация: 6-03-06
Из: Украина, г. Винница
Пользователь №: 15 017

|
Цитата ADC5: lsr mean1 ; 255=2 в степени 8 ror mean0 ; сдвигаем регистры в право 8 раз dec count brne ADC5 ; Конец процедуры вычисления среднего Цитата Конечно многое отсёк Даже слишком многое. Где точка входа в программу? Где границы прерываний? Вы привели просто обрывки кода.
|
|
|
|
|
Sep 23 2009, 18:39
|

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

|
Цитата(Rst7 @ Sep 23 2009, 12:43)  Нормально. Вполне правомочное требование курить оригинальные даташиты, а не перепевки с ошибками. Так уважаемыемые давайте без сор. Я не запросил бы Вашей поддержки , если бы не проштудировал DS , прочую литературу , того же Евстифеева и не попробывал всё проанализировать сам. Прилложенный код , это естесвенно не начальный вариант. Это плод прочитанной литературы и всяческой инфы Инета.Просто я решил остановится и запросить помощь. Многих команд не бывло в первоначальном варианте и всё равно всё работало также как и в предложенном коде т.е. при прогоне программы через Драгон+ макетка всё работает и АЦП выдает расчитаную инфу, но вот в автономе нет. И я в ступоре , не могу понять почему. Если Вы считаете , что я что-то упустил в DS , то ткните носом ( не обидно) . Моего англиского хватит , что бы самому разобраться.
Сообщение отредактировал ILYAUL - Sep 23 2009, 18:50
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
Sep 24 2009, 18:26
|
Местный
  
Группа: Свой
Сообщений: 256
Регистрация: 6-03-06
Из: Украина, г. Винница
Пользователь №: 15 017

|
Цитата Пояснения TIM2COMPB: это прерывание от таймера по которому и запускается АЦП- убрано за ненадобностью Здесь что-то не понятно. Что убрано за ненадобностью? Текст прерывания от таймера?? а что тогда приведено выше? Или убран запуск АЦП? Высказывайтесь, пожалуйста поконкретней. Цитата Ставил я и RETI толку , чуть. Прерывания всегда должны заканчиваться reti. При ret ход программы не нарушится, но останется очищенным флаг глобального разрешения прерываний. Конечно, никто конкретно вам не запретит пользоваться ret вместо reti, но есть все-таки общепринятые правила и принципы. И их соблюдение позволит Вам в дальнейшем избежать многих проблем. Кстати, одно из этих правил для авр-архитектуры - использовать вложенные прерывания с умом и ТОЛЬКО при большой нужде. За 7 лет программирования у меня такой наобходимости не возникало. А использование вложенных прерываний "без ума" грозит тем, что у Вас может образоваться рекурсия из прерываний. (Это я к тому, что судя по приведенному коду, команды sei, sleep у вас вызывается из прерывания по TIM2COMPB) Цитата АЦП запускается по команде sleep АЦП действительно запускается по команде SLEEP, но только в режиме ADC Noise Reduction. Цитата "ldi temp,(0<<SE)|(1<<SM0) - почитал классиков , пишут эта операция необходима при обработке прерывания. Не необходима, а рекомандована. Атмеловцы боятся, что MCU может сам войти в спячку, если ошибочно какую-то каманду воспримет как SLEEP. Или же стараются оградить нас от ошибок. : "To avoid the MCU entering the sleep mode unless it is the programmer’s purpose, it is recommended to write the Sleep Enable (SE) bit to one just before the execution of the SLEEP instruction and to clear it immediately after waking up." Теперь о проблеме. Отличие режима отладки и основной работы в том, что в режиме отладки при sleep не выключается частота тактирования ядра, поэтому работа контроллера в этих режимах может отличаться, если Вы не соблюдали рекомендаций атмела. 1. Смотрим раздел даташита 22.7 ADC Noise Canceler (порядок использования ADC Noise Canceler:) а) ADC is enabled (это есть) and is not busy converting (а вот этой проверки нет). Single Conversion Mode must be selected and the ADC conversion complete interrupt must be enabled. (это тоже есть) b ) Enter ADC Noise Reduction mode (or Idle mode). The ADC will start a conversion once the CPU has been halted. c) If no other interrupts occur before the ADC conversion completes, the ADC interrupt will wake up the CPU and execute the ADC Conversion Complete interrupt routine. If another interrupt wakes up the CPU before the ADC conversion is complete (В нашем случае это может быть прерывание от таймера 2), that interrupt will be executed , and an ADC Conversion Complete interrupt request will be generated when the ADC conversion completes. The CPU will remain in active mode until a new sleep command is executed - Т.е. как только вышли из режима спячки, мы не должны в него возвращаться до того момента, как не закончится преобразование АЦП. Это обеспечивается проверкой в пункте а). А выйти из режима спячки контроллер может в любой момент, так как таймер 2 в "вольном плаваньи". 2. Таймер2 у Ваc должен тактироваться от внешнего кварца. В таком случае Вам надо детально изучить раздел даташита "16.9 Asynchronous Operation of Timer/Counter2". Там есть описание того, как правильно войти в режим спячки. Причем обатить внимание на пункт, где говорится о повторном входе в режим спячки (If the time between wake-up and reentering sleep mode is less than one TOSC1 cycle, the interrupt will not occur, and the device will fail to wake up.) Далее еще замечания по коду. rjmp CHECK в конце TIM2COMPB - это куда? Я ожидал там увидеть reti ADC3: - это процедура прерывания. Поэтому все-таки желательно сохранять состояние рабочих регистров и SREG. А если выход из спящего режима у Вас осуществляется не только по прерыванию от АЦП, то это просто необходимо. Удалив в начале ADC3 инструкцию "cli" Вы сэкономите 2 байта в Program Memmory без ущерба для работы Вашего кода. P.S. Судя по ошибкам, Вы незнакомы с работой прерываний архитектуры AVR. Если кратко, то при входе в прерывание флаг I автоматически очищается. При выходе (инструкцией reti) - автоматически восстанавливается (естественно, в "1"). Поэтому нет нужды при входе/выходе из прерывания проделывать это все вручную. P.P.S Изложите, что Вы хотите от прибора (т.е требования к нему) и кратко расскажите, каким вы представляете себе его алгоритм работы. В частности, роль таймера2. А для поиска и анализа ошибок в коде лучше дополнительно прикрепите к сообщению полный исходный код. Р.P.P.S  Вопрос ко всем. Допустим, есть кусок кода Код cli nop nop nop ldi temp,(1<<SE)|(1<<SM0) оut SMCR,temp sei sleep Вопрос: Если прерывание от ацп возникнет после "nop", то выйдет ли контроллер из режима спячки для его обработки? Ведь после sei по-любому выполняется команда sleep и контроллер засыпает. В принципе, должен. А как на практике? никто не сталкивался?
|
|
|
|
|
Sep 24 2009, 21:49
|

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

|
Александр Огромное спаибо эа развёрнутый ответ. Наверное я очень сильно ужал код , решив оставить только относящееся к ADC Тогда по порядку: Цитата Здесь что-то не понятно. Что убрано за ненадобностью? Текст прерывания от таймера?? а что тогда приведено выше? Или убран запуск АЦП? Высказывайтесь, пожалуйста поконкретней. Таймер2 считает внешние 1Гц импульсы от DS1337 поэтому в теле программы используются прерывания и TIMCOMPA и TIMCOMPB , ну и несколько ещё. Вот первое (включён TWI) и убрано . Как Вы понимаете код длинный и в данном контексте не нужен. TIMCOMPB и запускает АЦП. Ну вроде сразу на два вопроса ответил. Цитата Прерывания всегда должны заканчиваться reti Так как я выхожу из прерывания отсчитав 256 циклов (FF), а ADC младшее по приоритету прерывание ( в моей программе и по DS AVR, ) хотя кончно есть приоритет ниже (TWI "прикрыл" таймером),но я повторюсь ,для моей программы , то только в старших я прописал запись всех регистров в стек Т.е АЦП запустится только тогда, когда все остальные "своё" отработают ( грубо , но надеюсь понятно). Поэтому , что RET , что RETI не имеют принципиальное значение , если всё равно SEI перед SLEEP перебросит ход программы на старшее прерывание. И чтобы не метаться в поиске "блох" при таких переходах, то пусть уж лучше знать, что из ADC возможен выход на старшее прерывание только перед SLEEP. И спасибо за науку- постораюсь оптимизировать программу так , чтобы убрать часть вложенных прерываний. Цитата Атмеловцы боятся, что MCU может сам войти в спячку, если ошибочно какую-то каманду воспримет как SLEEP Да ,и я прочёл это в DS , как рекомендацию Цитата ..and is not busy converting (а вот этой проверки нет) ( .. и не занят преобразованием ) а смысл проверять? Честно , пока не вижу  , но подумаю Цитата Далее еще замечания по коду. rjmp CHECK в конце TIM2COMPB - это куда? Я убирая лишнее ( температуру ,датчики, RS232...) просто основную программу заменил на цикл CHECK , хотя Вы правы , корректнее RETI P/S Ну и посыпаю голову пеплом т.к. в очередной раз проштудировав DS , я в двух местах, нашёл практически одну и ту же фразу
"В режиме одиночных преобразований запишите one в ADSC , оно автоматически сбросится только , если установлен режим ADC Noise Reduction или Idle mode"Цитата .P.P.S  Вопрос ко всем. Допустим, есть кусок кода Код cli nop nop nop ldi temp,(1<<SE)|(1<<SM0) оut SMCR,temp sei sleep Вопрос: Если прерывание от ацп возникнет после "nop", то выйдет ли контроллер из режима спячки для его обработки? Ведь после sei по-любому выполняется команда sleep и контроллер засыпает. В принципе, должен. А как на практике? никто не сталкивался? Завтра загоню 164 -посмотрю , что будет . В режиме одиночного или постоянного?
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
Sep 25 2009, 17:40
|
Местный
  
Группа: Свой
Сообщений: 256
Регистрация: 6-03-06
Из: Украина, г. Винница
Пользователь №: 15 017

|
Цитата Таймер2 считает внешние 1Гц импульсы от DS1337 Так, стоп. Вы меня уже совсем запутали. Где Вы нашли в таймере2 вход внешнего тактирования? Или Вы подаете их на ножку TOSC1?? Если так, то этого делать нельзя. И где Вы нашли фразу Цитата "В режиме одиночных преобразований запишите one в ADSC , оно автоматически сбросится только , если установлен режим ADC Noise Reduction или Idle mode" ? Приведите, пожалуйста, оригинальный вариант. С указанием номера страницы в ДШ. Желательно последней ревизии (на данный момент - rev.F: ATMega164P rev.F) Поиск по слову "ADSC" мне выдал 24 результата, но ни в одном из них ничего похожего не написано. Подозреваю, что это выдержка из какой-то книги, но никак из даташита. Насчет сохранения регистров в прерывании АЦП. Созранение можно не делать только в том случае, если запуск АЦП осуществляется ТОЛЬКО в Iddle/ADCNR-режиме и если выход из этого спящего режима может осуществится ТОЛЬКО по прерыванию/окончанию преобразования АЦП. Цитата В режиме одиночного или постоянного? В режиме постоянного преобразования нельзя загонять контроллер в спящий режим.
|
|
|
|
|
Oct 12 2009, 09:08
|

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

|
Извините , что долго не отвечал. Выкладываю полный код. Работает и как надо , но полный маразм. Толи Studio глючит , но если убрать строку в обработке прерывания ldi temp,(1<<ADEN)|(1<<ADIF)|(1<<ADPS2)|(1<<ADPS1)|(0<<ADPS0) sts ADCSRA,temp то флажок ADIF сбрасывается через раз, почему не понимаю. Даже и не знаю как объяснить,аппаратно , он обязан сброситься, но не сбрасывается.
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
Oct 14 2009, 15:03
|
Местный
  
Группа: Свой
Сообщений: 256
Регистрация: 6-03-06
Из: Украина, г. Винница
Пользователь №: 15 017

|
Исправлюсь по поводу своего высказывания: Цитата Так, стоп. Вы меня уже совсем запутали. Где Вы нашли в таймере2 вход внешнего тактирования? Или Вы подаете их на ножку TOSC1?? Если так, то этого делать нельзя. Использовать таймер 2 в асинхронном режиме для счета секундных импульсов если и правильно, то уж точно не целесообразно. Вообще он предназначался для работы от кварца или от внешего генератора частотой 32768. Работа этого таймера в асинхронном режиме требует от программиста мер по синхронизации асинхронной логики таймера2 с ядром контроллера, особенно перед входом в спящий режим. А на это нужно не менее 2х тактов таймера 2 (в Вашем случае - 2 сек). Подробнее - в даташите в разделе 17.9 Asynchronous Operation of the Timer/Counter2, стр.128. У Вас убран вектор прерываний по Int1, но сами прерывания вы не запретили. Поэтому возможны ложные вызовы следующего после Int1 вектора прерывания - TIM2COMPA При вычислении среднего Вы используете 255 отсчетов, а сумму делите на 256 В прерывании TIM2COMPA у Вас будет переполнение стека при ошибках передачи по TWI Вы не дожидаетесь завершения формирования условия СТОП на шине TWI перед стартом ДЛя чего у Вас используется АЦП? На него подвешаны кнопки? Если да, зачем использовать ADC noise canceler ? При 8 кнопках "расстояние" между ними составляет в идеальном случае 32 LSB при 8-битном преобразовании. Этого более чем достаточно и без режима уменьшения шума. В крайнем случае, с шумом справится и внешний конденсатор. Покажите схему, по которой у Вас подключены кнопки. С указанием номиналов компонентов. Как часто вы опрашиваете кнопки? судя по программе, 1 раз в минуту. Это так и задумывалось или я чего-то пропустил в коде? Таймер2 у Вас считает внешние импульсы от DS1337 с интервалом 1 секунда. Период переполнения таймера2 - 60 секунд.(OCR2A). На каждой 2-й секунде у вас запускается опрос кнопок (OCR2A = 1). P.S. Подход, который Вы избрали для написания программы, в корне неверный. Может в Вашем конкретном случае он приемлимый, но лучше сразу писать правильно. Прерывания обычно используются для того, чтобы по-быстрому отвлечься от текущей задачи, быстренько сделать самое необходимое (принять и буферизировать данные, выстивить флаги, подсчитать имульсы и т.п)и выйти. А обработку данных,которая требует значительно времени, уже делать в основном цикле. Извините, может я и слишком резко выразился, но я бы нокогда не делал прием/передачу данных по медленному интерфесу I2C в прерывании. То же касется и 256 преобразований АЦП. Если есть желание зделать устройство работоспособным, стучитесь в личку. Или лучше на аську - 275-707-581. Только при обращении укажите, что Вы с этого форума, а то забаню  . Помогу, чем смогу. Но для этого нужно сначала сформулировать задачу, которая стоит перед микроконтроллером в целом.
|
|
|
|
|
Oct 14 2009, 22:49
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(Александр Куличок @ Oct 14 2009, 18:03)  Подход, который Вы избрали для написания программы, в корне неверный. Может в Вашем конкретном случае он приемлимый, но лучше сразу писать правильно. Зато стиль хороший. Написано качественно, хорошо структурировано, аккуратно, читаемо и понимаемо. Уверен с таким стилем автору не составит труда самому изменить пару строк чтобы получить верный подход, а пока можно порассуждать почему же не всегда сбрасывается ADIF. Цитата то флажок ADIF сбрасывается через раз, почему не понимаю. Даже и не знаю как объяснить,аппаратно , он обязан сброситься, но не сбрасывается. А в железе как? тоже не сбрасывается?
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|