mikrocontroller.net

Forum: Compiler & IDEs SPI Probleme beim Auslesen


Autor: Andi B. (g_r_i_z_z_l_y)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wunderschönen Guten Abend!

...bzw. wohl besser Nacht, denn ich zerbreche mir hier schon seit 
Stunden den Kopf und kann den Fehler nicht finden.

Zu meinem Problem: Ich habe hier eine 8x8 Tastaturmatrix angeschlossen 
(Reihen) an das zweite von vier 74HC595. Der Status (Spalten) wird über 
ein 74HC165 ausgelesen.

Für einen Test habe ich folgende Zeilen Code geschrieben, die alle 
Zeilen durchgeht und mir die aktiven Spalten an ein 7-Segment-Display 
ausgibt:
while (1) {
    
    char byte_tmp = 0x00;
    char c_tmp[1];
    int i;

    for(i=1; i<9; i++) {
      
      waitms(100);

      byte_tmp = field_read_row(i);
      
      // first received bit is PINH/D7 == COL H
      if(byte_tmp) {
        
        itoa(i,c_tmp,10);
        switch(byte_tmp)
        {
          case 0x80: send_disp(c_tmp[0], 'H');  break; // 10000000 0x80
          case 0x40: send_disp(c_tmp[0], 'G');  break; // 01000000 0x40
          case 0x20: send_disp(c_tmp[0], 'F');  break; // 00100000 0x20
          case 0x10: send_disp(c_tmp[0], 'E');  break; // 00010000 0x10
          case 0x08: send_disp(c_tmp[0], 'D');  break; // 00001000 0x08
          case 0x04: send_disp(c_tmp[0], 'C');  break; // 00000100 0x04
          case 0x02: send_disp(c_tmp[0], 'B');  break; // 00000010 0x02
          case 0x01: send_disp(c_tmp[0], 'A');  break; // 00000001 0x01
        }
      }  
    }    
  }

Die aktiven Spalten werden mir auch korrekt ausgegeben, nur leider immer 
für zwei übereinanderliegende Reihen. Er springt also immer zwischen 
korrekter und +1 hin&her. Hardwareseitig hab ich die Sache schon 
überprüft und konnte keinen Fehler entdecken.

Der Code für die Abfrage lautet:
char field_read_row(char row) {

  char byte_tmp = 0x01;
  
  switch(row)
  {
    case 8: byte_tmp <<= 0;  break; // 00000001 0x01
    case 7: byte_tmp <<= 1;  break; // 00000010 0x02
    case 6: byte_tmp <<= 2;  break; // 00000100 0x04
    case 5: byte_tmp <<= 3;  break; // 00001000 0x08
    case 4: byte_tmp <<= 4;  break; // 00010000 0x10
    case 3: byte_tmp <<= 5;  break; // 00100000 0x20
    case 2: byte_tmp <<= 6;  break; // 01000000 0x40
    case 1: byte_tmp <<= 7;  break; // 10000000 0x80
  }

  byte_reed = byte_tmp;
  
  // RCK -> low
  PORTB &= ~(PORT_SS);
  // PL -> low
  PORTB &= ~(PORT_PL);
  // send bytewise in corresponding order of shift registers
  // µC -> RED -> REED -> GREEN -> GND
  SPI_MasterTransmit(byte_gnd);
  SPI_MasterTransmit(byte_grn);
  SPI_MasterTransmit(byte_reed);
  SPI_MasterTransmit(byte_red);
  // RCK -> high will set shift register > storage register
  PORTB |= (PORT_SS);
  // set clock pulse high and... (CLK & PL are internally wired together)
  //PORTB |= (PORT_SCK); // due to CPOL=1, SCK is high when idle
  // PL -> high will load pin state to shift register
  PORTB |= (PORT_PL);
  // activate Clock Enable input
  PORTB &= ~(PORT_CE);
  // receive data
  byte_tmp = SPI_MasterReceive();
  // deactivate Clock Enable input
  PORTB |= (PORT_CE);
  
  // byte_tmp = COL HGFEDCBA
  //        bit 7......0
  return (byte_tmp);
}

Die SPI Sende-/Empfangsroutinen:
void SPI_MasterTransmit(char cData) {
  
  // SPI Config: CPOL=1, CPHA=1 (we use SPI Mode 3 on HC595)
  SPCR |= (1<<CPOL)|(1<<CPHA);
  // Start transmission
  SPDR = cData;
  // Wait for transmission complete
  while(!(SPSR & (1<<SPIF)));
}

