| Autor |
Nachricht |
COM
Unregistrierter
|
COM Unregistrierter
20:01:36 30.05.2012 Titel: |
COM Port Bits senden |
Zitieren |
Hallo,
ich möchte einzelne Bits an meinen COM-Port senden. Im Prinzip 0-0-0-0-0-0-0-1 mit jeweils 200ms Abstand.
Mein Ansatz wäre jetzt:
| Code: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | #include <iostream>
#include <conio.h>
#include <windows.h>
int main(int argc, char* argv[])
{
char INBUFFER[2]; // Create Input Buffer
bool Zero = 0x00;
bool One = 0x01;
/* Komplement berechnen
char Komplement = '\xd5' ^ '\xff';
printf("%d\r\n",Komplement);
*/
DWORD bytes_read = 1; // Number of bytes read from port
DWORD bytes_written = 1; // Number of bytes written to the port
HANDLE comport = NULL; // Handle COM port
int bStatus; // Status indicator
DCB comSettings; // Contains various port settings
COMMTIMEOUTS CommTimeouts; // Contains various COM timeouts
// Open COM port
if ((comport =
CreateFile("\\\\.\\COM4", // open com4:
GENERIC_READ | GENERIC_WRITE, // for reading and writing
0, // exclusive access
NULL, // no security attributes
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL)) == INVALID_HANDLE_VALUE)
{
printf("CreateFile() funktioniert nicht\r\n"); // error processing code goes here
system("pause");
exit(0);
}
CommTimeouts.ReadIntervalTimeout = -1; // Timeout in ms
CommTimeouts.ReadTotalTimeoutMultiplier = 0; // Timeout in ms
CommTimeouts.ReadTotalTimeoutConstant = 0; // Timeout in ms
CommTimeouts.WriteTotalTimeoutMultiplier = 0; // Timeout in ms
CommTimeouts.WriteTotalTimeoutConstant = 65000; // Timeout in ms
bStatus = SetCommTimeouts(comport,&CommTimeouts); // Set COM timeouts
if (bStatus != 0)
{
printf("SetCommTimeouts() funktioniert nicht\r\n"); // error processing code goes here
}
GetCommState(comport, &comSettings); // Getting COM state
comSettings.BaudRate = 9600; // COM setting
comSettings.StopBits = ONESTOPBIT; // COM setting
comSettings.ByteSize = 7; // COM setting
comSettings.Parity = ODDPARITY; // COM setting
comSettings.fParity = FALSE; // COM setting
bStatus = SetCommState(comport, &comSettings); // Setting COM state
if (bStatus == 0)
{
printf("SetCommState() funktioniert nicht.\r\n"); // error processing code goes here
}
Sleep(5);
bStatus = WriteFile(comport, &Zero,1,&bytes_written,NULL);
Sleep(200);
bStatus = WriteFile(comport, &Zero,1,&bytes_written,NULL);
Sleep(200);
bStatus = WriteFile(comport, &Zero,1,&bytes_written,NULL);
Sleep(200);
bStatus = WriteFile(comport, &Zero,1,&bytes_written,NULL);
Sleep(200);
bStatus = WriteFile(comport, &Zero,1,&bytes_written,NULL);
Sleep(200);
bStatus = WriteFile(comport, &Zero,1,&bytes_written,NULL);
Sleep(200);
bStatus = WriteFile(comport, &Zero,1,&bytes_written,NULL);
Sleep(200);
bStatus = WriteFile(comport, &One,1,&bytes_written,NULL);
printf("Sending: %d\r\n", 0x46);
bStatus = ReadFile(comport,&INBUFFER,2,&bytes_read,NULL);
printf("Receiving: %d <-> %d\r\n", INBUFFER[0], INBUFFER[1]);
system("pause");
CloseHandle(comport);
return 0;
} | |
... allerdings ist WriteFile() nur für Bytes ausgelegt, kann ich irgendwie auch einzelne Bits senden? Der Code scheint so jedenfalls nicht zu funktionieren.
Danke & Gruß
COM |
|
|
|
 |
