Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: WDTimer
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
qulik
Доброго вечера!
Заметил такую особенность: при "небольшом" загрязнении между контактами TX и RX (видимо электрический контакт появился), функция gets() безнадежно зависла. Подумал, что хорошо бы запустить перед началом gets() сторожевой таймер, который сбросит контроллер в случае зависания, мало ли чего. WDT запустил путем записи в его регистр сначала комбинации битов, разрешающих изменение режима WDT, а потом записал нужное значение. Через положеные 8 секунд произошол сброс контроллера. Попробовал остановить WDT путем записи в его регистр 0x00. Но эффекта не последовало, произошел сброс... Что делать?!?
Xenia
Цитата(qulik @ Jun 19 2009, 02:15) *
WDT запустил путем записи в его регистр сначала комбинации битов, разрешающих изменение режима WDT, а потом записал нужное значение. Через положеные 8 секунд произошол сброс контроллера. Попробовал остановить WDT путем записи в его регистр 0x00. Но эффекта не последовало, произошел сброс... Что делать?!?


А вы пытались останавить его тоже комбинацией или простой записью?
Может быть так попробовать:

WDTCSR |= (1<<WDCE);
WDTCSR = 0;

или так:

WDTCSR |= (1<<WDCE) | (1<<WDE);
WDTCSR = 0;

Только не забудьте прерывания блокировать на время исполнения этих двух строк.
Ну в крайнем случае так:

cli();
wdt_reset();
MCUSR &= ~(1<<WDRF);
WDTCSR |= (1<<WDCE) | (1<<WDE);
WDTCSR = 0;
sei();

Ну тут уж кажется всё предусмотрено с запасом...
Qwertty
Цитата(qulik @ Jun 19 2009, 02:15) *
Доброго вечера!
Подумал, что хорошо бы запустить перед началом gets() сторожевой таймер, который сбросит контроллер в случае зависания, мало ли чего.

Вы бы лучше подумали - а нужна ли такая "полезная" функция. Которая видимо тупо ждет прихода чего бы то ни было в UDR. Используйте нормальный драйвер работающий по прерываниям.
qulik
Цитата(Xenia @ Jun 19 2009, 02:28) *
А вы пытались останавить его тоже комбинацией или простой записью?
Может быть так попробовать:

WDTCSR |= (1<<WDCE);
WDTCSR = 0;

или так:

WDTCSR |= (1<<WDCE) | (1<<WDE);
WDTCSR = 0;


Так пробовал, непомогло.

А вот следующий вариант выглядит убедительно! Что-то я припоменаю про MCUSR при сбросе бита WDE... smile.gif Пойду попробую!


Цитата(Qwertty @ Jun 19 2009, 04:41) *
Вы бы лучше подумали - а нужна ли такая "полезная" функция. Которая видимо тупо ждет прихода чего бы то ни было в UDR. Используйте нормальный драйвер работающий по прерываниям.


Ну дак у меня gets() и находится в блоке обработки прерывания, вызываемого при приеме очередного символа по USART!

INTERRUPT (SIG_USART_RCV)
{
gets();
}...

Или вы имеете ввиду посимвольно считывать строку???
singlskv
Цитата(Xenia @ Jun 19 2009, 02:28) *
А вы пытались останавить его тоже комбинацией или простой записью?
Может быть так попробовать:

WDTCSR |= (1<<WDCE);
WDTCSR = 0;

или так:

WDTCSR |= (1<<WDCE) | (1<<WDE);
WDTCSR = 0;

Только не забудьте прерывания блокировать на время исполнения этих двух строк.
Ну в крайнем случае так:

cli();
wdt_reset();
MCUSR &= ~(1<<WDRF);
WDTCSR |= (1<<WDCE) | (1<<WDE);
WDTCSR = 0;
sei();

Ну тут уж кажется всё предусмотрено с запасом...

Даже не знаю где здесь указывать на "неправильности"... поэтому текст не сокращаю,
ВСЕ показанные варианты не применимы.... тк принципиально зависят от уровня оптимизации компилятора...
Ну нельзя пользовать |= в ситуации наличии 4 тактов для операции и все тут... ну повторим это в 125раз...
qulik
Цитата(singlskv @ Jun 20 2009, 01:20) *
Ну нельзя пользовать |= в ситуации наличии 4 тактов для операции и все тут... ну повторим это в 125раз...


