Hi,
ich würde gerne mit dem im Titel genannten Chip den WDT über den ISR
verwenden.
(Zum testen ausschließlich den Vektor, später im Betrieb dann wie im
Datenblatt beschrieben erst Vector zum Wegspeichern, dann Reset)
Nun verwende ich:
1
#include <util/delay.h>
2
#include <avr/wdt.h>
3
4
ISR(WDT_vect) {
5
Beeper_ON();
6
7
8
/* ReEnable the watchdog interrupt,
9
* as this gets reset when entering this ISR and automatically enables the WDE signal
10
* that resets the MCU the next time the timer overflows */
11
WDTCSR |= (1<<WDIE);
12
}
13
14
void watchdogSetup() {
15
16
// Reset the watchdog reset flag
17
wdt_reset();
18
wdt_enable(WDTO_4S);
19
// Enable interrupts instead of reset
20
WDTCSR |= (1 << WDIE);
21
}
22
23
void loop() {
24
//Beeper_ON();
25
LED_SW2_ON();
26
for (int i = 0; i < 8; ++i) {
27
_delay_ms(100);
28
}
29
//Beeper_OFF();
30
LED_SW2_OFF();
31
for (int i = 0; i < 8; ++i) {
32
_delay_ms(100);
33
}
34
}
35
36
int main() {
37
watchdogSetup();
38
ioinit();
39
while (1) {
40
loop();
41
}
42
}
Als Minibeispiel.
Ich erkenne, dass die LED in gleichbleibenden Takt wie gewollt blinkt
und dann pötzlich eine Unregelmäßigkeit aufweißt, was ich als den RESET
deute.
Witziger weise, kommt kein Ton (wortwörtlich) aus dem ISR zur gleichen
Zeit :(.
(Dabei sind LED_SW2_ON() und Beeper_ON() problemlos gegeneinander
auszutauschen, womit ich 100% einen Fehler in der Ansteuerung
ausschließen kann)
Vermutlich stimmt die Reihenfolge von
"WDTCSR |= (1 << WDIE);"
zu: wdt_reset(); und wdt_enable(WDTO_4S);
nicht. Habe aber bereits alle möglichen Konstellationen durchprobiert.
Daher wollte ich fragen, ob ihr mir auf die Sprünge helfe könnt den ISR
sachgemäß zu aktivieren?
Danke und noch eine sonnigen Sonntag :)
Ertöhnt (direkt nach dem bestromen) das Piepen aus dem ISR genau 1x kurz
und er startet neu.
Ich hätte, wie man hoffentlich aber erkennt, erst 8sec normalen Betrieb
bzw, möchte das "if" hier nicht für den wdt verwenden, sondern
anderweitig.
Wenn ich den wdt-init Teil hier aber ohne if lasse, habe ich ein
endloses ISR-Restart drin.
Habt ihr nicht noch einen Rat?
Die Allgemeinen Infos und Datenblätter bringen mich hier nicht weiter
und erst recht nicht diese Arduino Schnipsel, welche man überall findet.
LG
Ich bin nicht gut genug, um deine SW zu debuggen, aber ich habe dir ein
ganz ähnlich funktionierendes Programm für den TinyX5 angehängt.
WD-Timer, WD-Interrupt, WD-Reset - alles enthalten.
Dient mir als Beispiel und sollte mit nur wenig Änderung auch beim 644
funktionieren.
HildeK schrieb:> Ich bin nicht gut genug, um deine SW zu debuggen, aber ich habe dir ein> ganz ähnlich funktionierendes Programm für den TinyX5 angehängt.
Beim Vergleichen erkenne ich keinen Makanten Unterschied.
Egal was ich mache, der WDTCSR scheint nicht lange genug zu warten.
Kurz nach dem Setup steht noch WDTCSR = 72 drin (debugged)
Und im ISR ist nur noch WDTCSR = 8.
Wo sind allso die verdammten Bits hin, oder muss ich die ALLE (WDIE ist
klar) nach einem IR neu sezten?
Ich weiß zwar nicht, ob der WDT im Debugg weiter läuft, aber wenn ich
die Breakpoints raus nehme, sollte ich doch an der blöden LED 2/4/8 Sek
erkennen können.:(
S. Landolt schrieb:> Haben Sie sich so etwas vorgestellt?
Lieb gemeint, aber da entdecke ich einige Fehler und keine Neuerungen zu
meinem Wissen/Fehler:
Sollte nicht im ISR sein...
1
ISR (WDT_vect) {
2
WDTCSR = (1<<WDIE);
3
}
interrupt kann den kritischen Bereich unterbrechen:
1
sei();
2
WDTCSR = (1<<WDE) | (1<<WDCE);//aktivieren und sofort ...
Habe gerade mal ein eigenes Projekt angesehen, in dem ich den
Watchdog-Interrupt als regelmäßigen Interrupt (ohne Reset) benutze.
Aus dem Kopf, ohne ins Datenblatt zu gucken:
WDTCSR beschreibt man am besten jeweils komplett, also kein "|=",
sondern eine direkte Zuweisung.
Eine erfolgreiche Änderung des WDE-Bits benötigt unmittelbar zuvor ein
aktives WDCE (watchdog change enable).
Vor allem Gefummel an WDTCSR zur Sicherheit immer erstmal den
Watchdog-Counter auf Anschlag setzen.
1
staticvoid
2
xxo_sleep(void)
3
{
4
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
5
6
cli();
7
wdt_reset();
8
WDTCSR=_BV(WDCE)|_BV(WDE);
9
WDTCSR=_BV(WDIF)|_BV(WDIE)|6;/* 1 s interrupts */
10
sei();
11
}
12
13
staticvoid
14
xxo_unsleep(void)
15
{
16
set_sleep_mode(SLEEP_MODE_IDLE);
17
18
cli();
19
wdt_reset();
20
WDTCSR=_BV(WDCE)|_BV(WDE);
21
WDTCSR=0;/* turn off */
22
sei();
23
}
24
25
ISR(WDT_vect)
26
{
27
if(++trigger_seconds==TRIGGER_LEVEL)
28
{
29
trigger_seconds=0;
30
timer_triggered=true;
31
xxo_unsleep();
32
}
33
else
34
{
35
xxo_sleep();
36
}
37
}
Bei mir wacht der Watchdog (in etwa) jede Sekunde auf, aber nur um
nachzusehen, ob "was zu tun ist". Das ist immer dann der Fall, wenn die
TRIGGER_LEVEL Anzahl an Sekunden erreicht ist. Dann wird der WDT erstmal
abgeschaltet, damit die Firmware normal arbeiten kann. Wenn sie fertig
ist, ruft sie wieder xxo_sleep() auf.
Ja, das sei() gibt, wenn die Funktionen aus der ISR heraus aufgerufen
werden, die Interrupts vorzeitig frei. Stört hier nicht. Man könnte
natürlich auch die übliche Logik drumrum bauen, SREG retten, cli(), und
am Ende SREG wieder herstellen.
D a v i d K. schrieb:> keine Neuerungen zu> meinem Wissen/Fehler
Da möchte ich denn doch widersprechen.
Mein Programm macht, in seiner Schlichtheit, zumindest das, was es soll:
eine LED an B0 blinkt gleichmäßig. Ihr Programm hingegen läuft offenbar
nicht korrekt, es lässt sich in der eingangs vorgestellten Version nicht
einmal übersetzen, da Teile nicht gezeigt wurden; so ließ sich auch der
Verdacht nicht bestätigen, dass es am fehlenden sei lag.
Eine Kritik jetzt anzubringen, ist etwas merkwürdig - vor zwei Tagen
wäre man in gemeinsamer Arbeit&Diskussion sicher weitergekommen.
S. Landolt schrieb:> D a v i d K. schrieb:>> keine Neuerungen zu>> meinem Wissen/Fehler>> Da möchte ich denn doch widersprechen.> Mein Programm macht, in seiner Schlichtheit, zumindest das, was es soll:
Bei mir leider nicht. Hab es 1:1 eingespielt.
Erst danach, sind mir die Dinge aufgefallen, welche ich als Hinweise
aus dem Datenblatt habe.
Meine Experimentierzeit beschränkt sich leider derzeit aufs Hotel unter
der Woche, weswegen ich leider nicht so spontan antworte.
Jörg W. schrieb:>...> Bei mir wacht der Watchdog (in etwa) jede Sekunde auf, aber nur um> nachzusehen, ob "was zu tun ist". Das ist immer dann der Fall, wenn die> TRIGGER_LEVEL Anzahl an Sekunden erreicht ist. Dann wird der WDT erstmal> abgeschaltet, damit die Firmware normal arbeiten kann. Wenn sie fertig> ist, ruft sie wieder xxo_sleep() auf.
Danke das werde ich so noch mal testen!
> Bei mir leider nicht.
Auf einem ATmega644 im Auslieferungszustand? Seltsam. Einer von uns
beiden macht etwas falsch - allerdings ist C nicht meine Sprache.