geeky
Mitglied
Benutzerprofil
Anmeldungsdatum: 04.05.2001
Beiträge: 6184
|
geeky Mitglied
21:55:20 30.05.2012 Titel: |
|
Zitieren |
200ms Abstand zwischen jedem Bit?
Wenn man das Muster einfach als 1-Byte sendet, wäre das eine Bitrate von 5 bits/s, aber vermutlich kann man typische COM-Ports gar nicht so langsam einstellen?
Zudem werden Start/Stoppbits da stören (und bei deinem Versuch zusätzlich noch der Pufferspeicher der COM-Schnittstelle und des Betriebssystems)
Ich würde nen Mikrocontroller dazwischenpacken und den das in das passende Format umsetzen lassen:
| Code: | | [PC] ---(COM1 oder USB)---> [Atmega/PIC Mikrocontroller] ---> (Bits im Abstand 200ms) | |
Pfusch-Möglichkeit wäre auch das Muster statt auf dem TX-Pin (mit WriteFile) auf einem der Handshake-Leitungen (DTR/DTS) auszugeben und den Pin als TX-Pin zu nutzen, die kann man einzeln an/aus schalten:
http://msdn.microsoft.com ....... ows/desktop/aa363254.aspx |
|
|
|
 |
COM
Unregistrierter
|
COM Unregistrierter
22:18:19 30.05.2012 Titel: |
|
Zitieren |
Es geht darum, das KW1281-Protokoll zu initialisieren (Fahrzeugdiagnose).
Laut KW1281 Standard muss man mit 5 Baud initialisieren und mit 9600 Baud weiterarbeiten, man kann denke ich die Baud-Rate nicht einfach während einer Verbindung ändern, daher müsste man ein künstliches Delay von 200ms einfügen.
http://blafusel.de/obd/obd2_kw1281.html
| Zitat: | Die erste Methode ist einfach, hat aber den Nachteil, daß sie nicht hundertprozentig akkurat ist. Ich hatte teilweise den Verdacht, daß nicht alle Daten protokolliert wurden. Allerdings findet man so heraus, wie die 5Bd Initialisierung abgewickelt wird: Statt die Geschwindigkeit an der Schnittstelle zu wechseln, wird diese gleich auf die gewünschte Datenrate für die folgende Kommunikation eingestellt (bspw. 9600Bd) und dann wird mit SET_BREAK die Übertragung simuliert:
IOCTL_SERIAL_SET_BREAK_ON
IOCTL_SERIAL_SET_RTS
IOCTL_SERIAL_CLR_DTR
IOCTL_SERIAL_SET_BREAK_OFF -> Start-Bit?
IOCTL_SERIAL_CLR_RTS
IOCTL_SERIAL_SET_BREAK_ON -> 0
IOCTL_SERIAL_SET_RTS
IOCTL_SERIAL_SET_BREAK_ON -> 0
IOCTL_SERIAL_SET_RTS
IOCTL_SERIAL_SET_BREAK_ON -> 0
IOCTL_SERIAL_SET_RTS
IOCTL_SERIAL_SET_BREAK_ON -> 0
IOCTL_SERIAL_SET_RTS
IOCTL_SERIAL_SET_BREAK_ON -> 0
IOCTL_SERIAL_SET_RTS
IOCTL_SERIAL_SET_BREAK_ON -> 0
IOCTL_SERIAL_SET_RTS
IOCTL_SERIAL_SET_BREAK_ON -> 0
IOCTL_SERIAL_SET_RTS
IOCTL_SERIAL_SET_BREAK_OFF -> 1
IOCTL_SERIAL_CLR_RTS
IOCTL_SERIAL_SET_DTR
Zwischen den einzelnen Umschaltungen liegen genau 200ms, woraus sich dann die 5Bd (1000ms/5bps) ergeben. Im Beispiel wird die Adresse 1 angesprochen. Dezimal 1 entspricht Binär 000 0001. |
Der jenige hat auch ein Tool in Delphi (?) dafür geschrieben, aber ich kann nicht viel mit dem Code anfangen.
http://sourceforge.net/pr ....... iag_frontend.zip/download
Danke schonmal, vielleicht kannst du oder jemand anders mir bei dem Problem weiterhelfen. |
|
|
|
 |
