Forum: Mikrocontroller und Digitale Elektronik AVR-Port über Funktionswert konfigurieren


von Sven (Gast)


Lesenswert?

Hallo,

ich bin gerade dabei eine Digital Steuerung für die MoBa zu 
entwickeln....

Dafür muss ich aus einem einprogrammierten Wert (0 - 127) eine Funktion 
im AVR machen. Also zum Beispiel:

Funktionswert = 23: dann soll der Port als Ausgang geschalten werden, 
bei einem entsprechenden Befehl von der Digi-Zentrale soll dann über 
diesen Port eine LED eingeschaltet werden, bei einem anderen Befehl die 
LED ausgeschaltet werden. (wie ein Toggle Flip-Flop)

Funktionswert = 71: dann soll der Port als Ausgang geschalten werden, 
Fu. wie oben, aber die LED soll Blinken (frequenz erst mal egal)

Funktionswert = 45: dann soll der Port als Eingang geschaltet werden, 
wenn eine Taste gedrückt wurde, soll eine Message an die Zentrale 
geschickt werden, wird diese noch einmal gedrückt wird eine andere 
Nachricht versendet.

Funktionswert = 37: dann soll der Port als Eingang geschaltet werden, 
wenn eine Taste gedrückt wurde, soll eine Message an die Zentrale 
geschickt werden, wird dieser losgelassen wird eine andere Nachricht 
versendet.

Von den I/O Ports hab ich insgesammt 16 Stk. also diese 
Funktionssubroutine muss für alle Ports benutzbar sein. z.B:

Port1 = Funktion 23 >> Subroutine
Port2 = Funktion 71 >> Subroutine
...
Port15 = Funktion 45 >> Subroutine
Port16 = Funktion 37 >> Subroutine

Wie muss nun diese Subroutine (Funktion) aussehen?
Programmiersprache ist erst mal egal, mir geht es nur um ein möglichst 
detailiertes Funktionsprinzip.

Also ich hoffe ihr versteht das Problem in etwa und könnt mir da ein 
wenig helfen.

Vielen Dank und LG

Sven

von TestX .. (xaos)


Lesenswert?

16ports, hm meinst du 16 einzelne IO/s oder wirklih 16*8Bit ports ?
im prinzip ist sowas einfach..du hast 4 verschiedene funktionen 0...3 
(ja gleich richtig nummerieren..) und baust dir 4 verschiedene routinen 
und ein globales array in dem du die aktuelle funktion des ports 
speicherst, das wars eigentlich schon.
im main loop hast du ne for-schleife, gehst damit dein array durch und 
je nachdem welche funktion konfiguriert ist wird diese ausgeführt. 
blinken, pin polling solltest du aber über timer machen, das empfangen 
von daten über eine ISR

von Klaus W. (mfgkw)


Lesenswert?

Naja, ganz so einfach ist es nicht.

Was er als "Funktion" bezeichnet, ist nicht unbedingt eine C-Funktion.

Zuerst müsste mal klar sein, welche "Funktionen" es alles geben muß.
Das ist offenbar:
- an als Ausgang
- aus als Ausgang
- Eingang
- blinken
- ... ?

Dann muß er sich eine sinnvolle Struktur überlegen, wie man die
ganzen Zustände für alle Ports abbilden kann (Feld von enums?).

Dann braucht es ein Programm drumrum, das diesen Zustand realisiert
und auf die Kommandos von außen (wie sollen die denn reinkommen?)
hin die Zustände ändert.

Soweit ich das verstanden habe...

Es hört sich etwas unausgegoren an.

von Mat (Gast)


Lesenswert?

du machst einfach eine Funktion die das gewünschte macht und übergibt 
ihr PIN und PORT.
1
DoSomething(PORTA, PIN0);
2
DoSomething(PORTB, PIN2);

und in der Routine wählst du aus was gemacht werden soll:
1
void DoSomething(...)
2
{
3
   switch(Funktionswert)
4
   {
5
     case 23:
6
     //den übergebenen Pin auf Ausgang schalten und Invertieren
7
     break;
8
9
     case 71:
10
     // Pin auf Ausgang und Timer starten z.b.
11
     break;
12
13
     case 45:
14
     // Pin auf eingang und Bit setzten, dass der Pin in der Hauptschleife gepollt wird
15
     break;
16
   }
17
}

