Watchdog-Timer-Problem - AVR ATmega324PA

Ich habe vorher ATmega32A verwendet und migriere jetzt zu ATmega324PA, nur um die Energieverwaltung zu verbessern. Jetzt teste ich den neuen Controller in jeder Hinsicht. Dies ist ein einfacher Code, um den Watchdog-Timer zu überprüfen, aber er setzt den Controller immer wieder zurück.

Code:

int main(void)
{
  uart_init();
  PORTA|=(1<<PORTA1);
  _delay_ms(1500);
  PORTA&=~(1<<PORTA1);
  _delay_ms(2000);
  uart_array("FFFFFFFFFFFFFFFFFF");
  wdt_enable(WDTO_2S);
  _delay_ms(5000);
}

void uart_init()
{
 /*set PinA1 as output for LED*/
 DDRA|=(1<<1);

 /*set PinD3 as output for UART*/
 DDRD|=(1<<3);

 /*set pinD2 as input for UART*/
 DDRD&=~(1<<2);

 /*enabling TX and RX*/
 UCSR1B |=(1<<TXEN1) | (1<<RXEN1);

 /*asynchronous mode selection*/
 UCSR1C&=~(1<<UMSEL11);
 UCSR1C&=~(1<<UMSEL10);

 /*setting data format to 8 bit*/
 UCSR1B &=~(1<<UCSZ12);
 UCSR1C|=(1<<UCSZ11)|(1<<UCSZ10);

 /* setting one bit as stop bit*/
 UCSR1C &=~(1<<USBS1);

 /*Disabling parity*/
 UCSR1C &= ~((1<<UPM11) | (1<<UPM10));

 /* loading 8 LSB to UBRRL*/
 UBRR1L = UBRRL_VALUE;

 /* loading 4 MSB to UBRRH*/
 UBRR1H = UBRRH_VALUE;
}

Der Code funktioniert beim ersten Mal gut, aber danach blinkt die LED weiter.

Hinweis: Das Sicherungsbit des Watchdog (WDTON) ist deaktiviert.

Antworten (2)

Ja, das liegt daran, dass Sie nach dem Auslösen des Watchdogs das entsprechende Flag zurücksetzen müssen, bevor Main wieder startet (es gibt ein Register, in dem Sie auslesen können, was den Reset verursacht hat) und den Watchdog daran hindern, immer wieder zu feuern.

Dieser Code behebt Ihr Problem:

    // This function is called upon a HARDWARE RESET:
void reset(void) __attribute__((naked)) __attribute__((section(".init3")));

/*! Clear SREG_I on hardware reset. */
void reset(void)
{
     cli();
    // Note that for newer devices (any AVR that has the option to also
    // generate WDT interrupts), the watchdog timer remains active even
    // after a system reset (except a power-on condition), using the fastest
    // prescaler value (approximately 15 ms). It is therefore required
    // to turn off the watchdog early during program startup.
    MCUSR = 0; // clear reset flags
    wdt_disable();
}

Dieses .init3Ding ist ein spezieller Codeabschnitt, in den Sie Code einfügen können, der vor dem Hauptstart ausgeführt wird. Hier ist ein Link , der das beschreibt, aber Sie sollten sich nicht zu viele Gedanken machen, der obige Code wird gut funktionieren, wenn er in die main.c.

Es hat funktioniert, ohne .init3-Zeug hinzuzufügen. Vielen Dank
Was meinst du mit ohne Init-Zeug? Hast du den Code einfach an den Anfang von main gesetzt? Wenn ja, ist das ein bisschen unsicher, da Sie nicht wissen, wie lange es dauern wird, in main einzutreten (es gibt einige andere Inits, die etw vor main tun), also platzieren Sie es besser so weit wie möglich nach vorne. Dadurch wird sichergestellt, dass Sie kein unerwartetes Verhalten erhalten.
Nach wdt_enable habe ich den Wert des Watchdog-Interrupts überprüft. Es wurde nur deaktiviert. Woher kam also der kontinuierliche Reset?
Was meinst du mit wdt Interrupt Wert? Wie auch immer: Der Watchdog bleibt nach einem wdt-Reset aktiviert, aber die Zeit, nach der er auslöst, ist auf 15 ms eingestellt! Sie müssen es also sehr schnell deaktivieren, sonst wird es immer wieder ausgelöst. Der Weg zu gehen ist also, es vor dem Main zu deaktivieren und es so zu aktivieren, wie es im Main funktionieren soll.

Über die vorherigen reset()Funktionshinweise hinaus müssen Sie den Watchdog im Bootloader deaktivieren (falls natürlich verwendet). Es gibt/war zB ein bekannter Fehler des ursprünglichen Arduino-Bootloaders, der den Watchdog nicht deaktiviert hat.