mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik [AVR Assember] Interrupt ohne reti beenden


Autor: Sascha T. (ernie1973)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe aktuell eine Ablaufsteuerung, bei der viele verschiedene
Aktionen durchgeführt werden. Während der Ablaufsteuerung muss immer
eine bestimmte Taste gedrückt sein und ab einem bestimmten Punkt darf
eine Zeit X nicht überschritten werden.

Sobald die Taste losgelassen wird oder die Zeit überschritten wird muss
der Ablauf sofort unterbrochen werden und es soll eine Fehlermeldung
kommen. Danach wird das Programm von vorne gestartet.

Die Überwachung der Abschaltkritierien erolfgt regelmäßig über Timer
Interrupts. Selbstverständlich kann ich mir dort einen Merker setzen und
diesen im Hauptprgramm abfragen. Allerdings muss ich die diese Abfrage
dann im Hauptprogramm an sehr viellen Stellen einfügen, damit es zu
keiner großen Verzögerung der Abschaltung kommt.

Aus diesem Grunde würde ich gerne direkt im Interrupt abschalten die
Fehlermeldung ausgeben und danach das Programm wieder von vorne starten.
Ich lese zwar öfters, dass es nicht sauber oder nicht der Sinn einer
Interruptroutine ist, aber spricht theoretisch wirklich was dagegen?

Wenn ich in der Interruptroutine mein Abschaltkriterium erkenne, dann
mein SREG wieder zurückschreibe und den Interrupt durch cli zurücksetze
bin ich doch wieder sauber und kann die Fehlermeldung ausgeben und mein
Programm neu starten. Das aktuelle reti müßte dann doch gelöscht sein
oder springt der mir beim nächsten reti an die alte Stelle?

Vielen Dank,

Ernie

