Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: atmega88pa
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
max_mart
всем привет,

Необходимо ресетить мегу. Как это можно реализовать через проограмму, принудительно по необходимости, например, при проверке одного флага, в определенный момент времени?
RabidRabbit
Соеденить какую-нибудь ногу GPIO с RESET, не?
kovigor
Цитата(max_mart @ Oct 8 2012, 12:06) *
Необходимо ресетить мегу. Как это можно реализовать через проограмму, принудительно по необходимости, например, при проверке одного флага, в определенный момент времени?

Посредством WatchDog ...
DmitryM
Цитата(max_mart @ Oct 8 2012, 13:06) *
Необходимо ресетить мегу. Как это можно реализовать через проограмму, принудительно по необходимости, например, при проверке одного флага, в определенный момент времени?

Завести Watchdog, и по необходимости "например, при проверке одного флага" уйти в бесконечный цикл.
Xenia
Ззапретить прерывания, завести Watchdog на самую короткую продолжительность, и только после этого уйти в бесконечный цикл.
Например так:
Код
void Reset()
{
  __disable_interrupt();
  WDTCSR |= (1<<WDCE) | (1<<WDE);
  WDTCSR = (1<<WDE);  // 16 ms
  for(;;);
}

(только это не для ATmega88pa писано).
demiurg_spb
Под avr-gcc для любых AVR.
Код
static inline void NORETURN mcu_reset(void)  {wdt_enable(WDTO_15MS); cli(); for(;;);}

Пора бы уже эту фишку в avr-libc реализовать...
max_mart
спасибо огромное
prottoss
Цитата(max_mart @ Oct 8 2012, 15:06) *
...принудительно по необходимости, например, при проверке одного флага, в определенный момент времени?

Цитата(RabidRabbit @ Oct 8 2012, 15:40) *
Соеденить какую-нибудь ногу GPIO с RESET, не?
Лучший вариант, ибо это будет как раз в определенный момент времени, а не после того как WDT сработает через определенный момент времени после определенного момента времени.
V_G
Цитата(prottoss @ Oct 8 2012, 22:41) *
Лучший вариант, ибо это будет как раз в определенный момент времени, а не после того как WDT сработает через определенный момент времени после определенного момента времени.

Ну, и здесь этот определенный момент также не очень-то определен, с учетом минимально допустимого времени сброса (2,5 мкс по даташиту), с учетом работы внутреннего счетчика задержки ресета, а также с учетом того, что при срабатывании ресета сигнал порта, вызывающего ресет, тоже сбрасывается.
prottoss
Цитата(V_G @ Oct 8 2012, 19:28) *
Ну, и здесь...
Согласен, все в мире относительно sm.gif Просто в случае с WDT ко всем выше перечисленным задержкам прибавляется минимальное время реакции WDT.
max_mart
Ram и все регитсры сбрасываются или сохраняются значения, при сбросе от WDT?
prottoss
Цитата(max_mart @ Oct 8 2012, 21:15) *
Ram и все регитсры сбрасываются или сохраняются значения, при сбросе от WDT?
Сброс по WDT работает так же как и сброс от внешнего RESET. Все регистры и порты ВВ принимают начальное значение описаное в даташите на МК. SRAM не изменится.
max_mart
т.е. значит флаги и некоторые переменные придется обнулять самому, поскольку я их в SRAM разместил

правильно я говорю?
И переменная сохранит свое значение до ресета?
prottoss
Цитата(max_mart @ Oct 8 2012, 21:57) *
т.е. значит флаги и некоторые переменные придется обнулять самому, поскольку я их в SRAM разместил

правильно я говорю?
И переменная сохранит свое значение до ресета?
Ну да. А разве при инициализации программы у Вас флаги не устанавливаются в какое то дефолтное значение? Типа:
Код
unsigned int g_Flag_1 = 0x0000;
unsigned int g_Flag_2 = DEF_FLAG_A | DEF_FLAG_B;