auf die schnelle würd ich das so machen ...

lg

von Sven (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

erst mal danke für die Antworten. Das ganze Programm soll auf einem 
Mega88 laufen, der Datenempfang/versand wird Interruptgesteuert über den 
Uart gemacht. Es hat mit RS232 nichts zu tun... es ist ein Protokoll von 
einem Digital-Hersteller (Digitr..), es funktioniert nur Halbduplex 
usw....

@ Andi D. : es sind wirklich nur 16 I/O Ports.
Vom Port D nutze ich die Pins 4 - 7, vom Port C die Pins 0 - 5 und vom 
Port B ebenfalls die Pins 0 - 5

@Klaus Wachtler: nein, neben den angegebenen Funktionen sind es noch ein 
Paar mehr. Oben die Liste dient nur als Beispiel.

@ Mat : so in etwa dachte ich es mir auch schon, aber es ist sehr 
Speicherfressend (hab es schon mal kurz probiert). Wir brauchen in etwa 
33 verschiedene Funktionen. Gibt es dafür nicht eine einfachere Methode?

Ich hab mal die Funktionsliste angehängt... so in etwa stell ich es mir 
vor..

LG

Sven

von Karl H. (kbuchegg)


Lesenswert?

Sven schrieb:

> erst mal danke für die Antworten. Das ganze Programm soll auf einem
> Mega88 laufen, der Datenempfang/versand wird Interruptgesteuert über den
> Uart gemacht. Es hat mit RS232 nichts zu tun... es ist ein Protokoll von
> einem Digital-Hersteller (Digitr..), es funktioniert nur Halbduplex
> usw....

OK

> @ Andi D. : es sind wirklich nur 16 I/O Ports.
> Vom Port D nutze ich die Pins 4 - 7, vom Port C die Pins 0 - 5 und vom
> Port B ebenfalls die Pins 0 - 5

Bitte benutze die richtige Nomenklatur.
Du sprichst von Port-'Pins'.
Ein Port im µC-Sprachgebrauch ist eine 'Geräteeinheit', die 8 Pins zur 
Verfügung stellt.

du benutzt also 3 unterschiedliche Ports, mit zusammen 16 benutzten 
Pins.

> @ Mat : so in etwa dachte ich es mir auch schon, aber es ist sehr
> Speicherfressend (hab es schon mal kurz probiert). Wir brauchen in etwa
> 33 verschiedene Funktionen. Gibt es dafür nicht eine einfachere Methode?

Die Methode von Mat ist nicht so clever.
Cleverer ist es, wenn du dir eine Tabelle mit Funktionspointern 
aufbaust, wobei jeder Pointer auf eine Funktion zeigt, die die 
gewünschte Funktionalität implementiert (oder aber ein großer 
switch/case über alle Funktionsnummern, der dann die jeweilige Funktion 
aufruft)

Dazu noch eine Tabelle, mit welcher du eine 'vituelle Pin-Nummer' (so 
wie sie über die Schnittstelle übertragen wird) in reale 
DDR/PORT/PIN/BIT Bezeichnungen ummappen kannst.


Alles in allem: in C nicht so schwer zu realisieren, wenn man sein 
Handwerk versteht. Allerdings auch nichts für Anfänger.

von Sven (Gast)


Lesenswert?

>Alles in allem: in C nicht so schwer zu realisieren, wenn man sein
>Handwerk versteht. Allerdings auch nichts für Anfänger.

@ Karl Heinz: nun hast du "A" gesagt nun musst du auch "B" 
sagen(schreiben)
kannst du mir dafür einen kurzen Pseudo Code schreiben? Ein richtiger 
Anfänger bin ich keiner mehr ;-)

LG, Sven

von Klaus W. (mfgkw)


Lesenswert?

nein, er hat C gesagt.

Programmieren wirst du es schon selber müssen.

von Karl H. (kbuchegg)


Lesenswert?

Sven schrieb:

> kannst du mir dafür einen kurzen Pseudo Code schreiben?

Wenn ich dir dafür Pseudo-Code schreibe, kann ich dir auch gleich C Code 
geben. Ist für mich einfacher.

Aber seis drum
1
globale Tabelle der Funktionspointer
2
3
Hauptprogramm:
4
5
   mache für immer