char SPI_MasterReceive( void ) {

  //SPI Config: CPOL=1, CPHA=0 (we use SPI Mode 2 on HC165)
  SPCR &= ~(1<<CPHA);
  // set dummy byte to SPDR for receiving data
  SPDR = 0x00;
  // Wait for reception complete
  while(!(SPSR & (1<<SPIF)));
  // Return Data Register
  return SPDR;
}

Ich habe bereits versucht die Taktrate zu senken, verschiedene 
Warteschleifen eingebaut und auch die Simulation hat mir leider nicht 
weitergeholfen.

Besten Dank für Eure Hilfe!

Gruss,
Andi

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
itoa erzeugt Strings, also mit einer Null-Terminierung. 1 ist als Größe 
für c_tmp daher zu wenig.

Autor: Andi B. (g_r_i_z_z_l_y)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es passt aber...da 'i' ja nie grösser als 9 wird, sollte in 'itoa' 
eigentlich nicht mehr passieren als: c_tmp[0] = '0' + i % 10; ,oder ?

Ich hab's aber jetzt trotzdem durch ('0' + i) ersetzt, spart ein wenig 
Platz...

Das Problem bleibt leider immer noch dasselbe. Ist Spalte A in Zeile 1 
aktiv, dann pendelt die Anzeige zwischen '1A' und '2A'.

Ich frage nie diesselbe Zeile zweimal ab und die Übertragung zum Display 
ist auch korrekt. Aber irgendwo muss noch ein '+1' versteckt sein...

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andi B. schrieb:
> Es passt aber...da 'i' ja nie grösser als 9 wird, sollte in 'itoa'
> eigentlich nicht mehr passieren als: c_tmp[0] = '0' + i % 10; ,oder ?

Doch, c_tmp[1] wird mit '\0' beschrieben -- und den Platz dafür
hast du ihm nicht eingeräumt.

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

Bewertung
0 lesenswert
nicht lesenswert
Ich würde vorschlagen, das Programm noch mal abzuspecken. Vergiss den 
genzen Schnickschnack mit den Buchstaben. Gib den Wert den du von der 
read Routine erhältst direkt aus, ohne Umwege.
Ein char Array gross genug dimensionieren, den Wert mittels itoa wandeln 
lassen, davor und dahinter noch ein Leerzeichen und raus damit aufs LCD.

(Solche Buffer, die für itoa oder sprintf benutzt werden, dimensioniert 
man NIE auf Knirsch.)

Autor: Andi B. (g_r_i_z_z_l_y)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt! Der Null-Term gehört natürlich dazu... aber wie gesagt, ich hab 
es bereits ersetzt, Fehler bleibt.

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

Bewertung
0 lesenswert
nicht lesenswert
Andi B. schrieb:

> Ich frage nie diesselbe Zeile zweimal ab und die Übertragung zum Display
> ist auch korrekt. Aber irgendwo muss noch ein '+1' versteckt sein...

+1 eher nicht.
Da du alles in 2-er Potenzen kodiert hast, taucht da irgendwo ein 
Bit-Versatz um 1 Bit auf. Sicher dass die SPI_MasterReceive so korrekt 
ist? Hast du die einzeln getestet?

Autor: Andi B. (g_r_i_z_z_l_y)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja ich hatte auch schon überlegt, ob ich mir in SPDR alte Werte 
einfange. Aber  zwischen den einzelnen Ausleseroutinen liegen 4 
Senderoutinen (0x00, 0x00, 0x01[<- Reihen], 0x00) und das Dummybyte beim 
Auslesen sollte keine Probleme machen.

Displayroutine ist auch in Ordnung und kodiert die anzuzeigenden Zeichen 
pro Aufruf jeweils neu.

Bleibt nur, dass bei zwei aufeinanderfolgenden Abfragen der gleiche Wert 
von SPDR zurückgegeben wird.

Edit: Kann es Probleme mit dem Umschalten des SPI Modes während der 
Laufzeit geben ?

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

Bewertung
0 lesenswert
nicht lesenswert
Andi B. schrieb:

> Edit: Kann es Probleme mit dem Umschalten des SPI Modes während der
> Laufzeit geben ?

Daran hab ich auch schon gedacht.
Daher die Frage, ob du die Receive einzeln getestet hast?

Matrix vom 595 abhängen. Nur einlesen und anzeigen. Und dann händisch 
eine Zeile mit einem Stück Draht aktivieren.