COM
Unregistrierter
|
COM Unregistrierter
22:26:25 30.05.2012 Titel: |
|
Zitieren |
So habe mal aus WBHDiag von Blafusel.de die entsprechenden Zeilen kopiert.
| Code: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | function kw1281_wakeup (adresse : Integer) : Boolean;
var
i,u : Integer;
erfolg, geoeffnet : boolean;
uart,txt : String;
baud : Integer;
begin
erfolg := false; // muß so umständlich sein, da "if kw1281_wakeup = true" die funktion rekursiv aufruft - argh!
WriteDebugFile ('IBT', InterByteTime);
WriteDebugFile ('BDT', InterBlockTime);
WriteDebugFile ('ECU Adresse', adresse);
Form1.StatusBar1.Panels[0].Text := LoadStr (langprefix + 22); // Statusbar Verbindunsgversuch
statuspanel0 := 1;
try
geoeffnet := open_comport();
if (geoeffnet) then
begin
Form1.ComPort1.Timeouts.ReadInterval := -1; // Die drei Einstellungen führen dazu, daß nur
Form1.ComPort1.Timeouts.ReadTotalConstant := 1000; // 1000 ms auf ein Zeichen im Puffer gewartet wird
Form1.ComPort1.Timeouts.ReadTotalMultiplier := -1 ;
u:=1;
if not PublicVersion then
Form1.Memo1.Lines.Add ('OPEN');
Form1.ComPort1.ClearBuffer(True, True);
Form1.ComPort1.WriteStr(chr(13)); // CR
uart := uartRead(false); // entweder > oder ?
if (uart = '') then // keine Antwort
begin
Application.MessageBox (PChar(LoadStr (langprefix + 306)), PChar(LoadStr (langprefix + 301))); // "Kein Kontakt zum Diagnoseinterface herstellbar."
end
else
begin
uartRead(false); // wenn ? dann das > verwerfen
Form1.ComPort1.WriteStr(chr(13)); // CR
uart := uartRead(false); // entweder > oder ?
uartRead(false); // wenn ? dann das > verwerfen
if (uart <> '') then // Zeichen empfangen => richtiger Port
begin
i := 0;
repeat
if not PublicVersion then
Form1.Memo1.Lines.Add ('ATZ');
Form1.ComPort1.WriteStr('ATZ'+chr(13));
uartRead(false); // das CR verwerfen
uart := uartRead(false);
uartRead(false); // das > verwerfen
inc (i);
until ((AnsiContainsText(uart, 'WBH-Diag Pro')) OR (i>5)); // bis Info aber nur maximal 5x
if (AnsiContainsText(uart, 'WBH-Diag Pro')) then // WBH gefunden
begin
Form1.StatusBar1.Panels[2].Text := uart; //LoadStr (langprefix + 22); // Statusbar Verbindunsgversuch
if not PublicVersion then
Form1.Memo1.Lines.Add ('ATIBT' + IntToHex(InterByteTime, 2));
Form1.ComPort1.WriteStr('ATIBT' + IntToHex(InterByteTime, 2) + chr(13));
repeat
uart := uartRead(false);
until ((uart = 'ERROR') OR (uart = 'DATA ERROR') OR (uart = '>') );
if not PublicVersion then
Form1.Memo1.Lines.Add ('ATBDT' + IntToHex(InterBlockTime, 2));
Form1.ComPort1.WriteStr('ATBDT' + IntToHex(InterBlockTime, 2) + chr(13));
repeat
uart := uartRead(false);
until ((uart = 'ERROR') OR (uart = 'DATA ERROR') OR (uart = '>') );
case BaudrateIniFile of
1200 : baud := 1;
2400 : baud := 2;
4800 : baud := 3;
9600 : baud := 4;
14400 : baud := 5;
else
baud := 0;
end;
if not PublicVersion then
Form1.Memo1.Lines.Add ('ATN' + IntToStr(baud));
Form1.ComPort1.WriteStr('ATN' + IntToStr(baud) + chr(13));
repeat
uart := uartRead(false);
until ((uart = 'ERROR') OR (uart = 'DATA ERROR') OR (uart = '>') OR (LeftStr(uart, 7) = 'CONNECT'));
if not PublicVersion then
Form1.Memo1.Lines.Add ('ATD' + IntToHex(adresse, 2));
Form1.ComPort1.WriteStr('ATD' + IntToHex(adresse, 2) + chr(13));
repeat
uart := uartRead(false);
until ((uart = 'ERROR') OR (uart = 'DATA ERROR') OR (uart = '>') OR (LeftStr(uart, 7) = 'CONNECT'));
if (LeftStr(uart, 7) = 'CONNECT') then // Connect OK
begin
case StrToInt(Copy(uart,10,1)) of // Aus der Connectmeldung die Geschwindigkeit extrahieren
1 : txt := '1200';
2 : txt := '2400';
3 : txt := '4800';
4 : txt := '9600';
5 : txt := '14400';
end;
Form1.StatusBar1.Panels[1].Text := txt + ' Baud'; // Statusbar
Form1.StatusBar1.Panels[0].Text := LoadStr (langprefix + 23); // Verbunden
statuspanel0 := 2;
case StrToInt(RightStr(uart,1)) of // Aus der Connectmeldung das Protokoll extrahieren
1 : begin txt := 'KW 1281'; protokoll := 1; end;
2 : begin txt := 'KW 2000'; protokoll := 2; end;
end;
Form1.StatusBar1.Panels[3].Text := LoadStr (langprefix + 24) + txt; // Protokoll
erfolg := true;
end ;
end // if "WBH-Diag..."
else
begin
Application.MessageBox (PChar(LoadStr (langprefix + 305)), PChar(LoadStr (langprefix + 301))); // "Kein Kontakt zum Diagnoseinterface herstellbar."
end;
end // if falscher Port (kein CR)
else
begin
Application.MessageBox (PChar(LoadStr (langprefix + 306)), PChar(LoadStr (langprefix + 301))); // "Kein Kontakt zum Diagnoseinterface herstellbar."
end;
end; // keine Antwort auf 1. Anfrage
end
else // COM Port nicht zu öffnen
begin
kw_Disconnect;
end;
if (erfolg = false) AND geoeffnet then
begin
Form1.StatusBar1.Panels[0].Text := LoadStr (langprefix + 6); // Statusbar keine Verbindung
statuspanel0 := 0;
Form1.StatusBar1.Panels[1].Text := ''; // keine Baudrate
Form1.StatusBar1.Panels[2].Text := ''; // kein Chip
Form1.StatusBar1.Panels[3].Text := ''; // kein Protkoll
Form1.ComPort1.Close;
end;
kw1281_wakeup := erfolg;
except
end;
end; | | |
|
|
|
 |