void main(void)
{
...
}
_Артём_
Цитата(max_mart @ Oct 8 2012, 18:57) *
т.е. значит флаги и некоторые переменные придется обнулять самому, поскольку я их в SRAM разместил
правильно я говорю?

А обычно вы их сами обнуляете? Или в стартапе они обнуляются?
Сброс по WDT аналогичен обычному, то есть всё пойдёт по тому же сценарию.
max_mart
Ну я обычно сразу в переменную 0х00 прописываю при ее инициализации.
Например:
volatile unsigned char example=0x00;
prottoss
Цитата(max_mart @ Oct 8 2012, 22:30) *
Ну я обычно сразу в переменную 0х00 прописываю при ее инициализации
Вот Вы и ответили на свой вопрос - программа ведь после ресета стартует. Она все сделает, что Вы прописали в тексте программы.
_Артём_
Цитата(max_mart @ Oct 8 2012, 19:30) *
volatile unsigned char example=0x00;

Совершенно излишне:
Код
volatile unsigned char example;

тот же результат даст.
max_mart
Артем
Т.е. вы хотите сказать, что она все время будит инициализироваться нулевой при самом первом запуске(по питанию)? А не может быть такого, что там может быть записан мусор, а у меня по этой переменной важное событие должно пройти, и тогда что? А мне необходимо, чтобы при самом первом запуске она именно нулевая была!
esaulenka
Во-первых, обнулять глобальные (не локальные!) переменные компилятор Си должен согласно спецификации.
А во-вторых, если переменная прямо такая важная, её изначально привести в нужное состояние можно и руками.
_Артём_
Цитата(max_mart @ Oct 8 2012, 19:59) *
хотите сказать, что она все время будит инициализироваться нулевой при самом первом запуске(по питанию)?

При любом перезапуске так будет (они все через один вектор идут).

Цитата(max_mart @ Oct 8 2012, 19:59) *
А не может быть такого, что там может быть записан мусор

Не может такого быть, если условия эксплуатации не нарушены.
max_mart
Кстати, а флаг WDRF регистра MCUSR, сохраняет свое значение 1, после сброса, что сброс был? По описанию он вроде только может быть сброшен вручную или по питанию.

В принципе контролировать WDRF будит достаточно)))
_Артём_
Цитата(max_mart @ Oct 8 2012, 20:24) *
Кстати, а флаг WDRF регистра MCUSR, сохраняет свое значение 1, после сброса, что сброс был?

Естественно сохраняет.
Причём его надо обязательно сбрасывать, иначе не удасться установиь период WDT, отличный от минимального.
ReAl
Цитата(prottoss @ Oct 8 2012, 18:26) *
Сброс по WDT работает так же как и сброс от внешнего RESET.
За исключением того, что при этом взводится флаг WDRF в MCUSR, который держит в 1-ке бит WDE в WDTCSR (обратите внимание на X вместо 0 в «состоянии после сброса» для WDE).

Т.е. после сброса по WDT этот самый WDT оказывается гарантированно разрешённым, а после сброса по RESET — ну, зависит от фьюза WDTON :-)

Т.е. мало просто использовать вызов вызов рекомендованных Reset()/mcu_reset(), надо добавить при старте очистку источников сброса в MCUSR и запрет WDT.
max_mart
ну значит сделаю тогда, так
if (!(MCUSR&0b00001000)) {...}
// проверяю флаг: если сброс вызван вотчдог, то ничего не делать, если питание на МК только поступило и флаг не установлен, то выполнить действие
MCUSR=0x00;

REAL
Т.е. Вы хотите сказать, что надо добавить еще сюда wdt_disable();?

И еще момент. Порты сбрасываются все как выхода в высокоомное состояние(состояние высокого импенданса)?
ReAl
MCUSR = 0; сделать всегда, так как оставшийся от сброса по WDT бит (1 << WDRF) не даст ни запретить WDT, ни, как выше было сказано, изменить время (а уж оно-то по сбросу будет поставлено на минимальное).