Autor: Andi B. (g_r_i_z_z_l_y)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok...war ein wenig umständlicher als gedacht, da Matrixein/-ausgang auf 
demselben Pfostenstecker enden. Wie dem auch sei, ich habe jetzt die 
vorherigen 595-Senderoutinen entfernt, eine einzelne Zeile an Vcc 
gehängt und lasse mir den ausgelesenen Wert anzeigen.
while (1) {
    
  char byte_tmp = 0x00;
  int i;

  for(i=1; i<9; i++) {
      
    waitms(100);
      
    byte_tmp = field_read_row(i);
    send_disp(('0'+i), (byte_tmp));
  }
}

Ist keine Spalte aktiv, wirft er mir sporadisch die Werte ' '(0x20) & 
'.'(0x2E) aus. Ist eine Spalte dagegen aktiv, kommt gar nix.

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

Bewertung
0 lesenswert
nicht lesenswert
Andi B. schrieb:
> Ok...war ein wenig umständlicher als gedacht, da Matrixein/-ausgang auf
> demselben Pfostenstecker enden. Wie dem auch sei, ich habe jetzt die
> vorherigen 595-Senderoutinen entfernt, eine einzelne Zeile an Vcc
> gehängt und lasse mir den ausgelesenen Wert anzeigen.
>
>
> while (1) {
> 
>   char byte_tmp = 0x00;
>   int i;
> 
>   for(i=1; i<9; i++) {
> 
>     waitms(100);
> 
>     byte_tmp = field_read_row(i);
>     send_disp(('0'+i), (byte_tmp));
>   }
> }
>
> Ist keine Spalte aktiv, wirft er mir sporadisch die Werte ' '(0x20) &
> '.'(0x2E) aus. Ist eine Spalte dagegen aktiv, kommt gar nix.

Irgendwas muss kommen.
Gar nix ist in deinem Programm nicht vorgesehen :-)

Machst du dir das Leben absichtlich schwer?
>     send_disp(('0'+i), (byte_tmp));
und jetzt aus 0x20 zurückrechnen, welche Bits gesetzt sein müssen, damit 
bei einer Addition mit '0' genau 0x20 rauskommt? Du wirst doch wohl eine 
Funktion haben, die einen String aufs LCD pinseln kann

  while (1) {

  char byte_tmp = 0x00;
  char buffer[20];
  int i;

   for(i=1; i<9; i++) {

     waitms(100);

     byte_tmp = field_read_row(i);
     format( byte_tmp, buffer );
     send_string( buffer );
   }
 }

void format( char* buffer, unsigned char byte )
{
  char tmp[20];
  char zeros[] = "00000000";

  utoa( byte, tmp, 2 );
  strcpy( buffer, &zeros[ strlen( tmp ) ];
  strcat( buffer, tmp );
}

und dann kann man sich auch mal die Bits in 'Aktion' ansehen.
Welche stehen wie eine 1, welche kippen. Wandern sie vielleicht durch 
das Byte durch etc.

Um das gleich klarzustellen:
Offensichtlichen Fehler gibt es in deinem Programm keinen mehr. Daher 
musst du dir selber helfen, wir hier auf der anderen Seite des Schirms 
können nur noch raten (es sei denn jemand hat noch eine göttliche 
Eingebung). Dazu musst du dir aber eine Visualisierung der Daten 
schaffen, mit der du etwas anfangen kannst. Bei dir spielt sich da 
irgendwas auf Bitebene ab, also ist es sinnvoll, sich die 
Einelese-Ergebnisse auch auf Bitebene anzusehen (dann braucht man nicht 
dauernd umrechnen)

Autor: Andi B. (g_r_i_z_z_l_y)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh, da hat ich wohl noch einen Denkfehler drin. Muss natürlich:
send_disp(('0'+i), ('0'+byte_tmp));

heissen und sollte mir dir aktiven Spalten bis A bis D (entsprechend '1' 
bis '8') anzeigen. Tut's natürlich nicht, sondern spuckt willkürliche 
(?) Werte ohne erkennbares Muster aus.

Autor: Andi B. (g_r_i_z_z_l_y)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Machst du dir das Leben absichtlich schwer?

Ja, das Gefühl hab ich schonmal...aber ohne wär ja langweilig ;)

LCD hängt keins dran, nur ein doppeltes 7-Segment-Display am 
I2C-Controller.  Aber Du hast Recht, ich werd das Ganze mal so umbauen, 
dass ich die ausgelesenen Bits direkt angezeigt bekomme. Wärn's doch 
8-Segmenter ;-))

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

Bewertung
0 lesenswert
nicht lesenswert
Andi B. schrieb:

> LCD hängt keins dran, nur ein doppeltes 7-Segment-Display am
> I2C-Controller.

