www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AVR Stürzt ab --> interner Reset Hilfe


Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe ein Gerät, welches ein PWM (250Hz) Singnal ausgibt.
Dieses möchte ich auswerten.
Das Singnal wird mit einem Transitor erzeugt der GND Durchschaltet.
Jetzt habe ich denn Port als eingang Deklariert und denn internen Pull 
up eingeschaltet.

gebe ich nun das singnal auf den Port macht der AVR einen internen 
Reset!!

Woran könnte das liegen.

Ziehe ich den eingang manuell auf GND oder + passiert nichts.

Bin für jede Idee dankbar.

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vermutlich ein Softwarfehler.

Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
//Port A und D Ausgang
DDRA = 0xFF;
DDRD = 0x1F;
// PortC als eingang alle Pull up Widerstände acktiviert
DDRC = 0x00;
PORTC = 0xFF;
PORTD = 0xE0;

Könnte es an der Init der Ausgänge liegen.

PortD 7 soll der Eingang sein ???

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Soweit passt alles.

Autor: risu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Micha,

wie Benedikt schon sagte, handelt es sich vermutlich um einen 
Software-Fehler -- es sei denn, der Reset-Pin wird auf 0 gezogen. 
Ursachen können sein:
1. undefinierter Interrupt-Vektor (PC springt an eine Adresse ohne 
Interrupt-Handler)
2. Stack-Überlauf
3. PC zeigt (z.B. wegen "2.") auf die "NOP"-Zellen nach dem Ende des 
Programms, läuft über und fängt wieder bei 0 (=Reset-Vektor) an.

Du musst schon mehr von Deinem Code zeigen, um effiziente Hilfe zu 
bekommen!

Gruß
  risu

Autor: Micha (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Das Programm.

Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sobald ich an Pin 7 das Singnal lege, macht er einen Reset.

Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
if((!(PIND & (1<<PIND7)))) // Wenn PinD 7 -> 0 ist dann
{
Pause++;
}

Wenn ich diese Zeile weglasse geht es.

Jedoch kann ich dann die Pausenlänge nicht mehr messen.

Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kann es sein das solange PinD7 0 ist er in der Interupt Rotine bleibt.

Und ein neuer Interupt vom timer Ausgelöst wird, wärend der Alte noch 
bearbeitet wird ?

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Von welchem Controller redest du eigentlich? Weder hier noch im Programm 
ist eine Angabe dazu.

MfG Spess

Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ATMega8535
16 Mhz externer Quarz

Autor: risu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

1. Die Frage von Spess53 habe ich auch.
2. Die Variablen "PWM" und "Pause" müssen "volatile" sein.

Gruß
 risu

Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was heist "volatile"???

Autor: risu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Micha,

> Was heist "volatile"???

http://www.netrino.com/node/80

Gruß

 risu

Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
//-----
int volatile PWM;
int volatile Pause;

habe ich gemacht ändert garnix. :-(

Autor: risu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Woraus schließt Du, dass es zu einem "internen Reset" kommt?

Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das PWM Singnal verschwimmpt. Also wird es wird überlagert.

Dies passiert nur wenn ich:

1.)
if((!(PIND & (1<<PIND7)))) // Wenn PinD 7 -> 0 ist dann
{
Pause++;
}
das ins Programm einfüge egal wo !

2.) ich extern einen Reset oft hindereinander auslöse

3.)
das PWM Singnal anschliese

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Ganze macht einen ziemlich wirren Eindruck:

1. Das gepostete Programm nicht das sein, was auf deinem Controller
   läuft, weil es einen Syntaxfehler enthält (schließende Klammer am
   Ende von main() fehlt).

2. Du greifst auf die Variable PWM sowohl im Interrupthandler als auch
   im Hauptprogramm lesend und schreibend zu. Hast du dir Gedanken
   gemacht, was passiert, wenn an der ungeschicktesten Stelle im
   Hauptprogramm dieses unterbrochen wird und der Interrupthandler PWM
   ändert? Da PWM aus zwei Bytes besteht, kann die Unterbrechung sogar
   innerhalb eines Zugriffs auf die Variable passieren.