Ой! А как же тогда быть? Использовать простое приравнивание REGISTOR=0x05?
Xenia
Цитата(singlskv @ Jun 20 2009, 01:20) *
ВСЕ показанные варианты не применимы.... тк принципиально зависят от уровня оптимизации компилятора...
Ну нельзя пользовать |= в ситуации наличии 4 тактов для операции и все тут... ну повторим это в 125раз...


Вот, пожалуйста, результат компиляции на IAR EWAVR:

Код
WDTCR |= (1<<WDCE) | (1<<WDE);
00000000   B501               IN      R16, 0x21
00000002   6108               ORI     R16, 0x18
00000004   BD01               OUT     0x21, R16

WDTCR = 0;
00000006   E000               LDI     R16, 0
00000008   BD01               OUT     0x21, R16


- между записями в регистр WDTCR только одна лишняя команда. Итого всего 2 такта между операциями записи.
А про оптимизацию вы не совсем правы, когда речь идет о записи в регистры, то компилятор (IAR) никогда не опускает присваивание, даже если оно повторное. И это при любом типе оптимизации - как по размеру, так и по скорости.
Однако не забывайте название темы - сказано, что WatchDog запустить удалось. А, значит, компиляция велась в условиях, когда требование 4-х тактов соблюдалось. Поэтому это условие я не стала особо оговаривать.
singlskv
Цитата(Xenia @ Jun 20 2009, 02:00) *
- между записями в регистр WDTCR только одна лишняя команда. Итого всего 2 такта между операциями записи.
Один раз повезло другой нет...
так и рождаются легенды...



Цитата(qulik @ Jun 20 2009, 01:58) *
Ой! А как же тогда быть? Использовать простое приравнивание REGISTOR=0x05?
Лучше всего заготовьте ВСЕ константы заранее а потом их присваивайте регистрам...



Цитата(Xenia @ Jun 20 2009, 02:00) *
А про оптимизацию вы не совсем правы, когда речь идет о записи в регистры, то компилятор (IAR) никогда не опускает присваивание, даже если оно повторное. И это при любом типе оптимизации - как по размеру, та и по скорости.
я как раз и не забываю, и volatile у Вашего регистра как раз и заставляет делать много(иногда >4) операций
Xenia
Цитата(singlskv @ Jun 20 2009, 02:09) *
Один раз повезло другой нет...
так и рождаются легенды...


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

Цитата(singlskv @ Jun 20 2009, 02:09) *
Лучше всего заготовьте ВСЕ константы заранее а потом их присваивайте регистрам...


Константы невозможно "приготовить заранее". Если вы намереваетесь поместить их в память, то вытаскивание оттуда обойдется дороже - тогда действительно в 4 такта можно не уложиться. А если положить в регистр, то примерно так оно и получится.

P.S. Мой предыдущий пост, адресованный вам, был мною отредактирован. Ознакомьтесь с ним пожалуйста еще разик.
qulik
А что меняет выбор варианта оптимизации? В AVR Studio есть варианты: О0 - Оs. Поисковик ничего не выдал.

Спасибо! Замечание с константами я учту на будущее.
singlskv
Цитата(Xenia @ Jun 20 2009, 02:14) *
Константы невозможно "приготовить заранее". Если вы намереваетесь поместить их в память, то вытаскивание оттуда обойдется дороже - тогда действительно в 4 такта можно не уложиться. А если положить в регистр, то так оно и получится.
Я Вам и предлагаю положить их(константы) во временные регистры...
Цитата
P.S. Мой предыдущий пост, адресованный вам, был мною отредактирован. Ознакомьтесь с ним пожалуйста еще разик.
Вы очень настойчивая девушка... , хотя наверное это и не плохо... но очень торопитесь...
не спешите в своих суждениях... smile.gif
Xenia
Цитата(singlskv @ Jun 20 2009, 02:21) *
Вы очень настойчивая девушка... , хотя наверное это и не плохо... но очень торопитесь...
не спешите в своих суждениях...


Докажите обратное! Приведите результат компиляции этих двух сишных строк, чтобы компилятор допустил больше одной промежуточной инструкции между записями в регистр WDTCR. Условия оптимизации можете выбирать любые.
singlskv
Цитата(qulik @ Jun 20 2009, 02:18) *
А что меняет выбор варианта оптимизации? В AVR Studio есть варианты: О0 - Оs. Поисковик ничего не выдал.
Все меняет, если хотите работу на С для таких вариантов(4такта на все) то только -Os или -O2 рулит..
Цитата
Спасибо! Замечание с константами я учту на будущее.
Ну и подготовленные заранее константы рулят всегда...