Tschuldigung. Mein Fehler.
Da hab ich wohl die Informationen aus ein paar anderen Threads 
durcheinander gewürfel. Hst du ja ganz am Anfang schon gesagt, dass da 
ein 7_Seg drann hängt.

>  Aber Du hast Recht, ich werd das Ganze mal so umbauen,
> dass ich die ausgelesenen Bits direkt angezeigt bekomme. Wärn's doch
> 8-Segmenter ;-))

Du hast ja 2 davon :-)
Und ein Byte hat 2 Nibbles, die man wunderbar als jeweils eine 
HEX-Ziffer auf einem 7-Seg anzeigen kann :-)

Autor: Andi B. (g_r_i_z_z_l_y)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für Deine Hilfe Karl Heinz!

Mir scheint ich hab hier ein weitaus schwerwiegenderes Problem, da ich 
je nach Handauflegen ein anderes Bitmuster erzeugen kann... (und das hab 
ich jetzt grad noch gebraucht)

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Mir scheint ich hab hier ein weitaus schwerwiegenderes Problem, da ich
>je nach Handauflegen ein anderes Bitmuster erzeugen kann... (und das hab
>ich jetzt grad noch gebraucht)

Das riecht geradezu nach floatenden Pins oder nach
Haarrissen und dadurch nur kapazitive Kopplung.
Oder kalte Lötstelle.

Autor: Andi B. (g_r_i_z_z_l_y)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kalte Lötstellen und Haarrisse kann ich ausschließen, der Aufbau 
befindet sich auf einem Sperrholzbrettchen. Dann wohl eher das 
"spassige" Kabelgewirr auf der Unterseite.