3. Die Zeile

     OCR1A = 64;

   hat wenig Sinn, da du den Timer im Normalmodus (nicht CTC-Modus)
   betreibst, wo er immer bis zum Maximalwert von 65535 hochzählt. So
   dürftest du nur eine Interrupfrequenz von 244Hz und damit eine
   PWM-Frequenz von etwa 0,5Hz erhalten. Oder habe ich da etwas
   übersehen? Wahrscheinlich möchtest du aber den CTC-Modus. Dazu müssen
   in auch TCCR1A die entsprechenden Bits gesetzt werden.

> Das PWM Singnal verschwimmpt. Also wird es wird überlagert.

Kannst etwas genauer beschreiben, wie das Signal aussieht?

Autor: Micha (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
CH2 input Singnal das ich messen will !!

Messung also abfrage
if((!(PIND & (1<<PIND7)))) // Wenn PinD 7 -> 0 ist dann
{
Pause++;
}

ist acktiviert

Autor: Micha (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Singnal liegt weiterhin am Eingang !!

Jedoch habe ich jetzt die Abfrage deaktiviert.



Was mache ich nur falsch.

Kann ich das PWM Singnal auch anders erzeugen.
Es muß 250 HZ haben !!


Oder wie könnte ich die Auswertung anders machen.

Ist irgendwas mit dem Interrupt Aufruf falsch ??

Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
//Timer einstellen
//TCCR1B = (1<<CS10) | (1<<CS11);       //setzt den Prescaler 64
TCCR1B = (1<<CS10) | (0<<CS11);         //setzt den Prescaler 1
TCCR1A = (1<<WGM12) | (1<<WGM13);        //CTC MODE
OCR1A = 400;                         //setzt den Vergleichswert
TCNT1 = 0;                             //startewert des Counters
TIMSK = 1<<OCIE1A;                     //Compare-Int aktivieren
sei();                                 //globale Ints aktivieren

Wenn ich denn Vergleichswert erhöhe geht es ab ca. 400. Warum?

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Was mache ich nur falsch.

Wenn der Timer im CTC-Modus läuft und OCR1A=64 ist, generiert er alle 64
Taktzyklen einen Interrupt. Der Aufruf und die Ausführung des
Interrupthandlers dauert im worst Case etwa 59 Zyklen. Somit bleiben dem
Hauptprogramm zwischen zwei Interrupts gerade einmal 7 Zyklen. In dieser
Zeit kann aber nur ein Bruchteil eines vollen Durchlaufs der
Hauptschleife stattfinden. D.h. zwischen der Ausführung der Zeile
    if (PWM == Prozent) // 0 bis 500

in zwei aufeinanderfolgenden Schleifendurchläufen werden gleich mehrere
Interrupts ausgelöst, von denen jeder zur Inkrementierung der Variable
PWM führt. Bei der Auswertung der Bedingung PWM==Prozent hat also PWM in
einem Schleifedurchlauf bspw. den Wert 100, im nächsten (nach vielleicht
fünf Interrupts) aber schon 105. Liegt der Wert von Prozent dazwischen,
wird die ==-Bedingung nicht wahr, und es erfolgt in der aktuellen
PWM-Periode kein Wechsel von low nach high. Deswegen erhältst du im
Ausgangssignal die vielen Aussetzer.

Der Wechsel von high nach low passiert dagegen immer, weil du dort
klugerweise auf PWM>=500, und nicht auf PWM==500 abfragst.

Um das Problem etwas einzudämmen, kannst du auch in der ersten Abfrage
ein >= anstelle des == verwenden, also
    if (PWM >= Prozent) // 0 bis 500

Das löst aber nicht das eigentliche Problem, nämlich die fast
vollständige Auslastung der CPU mit den Interrupts. Außerdem besteht
immer noch das Problem des simultanen Zugriffs auf 16-Bit-Variablen im
Hauptprogramm und im Interrupthandler. Die kann man zwar durch Einfügen
von Interruptsperren an den entsprechenden Stellen im Hauptprogramm
beseitigen, dadurch wird aber das erste Problem noch verschärft, und es
kann zu Interruptstaus kommen, weil der jeweils nächste Interrupt schon
eintrifft, bevor der aktuelle abgearbeitet ist.

> Wenn ich denn Vergleichswert erhöhe geht es ab ca. 400. Warum?

Dann bleiben dem Hauptprogramm 341 statt 7 Zyklen bis zum jeweils
nächsten Interrupt. In dieser Zeit schafft es wahrscheinlich sogar
mehrere Schleifendurchläufe. Eigentlich sollte es schon mit weniger als
400 funktionieren. Hast du beim Compiler vielleicht die Optimierung
nicht eingeschaltet?

> Kann ich das PWM Singnal auch anders erzeugen. Es muß 250 HZ haben !!
>
> Oder wie könnte ich die Auswertung anders machen.

Zum Glück hat der ATmega8535 sowohl für die PWM-Generierung als auch die
Pulsbreitenmessung des Eingangssignals spezielle Hardwareeinheiten, die
diese Aufgaben (fast) ohne das Mitwirken der CPU erledigen. Sie heißen
"Input Capture Unit" (für die Zeitmessung) und "Output Compare Unit"
(für die PWM-Generierung) und sind jeweils in einem eigenen Abschnitt im
Datenblatt beschrieben.

Damit kannst du alle der beschriebenen Probleme auf einen Schlag
beseitigen, und die CPU hat wieder Luft, um noch andere nützliche Dinge
zu tun. Dazu musst du allerdings das Eingangssignal nicht an PD7,
sondern an PD6 (ICP1) anschließen und das Ausgangssignal nicht von PD1,
sondern von PD4 (OC1B) abnehmen. Vielleicht kannst du das in deiner
Schaltung ja noch ändern.

Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja,PD7 auf PD6 legen ginge eventuell mit ner Zinnbrücke.

Aber die AVR Kontroller sind doch schnell !!

Der AVR läuft mit 16 Mhz!
Das sind 16000000 Befehle pro Sekunde.

Und ich will nur ein Signal von 250 Hz erzeugen.

Und gleichzeitig eins messen.

Das muss doch zu schaffen sein!

Könntest du mir ein Beispiel geben, wie ich das einstelle mit PD6.

Autor: Niels Hüsken (monarch35)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Micha wrote:

> Der AVR läuft mit 16 Mhz!
> Das sind 16000000 Befehle pro Sekunde.

Nein, sind es nicht.

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Und ich will nur ein Signal von 250 Hz erzeugen.

Die 250Hz sind, für sich gesehen, nicht das Problem, aber die 250Hz in
Verbindung mit der PWM-Auflösung von 500 Schritten. Um diese Auflösung
softwaremäßig zu erreichen, muss die Software 250*500=125000 Mal pro
Sekunde aktiv werden. Dann hat sie genau 128 Taktzyklen Zeit, das
Eingangssignal zu verarbeiten und das Ausgangssignal zu generieren. Wie
Niels andeutete, benötigen viele Befehle nicht einen, sondern zwei
Zyklen, einige sogar noch länger.

Wenn man's geschickt anstellt, geht das trotzdem, auch softwaremäßig.
Ich vermute aber, dass das Programm, bis es fertig ist, noch ein paar
Dinge mehr tun soll. Bei der Softwarelösung bist du dann ständig am
Zyklenzählen, um sicherzustellen, dass der Zeittakt auch unter den
ungünstigsten Bedingungen eingehalten wird.

Was soll dein Programm denn außer der Pulslängenmessung und der
PWM-Generierung sonst noch tun? Irgendetwas muss ja bspw. mit der
gemessenen Pulslänge getan werden. Und du hättest sicher keinen
40-Füßler genommen, wenn mit den anderen Ports nicht auch noch etwas
gemacht würde.

> Könntest du mir ein Beispiel geben, wie ich das einstelle mit PD6.

Ich habe gerade nichts fertiges im Zugriff, schon gar nicht für den
ATmega8535. Es sollte aber genügend Beispiele hier im Forum, in den
Tutorials und sonstwo im Netz geben, die du entsprechend anpassen
kannst.

Da fällt mir gerade ein: Wieso möchtest du überhaupt die PWM in 500
Schritten auflösen? Das Tastverhältnis wird doch, wenn ich das richtig
gesehen habe, von Port C als ganze Zahl von 0 bis 100 eigelesen. Damit
genügt es, nur 100*250=25000 Mal den Interrupt zu generieren und du hast
640 CPU-Zyklen zwischen zwei Interrupts zur Verfügung. So dürfte es auch
bei softwaremäßiger PWM keine Probleme geben.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.