6
     hole die Funktionsnummer
7
     ist die Funktionsnummer gültig?
8
        ja: hole aus der Tabelle den Funktionspointer wobei du
9
            die Funktionsnummer als Index benutzt
10
            rufe die Funktion indirekt über den Funktionspointer auf

ist dir jetzt geholfen? :-)


> Ein richtiger
> Anfänger bin ich keiner mehr ;-)

Na ja
Das was du vorhast, ist reine Tabellenarbeit (*). OK. Funktionspointer 
muss man sich einmal ansehen. aber auch die sind halb so wild. Wenn du 
dafür eine Idee brauchst, überschätzt du dein Kentnisse ein wenig :-) 
(**)

(*) und natürlich: Arbeiten mit Pointern

(**) was ich speziellen sowieso glaube. Denn deine Beschreibungen sind 
ein wenig .... konfus. Man kann zwar erraten was du meinst, aber wenn 
man es genau nimmt, ist in dem was du im ersten Posting geschrieben hast 
kaum ein Satz, der Sinn macht.

von Karl H. (kbuchegg)


Lesenswert?

Mal eine andere Frage:
Wieviel Erfahrung hast du denn schon in der AVR-Programmierung?
Wenn ich dir den Auftrag gebe "Schalte den Pin 4 am Port C auf Ausgang 
und schalte ihn auf 1" kriegst du das hin?

Wie sieht der Code aus?
1
int main()
2
{
3
4
   .....
5
}

Es geht mir nicht darum, dich da jetzt fertig zu machen. Ich will nur 
wissen, ob du das Zusammenspiel der DDR/PORT/PIN Register und der Bits 
kennst.

von Karl H. (kbuchegg)


Lesenswert?

Noch eine Frage

> Funktionswert = 23: dann soll der Port als Ausgang geschalten
> werden, bei einem entsprechenden Befehl von der Digi-Zentrale
> soll dann über

In welcher Form kriegst du diese 'Portnummer'?

Ich geh davon aus, dass die Zentrale nichts darüber weiß und auch nicht 
wissen soll, dass das auf dem AVR zb der PORTC und dort der Pin 0 ist.
Die Zentrale arbeitet einfach nur mit abstrakten, virtuellen Nummern.
Es sagt dem AVR: schalte den Anschluss 5 auf Ausgang, und der AVR muss 
dann selbst wissen, dass das PORTC Pin0 ist.

Das kann man jetzt natürlich ganz klassisch ausprogrammieren
1
// Vom Port D nutze ich die Pins 4 - 7, vom Port C die Pins 0 - 5 und vom
2
// Port B ebenfalls die Pins 0 - 5
3
4
void ConfigureAsOutput( uint8_t ConnectionNr )
5
{
6
  uint8_t PinNr;
7
8
  if( ConnectionNr < 6 ) {   // handelt sich um den Port B
9
    PinNr = ConnectionNr;    // ConnectionNr:  0 bis 4
10
    DDRB |= ( 1 << PinNr );
11
  }
12
13
  else if( ConnectionNr < 11 ) {   // muss am Port C sein
14
    PinNr = ConnectionNr - 5;      // ConnectionNr:  5 bis 9
15
    DDRC |= ( 1 << PinNr );
16
  }
17
18
  else if( ConnectionNr < 17 ) {   // muss am Port D sein
19
    PinNr = ConnectionNr - 10 + 4; // ConnectionNr:  10 bis 15
20
21
    DDRD |= ( 1 << PinNr );
22
  }
23
}

dasselbe für die Ausgabefunktion bzw. die restlichen Funktionen.

Für die Konfiguration auf Eingang müsste man noch Buch führen, welche 
Pins auf Eingang sind und dann in der Hauptschleife diese Pins abfragen, 
auf Veränderung auswerten und bei einer erkannten Veränderung die 
entsprechende Message auf den Weg bringen.

von Sven (Gast)


Lesenswert?

@ Karl Heinz, dann ist das eben ein Sinnloses unterfangen. Gott sei 
dank, kommen heute alle Menschen mit fundierten C-Kenntnissen zur Welt. 
Aber dennoch danke für deine hilfe...

Ciao Sven

von Sven (Gast)


Lesenswert?

