реклама на сайте
подробности

 
 
> Запись в EEPROM, не работает пример из даташита
smk
сообщение Jan 11 2008, 18:06
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



ATtiny24

Имеется код:
void EEPROM_write(unsigned char Address, unsigned char Data)
{
while (EECR & (1<<EEPE));
EECR = (0<<EEPM1) | (0>>EEPM0)
->EEARH=0b00000000;
EEARL= Address;
EEDR = Data;
EECR |= (1<<EEMPE);
EECR |= (1<<EEPE);
}

Имеется сообщение об ошибке:
../1.c: In function 'EEPROM_write':
../1.c:23: error: called object '0' is not a function

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

Пример 'один в один'. Написано в WinAVR 2007, симулятор AVR Studio 4.13

Помогите разобраться в чем причина? Заранее благодарен!

Кстати нижеприведенный код проблем не вызывает:
unsigned char EEPROM_read (unsigned char Address)
{
while (EECR & (1<<EEPE));
EEARL= Address;
EECR |= (1<<EERE);
return EEDR;
}

Сообщение отредактировал smk - Jan 11 2008, 18:18


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 21)
Сергей Борщ
сообщение Jan 11 2008, 18:20
Сообщение #2


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(smk @ Jan 11 2008, 20:06) *
если строчку закомментировать, то указатель покажет на ту что под ней, ошибка та же.
Вы забыли точку с запятой в конце предыдущей строки поставить.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
smk
сообщение Jan 11 2008, 18:25
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Цитата
Вы забыли точку с запятой в конце предыдущей строки поставить.

Точно! Благодарю за совет, очень признателен , простите что отвлек по такой простой причине.


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
smk
сообщение Jan 11 2008, 20:48
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Теперь другая непонятная штука. Не выполняется оператор i++; Он просто пропускается симулятором. Почему?

unsigned char i;
while (i<240)
{
while(TIFR1 & (1<<TOV1))
{
TCNT1H = 0xF8;
TCNT1L = 0x5F;
i++;
PORTA^=0b00000100;
TIFR1 |= (1<<TOV1);
}
}

Буду благодарен за подсказку.

Сообщение отредактировал smk - Jan 11 2008, 20:49


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
Stanislav
сообщение Jan 11 2008, 21:29
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 4 363
Регистрация: 13-05-05
Из: Москва
Пользователь №: 4 987



Цитата(smk @ Jan 11 2008, 23:48) *
Теперь другая непонятная штука. Не выполняется оператор i++; Он просто пропускается симулятором. Почему?

unsigned char i;
while (i<240)
{
while(TIFR1 & (1<<TOV1))
{
TCNT1H = 0xF8;
TCNT1L = 0x5F;
i++;
PORTA^=0b00000100;
TIFR1 |= (1<<TOV1);
}
}

Буду благодарен за подсказку.

Э-э, а чему равно начальное значение i ?

PS. Пропускаться может по такой причине: переменная i у Вас во внутреннем цикле явно не используется, поэтому она была "оптимизирована" компилятором.

Не разобрался, сперва для чего нужно i. Для того, чтобы не оптимизилось, операцию нужно сделать volatile.


--------------------
Самонадеянность слепа. Сомнения - спутник разума. (с)
Go to the top of the page
 
+Quote Post
smk
сообщение Jan 11 2008, 21:34
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Цитата
чему равно начальное значение i ?

равно 0.

применил volatile - проблема снялась. странно почему заоптимизировал....


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
Stanislav
сообщение Jan 11 2008, 21:46
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 4 363
Регистрация: 13-05-05
Из: Москва
Пользователь №: 4 987



Цитата(smk @ Jan 12 2008, 00:34) *
равно 0.
Вообще-то, инициализировать нужно обязательно, если это не глобальная переменная.
Цитата(smk @ Jan 12 2008, 00:34) *
применил volatile - проблема снялась. странно почему заоптимизировал....
Точно.
Видимо, оптимизатор за рамки вложенного цикла вылезти не может. Впрочем, здесь я не спец; возможно, старшие товарищи разъяснят. smile.gif

PS. Кстати, лажа у Вас, по-моему, написана...


--------------------
Самонадеянность слепа. Сомнения - спутник разума. (с)
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jan 11 2008, 22:07
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(smk @ Jan 11 2008, 23:34) *
применил volatile - проблема снялась.