Nochmal zur Idee von Karl-Heinz, die Anzeige des Bitmusters (LS0-3 sind 
die Register des I2C-Controller):
char tmp_ascii[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
  
decode_char(tmp_ascii[(bits >> 4)], 1, &LS0, &LS1);
decode_char(tmp_ascii[(bits & 0xF)], 0, &LS2, &LS3);

ergibt beim Test, wie schon erahnt, eine Bitverschiebung.

Spalte  erwartet  ausgelesen
1.      0x01    0x02
2.      0x02    0x04
3.      0x04    0x08
4.      0x08    0x10
5.      0x10    0x20
6.      0x20    0x40
7.      0x40    0x80
8.      0x80    0x10

...und das jeweils für zwei auffeinanderfolgende Zeilen.

Autor: Andi B. (g_r_i_z_z_l_y)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, die o.a. Verschiebung hat sich wieder erledigt...mein Fehler. Ich 
hatte zwischenzeitlich den SPI Mode beim Senden von 3 auf 0 geändert, 
was natürlich genau das hervorruft.

> ...und das jeweils für zwei auffeinanderfolgende Zeilen.

Aber daran verzweifel ich grad...

Autor: Andi B. (g_r_i_z_z_l_y)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mahlzeit und ein kurzes Update:

Nachdem ich nochmals an den einzelnen Pins des HC165 nachgemessen habe 
und dort auch wirklich nur die aktiven Spalten der Matrix wiedergefunden 
habe, scheint es wohl doch das SPDR zu sein welches bei einmaliger SPI 
Abfrage die falschen Werte (sprich bei 2 aufeinanderfolgenden Zeilen die 
gleichen aktiven Spalten) ausgibt.

Ich habe das Auslesen dementsprechend auf eine mehrmalige Abfrage 
geändert:
for(i=1; i<9; i++) {
      
  j=0;
  while(j<200) {
            
    byte_tmp = field_read_row(i);
    send_disp_bits(byte_tmp, i);
    waitms(100);
    j++;}
}

...und überlege nun, ob ich das Ganze in die o.a. 'SPI_MasterReceive()' 
(vorheriges Neuladen des HC165 vorrausgesetzt) oder in die Routine zum 
Spalten auslesen 'field_read_row(char row)' packe.

btw: Zusätzliche hochohmige Pulldown-Widerstände an den Eingängen des 
HC165 scheinen wohl auch nicht verkehrt.

Autor: Andi B. (g_r_i_z_z_l_y)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Update 2: Und wenn man vor dem Crimpen des Pfostensteckers das Ende des 
Flachbandkabels ordentlich abschneidet, so dass keine Kupferadern als 
kleine Antennen herausschauen, verschwinden auch die Probleme des 
"Handauflegens".

Und wie bereits gesagt, mit mehrfachem Auslesen funktioniert nun alles 
bestens!

(Nur das angesprochene SPDR Problem bleibt mir immer noch ein Rätsel...)

Gruss,
Andi

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Andi B. schrieb:

>btw: Zusätzliche hochohmige Pulldown-Widerstände an den Eingängen des
>HC165 scheinen wohl auch nicht verkehrt.

Falls da Tasten an den Eingängen sind, wo soll wohl bei offener Taste 
ein definierter Pegel herkommen? Das ist CMOS, das lädt sich je nach 
Sonnenstand, Luftfeuchte, Stürungen im Umfeld auf irgendwas auf...

Selbstverständlich müssen da PullDown/PullUp-Widerstände ran, je nach 
dem wie der Ruhepegel sein soll.

PS: Mit Schaltplan hätten es die Forumsmitglieder merklich einfacher 
gehabt.

Gruß aus Berlin
Michael

Autor: Andi B. (g_r_i_z_z_l_y)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael U. schrieb:
> Selbstverständlich müssen da PullDown/PullUp-Widerstände ran, je nach
> dem wie der Ruhepegel sein soll.

Daran zweifelt ja keiner. Aber das war ja nicht das ursprüngliche 
Problem, welches nach wie vor eigentlich vorhanden ist und bei dem der 
Schaltplan nicht weiterhilft.

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Andi B. schrieb:
> Michael U. schrieb:
>> Selbstverständlich müssen da PullDown/PullUp-Widerstände ran, je nach
>> dem wie der Ruhepegel sein soll.
>
> Daran zweifelt ja keiner. Aber das war ja nicht das ursprüngliche
> Problem, welches nach wie vor eigentlich vorhanden ist und bei dem der
> Schaltplan nicht weiterhilft.

ich habe nicht alles verfolgt, aber Du bist sicher, daß Du einen 
Programmfehler suchst und nicht einfach nur die offenen Leitungen des 
HC165 viel zu lange brauchen, un einen definierten Pegel anzunehmen?

Wer sagt Dir, daß nicht schon das kapazitive Übersprechen zwischn den 
benachbarten Pins und Leitungen für den Fehler sorgt?

Ich habe jedenfalls noch keine Abweichung im Verhalten des SPI gefunden, 
der hat bisher immer genau das eingelesen, was ihm von außen angeboten 
wurde.

Dein "mehrmals einlesen" deutet zumindest darauf hin, daß die Pegel an 
den Eingängen des 165 ewig brauchen, bis sie mal zu Deinen Erwartungen 
passen.

Gruß aus Berlin
Michael

Autor: Andi B. (g_r_i_z_z_l_y)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael U. schrieb:
> ich habe nicht alles verfolgt, aber Du bist sicher, daß Du einen
> Programmfehler suchst und nicht einfach nur die offenen Leitungen des
> HC165 viel zu lange brauchen, un einen definierten Pegel anzunehmen?

Die offenen Leitungen haben ja nun durch die Pulldown Ihren definierten 
Pegel (keine Ahnung was mich da geritten hat, die zu vergessen) und an 
den Pins liegt auch definitiv nur die aktive Spalte an. Zumindest im 
Messgeschwindigkeitsbereich eines Multimeters soweit nachgeprüft (mit 
Oszi kann ich leider nicht dienen).

Michael U. schrieb:
> Dein "mehrmals einlesen" deutet zumindest darauf hin, daß die Pegel an
> den Eingängen des 165 ewig brauchen, bis sie mal zu Deinen Erwartungen
> passen.

Genau das habe ich auch weiterverfolgt und eine kurze Wartezeit zwischen 
Setzen der aktiven Zeile und Übernahme der aktiven Spalten in den HC165 
eingefügt:
// RCK -> low
PORTB &= ~(PORT_SS);
// PL -> low
PORTB &= ~(PORT_PL);
// send bytewise in corresponding order of shift registers
// µC -> RED -> REED -> GREEN -> GND
SPI_MasterTransmit(byte_gnd);
SPI_MasterTransmit(byte_grn);
SPI_MasterTransmit(byte_reed);
SPI_MasterTransmit(byte_red);
// RCK -> high will set shift register > storage register
PORTB |= (PORT_SS);
// give some time for setting shift register > storage register
waitms(1);
// set clock pulse high and... (CLK & PL are internally wired together)
//PORTB |= (PORT_SCK); // due to CPOL=1, SCK is high when idle
// PL -> high will load pin state to shift register
PORTB |= (PORT_PL);
// activate Clock Enable input
PORTB &= ~(PORT_CE);
// receive data
byte_tmp = SPI_MasterReceive();
// deactivate Clock Enable input
PORTB |= (PORT_CE);

Ergebnis: Funktioniert auch... ;)

Trotzdem nochmals Dank an alle!

Gruss,
Andi

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.