Autor: A. N. (netbandit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du kannst es doch einfach so machen, dass sobald er das Kriterium 
erkennt, der Stack so verändert wird, dass reti nicht die 
Rücksprungadresse holt sondern eine von der gewünschte Adresse (z.b. die 
Programmstartadresse).

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sascha T. wrote:
> Wenn ich in der Interruptroutine mein Abschaltkriterium erkenne, dann
> mein SREG wieder zurückschreibe und den Interrupt durch cli zurücksetze
> bin ich doch wieder sauber
Nö, bist Du nicht. Was ist mit dem Stack (Programmzähler)?

Ich weiß nicht, ob ich zu 100% verstehe, was Du machen willst, aber wenn 
Du bei Auftreten eines speziellen Interrupt möchtest, dass nach der 
Rückkehr aus dem Handler die Interrupts nicht automatisch wieder 
freigegeben werden, dann mach den Rücksprung mit einem ret anstelle 
des reti. Der einzige Untschied des reti gegenüber einem ret ist 
schließlich, dass das reti das I-Bit im SREG wieder setzt.

Wenn Du allerdings einfach aus dem Handler das Programm quasi als 
"Warmstart" von Anfang an neu starten willst (also ein Reset), dann 
kannst Du natürlich zur Adresse 0 jumpen und anschließend bei der 
Stack-Neuinitialisierung wird eh alles, was vorher da war, platt 
gemacht. Das setzt natürlich voraus, dass Dein Controller keinen 
Hardware-Stack hat und dass der Stack am Programmanfang tatsächlich 
explizit initialisiert wird (was bei neueren AVRs eigentlich nicht mehr 
unbedingt eforderlich ist, da der Reset-Wert des Stack Pointers schon 
entsprechend gesetzt ist).

Von einer direkten Stackmanipulation ist abzuraten.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Um es kurz zu machen (und ohne das Programm gesehen zu haben):
Dein Programmierstil ist falsch :-o

Du solltest in deinem Programm zyklisch die Schritte
- Eingabe 
    (nur hier werden Eingänge in das Prozessabbild eingelesen)
- Verarbeitung 
    (Verknüpfen der eingelesenen Eingänge mit dem aktuellen Zustand)
- Ausgabe
    (nur hier werden die Ausgänge des Prozessabbilds geschrieben)
durchlaufen. Die Durchlaufzeit muß so kurz sein, dass deine Definition 
von "Echtzeit" erfüllt ist.
In einer etwaigen Interruptroutine werden nur Flags gesetzt, die im 
Eingabeteil auf dein Prozessabbild eingelesen werden.

Auf diese Art funktionieren zigtausende SPSen (und alle meine Programme) 
problemlos.

Autor: Winfried (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für Sonder-/Ausnahmebehandlung kann man so ein Design durchaus machen. 
Ich sehe erstmal nichts, was dagegen spricht, insofern du das Programm 
dann vollständig neu startest und alle Hardware nicht in gefährliche 
Zustände reinfahren kann.

Autor: Sascha T. (ernie1973)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die ersten Hinweise.

Im Grunde will ich halt sicherstellen, dass z.B. alle 100µs überprüft 
wird, ob die Taste noch gedrückt ist und nicht losgelassen wurde. Diese 
regelmäßige Überprüfung ist ein Sicherheitskriterium und ist halt nur 
mit einem Interrupt sauber zu lösen.

Während des Programmablaufs werden halt viele Routinen durchlaufen und 
ich müßte in jeder Routine eine Abfrage reinbringen und ob in dem Timer 
Interrupt ein Merker für das Loslassen der Taste gesetzt wurde. So wäre 
es vielleicht "sauber" programmiert.

Wenn ich aber den Programmablauf direkt im Interrupt abbreche, kann ich 
mir diese Abfragen ja sparen und ich finde diesen Ablauf vom Sinn her 
"sauberer". Der Interrupt soll ja den normalen Programmablauf 
unterbrechen :o)

Die Frage ist halt, was ich alles berücksichtigen müßte, damit der 
Interrupt sauber beendet wird.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du kannst Dir nen Longjump in Assembler proggen:
.dseg
longjump_addr:  .db 2
.cseg

longjump_dst:
        cli
        in      r16, spl
        sts     longjump_addr, r16
        in      r16, sph
        sts     longjump_addr+1, r16
        sei
; ...


; sprung zu longjump_dst:
        cli
        lds     r16, longjump_addr
        out     spl, r16
        lds     r16, longjump_addr+1
        out     sph, r16
        rjmp    longjump_dst


Peter

Autor: Hannes Lux (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Im Grunde will ich halt sicherstellen, dass z.B. alle 100µs überprüft
> wird, ob die Taste noch gedrückt ist und nicht losgelassen wurde. Diese
> regelmäßige Überprüfung ist ein Sicherheitskriterium und ist halt nur
> mit einem Interrupt sauber zu lösen.

Dann zieh' halt mit der Taste Reset gegen einen PullDown-R nach Vcc... 
;-)

...

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sascha T. wrote:
> Im Grunde will ich halt sicherstellen, dass z.B. alle 100µs überprüft
> wird, ob die Taste noch gedrückt ist und nicht losgelassen wurde.

Kein Mensch kann nur 100µs lang ne Taste betätigen.
Bei menschlicher Betätigung sind 100ms vollkommen ausreichend.


> Diese
> regelmäßige Überprüfung ist ein Sicherheitskriterium und ist halt nur
> mit einem Interrupt sauber zu lösen.

100µs sind gut geeignet, alle möglichen Störimpulse fälschlich als 
Loslassen zu erkennen.


> Während des Programmablaufs werden halt viele Routinen durchlaufen und
> ich müßte in jeder Routine eine Abfrage reinbringen und ob in dem Timer
> Interrupt ein Merker für das Loslassen der Taste gesetzt wurde. So wäre
> es vielleicht "sauber" programmiert.

Sauber (d.h. Fehlersicher) wäre es, wenn Du die Taste entprellst (4 
Abfragen etwa alle 10ms sind gleich).


Peter

Autor: Sascha T. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hatte mich sowieso verschriebn. Aktuell prüfe ich die Taste alle 100ms. 
Entprellung steht sowieso schon hardwareseitig.

Aber es geht hier doch um was anderes. Normalerweise habe ich auch immer 
strikt zyklisch programmiert und alle Interruptroutinen sauber beendet.

In diesem Fall habe ich aber mal umgedacht und zwar aus folgenden 
Gründen:

Der Tastendruck und das Halten der Taste ist für einen bestimmten 
Programmteil die Voraussetzung und höchste Priorität. Einen Reset direkt 
kann ich nicht durchführen, da ich ja eine Fehlermeldung erzeugen muss. 
Während diese Programmablauf werden z.B. UART und SPI 
Kommunikationsroutinen aufgerufen. Diese Routinen rufen ja wieder 
Abfrageroutinen auf z.B. ob etwas empfangen wurde. Diese Abfrageroutinen 
laufen natürlich Schleifen durch und werden z.B. abgebrochen wenn 
mehrere Sekunden lang nichts empfangen wurde.

Wenn ich jetzt "normal" programmiere, dann frage ich in der Schleife 
einen Merker ab, ob bei dem Timer Interrupt ein Loslassen der Taste 
festgestellt wurde. Falls ja breche ich ab und springe zu der Routine 
darüber. Dort muss ich natürlich auch wieder abfragen, ob der Merker 
gesetzt wurde und dann diese Routine verlassen. Wenn ich dann im 
Hauptprogramm bin, dann muss ich natürlich auch wieder gucken ob der 
Merker gesetzt wurde und dann springe ich endlich in meine 
Fehlerroutine.

Ist ja so weit auch kein Problem. Allerdings muss ich dann diese 
Abfragen überall einfügen und die Gefahr besteht, dass ich irgendwo mal 
eine vergesse und somit doch mal eine Verzögerung bis zum Erkennen des 
Loslassen habe.

Somit ist die Beendigung des Programmablaufs direkt im Interrupt 
natürlich eine sichere Sache. Ich habe das Programm ja aktuell so laufen 
und es funktioniert auch einwandfrei. Aber ich wollte halt mal 
theoretisch nachvollziehen, ob diese Art der Interruptbeendigung zu 
Problemen führen könnte.

Autor: Uwe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!
Ja das geht, habe ich selbst schon gemacht.
Aber du musst auch den Resetstatus der Register und E/A's bedenken wenn 
du dir keine Fehler einbauen willst.
Eine andere Möglichkeit wäre noch den µC vom Wachhund schnappen zu 
lassen.
Das ist dann, glaube ich jedenfalls, ein sauberes Reset.

Autor: Sascha T. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Register und E/A werden ja im Reset wieder definiert. Aber was ist 
dem Stack. Habe ich da was zu befürchten?

Autor: Uwe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!
>Aber was ist dem Stack. Habe ich da was zu befürchten?
Hä? Initialisierst du den am Anfang nicht? Das ist doch Standard.
Da muss man eher aufpassen dass alle I-Flags gelöscht werden.
(meine nicht das I-Flag im SREG)

Viel Erfolg, Uwe

Autor: Klugscheisser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Sascha

Ich meine Deine Gründe zu verstehen und die Lösungsansätze die hier 
genannt wurden, sind sicherlich sinnvoll.
Trotzdem kräuselt sich da was bei mir und ich habe mir überlegt ob es 
nicht doch eine "saubere" Möglichkeit gibt.

Wenn Du den Ablauf in mehrere Teilschritte unterteilen kannst 
(vermutlich rufst Du ohnehin verschiedene Funktionen auf und hast nicht 
eine Riesenfunktion) dann wäre eine Lösung, das Du eine State-Machine 
daraus machst und vor dem Wechsel in den jeweiligen Folgezustand ein 
Flag abfragst, das in dem fraglichen Interrupt gesetzt werden kann.
Auf diese Weise wärst Du sicher, regelmäßig die Abfrage zu machen, hast 
aber trotzdem nur eine Stelle im Code wo diese geschieht und vermeidest 
dieses return-from-int ohne RETI.
Genaugenommen hat diese Methode allerdings doch einen Nachteil. Wie fein 
die möglichen Abbruchstellen im Ablauf verteilt sind (das ist ein 
bischen ungeschickt ausgedrückt) hängt davon ab, wieviele Zustände Du 
der State-Machine gibtst. Je mehr desto feiner.

Naja. Vielleicht hilft Dir das was.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Uwe wrote:
> Hä? Initialisierst du den am Anfang nicht? Das ist doch Standard.
Hab ich oben schon mal erwähnt: Bei den neueren AVRs muss man den Stack 
Pointer nicht mehr zwangsläufig von Hand initialisieren, da der 
Reset-Wert schon auf RAMEND voreingestellt ist...

Autor: Sascha T. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die weiteren Hinweise.

@Klugscheisser: Ich verstehe jetzt nicht ganz was Du meinst. Ist diese 
State Machine denn nicht dasselbe wie ein Merker, den ich mir in der 
Interruptroutine setzte und dann bei jeder Unterroutine abfrage?

@Uwe: Du hast ja recht, natürlich initialisiere ich den Stack zu Beginn. 
Also dürfte ja kein Risiko bestehen, wenn ich im Interrupt die 
Fehlerausgabe mache und einen Reset durchführe. Welche Interrupt Flags 
meinst Du denn noch?

Autor: Klugscheisser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Sascha

>Ich verstehe jetzt nicht ganz was Du meinst. Ist diese
>State Machine denn nicht dasselbe wie ein Merker, den ich mir in der
>Interruptroutine setzte und dann bei jeder Unterroutine abfrage?
Möglicherweise verstehe ich Dich jetzt nicht.
Ein Merker ist grundsätzlich etwas anderes als eine State-Machine.

Ich konstruiere mal ein Beispiel:

Gegeben sei etwa folgernder Pseudcode, den es gilt unterbrechbar zu 
machen.
In diesen würdest Du dann (was Du ja vermeiden möchtest den Test auf das 
Flag einfügen:
a();
flag_test();
b();
flag_test();
c();
flag_test();
d();
flag_test();
e();
flag_test();
f();
flag_test();
g();
flag_test();
h();
flag_test();
i();
flag_test();

Daraus würde ich nun die State-Machine machen:
do {
   switch (state) {
      case 1: a(); state = 2; break;
      case 2: b(); state = 3; break;
      case 3: c(); state = 4; break;
      case 4: d(); state = 5; break;
      case 5: e(); state = 6; break;
      case 6: f(); state = 7; break;
      case 7: g(); state = 8; break;
      case 8: h(); state = 9; break;
      case 9: i(); state = 10; break;
      default: break;
   }
   if (test_flag ()) state = 10; // "Ausnahmezustand"
} while (state != 10);    // 10 ist der Endzustand


Das kann man noch varieren, aber so ungefähr.

Klar?

Autor: Sascha T. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, aber da ich in Assembler programmiere kann ich dir auf Anhieb 
nicht folgen. Deshalb kenne ich wohl auch keine State Machine :(

Autor: Klugscheisser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
State-Machines sind ein Konzept. Hat nichts mit der Programmiersprache 
zu tun. Soll heissen: Wenn Du Asm kannst dann begreifst Du auch das.

Ein wenig gurgeln sollte die grundlegende Idee klarmachen.

(More-Mealy vielleicht noch vom Studium bekannt?)

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sascha T. wrote:
> Hallo,
>
> Sobald die Taste losgelassen wird oder die Zeit überschritten wird muss
> der Ablauf sofort unterbrochen werden und es soll eine Fehlermeldung
> kommen. Danach wird das Programm von vorne gestartet.
>
> Die Überwachung der Abschaltkritierien erolfgt regelmäßig über Timer
> Interrupts. Selbstverständlich kann ich mir dort einen Merker setzen und
> diesen im Hauptprgramm abfragen. Allerdings muss ich die diese Abfrage
> dann im Hauptprogramm an sehr viellen Stellen einfügen, damit es zu
> keiner großen Verzögerung der Abschaltung kommt.
>
> Aus diesem Grunde würde ich gerne direkt im Interrupt abschalten die
> Fehlermeldung ausgeben und danach das Programm wieder von vorne starten.
> Ich lese zwar öfters, dass es nicht sauber oder nicht der Sinn einer
> Interruptroutine ist, aber spricht theoretisch wirklich was dagegen?

Was spricht dagegen, das in der ISR zu machen?

Wenn die Bedingung ni der ISR erfüllt ist, wird die Fehlermeldung 
ausgegeben (wie immer das auszusehen hat) und der µC macht per WatchDog 
nen RESET.

Wenn die Fehler absolute Priorität hat, dann ist's nun mal so. Ich würd 
mir da keinen Kopp um irgendwelche Dogmen machen (eine ISR darf nicht 
"lange" dauern, etc.)

Nach der Meldung erfolgt der RESET per WatchDog, weil er im Gegensatz zu 
einem direkten Sprung zum Reset-Vektor die Hardware zurücksetzt (Timer, 
UART, SPI, ...)

Und dann begint das Spiel von neuem. Wozu also die Applikation 
verfrickeln mit Abfragen?

Weitere Möglichkeit könnte ein Software-Interrupt sein, aber dafür weiß 
man zu wenig über deine Anwendung.

Johann

Autor: Sascha T. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt, dass ist eigentlich eine sehr gute Idee. Sobald in der 
Interruptroutine erkenne, dass die Taste losgelassen wurde gebe ich kurz 
die Fehlermeldung aus (3 Bytes über SPI) und dann lasse ich den Wachhund 
los.

Mit einem Softwarinterrupt habe ich mich bisher nocht nicht beschäftigt. 
Hört sich aber auch gut interessant an.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Deshalb kenne ich wohl auch keine State Machine :(
Ich hatte den Verdacht schon recht früh:
>> Dein Programmierstil ist falsch :-o

Sieh dir mal das an:
:
:
    rcall  SIOInit         ;
    rcall  ADInit          ;
    rcall  InterruptInit   ;
    sei                    ; 
forever:                   ; Endlosschleife, ein Durchlauf dauert max. 300us
    rcall  SioEinlesen     ;
    rcall  ADWandlung      ;
    rcall  InputsEinlesen  ;
    rcall  DrehzahlEinlesen;
    rcall  Greifer         ;
    rcall  Ventil          ; 
    rcall   Ausgabe        ;
    rcall  SIOAusgabe      ;
    rcall  Fehler          ;
    rjmp  forever          ; eternal loop

Und hier exemplarisch die Funktion zum Zeicheneinlesen
SioEinlesen:
    sbis  UCSRA,RXC    ; Zeichen da?
    ret                ; nein: sofort Ende
                       ;
    in  temp,UDR       ; sonst: Daten holen
    sbrc  temp,6       ; Zahlen nicht wandeln
    andi  temp,$DF     ; Umwandlung kleine->grosse Buchstaben
                       ; a..f: $61..$66,  A..F: $41..$46
    cpi   temp,'T'     ; 'T' angekommen? Tabellenanfang
    brne  SE000        ; nein: weiter
    clr   RxCnt        ; Zaehler zuruecksetzen
    ret                ;

SE000:  cpi   temp,'Z' ; 'Z' angekommen? 
    brne  SE00a        ; nein: weiter
    ret                ; ja: Ende
:
:
Es wird nicht gewartet, bis ein Zeichen da ist. Sondern wenn kein 
Zeichen da ist, bin ich sofort fertig und es geht weiter in der 
Haupt-Schleife. In keiner der Unterprogramme wird auf irgendwas 
gewartet. Es wird erst geprüft, ob sich etwas geändert hat (z.B. ein 
Eingang, Timer oder ein anderer Zustand) und dann darauf reagiert.

@ Johann L.
> Nach der Meldung erfolgt der RESET per WatchDog, weil er im Gegensatz
> zu einem direkten Sprung zum Reset-Vektor die Hardware zurücksetzt
> (Timer, UART, SPI, ...)
> Und dann begint das Spiel von neuem.
Na toll, hoffentlich passiert das nicht beim Landeanflug....  :-/
Game Over *Insert Coin*

Autor: Sascha T. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja von Automaten habe ich schonmal was gehört, auch wenn es auch schon 
lange her ist. State-Machine war mir bisher allerdings kein Begriff.

Aber vielen Dank Lothar. Mit der Assembler Routine ist das Prinzip 
direkt bei mir angekommen. Das trifft halt meine Synapsen schneller als 
die C Routinen, ist ja auch "Hardwarenäher" :o)

Ich werde mir mein Programm morgen nochmal dahingehend anschauen und 
denke, dass ich es dann auch sehr gut ohne Interrupt Abbruch hinbekomme.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller wrote:

> @ Johann L.
>> Nach der Meldung erfolgt der RESET per WatchDog, weil er im Gegensatz
>> zu einem direkten Sprung zum Reset-Vektor die Hardware zurücksetzt
>> (Timer, UART, SPI, ...)
>> Und dann begint das Spiel von neuem.
> Na toll, hoffentlich passiert das nicht beim Landeanflug....  :-/
> Game Over *Insert Coin*

Klar. Ein AKW schaltet man auch nicht einfach aus. Ich vermute mal, daß 
die Anwendung kein AKW oder Airbus steuert. Und wenn für die Anwendung 
ein RESET ok ist, kommt das als "Design Pattern" auch in Betracht. (Ich 
selbst würd es zugegebenermassen ohne Reset machen).

Zumal 3 Bytes per SPI auszugeben ist doch kein Drama, also warum nicht 
einfach ausgeben? Ausser, wenn die Übtrtragungsrate 1 Bit/Minute ist. 
Und selbst dann geht das über des SPI-IRQ (falls HW-SPI).

Johann

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johann L. wrote:
> Und wenn für die Anwendung
> ein RESET ok ist, kommt das als "Design Pattern" auch in Betracht. (Ich
> selbst würd es zugegebenermassen ohne Reset machen).

Ich würds mal so formulieren:
Da das Kind nun mal in den Brunnen gefallen ist, ist es vernünftig das 
Beste draus zu machen und einen Schwimmreifen hinterher zu werfen.
Aber für die Zukunft merken dass ein Gitter am Brunnen das Ganze hätte 
verhindern können.

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.