Обсуждаем контроллеры компании Atmel.
Ответить

atmega8 гонит ADC или я косячу?

Пн мар 26, 2012 06:55:45

Здравствуйте!

Код:

ADMUX = (1<<REFS0|1<<REFS1|0<<ADLAR);//настройка АЦП
while(1)
{
int n = 0;
int n1 = 0;

//вырезано все лишнее
        ADMUX = (0<<MUX0|0<<MUX1|0<<MUX2|0<<MUX3);//выбор канала АЦП
   ADCSRA = (1<<ADEN|1<<ADSC|1<<ADPS0|1<<ADPS1|1<<ADPS2);//Запуск АЦП, выбор скорости = 1\128 от скорости проца
       
       _delay_ms(1000);            /*задержка 1 секунда*/
   n = ADCH;
        n1 = ADCL;
//тут еще 10 строк кода, которые все это показывают на LCD дисплейчик
}


Протеус при симуляции делает 1 выборку, потом начинает сыпать ошибками

"result is not written to the ADC register because it has been locked"

Что я делаю не правильно? что может лочить бит АЦП?

Re: atmega8 гонит ADC или я косячу?

Пн мар 26, 2012 07:28:14

||
И сначала нужно читать младший, и только потом старший байт преобразования.

Re: atmega8 гонит ADC или я косячу?

Пн мар 26, 2012 08:04:02

О! после чтения сначала ADCL, а потом ADCH стало все ок, а вот если | заменить на || все работать перестало...
Спасибо!

Re: atmega8 гонит ADC или я косячу?

Пн мар 26, 2012 09:25:47

Все верно, поторопился с ||. Это же логическое. :oops:

Re: atmega8 гонит ADC или я косячу?

Ср мар 28, 2012 07:23:20

Код:
return ADC;

И без всяких старших-младших. На сях же пишите :facepalm: Вот только если прерывания что-то ещё делают в АЦП - надо предвидеть. Да и в вашем случае тоже надо это предвидеть.

UPD:
Код:
_delay_ms(1000);
А вот это тот ещё костыль. Как бы лучше сделать вот так:
Код:
while( ! (ADCSRA&(1<<ADIF)) ) asm("nop");
ADCSRA |= (1<<ADIF);
Последняя строка сбрасывает бит, не смотря на то, что он установлен в 1.

Re: atmega8 гонит ADC или я косячу?

Ср мар 28, 2012 07:55:15

hybroid писал(а):
Код:
return ADC;

И без всяких старших-младших. На сях же пишите :facepalm: Вот только если прерывания что-то ещё делают в АЦП - надо предвидеть. Да и в вашем случае тоже надо это предвидеть.

UPD:
Код:
_delay_ms(1000);
А вот это тот ещё костыль. Как бы лучше сделать вот так:
Код:
while( ! (ADCSRA&(1<<ADIF)) ) asm("nop");
ADCSRA |= (1<<ADIF);
Последняя строка сбрасывает бит, не смотря на то, что он установлен в 1.


1) мне младший байт вообще не нужен, потому по половинкам....
2) это не костыль это сознательная пауза, она там нужная - проц слишком быстрый...
3) прерывания не нужны, иначе конечно
Если бы хотелось быстродействия, то естественно считывал бы АЦП в прерывании, а так тут всей программы на 5 экранов - надо считать поочередно 3 каналов ацп, и вывести на ЖКИ что у нас с вольтажом у ветряка, солнечной батарейки, SAL и ориентировочное время жизни\зарадки, а когда батарейка полная потянуть за релюху и посадить ветряк на грелку, а солнечную батарейку просто в воздух повесить.

Re: atmega8 гонит ADC или я косячу?

Ср мар 28, 2012 08:01:32

Ну и на хрена цитировать простыню сразу после поста? Есть кнопка "ответить".

Пауза должна быть паузой. А это - костыль ожидания конца преобразования. Вот это делается так, как я написал, а не паузой. Почему - поймёте, когда половите глюки из-за вашей "паузы".
Qwq писал(а):1) мне младший байт вообще не нужен, потому по половинкам....
Когда младший не нужен, то считывают только старший, а не по половинкам.
Qwq писал(а):проц слишком быстрый...
Впервые слышу такое про АВРки :))

Re: atmega8 гонит ADC или я косячу?

Ср мар 28, 2012 08:02:03

hybroid писал(а):Как бы лучше сделать вот так:
Код:
while( ! (ADCSRA&(1<<ADIF)) ) asm("nop");
ADCSRA |= (1<<ADIF);
Последняя строка сбрасывает бит, не смотря на то, что он установлен в 1.

Как бы лучше сделать вот так:
Код:
while( ADCSRA & _BV(ADSC) );
проще однако

Re: atmega8 гонит ADC или я косячу?

Ср мар 28, 2012 08:06:21

_BV() привязывает жёстко к AVR-GCC, который не является единственным компилатором для АВР. Даже по числу вводимых символов с клавиатуры - один хрен :)) И вообще вы, уважаемый, забыли "!" поставить в условии while, от чего ваш "проще" превратился в полную фигню.