После чего запретить либо сбросить WDT, в зависимости от того, используется ли он по прямому назначению.

Если WDT использовался только для сброса контроллера, то надо его запретить. Он разрешён после своей сработки и через 16 мс сработает опять.
max_mart
только для сброса контроллера. Сначала инициализирую МК,потом отключаю watchdog и сбрасываю флаг WDRF функцией WDT_Off(функцию взял прямо из даташита)
max_mart
Да и еще момент: Не может быть такого, что дапустим сразу при первом запуске МК(подачи питания) флаг WDRF установится в 1 или же он строго устанавливается только по срабатыванию ресета от вотчдог?
И порты сбрасываются все в состояние, как выхода в высокоомном состоянии(состояние высокого импенданса)?
_Артём_
Цитата(max_mart @ Oct 8 2012, 21:01) *
Сначала инициализирую МК,потом отключаю watchdog и сбрасываю флаг WDRF функцией WDT_Off(функцию взял прямо из даташита)

Тоже как-то взял из даташита - но она в 4 такта не уложилась...

Цитата(max_mart @ Oct 8 2012, 22:36) *
Да и еще момент: Не может быть такого, что дапустим сразу при первом запуске МК(подачи питания) флаг WDRF установится в 1 или же он строго устанавливается только по срабатыванию ресета от вотчдог?


Цитата
This bit is set if a Watchdog System Reset occurs. The bit is reset by a Power-on Reset, or by
writing a logic zero to the flag.

То есть если флаг установился (сбросом по wdt), то вернуть его в 0 может только запись 0 или Power-on Reset (но не BOD или Ext Reset).

Цитата(max_mart @ Oct 8 2012, 22:36) *
И порты сбрасываются все в состояние, как выхода в высокоомном состоянии(состояние высокого импенданса)?

Да все в Z-state. Initial Value для DDRx и PORTx = 0.

max_mart
Артем,
Как тогда посоветуете правильно его отключить?


static inline void WDT_off(void)
{
wdt_reset();
/* Clear WDRF in MCUSR */
MCUSR &= ~(1<<WDRF);
/* Write logical one to WDCE and WDE */
/* Keep old prescaler setting to prevent unintentional time-out */
WDTCSR = 0b00011000;
/* Turn off WDT */
WDTCSR = 0x00;
}
Так?

И еще момент:
после сброса, я флаги все обнуляю и выключаю вотчдог. Но если мне он опять нужен , то перед включением я должен бит WDRF выставить в 1?

Либо он(WDRF) устанавливается автоматически при записи 1 в WDE?
_Артём_
Цитата(max_mart @ Oct 9 2012, 07:58) *
Как тогда посоветуете правильно его отключить?
static inline void WDT_off(void)
{
wdt_reset();
/* Clear WDRF in MCUSR */
MCUSR &= ~(1<<WDRF);
/* Write logical one to WDCE and WDE */
/* Keep old prescaler setting to prevent unintentional time-out */
WDTCSR = 0b00011000;
/* Turn off WDT */
WDTCSR = 0x00;
}
Так?