Цитата(Xenia @ Jun 20 2009, 02:28) *
Докажите обратное! Приведите результат компиляции этих двух сишных строк, чтобы компилятор допустил больше одной промежуточной инструкции между записями в регистр WDTCR. Условия оптимизации можете выбирать любые.
Ксения, я Вам позволю самой воспользоваться поиском, особенно по теме записи в EEPROM, и там Вы найдете
ВСЕ ответы, в том числе и мои...
Xenia
Цитата(qulik @ Jun 20 2009, 02:18) *
Спасибо! Замечание с константами я учту на будущее.


В данном случае варианты компиляции выражения
WDTCR |= (1<<WDCE) | (1<<WDE);
несущественны, поскольку запись в регистр WDTCR всегда будет ПОСЛЕДНЕЙ инструкцией. А, стало быть, протяжка перед следующей строкой
WDTCR = 0;
зависит исключительно от сложности обнуления регистра. Дольше двух тактов это не затянется при любых способах оптимизации или отсутствия оной.
singlskv
Цитата(Xenia @ Jun 20 2009, 02:36) *
Дольше двух тактов это не затянется при любых способах оптимизации или отсутствия оной.
Давайте Вы уже избавитесь от илюзий и попробуете это сделать совсем без оптимизации..
Qwertty
Цитата(qulik @ Jun 20 2009, 01:13) *
Ну дак у меня gets() и находится в блоке обработки прерывания, вызываемого при приеме очередного символа по USART!

INTERRUPT (SIG_USART_RCV)
{
gets();
}...

Или вы имеете ввиду посимвольно считывать строку???

Именно посимвольно. Данные пришли - только тогда читаем. Ничего не ждем. Ваш же метод - просто ужас. Если строка не придет, а это НОРМАЛЬНАЯ ситуация при работе в реальных условиях, а не у Вас на столе, то контроллер просто повиснет. Предусматривать выход из нормальной ситуаци через сброс по собаке не надо. Плохо это и неправильно. smile.gif И еще момент - Вы представляете время выполнения этой функции? К примеру при 9600бод и строке символов в 30? А она у Вас внутри обработчика - значит на это время все другие события(прерывания) будут отброшены.
Вот - почитайте - http://ru.wikipedia.org/wiki/Gets
Цитата
Применение gets весьма осуждается. Функция оставлена в стандартах C89 и C99 для обратной совместимости. Множество инструментов разработки ПО, как например, GNU ld выдает предупреждения в случае обнаружения при компоновке кода с использованием gets.

Тут в шапке форума тема - Исходники программ и библиотек. Наверняка там есть нормальный драйвер с кольцевым буфером. Или напишите свой, там работы на пару часов. И не надо отключать ватчдог.
qulik
Да, соглашусь со всем! gets() "убъет" кучу времени, да и надежность никакая. Спасибо за рекомендации! smile.gif А драйвер для считывания строки по одному символу я попробую свой сделать. Хочется разобраться до конца.
Xenia
Цитата(qulik @ Jun 21 2009, 01:52) *
Да, соглашусь со всем! gets() "убъет" кучу времени, да и надежность никакая. Спасибо за рекомендации!


Совсем запугали бедного Кулика smile.gif. Делать так, как он вознамерился - можно! Только никакая gets() тут не нужна, хватай символ из UDR1 - вот и вся процедура получения байта. Обычно, байтики, схваченные в прерывании кладут друг за дружкой в строку до тех пор, пока очередным байтом не окажется "конец строки" (Enter). Этот символ можно в строку не класть, а вместо этого заняться ее анализом и исполнением того, что эта строка означает.
qulik
Цитата(Xenia @ Jun 21 2009, 03:23) *
Совсем запугали бедного Кулика smile.gif. Делать так, как он вознамерился - можно! Только никакая gets() тут не нужна, хватай символ из UDR1 - вот и вся процедура получения байта. Обычно, байтики, схваченные в прерывании кладут друг за дружкой в строку до тех пор, пока очередным байтом не окажется "конец строки" (Enter). Этот символ можно в строку не класть, а вместо этого заняться ее анализом и исполнением того, что эта строка означает.


Принцип получения строки по одному символу достаточно прост. А gets() я хотел применить, что бы текст программы сократить. Но после обсуждения понял, что лучше таки по одному символу принимать. smile.gif
А вот по поводу символа конца строки. передавать его все равно нужно, так что лучше сохранить.

