|
WDTimer, Запустил, а как остановить? |
|
|
|
Jun 18 2009, 22:15
|
Участник

Группа: Новичок
Сообщений: 23
Регистрация: 2-04-08
Из: Санкт-Петербург
Пользователь №: 36 424

|
Доброго вечера! Заметил такую особенность: при "небольшом" загрязнении между контактами TX и RX (видимо электрический контакт появился), функция gets() безнадежно зависла. Подумал, что хорошо бы запустить перед началом gets() сторожевой таймер, который сбросит контроллер в случае зависания, мало ли чего. WDT запустил путем записи в его регистр сначала комбинации битов, разрешающих изменение режима WDT, а потом записал нужное значение. Через положеные 8 секунд произошол сброс контроллера. Попробовал остановить WDT путем записи в его регистр 0x00. Но эффекта не последовало, произошел сброс... Что делать?!?
|
|
|
|
|
Jun 18 2009, 22:28
|

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

|
Цитата(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(); Ну тут уж кажется всё предусмотрено с запасом...
Сообщение отредактировал Xenia - Jun 18 2009, 22:41
|
|
|
|
|
Jun 19 2009, 00:41
|
Местный
  
Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527

|
Цитата(qulik @ Jun 19 2009, 02:15)  Доброго вечера! Подумал, что хорошо бы запустить перед началом gets() сторожевой таймер, который сбросит контроллер в случае зависания, мало ли чего. Вы бы лучше подумали - а нужна ли такая "полезная" функция. Которая видимо тупо ждет прихода чего бы то ни было в UDR. Используйте нормальный драйвер работающий по прерываниям.
|
|
|
|
|
Jun 19 2009, 21:13
|
Участник

Группа: Новичок
Сообщений: 23
Регистрация: 2-04-08
Из: Санкт-Петербург
Пользователь №: 36 424

|
Цитата(Xenia @ Jun 19 2009, 02:28)  А вы пытались останавить его тоже комбинацией или простой записью? Может быть так попробовать:
WDTCSR |= (1<<WDCE); WDTCSR = 0;
или так:
WDTCSR |= (1<<WDCE) | (1<<WDE); WDTCSR = 0; Так пробовал, непомогло. А вот следующий вариант выглядит убедительно! Что-то я припоменаю про MCUSR при сбросе бита WDE...  Пойду попробую! Цитата(Qwertty @ Jun 19 2009, 04:41)  Вы бы лучше подумали - а нужна ли такая "полезная" функция. Которая видимо тупо ждет прихода чего бы то ни было в UDR. Используйте нормальный драйвер работающий по прерываниям. Ну дак у меня gets() и находится в блоке обработки прерывания, вызываемого при приеме очередного символа по USART! INTERRUPT (SIG_USART_RCV) { gets(); }... Или вы имеете ввиду посимвольно считывать строку???
|
|
|
|
|
Jun 19 2009, 21:20
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(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раз...
|
|
|
|
|
Jun 19 2009, 21:58
|
Участник

Группа: Новичок
Сообщений: 23
Регистрация: 2-04-08
Из: Санкт-Петербург
Пользователь №: 36 424

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

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

|
Цитата(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-х тактов соблюдалось. Поэтому это условие я не стала особо оговаривать.
Сообщение отредактировал Xenia - Jun 19 2009, 22:17
|
|
|
|
|
Jun 19 2009, 22:13
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(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) операций
|
|
|
|
|
Jun 19 2009, 22:14
|

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

|
Цитата(singlskv @ Jun 20 2009, 02:09)  Один раз повезло другой нет... так и рождаются легенды... Длиннее просто невозможно скомпилировать, т.к. операции с константами всегда производятся еще при компиляии, а не в runtime. Приведенная в моем прошлом посте компиляция одинакова как при отсутствии оптимизации, так и при оптимизации по скорости или размеру. Поскольку из-за примитивности примера ее невозможно оттранслировать ни длиннее, ни короче. Цитата(singlskv @ Jun 20 2009, 02:09)  Лучше всего заготовьте ВСЕ константы заранее а потом их присваивайте регистрам... Константы невозможно "приготовить заранее". Если вы намереваетесь поместить их в память, то вытаскивание оттуда обойдется дороже - тогда действительно в 4 такта можно не уложиться. А если положить в регистр, то примерно так оно и получится. P.S. Мой предыдущий пост, адресованный вам, был мною отредактирован. Ознакомьтесь с ним пожалуйста еще разик.
Сообщение отредактировал Xenia - Jun 19 2009, 22:22
|
|
|
|
|
Jun 19 2009, 22:18
|
Участник

Группа: Новичок
Сообщений: 23
Регистрация: 2-04-08
Из: Санкт-Петербург
Пользователь №: 36 424

|
А что меняет выбор варианта оптимизации? В AVR Studio есть варианты: О0 - Оs. Поисковик ничего не выдал.
Спасибо! Замечание с константами я учту на будущее.
|
|
|
|
|
Jun 19 2009, 22:21
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(Xenia @ Jun 20 2009, 02:14)  Константы невозможно "приготовить заранее". Если вы намереваетесь поместить их в память, то вытаскивание оттуда обойдется дороже - тогда действительно в 4 такта можно не уложиться. А если положить в регистр, то так оно и получится. Я Вам и предлагаю положить их(константы) во временные регистры... Цитата P.S. Мой предыдущий пост, адресованный вам, был мною отредактирован. Ознакомьтесь с ним пожалуйста еще разик. Вы очень настойчивая девушка... , хотя наверное это и не плохо... но очень торопитесь... не спешите в своих суждениях...
|
|
|
|
|
Jun 19 2009, 22:35
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

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

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

|
Цитата(qulik @ Jun 20 2009, 02:18)  Спасибо! Замечание с константами я учту на будущее. В данном случае варианты компиляции выражения WDTCR |= (1<<WDCE) | (1<<WDE); несущественны, поскольку запись в регистр WDTCR всегда будет ПОСЛЕДНЕЙ инструкцией. А, стало быть, протяжка перед следующей строкой WDTCR = 0; зависит исключительно от сложности обнуления регистра. Дольше двух тактов это не затянется при любых способах оптимизации или отсутствия оной.
Сообщение отредактировал Xenia - Jun 19 2009, 22:40
|
|
|
|
|
Jun 19 2009, 22:51
|
Местный
  
Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527

|
Цитата(qulik @ Jun 20 2009, 01:13)  Ну дак у меня gets() и находится в блоке обработки прерывания, вызываемого при приеме очередного символа по USART!
INTERRUPT (SIG_USART_RCV) { gets(); }...
Или вы имеете ввиду посимвольно считывать строку??? Именно посимвольно. Данные пришли - только тогда читаем. Ничего не ждем. Ваш же метод - просто ужас. Если строка не придет, а это НОРМАЛЬНАЯ ситуация при работе в реальных условиях, а не у Вас на столе, то контроллер просто повиснет. Предусматривать выход из нормальной ситуаци через сброс по собаке не надо. Плохо это и неправильно.  И еще момент - Вы представляете время выполнения этой функции? К примеру при 9600бод и строке символов в 30? А она у Вас внутри обработчика - значит на это время все другие события(прерывания) будут отброшены. Вот - почитайте - http://ru.wikipedia.org/wiki/GetsЦитата Применение gets весьма осуждается. Функция оставлена в стандартах C89 и C99 для обратной совместимости. Множество инструментов разработки ПО, как например, GNU ld выдает предупреждения в случае обнаружения при компоновке кода с использованием gets. Тут в шапке форума тема - Исходники программ и библиотек. Наверняка там есть нормальный драйвер с кольцевым буфером. Или напишите свой, там работы на пару часов. И не надо отключать ватчдог.
|
|
|
|
|
Jun 20 2009, 21:52
|
Участник

Группа: Новичок
Сообщений: 23
Регистрация: 2-04-08
Из: Санкт-Петербург
Пользователь №: 36 424

|
Да, соглашусь со всем! gets() "убъет" кучу времени, да и надежность никакая. Спасибо за рекомендации!  А драйвер для считывания строки по одному символу я попробую свой сделать. Хочется разобраться до конца.
|
|
|
|
|
Jun 20 2009, 23:23
|

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

|
Цитата(qulik @ Jun 21 2009, 01:52)  Да, соглашусь со всем! gets() "убъет" кучу времени, да и надежность никакая. Спасибо за рекомендации! Совсем запугали бедного Кулика  . Делать так, как он вознамерился - можно! Только никакая gets() тут не нужна, хватай символ из UDR1 - вот и вся процедура получения байта. Обычно, байтики, схваченные в прерывании кладут друг за дружкой в строку до тех пор, пока очередным байтом не окажется "конец строки" (Enter). Этот символ можно в строку не класть, а вместо этого заняться ее анализом и исполнением того, что эта строка означает.
|
|
|
|
|
Jun 21 2009, 12:28
|
Участник

Группа: Новичок
Сообщений: 23
Регистрация: 2-04-08
Из: Санкт-Петербург
Пользователь №: 36 424

|
Цитата(Xenia @ Jun 21 2009, 03:23)  Совсем запугали бедного Кулика  . Делать так, как он вознамерился - можно! Только никакая gets() тут не нужна, хватай символ из UDR1 - вот и вся процедура получения байта. Обычно, байтики, схваченные в прерывании кладут друг за дружкой в строку до тех пор, пока очередным байтом не окажется "конец строки" (Enter). Этот символ можно в строку не класть, а вместо этого заняться ее анализом и исполнением того, что эта строка означает. Принцип получения строки по одному символу достаточно прост. А gets() я хотел применить, что бы текст программы сократить. Но после обсуждения понял, что лучше таки по одному символу принимать.  А вот по поводу символа конца строки. передавать его все равно нужно, так что лучше сохранить. Принимаемая строка - это условность (для универсальности программы). Примимается один символ и в зависимости от его значения принимается решение. А вот передавать по USART нужно строку. Передается она при помощи puts(). Возникает мысль передавать тоже по символу  , но как на это среагирует копьютер? Тоже надо драйвер по прерыванию собрать, думаю справлюсь...
Сообщение отредактировал qulik - Jun 21 2009, 12:29
|
|
|
|
|
Jun 21 2009, 13:58
|

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

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

Группа: Новичок
Сообщений: 23
Регистрация: 2-04-08
Из: Санкт-Петербург
Пользователь №: 36 424

|
Цитата(Xenia @ Jun 21 2009, 17:58)  По одному символу, как правило, принять решение не удается. Приходится прочесть слово целиком, чтобы понять, что оно означает. И вообще, символ конца строки (Enter) это не просто символ, а символ ПОДТВЕРЖДЕНИЯ того, что бы сказано. До его появления программа не имеет права начать выполнение команды, даже если смысл ее вполне понятен. Например, компьютеру нельзя выполнять "FORMAT C:"  , пока не нажат Enter. А вы вознамерились по одному символу принимать решение. Верно подмечено по поводу enter. Подтверждение переданного байта - это как минимум грамотно. А вот символа мне вполне достаточно для принятия решения (выбрать один из 8 вариантов): switch © { case 48: mig_led1(); break; //0 case 49: mig_led2(); break; //1 ... и т.д. } По крайней мере не требуется сравнивать строки! Что сэкономит Flash память. П.С. Посимвольный прием(передачу) я освоил.
Сообщение отредактировал qulik - Jun 24 2009, 17:07
|
|
|
|
|
Jun 24 2009, 23:11
|

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

|
Цитата(qulik @ Jun 24 2009, 21:06)  По крайней мере не требуется сравнивать строки! Что сэкономит Flash память. Когда команды примитивные (т.е. без параметров), и их число не превышает 256, то, несомненно, удобнее односимвольная кодировка - тут она самоя короткая. Но как только символов ASCII перестало хватать - приходится использовать слова, а тут уже потребуются какие-то разделители между ними: пробел, табулятор, символ конца строки и т.п. В этой связи вспоминается фраза на манер японских хайку: "Кончилось место на Z, Что же мне делать теперь? Ведь это последний..."
|
|
|
|
|
Jun 25 2009, 17:08
|
Участник

Группа: Новичок
Сообщений: 23
Регистрация: 2-04-08
Из: Санкт-Петербург
Пользователь №: 36 424

|
Цитата(Xenia @ Jun 25 2009, 03:11)  "Кончилось место на Z, Что же мне делать теперь? Ведь это последний..."   Ну да! Место бывает и заканчивается! Приходиться брать МК "потолще"!  ))) Цитата(Qwertty @ Jun 25 2009, 05:40)  Вообще то неплохо контролировать правильность посылки. Тем более если команда в один символ. Какой нибудь CRC не помешает. Вот так по чуть чуть добавлять и... получится что то типа modbus  Посмотрел про modbus в Википедии. А это интересно! Я новичек в использовании интерфейсов (да и МК тоже  )и пока кроме как SPI и RS-232 ничего не использовал. А modbus - это уже что-то! Точнее это уже протокл. Надо познакомится с ним поближе.
Сообщение отредактировал qulik - Jun 25 2009, 17:08
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|