@ Karl Heinz, ich müsste dir dafür das ganze Loconet Prottokoll 
erklären.

Die Daten vom LN kann ich empfangen, speichern und auswerten.... was mir 
fehlt ist eben die Oben beschriebene Funktion.

und ja den Unterschied zwischen DDR Registern, Port und Pin kenne ich...

LG Sven

von Karl H. (kbuchegg)


Lesenswert?

Sven schrieb:
> @ Karl Heinz, ich müsste dir dafür das ganze Loconet Prottokoll
> erklären.

musst du nicht.
Du musst nur sagen:
In diesen und jenen Variablen habe ich nach Empfang eines Datensatzes 
diese Werte stehen (und das bedeuten sie)

> Die Daten vom LN kann ich empfangen, speichern und auswerten.... was mir
> fehlt ist eben die Oben beschriebene Funktion.

Ich hab dir weiter oben eine ganz klassische Variante davon skizziert.
Ohne irgendwelche Tricks, ganz straight forward.

von Klaus W. (mfgkw)


Lesenswert?

Sven schrieb:
> Gott sei
> dank, kommen heute alle Menschen mit fundierten C-Kenntnissen zur Welt.

Das nicht, aber früher (tm) war man bereit etwas zu lernen, auch wenn es 
länger als 5 min dauert.

von Karl H. (kbuchegg)


Lesenswert?

Karl heinz Buchegger schrieb:
> Sven schrieb:
>> @ Karl Heinz, ich müsste dir dafür das ganze Loconet Prottokoll
>> erklären.
>
> musst du nicht.
> Du musst nur sagen:
> In diesen und jenen Variablen habe ich nach Empfang eines Datensatzes
> diese Werte stehen (und das bedeuten sie)
>
>> Die Daten vom LN kann ich empfangen, speichern und auswerten.... was mir
>> fehlt ist eben die Oben beschriebene Funktion.
>
> Ich hab dir weiter oben eine ganz klassische Variante davon skizziert.
> Ohne irgendwelche Tricks, ganz straight forward.

Die beruht darauf, dass das Wissen über die Aufteilung in den Code 
selber gebracht wird.

Eine andere Lösung wäre zb die hier
1
struct connectInfo {           // definiert die Umsetzung der virtuellen
2
                               // Connect Nummern auf reale Ports
3
  volatile uint8_t * ddrRegister;
4
  volatile uint8_t * portRegister;
5
  volatile uint8_t * pinRegister;
6
  volatile uint8_t   bitMask;
7
};
8
9
// und hier sind sie: die benutzen Pins in der richtigen Reihenfolge
10
//
11
// Vom Port D nutze ich die Pins 4 - 7, vom Port C die Pins 0 - 5 und vom
12
// Port B ebenfalls die Pins 0 - 5
13
14
struct connectInfo pinInfo[] = {
15
  { &DDRB, &PORTB, &PINB, 1<<PB0 },   //  0
16
  { &DDRB, &PORTB, &PINB, 1<<PB1 },   //  1
17
  { &DDRB, &PORTB, &PINB, 1<<PB2 },   //  2
18
  { &DDRB, &PORTB, &PINB, 1<<PB3 },   //  3
19
  { &DDRB, &PORTB, &PINB, 1<<PB4 },   //  4
20
  { &DDRB, &PORTB, &PINB, 1<<PB5 },   //  5
21
22
  { &DDRC, &PORTC, &PINC, 1<<PC0 },   //  6
23
  { &DDRC, &PORTC, &PINC, 1<<PC1 },   //  7
24
  { &DDRC, &PORTC, &PINC, 1<<PC2 },   //  8
25
  { &DDRC, &PORTC, &PINC, 1<<PC3 },   //  9
26
  { &DDRC, &PORTC, &PINC, 1<<PC4 },   // 10
27
  { &DDRC, &PORTC, &PINC, 1<<PC5 },   // 11
28
29
  { &DDRD, &PORTD, &PIND, 1<<PD4 },   // 12
30
  { &DDRD, &PORTD, &PIND, 1<<PD5 },   // 13
31
  { &DDRD, &PORTD, &PIND, 1<<PD6 },   // 14
32
  { &DDRD, &PORTD, &PIND, 1<<PD7 },   // 15
33
};
34
35
#define ARRAY_SIZE(x)  ( sizeof( x ) / sizeof( *x ) )
36
37
void ConfigureAsOutput( uint8_t ConnectionNr )
38
{
39
  if( ConnectionNr < ARRAY_SIZE( pinInfo ) )
40
    pinInfo[ ConnectionNr].ddrRegister |= pinInfo[ ConnectionNr].bitMask;
41
}