Главная проблема не снялась - написан мягко говоря непонятный код. Не понятный ни человеку ни тем более компилятору.
1. Даже если переменная i глобальная, то обнулена она будет только при первом проходе.
2. i бесконтрольно и независимо увеличивается во внутреннем цикле. Чем ограничено количество внутренних циклов? 1 - 100 - миллион? Что будет с i при, например, 256 циклах - Вам ведомо?
3. Вы хоть сами сможете словами обьяснить для чего пляски с бубном вокруг i ?
4. Остальное выглядит еще хуже sad.gif
5. Если после всего этого несчастному симулятору снесет крышу, я не решусь его упрекнуть.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Gogan
сообщение Jan 12 2008, 06:06
Сообщение #9


Частый гость
**

Группа: Участник
Сообщений: 83
Регистрация: 25-10-07
Из: Киев
Пользователь №: 31 728



Цитата(smk @ Jan 11 2008, 22:48) *
while(TIFR1 & (1<<TOV1))

я бы это заменил на if, так как при первом же проходе устанавливается регистр так, чтобы след. раз условие не выполнялось... и наглядней.
Хотя не понятно зачем считывать флаг прерываний вместо того, чтобы использовать само прерывание.
Можно либо разрешить прерывание по переполнению и в нем выполнять
TCNT1H = 0xF8;
TCNT1L = 0x5F;
i++;
PORTA^=0b00000100;
где i должна быть глобальной
либо запустить режим сброса таймера по сравнению (CTC mode), чтобы он считал от 0 до сравнения (например до OCR1A=0xFFFF - 0xF85F=0x7A0), затем в прерывании по сравнению делать тоже кроме обновления счетчика.

Сообщение отредактировал Gogan - Jan 12 2008, 06:07
Go to the top of the page
 
+Quote Post
smk
сообщение Jan 12 2008, 08:23
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Цитата
1. Даже если переменная i глобальная, то обнулена она будет только при первом проходе.

да, она глобальная. пользую везде где нужен счетчик.

Цитата
2. i бесконтрольно и независимо увеличивается во внутреннем цикле. Чем ограничено количество внутренних циклов? 1 - 100 - миллион? Что будет с i при, например, 256 циклах - Вам ведомо?

Программа жздет появление флага переполнения таймера,
while(TIFR1 & (1<<TOV1))
выполняет предустановку
{
выполняет предустановку
TCNT1H = 0xF8;
TCNT1L = 0x5F;
наращивает счетчик
i++;
делает что-то полезное
PORTA^=0b00000100;
сбрасывает флаг
TIFR1 |= (1<<TOV1);
}
и так до очередного выброса флага...

когда i=240 - программа выходит из внешнего цикла. прерывания не использовал т.к. нет нужды делать чего-то во время ожидания.
Цитата
запустить режим сброса таймера по сравнению (CTC mode)

так и есть, режим СТС.

ну мне так видится, а как бы вы написали? я учусь и мне юудет интересно посмотреть на иные решения. Заранее спасибо.

Цитата
4. Остальное выглядит еще хуже

все может быть... а как правильнее?

Цитата
3. Вы хоть сами сможете словами обьяснить для чего пляски с бубном вокруг i ?

попробую... суть в том, что мне нужно отмерять промежутки времени, кратные 1 с, сигнализируя об их течении мигающим светодиодом или выполняя какие-либо действия в иные промежутки:
промежуток 1 - действие 1;
промежуток 2 - действие 2;
.
.
.
промежуток N - действие N.


а так лучше?

while((TIFR1 & (1<<TOV1))&(i<240))
{
TCNT1H = 0xF8;
TCNT1L = 0x5F;
i++;
PORTA^=0b00000100;
TIFR1 |= (1<<TOV1);
}

Сообщение отредактировал smk - Jan 12 2008, 07:52


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
Gogan
сообщение Jan 12 2008, 09:58
Сообщение #11


Частый гость
**

Группа: Участник
Сообщений: 83
Регистрация: 25-10-07
Из: Киев
Пользователь №: 31 728



Цитата(smk @ Jan 12 2008, 10:23) *
а так лучше?

while((TIFR1 & (1<<TOV1))&(i<240))

Тут ошибка, нужно while((TIFR1 & (1<<TOV1))&&(i<240)) (второе И логическое а не побитное)
Вобщем, если ничего более выполнять не нужно, либо оно выполняется в других прерываниях, тогда ваш вариант решения сойдет, да и проще чем через прерывания.

Сообщение отредактировал Gogan - Jan 12 2008, 09:58
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 12 2008, 10:13
Сообщение #12


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(smk @ Jan 12 2008, 10:23) *
да, она глобальная. пользую везде где нужен счетчик.
И очень напрасно. Если бы вы заводили ее каждый раз локально, компилятор мог бы, во-первых, разместить ее в регистре (что очень хорошо как для скорости, так и для размера) и, во-вторых, не сохранять ее значение после окончания цикла (оно ведь вам не нужно).