COM
Unregistrierter
|
COM Unregistrierter
22:35:55 30.05.2012 Titel: |
|
Zitieren |
##########
##########
##########
So und hier noch eine Funktion kwp..wakeup
| Code: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | function kw1281_wakeup (adresse : Integer) : Boolean;
var
ecu0, ecu1, ecu2, ecu3, i, bit, start : Integer;
erfolg : boolean;
baudrate: Integer;
parity : Integer;
zeit : integer;
TickValue : DWORD;
begin
erfolg := false; // muß so umständlich sein, da "if kw1281_wakeup = true" die funktion rekursiv aufruft - argh!
baudrate := 0; // Delphi kann lokale variablen nicht bei der Deklaration initialisieren :-(
if Form1.CheckBox8.Checked then
begin
zeit := 196; // eigentlich 200 aber bei USB Interface MUSS 195-196
end
else
begin
zeit := 200;
end;
WriteDebugFile ('Timing', zeit);
WriteDebugFile ('IBT', InterByteTime);
WriteDebugFile ('BDT', InterBlockTime);
WriteDebugFile ('ECU Adresse', adresse);
begin
if (BaudrateIniFile > 0) then
start := 0
else
start := 1;
for i:=start to 5 do
begin
case i of
0 : begin
baudrate := BaudrateIniFile;
Delay (1500); // warten vor nächstem Baudratenversuch (Wert + 1 Sekunde = VAG-COM)
end;
1 : begin
baudrate := 10400; //10400
end;
2 : begin
Delay (1500); // warten vor nächstem Baudratenversuch (Wert + 1 Sekunde = VAG-COM)
baudrate := 9600;
end;
3 : begin
Delay (1500); // warten vor nächstem Baudratenversuch (Wert + 1 Sekunde = VAG-COM)
baudrate := 4800;
end;
4 : begin
Delay (1500); // warten vor nächstem Baudratenversuch (Wert + 1 Sekunde = VAG-COM)
baudrate := 2400;
end;
5 : begin
Delay (1500); // warten vor nächstem Baudratenversuch (Wert + 1 Sekunde = VAG-COM)
baudrate := 1200;
end;
// 5 : baudrate := 19200;
end;
Form1.StatusBar1.Panels[0].Text := LoadStr (langprefix + 22); // Statusbar Verbindunsgversuch
Form1.StatusBar1.Panels[1].Text := IntToStr(baudrate) + ' Baud'; // Statusbar
if (open_comport (baudrate) = true) then
begin
// Invertierte Signal-Logik
// TXD = K-Leitung
// RTS = L-Leitung
DTR (1); // für Jeffs Interface: Eingangs Opto nach Masse ziehen.
// Delay (3); // muß nicht sein, aber theoretisch braucht die Umschltung bei USB 3ms.
TXD (0); RTS (0); Delay (2000); // Vorbereitung HIGH (MUSS 2000 für Kombiinstr. T4 sein)
DTR (0);
TXD (1); RTS (1); Delay (zeit); // Start-Bit 1->0 LOW
// Bits der Adresse durchlaufen LSB->HSB aber nur 128 möglich (7 Bit)
parity := 0;
for bit:=7 downto 1 do
begin
if (TestBit (adresse, bit) = true) then
begin
TXD (0); RTS (0); Delay (zeit); // HIGH
parity := parity + 1;
end
else
begin
TXD (1); RTS (1); Delay (zeit); // LOW
end;
end;
// Odd Parity
if ((parity MOD 2) = 0) then // true=gerade
begin
TXD (0); RTS (0); Delay (zeit); // HIGH = mache Stream ungerade, Odd Parity
end
else
begin
TXD (1); RTS (1); Delay (zeit); // LOW
end;
DTR(1); // für Jeffs Interface
TXD (0); RTS (0); Delay (zeit); // Stop-Bit
CLEARBUFFER; // nicht ganz logisch, muß aber sein, da nach den TXDs 2 Bytes im Puffer sind.
TickValue := GetTickCount; // ms seit Windows Start
while ((INBUFFER = 0) and (GetTickCount-TickValue < 500)) do // solange kein Zeichen und noch keine 500ms vergangen sind
asm nop //Application.ProcessMessages;
end;
// Delay (250); // 250
if INBUFFER >0 then // Zeichen im Puffer = init klappte vermutlich
begin
// ECU wake-up Bestätigung empfangen:
Form1.Memo1.Lines.Add ('+++');
ecu0 := myReadByte; // Sync-Byte
Form1.Memo1.Lines.Add (IntToHex(ecu0,1));
WriteDebugFile ('Sync', ecu0);
if (ecu0 = $55) then
begin
erfolg := true;
ecu1 := myReadByte; // KB1
WriteDebugFile ('KB1', ecu1);
Form1.Memo1.Lines.Add (IntToHex(ecu1,1));
ecu2 := myReadByte; // KB2
WriteDebugFile ('KB2', ecu2);
Form1.Memo1.Lines.Add (IntToHex(ecu2,1));
Form1.Memo1.Lines.Add ('---');
Delay (30); SENDBYTE ($FF-ecu2); myReadByte; // InterByteTime Inv. KB senden, ECHO ignorieren
// 30 VAG-COM
ecu3 := ((ecu2 and $7F) * 128) + (ecu1 and $7F); // Protokollbezeichner berechnen
WriteDebugFile ('Proto', ecu3);
if (ecu3 = 1281) then
begin
Form1.StatusBar1.Panels[0].Text := LoadStr (langprefix + 23); // Verbunden
Form1.StatusBar1.Panels[2].Text := LoadStr (langprefix + 24) + 'KW ' + IntToStr (ecu3); // Protokoll
end
else
begin
erfolg := false;
Application.MessageBox(Pchar ('KW ' + IntToStr (ecu3) + ' ' + LoadStr (langprefix + 53)),'',MB_OK or MB_ICONEXCLAMATION);
end;
break; // Schleife beenden
end
end;
end
else // COM Port nicht zu öffnen => Abbruch Durchlauf Baudraten
begin
kw_Disconnect;
break;
end;
CLOSECOM(); // zu machen vor nächstem Aufbau mit neuer Baudrate
end; // for
end; // if verbinden
if (erfolg = false) then
begin
Form1.StatusBar1.Panels[0].Text := LoadStr (langprefix + 6); // Statusbar keine Verbindung
Form1.StatusBar1.Panels[1].Text := ''; // keine Baudrate
Form1.StatusBar1.Panels[2].Text := ''; // kein Protkoll
CLEARBUFFER;
CLOSECOM();
// Delay (1500);
end;
kw1281_wakeup := erfolg;
end; | | |
|
|
|
 |