Без nop'а соглашусь, проще, но кому-то нагляднее с ним. К тому же, результат будет один и тот же.

Re: atmega8 гонит ADC или я косячу?

Ср мар 28, 2012 08:07:51

Раз уж пошло ковырятельство, то поучаствую тоже.
Код:
int n = 0;
int n1 = 0;
.
.
.
   n = ADCH;
        n1 = ADCL;

Нафига?

Re: atmega8 гонит ADC или я косячу?

Ср мар 28, 2012 08:09:32

pyzhman писал(а):Нафига?
До сих пор выясняем :)

Re: atmega8 гонит ADC или я косячу?

Ср мар 28, 2012 08:11:13

О, да тут двойной прикол:
1. Использование типа int для байтовой величины.
2. Обнуление перед чтением.
:o

Re: atmega8 гонит ADC или я косячу?

Ср мар 28, 2012 08:15:57

signed int, а не unsigned int. Так что прикол скорее всего тройной. Обнуление перед чтением часто можно увидеть. Как будто переменная объявляется через рандом-генератор :)

Re: atmega8 гонит ADC или я косячу?

Ср мар 28, 2012 08:18:17

hybroid писал(а): И вообще вы, уважаемый, забыли "!" поставить в условии while, от чего ваш "проще" превратился в полную фигню.
Вы ошибаетесь. Мастер Ломастер проверяет другой флаг. ADSC сбрасывается по окончании преобразования.

Re: atmega8 гонит ADC или я косячу?

Ср мар 28, 2012 08:23:00

hybroid писал(а):_BV() привязывает жёстко к AVR-GCC, который не является единственным компилатором для АВР. Даже по числу вводимых символов с клавиатуры - один хрен :)) И вообще вы, уважаемый, забыли "!" поставить в условии while, от чего ваш "проще" превратился в полную фигню.

Без nop'а соглашусь, проще, но кому-то нагляднее с ним. К тому же, результат будет один и тот же.

извините, но по всем пунктам не соглашусь.
1. _BV() - это всего лишь макрос, который при переносе на другой компилятор определяется в 5 секунд, и не может служить препятствием дл применения. ну а раз уж тут рассматривается код WinAVR, то почему бы не использовать все, что в нем имеется и так?
2. про ! уже ответили
3. про nop - один и тот же результат У ВАС мог получаться только из-за того, что вы допустил ошибку. в вашем случае правильно нужно писать while(...) asm volatile ("nop"); без volatile оптимизатор все NOP-ы убирает, как ненужные, и тогда получается совершенно одинаковый ассемблерный код с while(...); если сделать ПРАВИЛЬНО - код получится РАЗНЫЙ.

Re: atmega8 гонит ADC или я косячу?

Ср мар 28, 2012 08:34:30

Чорт, точно. Ну тогда дико извиняюсь, попутал я :))

Re: atmega8 гонит ADC или я косячу?

Ср мар 28, 2012 10:14:32

Мастер Ломастер писал(а):3. про nop - один и тот же результат У ВАС мог получаться только из-за того, что вы допустил ошибку. в вашем случае правильно нужно писать while(...) asm volatile ("nop"); без volatile оптимизатор все NOP-ы убирает, как ненужные, и тогда получается совершенно одинаковый ассемблерный код с while(...); если сделать ПРАВИЛЬНО - код получится РАЗНЫЙ.
Заинтересовало. Попробовал несколько различных вариантов, без volatile. При оптимизации -Os ничего не выкинуло. Какие дополнительные условия необходимы для вашего результата?

Re: atmega8 гонит ADC или я косячу?

Ср мар 28, 2012 10:18:21

Версии GCC может. Я вот даже и не в курсе какая у меня. Та, которая в репозитории Debian testing лежит :) У меня вроде тоже ничего не выкидывает. Сейчас полезу проверять.

UPD: в рот мне ноги! Действительно, без "nop" меньше на 4 байта. Но и без volatile nop'ы стоят на месте, никто их не выкидывает. -Os есть. gcc version 4.5.3 (GCC)

Re: atmega8 гонит ADC или я косячу?

Ср мар 28, 2012 10:36:25

чтобы не ломать голову по поводу версии, надо в НУЖНЫХ случаях писать volatile для NOP-ов, а в ненужных - просто их не ставить. в принципе, это и есть правильный подход, когда сам делаешь то, чего хочешь, не надеясь на версии компилятора.

что касается выкидывает или нет - о необходимости volatile перед нопами не раз писалось на форумах, и это реально работает/работало. с определенного момента я перестал заботиться о версиях, стараясь следовать стандарту Си.

P.S. однако, с AVR-GCC надо все-таки держать ухо востро! пришлось пересесть на версию 4.7 после того, как при наличии static перед одной функцией генерировался полностью нерабочий код из-за того, что в main убирался целый кусок совершенно не связанного с этой функцией кода! это был единственный случай, когда версия 20100110 меня подвела, и так сильно!

Re: atmega8 гонит ADC или я косячу?

Ср мар 28, 2012 11:18:47

Я уже совсем запутался, как отличить "НУЖНЫЙ" nop от ненужных? и зачем вообще вводить "ненужный" nop в свою программу?
Ответить