По циклу - лучше переменную увеличивать прямо в месте проверки или сразу перед ним - тогда компилятор сможет для проверки воспользоваться флагами, остающимися от операции инкремента. Еще с точки зрения эффективности лучше инициализировать i числом и потом уменьшать, проверяя на ноль.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jan 12 2008, 10:42
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Это BLINKS раз моргнет светодиодиком используя опрос флага переполнения таймера.
Код
#define BLINKS 120
#define BIT_MY_LED (1<<2)
#define T1_DIV 0xF85F

for( uint_least8_t  i = (BLINKS)<<1;; )
{
    if( TIFR1 & (1<<TOV1) ) )
   {    TCNT1H = (unsigned char)((T1_DIV)>>8);
         TCNT1L = (unsigned char)T1_DIV;
         PORTA ^= BIT_MY_LED;
         TIFR1 |= (1<<TOV1); // Уверены, что сбрасывается '1' а не нулем?
         if( !--i )
              break;
    }
}


Если честно, то я из тестового описания не уверен, что понял. Проблема Вашего описаня в том, что Вы задачу так ине сформулировали. Задача, например, - выкопать канаву. Вместо этого Вы попыталтсь рассказать как Вы держите лопату и как далеко кидаете землю и прочее.... Понято, что что-то хотите выкопать, но что уже не совсем понятно sad.gif


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
smk
сообщение Jan 12 2008, 14:26
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Цитата
Задача, например, - выкопать канаву

Задача держать включенным некий прибор в течение определенного времени (например 1 мин), мигая при этом светодиодом. Далее проверяем условие и решаем что делать дальше в зависимости от результата.


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jan 12 2008, 15:14
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(smk @ Jan 12 2008, 16:26) *
Задача ...

Тогда приведенное выше где-то как-то может послужить мигалкой.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
smk
сообщение Jan 12 2008, 15:44
Сообщение #16


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Строчка:
for( uint_least8_t i = (BLINKS)<<1;; )
привела вот к такому сообщению:
../1.c:157: error: 'for' loop initial declaration used outside C99 mode

а вообще не уверен что аналог...


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jan 12 2008, 15:58
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(smk @ Jan 12 2008, 17:44) *
../1.c:157: error: 'for' loop initial declaration used outside C99 mode

Переключите компилятор в режим следования свежему 1999 года стандарту языка "C".
Если вдруг найдутся неведомые мне причины не использовать современные компиляторы, то тогда
так:
Код
{
   uint_least8_t  i = (BLINKS)<<1;
   for(;; )
   {
......
   }
}


Цитата
а вообще не уверен что аналог...

Договаривайте.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
smk
сообщение Jan 12 2008, 17:21
Сообщение #18


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Цитата
Переключите компилятор в режим следования свежему 1999 года стандарту языка "C".


не могу разобраться как... пробовал в makefile, но не дает. в makefile из директории WinAVR установлен режим gnu99. а есть ли возможность из AVR Studio изменить этот режим?

gnu99
gnu9x The 1999 C standard plus GNU extensions.

вот такое сейчас включено. если я не ошибаюсь, по умолчанию всегда так у WinAVR.


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jan 12 2008, 17:23
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(smk @ Jan 12 2008, 18:57) *
но не дает....

Что такое "не дает" мне не ведомо, но найдите, где можно добавить ключи для командной строки относящиеся ко всему проекту и допишите туда:
-std=c99
или
-std=gnu99



Цитата(smk @ Jan 12 2008, 19:21) *
если я не ошибаюсь, по умолчанию всегда так у WinAVR.

без понятия, разнообразными IDE не пользуюсь в принципе.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
smk
сообщение Jan 12 2008, 18:21
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



попробовал - решение действительно хорошее и код стал меньше.


А чем i = (BLINKS<<1); лучше i=240?


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jan 12 2008, 18:25
Сообщение #21


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(smk @ Jan 12 2008, 20:21) *
А чем i = (BLINKS<<1); лучше i=240?

240 это какое-то число, а BLINKS это осмысленное количество морганий. На код, естественно, совершенно не повлияет, но ошибиться задав нечтное число - нельзя, читать и потом сопровождать - удобнее.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
smk
сообщение Jan 12 2008, 18:56
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Цитата
BLINKS это осмысленное количество морганий

Спасибо за идею!
тогда уже i = (BLINKS<<2); - длительность включения нагрузки в секундах. это точно лучше. А количество морганий - главное чтоб не нудно мограло, а живенько более-менее.


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 10:09
Рейтинг@Mail.ru


Страница сгенерированна за 0.01588 секунд с 7
ELECTRONIX ©2004-2016