Das ist eine ein wenig ausgeklügeltere Variante, in der die komplette 
Information, wie sich die virtuellen Anschluss Nummern auf die einzelnen 
Port Bits verteilen, in einer Tabelle gesammelt werden.

Vorteil: das ist änderungsfreundlicher, wenn mal µC-Pins auf einen 
anderen Port umziehen müssen. Und es erweitert sich auch besser auf noch 
mehr Anschlussnummern. Die Anschlüsse können dann auch ganz einfach wild 
verteilt am µC angeordnet werden.
Regelt alles die Tabelle.


Aber auch hier wieder:
Das erfordert noch immer keine fundierten Kentnisse, so leid mir das 
auch für dich tut. Das ist reines Handwerk.

von Sven (Gast)


Lesenswert?

So, jetzt wieder ganz normal und friedlich...

Die Nachricht der Zentrale enthält 4 Bytes, daraus separiere ich die 
Adresse für den Port und ein Controllbyte das mir dann sagt ob der Port 
High oder Low schalten soll...

1.Byte = Opcode
2.Int = Adresse vom Port
3.Byte = Controllbyte

1 = 0xB0 > Port soll bei "Switchmeldung der Zentrale" und
2 = 0x4D2 > dieser Adresse
3 = 0x03 > den Port auf High schalten
3 = 0x01 > den Port auf Low schalten

Beim Datenversand mach ich es so, ich erechne aus der Adresse dem 
Controllbyte und dem, der Funktion entsprechenden "OpCode" eine gültige 
Nachricht...

1 = 0xB2 > Pin Meldet der Zentrale "belegtmeldung"
2 = 0x78 > Adresse ist
3 = 0x03 > Gleis ist frei
3 = 0x01 > Gleis ist besetzt

meinst du das so?

LG Sven

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Karl heinz Buchegger schrieb:
>
1
>   if( ConnectionNr < ARRAY_SIZE( pinInfo ) )
2
>     pinInfo[ ConnectionNr].ddrRegister |= pinInfo[
3
> ConnectionNr].bitMask;
4
> }
5
>

Fehlt da nicht ein Sternchen?

Gruß,

Frank

von Karl H. (kbuchegg)


Lesenswert?

Sven schrieb:

> Beim Datenversand mach ich es so, ich erechne aus der Adresse dem
> Controllbyte und dem, der Funktion entsprechenden "OpCode" eine gültige
> Nachricht...
>
> 1 = 0xB2 > Pin Meldet der Zentrale "belegtmeldung"
> 2 = 0x78 > Adresse ist
> 3 = 0x03 > Gleis ist frei
> 3 = 0x01 > Gleis ist besetzt
>
> meinst du das so?

Das ist schonmal ein Anfang.

> 1.Byte = Opcode
> 2.Int = Adresse vom Port
> 3.Byte = Controllbyte

Die Adresse ist interessant.
Wie bildet sich die?

> 1 = 0xB0 > Port soll bei "Switchmeldung der Zentrale" und
> 2 = 0x4D2 > dieser Adresse

Warum 0x4D2?

Kann man sagen, dass die Adressen der 'Ports' an einem µC aufsteigend 
sind?
Jeder µC hat einen Startwert und alle 'Adressen' sind dann einfach nur 
die nächsten 16 Nummern?

von Karl H. (kbuchegg)


Lesenswert?

Frank M. schrieb:
> Karl heinz Buchegger schrieb:
>>
1
>>   if( ConnectionNr < ARRAY_SIZE( pinInfo ) )
2
>>     pinInfo[ ConnectionNr].ddrRegister |= pinInfo[
3
>> ConnectionNr].bitMask;
4
>> }
5
>>
>
> Fehlt da nicht ein Sternchen?