Я делал примерно также, просто в однажды ИАР сгенерил код который перестал укладываться в 4 цикла.
Переделал так:
Код
void WDT_Prescaler_Change(unsigned char new_wdt_period);
int main() {
    MCUSR = ~(1<<WDRF);
    WDT_Prescaler_Change(6|(1<<WDE));
    __watchdog_reset();


Код
WDT_Prescaler_Change:
; Turn off global interrupt

    push r17
    mov r17, r16
    cli
; Reset Watchdog Timer
    wdr
; Start timed sequence
    lds r16, 0x60
    ori   r16, 0x18
    sts 0x60, r16
; --  Got four cycles to set the new values from here -
; Set new prescaler(time-out) value = 64K cycles (~0.5 s)
    sts 0x60, r17
; --  Finished setting new values, used 2 cycles -
; Turn on global interrupt
    pop r17
    ret




Цитата(max_mart @ Oct 9 2012, 07:58) *
И еще момент:
после сброса, я флаги все обнуляю и выключаю вотчдог. Но если мне он опять нужен , то перед включением я должен бит WDRF выставить в 1?
Либо он(WDRF) устанавливается автоматически при записи 1 в WDE?

Цитата
This bit is set if a Watchdog System Reset occurs.

Вы не можете установить WDRF - он устанавливается аппаратно. Его нужно просто сбросить на старте записью в него единицы и больше о нём не вспоминать.
max_mart
Почему 1??? Когда в описании написано 0!

Цитата(max_mart @ Oct 9 2012, 20:30) *
Почему 1??? Когда в описании написано 0!

"Вы не можете установить WDRF - он устанавливается аппаратно." - т.е. мне достаточно только прописать WDE, если мне необходим ресет и вотчдог включится
_Артём_
Цитата(max_mart @ Oct 9 2012, 19:35) *
Почему 1??? Когда в описании написано 0!

Я ошибся - писать нужно 0.

Цитата(max_mart @ Oct 9 2012, 19:35) *
т.е. мне достаточно только прописать WDE, если мне необходим ресет и вотчдог включится

да
abi
Вариант без WDT
Код
__disable_interrupt();
((void (*)())0x0000)();
_Артём_
Цитата(abi @ Oct 10 2012, 01:08) *
Вариант без WDT
Код
__disable_interrupt();
((void (*)())0x0000)();

Это не то же самое - процессор сброшен не будет и вся периферия останется в несброшенном состоянии.
abi
Цитата(_Артём_ @ Oct 10 2012, 03:49) *
Это не то же самое - процессор сброшен не будет и вся периферия останется в несброшенном состоянии.

Согласен, внутреннего системного сброса не произойдет. В зависимости от замысла принудительного программного сброса, системный сброс может и не понадобиться. В любом случае используемая периферия будет проинициализирована программой.
_Артём_
Цитата(abi @ Oct 10 2012, 05:40) *
В любом случае используемая периферия будет проинициализирована программой.

Не в любом случае, а только есть этим озаботиться.
ReAl
А иногда и озабоченность озабачивание даже если этим озаботиться, то все равно разница с аппаратным сбросом будет, и существенная.
Например
Цитата(ATmega88PA doc)
• Bit 3 – TXENn: Transmitter Enable n
Writing this bit to one enables the USART Transmitter. The Transmitter will override normal port operation for the TxDn pin when enabled. The disabling of the Transmitter (writing TXENn to zero) will not become effective until ongoing and pending transmissions are completed, i.e., when the Transmit Shift Register and Transmit Buffer Register do not contain data to be transmitted. When disabled, the Transmitter will no longer override the TxDn port.
Т.е. даже если записать «сбросовое» значение 0x00 в UCSR0B, передатчик ещё будет передавать недопереданное. Куда-то в астрал, так как ножка отключится, но кто его знает, как там себя автоматы поведут, если до конца передачи опять проинициализировать USART либо даже не занулять UCSR0B а просто заново записать то, что нужно.
Как миниум, аккуратненько взведётся (вполне возможно не ожидаемый ещё программой) флаг TXC.
vgo1
А нельзя по флагу сделать переход на самое начало программы /адрес 0000/и не задействовать WDT? Надо сбросить флажки всех прерываний и инициализировать указатель стека. Я похожее сделал, работает.
prottoss
Цитата(vgo1 @ Oct 11 2012, 22:40) *
А нельзя по флагу сделать переход на самое начало программы /адрес 0000/и не задействовать WDT? Надо сбросить флажки всех прерываний и инициализировать указатель стека. Я похожее сделал, работает.
Тогда глобальные переменные инициализируются, а вот порты в дефолтное состояние не установятся. Стек, кстати, сам инициализируется, если на Си, конечно, пишите.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.