Принимаемая строка - это условность (для универсальности программы). Примимается один символ и в зависимости от его значения принимается решение. А вот передавать по USART нужно строку. Передается она при помощи puts(). Возникает мысль передавать тоже по символу smile.gif , но как на это среагирует копьютер? Тоже надо драйвер по прерыванию собрать, думаю справлюсь...
Xenia
Цитата(qulik @ Jun 21 2009, 16:28) *
Принимаемая строка - это условность (для универсальности программы). Принимается один символ и в зависимости от его значения принимается решение.


По одному символу, как правило, принять решение не удается. Приходится прочесть слово целиком, чтобы понять, что оно означает. И вообще, символ конца строки (Enter) это не просто символ, а символ ПОДТВЕРЖДЕНИЯ того, что бы сказано. До его появления программа не имеет права начать выполнение команды, даже если смысл ее вполне понятен. Например, компьютеру нельзя выполнять "FORMAT C:" smile.gif, пока не нажат Enter. А вы вознамерились по одному символу принимать решение.

Цитата(qulik @ Jun 21 2009, 16:28) *
А вот передавать по USART нужно строку. Передается она при помощи puts(). Возникает мысль передавать тоже по символу smile.gif , но как на это среагирует копьютер? Тоже надо драйвер по прерыванию собрать, думаю справлюсь...


Компьютеру все равно, как было передано - отдельными символами или строкой, поскольку на физическом уровне в обоих случаях прием и передача ведутся по символьно. Точно так же и AVRка получает прерывания (если их разрешить) при поступлении очередного байта, не зная того, gets'ом или getchar'ом отправлялась посылка.
qulik
Цитата(Xenia @ Jun 21 2009, 17:58) *
По одному символу, как правило, принять решение не удается. Приходится прочесть слово целиком, чтобы понять, что оно означает. И вообще, символ конца строки (Enter) это не просто символ, а символ ПОДТВЕРЖДЕНИЯ того, что бы сказано. До его появления программа не имеет права начать выполнение команды, даже если смысл ее вполне понятен. Например, компьютеру нельзя выполнять "FORMAT C:" smile.gif, пока не нажат Enter. А вы вознамерились по одному символу принимать решение.


Верно подмечено по поводу enter. Подтверждение переданного байта - это как минимум грамотно. А вот символа мне вполне достаточно для принятия решения (выбрать один из 8 вариантов):

switch ©
{
case 48: mig_led1(); break; //0
case 49: mig_led2(); break; //1
... и т.д.
}
По крайней мере не требуется сравнивать строки! Что сэкономит Flash память.

П.С. Посимвольный прием(передачу) я освоил. smile.gif
Xenia
Цитата(qulik @ Jun 24 2009, 21:06) *
По крайней мере не требуется сравнивать строки! Что сэкономит Flash память.


Когда команды примитивные (т.е. без параметров), и их число не превышает 256, то, несомненно, удобнее односимвольная кодировка - тут она самоя короткая. Но как только символов ASCII перестало хватать - приходится использовать слова, а тут уже потребуются какие-то разделители между ними: пробел, табулятор, символ конца строки и т.п.
В этой связи вспоминается фраза на манер японских хайку:
"Кончилось место на Z,
Что же мне делать теперь?
Ведь это последний..." smile.gif
Qwertty
Вообще то неплохо контролировать правильность посылки. Тем более если команда в один символ. Какой нибудь CRC не помешает. Вот так по чуть чуть добавлять и... получится что то типа modbus smile.gif
qulik
Цитата(Xenia @ Jun 25 2009, 03:11) *
"Кончилось место на Z,
Что же мне делать теперь?
Ведь это последний..." smile.gif


smile.gif Ну да! Место бывает и заканчивается! Приходиться брать МК "потолще"! smile.gif)))

Цитата(Qwertty @ Jun 25 2009, 05:40) *
Вообще то неплохо контролировать правильность посылки. Тем более если команда в один символ. Какой нибудь CRC не помешает. Вот так по чуть чуть добавлять и... получится что то типа modbus smile.gif


Посмотрел про modbus в Википедии. А это интересно! Я новичек в использовании интерфейсов (да и МК тоже smile.gif)и пока кроме как SPI и RS-232 ничего не использовал. А modbus - это уже что-то! Точнее это уже протокл. Надо познакомится с ним поближе. 1111493779.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.