Ooops. Du hast recht.
Hab ich beim Tippen hier im Forum übersehen.
Danke.
1
void ConfigureAsOutput( uint8_t ConnectionNr )
2
{
3
  if( ConnectionNr < ARRAY_SIZE( pinInfo ) )
4
    *(pinInfo[ ConnectionNr].ddrRegister) |= pinInfo[ ConnectionNr].bitMask;
5
}

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Karl heinz Buchegger schrieb:
> Hab ich beim Tippen hier im Forum übersehen.

Du schüttelst hier immer in kürzester Zeit (fast) fehlerfreien 
ausführlichsten (und lauffähigen!) Code aus dem Ärmel... wie machst Du 
das? Schickst Du den Code vorher durch den AVR-gcc oder hat Andreas 
speziell für Dich einen Syntax-Parser ins Forum eingebaut? ;-)

Die Frage war rhetorisch gemeint, ich bewundere immer wieder, wie weit 
Du mit Deiner Hilfsbereitschaft gehst...

von Klaus W. (mfgkw)


Lesenswert?

Das kommt davon, wenn man einen Zeiger ddrRegister nennt und nicht 
p_ddrRegister :-)

von Karl H. (kbuchegg)


Lesenswert?

Karl heinz Buchegger schrieb:

> Das ist eine ein wenig ausgeklügeltere Variante, in der die komplette
> Information, wie sich die virtuellen Anschluss Nummern auf die einzelnen
> Port Bits verteilen, in einer Tabelle gesammelt werden.

Anzumerken wäre noch, dass man sich diese ConnectionInfo natürlich noch 
um weitere Informationen anreichern wird, die sich dann zur Laufzeit 
ergeben. Ich denke da an ein Flag welches eine Aussage erlaubt, ob der 
Pin auf Ausgang oder Eingang geschaltet ist; welchen Zustand er im 
Moment hat (um Veränderungen feststellen zu können) etc.

Dieses Tabellenschema ist sehr universell und vor allen Dingen lassen 
sich damit die Funktionen damit sehr universell schreiben.
Nachteil: Man verschenkt unter Umständen ein wenig Laufzeit (dürfte hier 
aber keine Rolle spielen) und man braucht natürlich auch entsprechend 
viel SRAM (aber auch das wird hier keine Rolle spielen)

von Sven (Gast)


Lesenswert?

@ Karl Heinz,

Die Adresse 1234 ist jetz mal frei erfunden... ich könnte auch 487 
nehmen.

Jeder Port, von den 16 Ports, bekommt eine eigene Adresse 0 - 2047 auf 
die er dann höhren soll, bzw unter welcher er dann Daten zur Zenrale 
schickt. Das Controllbyte ist nun dazu da um den Port entsprechend 
reagieren zu lassen( irgendetwas ein/ausschalten, blinken lassen...)

Das Programmieren der Port Adresse hab ich schon separat gelöst, die 
Port Adresse ist zudem noch im EEprom hinterlegt ebenso wie der Port 
Funktionswert ....

Die Adresse und das Controllbyte ist in der Ursprünglichen LN Message in 
zwei Bytes (nur 0 - 127) hinterlegt, daraus separiere ich über 
Schiebefunktionen die Adresse und das Controllbyte.

Zu dem Opcode Byte am anfang einer Message ist noch zu sagen:

Daten senden:
Wenn ich eine, am Port, angeschlossene Taste drücke soll das Opcode Byte 
=0xB0 sein, wenn an dem Port ein Belegtmelder angeschlossen ist soll der 
Opcode = 0xB2 sein...
So wie es in der "PortFunktion" eingestellt wurde!

Daten empfangen:
Wenn ich eine Message mit Opcode =0xB0 empfange soll die darin 
enthaltene Adresse und Controllbyte separiert werden und der Port 
entsprechend gesetzt werden (Blinken, An/aus...)
Ebenso wenn eine Message den opcode 0xB0 enthällt...
So wie es in der "PortFunktion" eingestellt wurde!

LG Sven

von Karl H. (kbuchegg)


Lesenswert?

Sven schrieb:

> LG Sven

OK.
Dann hast du ja jetzt alles was du brauchst.

von Sven (Gast)


Lesenswert?

Ich hoffe doch. Ich werde mal alles durcharbeiten, ist doch etwas viel 
auf's mal ;-)

Wenn ich dann noch fragen habe "klopf" ich wider an.

Nochmals vielen Dank an alle!!

Gruss Sven

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.