geeky
Mitglied
Benutzerprofil
Anmeldungsdatum: 04.05.2001
Beiträge: 6184
|
geeky Mitglied
22:37:45 30.05.2012 Titel: |
|
Zitieren |
Hmm, interessanter Ansatz. Mit Break ändert er quasi den Pegel auf der Leitung und simuliert 0/1.
IOCTL_SERIAL_SET_BREAK_ON ist für DeviceIoControl() gedacht, man kann aber auch direkt EscapeCommFunction(comporthandle,SETBREAK) nehmen ;D
...allerdings sind die 200ms dort von der verbauten COM-Schnittstelle abhängig, die könnte auch mehr oder weniger ms nehmen. |
|
|
|
 |
COMCOM
Unregistrierter
|
COMCOM Unregistrierter
23:01:09 30.05.2012 Titel: |
|
Zitieren |
Ja, dass mit dem Timeout wird auch erwähnt:
| Zitat: | | zeit := 196; // eigentlich 200 aber bei USB Interface MUSS 195-196 |
Also ist BREAK immer ein künstliches Delay für ein 0-Bit? |
|
|
|
 |
geeky
Mitglied
Benutzerprofil
Anmeldungsdatum: 04.05.2001
Beiträge: 6184
|
geeky Mitglied
23:19:52 30.05.2012 Titel: |
|
Zitieren |
Ja, ein Break setzt die Leitung für ein paar ms auf den Ruhepegel (logisch 0) |
|
|
|
 |
COM
Unregistrierter
|
COM Unregistrierter
07:27:04 31.05.2012 Titel: |
|
Zitieren |
Ich schau mal, was sich daraus machen lässt. Danke |
|
|
|
 |
|
Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können Beiträge in dieses Forum schreiben. Sie können auf Beiträge in diesem Forum antworten. Sie können Ihre Beiträge in diesem Forum nicht bearbeiten. Sie können Ihre Beiträge in diesem Forum nicht löschen. Sie können an Umfragen in diesem Forum nicht mitmachen.
|
|
|
|
|