4 Zeiliges Display mit library für 2 zeiliges Display ansteuern

OP #2244949
Lesenswert?

Hallo,
Ich will ein 4-Zeiliges Display mit der Artikelbezeichnung EA W164B-NLW 
ansteuern. Verkabelt etc ist schon alles, es funktioniert auch schon.
Habe dazu eine Library die ich für 2 zeilige Displays verwende 
verwendet. Darum funktionieren auch nur die ersten 2 Zeilen des 
Displays.
Habe schon probiert die Library auf 4 Zeilig umzumodifizieren, da aber 
meine C-Künste im Keller liegen funktionierts aber leider nicht.
Die Koordinaten für den Curser werden im C-Code mit lcd_gotoxy(x,y) 
angegeben. y sind die Zeilen.

Hier die Original-Library für 2-zeilige Displays:
1
///////////////////////////////////////////////////////////////////////////
2
////                             LCD_WSH.C                             ////
3
////                 Driver for common LCD modules                     ////
4
////                                                                   ////
5
////  lcd_init()   Must be called before any other function.           ////
6
////                                                                   ////
7
////  lcd_putc(c)  Will display c on the next position of the LCD.     ////
8
////                     The following have special meaning:           ////
9
////                      \f  Clear display                            ////
10
////                      \n  Go to start of second line               ////
11
////                      \b  Move back one position                   ////
12
////                                                                   ////
13
////  lcd_gotoxy(x,y) Set write position on LCD (upper left is 1,1)    ////
14
////                                                                   ////
15
////  lcd_getc(x,y)   Returns character at position x,y on LCD         ////
16
////                                                                   ////
17
////  lcd_set_CG(ChNum, *Buffer) Sets Custom-Graphics for User-Chars.  ////
18
////                ChNum:   User-Char 0 .. 7                          ////
19
////                *Buffer: 8 Bytes Pixel-Data. details: see below!   ////
20
////                                                                   ////
21
////  lcd_cursor(On, Blink) Cursor-Functionaliy details: see below!    ////
22
////                                                                   ////
23
///////////////////////////////////////////////////////////////////////////
24
////        (C) Copyright 1996,2003 Custom Computer Services           ////
25
//// This source code may only be used by licensed users of the CCS C  ////
26
//// compiler.  This source code may only be distributed to other      ////
27
//// licensed users of the CCS C compiler.  No other use, reproduction ////
28
//// or distribution is permitted without written permission.          ////
29
//// Derivative programs created using this software in object code    ////
30
//// form are not restricted in any way.                               ////
31
///////////////////////////////////////////////////////////////////////////
32
//// History:                                                          ////
33
//// 09-06-27   Martin Scharfetter: adapted for use of                 //// 
34
////            Werkschulheim Felbertal, Salzburg, AUSTRIA:            ////
35
////            16F876, 18F2550+BootLoader + defining Custom-Graphics: ////
36
////            added lcd_set_CG() for up to 8 defineable Pixel-Chars  ////
37
//// 09-06-28   Martin Scharfetter: added Cursor-Control lcd_cursor()  ////
38
///////////////////////////////////////////////////////////////////////////
39

40
// As defined in the following structure the pin connection is as follows:
41
//    PIC  LCD
42
//     D0  enable
43
//     D1  rs
44
//     D2  rw
45
//     D3  not connected
46
//     D4  D4
47
//     D5  D5
48
//     D6  D6
49
//     D7  D7
50
//
51
//   LCD pins D0-D3 are not used and PIC D3 is not used.
52

53

54
struct lcd_pin_map {                 // This structure is overlayed
55
           BOOLEAN enable;           // on to an I/O port to gain
56
           BOOLEAN rs;               // access to the LCD pins.
57
           BOOLEAN rw;               // The bits are allocated from
58
           BOOLEAN unused;           // low order up.  ENABLE will
59
           int     data : 4;         // be pin B0.
60
        } lcd;
61

62

63
#if defined(__PCH__)
64
    #if defined use_portb_lcd
65
    #byte lcd = 0xF81                   // This puts the entire structure
66
    #elif defined use_portc_lcd
67
    #byte lcd = 0xF82                   // This puts the entire structure
68
    #elif defined use_portd_lcd
69
    #byte lcd = 0xF83                   // This puts the entire structure
70
    #else 
71
    #error Port for LCD not defined: use '#define use_portX_lcd' before including LCD_WSH.C (X=>Port: b, c or d)!
72
    #endif
73
#else
74
    #if defined use_portb_lcd
75
    #byte lcd = 0x6                     // on to port B (at address 6)
76
    #elif defined use_portc_lcd
77
    #byte lcd = 0x7                     // on to port C (at address 7)
78
    #elif defined use_portd_lcd
79
    #byte lcd = 0x8                     // on to port D (at address 8)
80
    #else 
81
    #error Port for LCD not defined: use '#define use_portX_lcd' before including LCD_WSH.C (X=>Port: b, c or d)!
82
    #endif
83
#endif
84

85
#if defined use_portb_lcd
86
   #define set_tris_lcd(x) set_tris_b(x)
87
#elif defined use_portc_lcd
88
   #define set_tris_lcd(x) set_tris_c(x)
89
#elif defined use_portd_lcd
90
   #define set_tris_lcd(x) set_tris_d(x)
91
#endif
92

93

94

95

96
#define lcd_type 2           // 0=5x7, 1=5x10, 2=2 lines
97
#define lcd_line_two 0x40    // LCD RAM address for the second line
98

99

100
BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
101
                             // These bytes need to be sent to the LCD
102
                             // to start it up.
103

104

105
                             // The following are used for setting
106
                             // the I/O port direction register.
107

108
struct lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; // For write mode all pins are out
109
struct lcd_pin_map const LCD_READ = {0,0,0,0,15}; // For read mode data pins are in
110

111

112

113
BYTE lcd_read_byte() {
114
      BYTE low,high;
115
      set_tris_lcd(LCD_READ);
116
      lcd.rw = 1;
117
      delay_cycles(1);
118
      lcd.enable = 1;
119
      delay_cycles(1);
120
      high = lcd.data;
121
      lcd.enable = 0;
122
      delay_cycles(1);
123
      lcd.enable = 1;
124
      delay_us(1);
125
      low = lcd.data;
126
      lcd.enable = 0;
127
      set_tris_lcd(LCD_WRITE);
128
      return( (high<<4) | low);
129
}
130

131

132
void lcd_send_nibble( BYTE n ) {
133
      lcd.data = n;
134
      delay_cycles(1);
135
      lcd.enable = 1;
136
      delay_us(2);
137
      lcd.enable = 0;
138
}
139

140

141
void lcd_send_byte( BYTE address, BYTE n ) {
142

143
      lcd.rs = 0;
144
      while ( bit_test(lcd_read_byte(),7) ) ;
145
      lcd.rs = address;
146
      delay_cycles(1);
147
      lcd.rw = 0;
148
      delay_cycles(1);
149
      lcd.enable = 0;
150
      lcd_send_nibble(n >> 4);
151
      lcd_send_nibble(n & 0xf);
152
}
153

154

155

156
void lcd_init() {
157
    BYTE i;
158
    set_tris_lcd(LCD_WRITE);
159
    lcd.rs = 0;
160
    lcd.rw = 0;
161
    lcd.enable = 0;
162
    delay_ms(15);
163
    for(i=1;i<=3;++i) {
164
       lcd_send_nibble(3);
165
       delay_ms(5);
166
    }
167
    lcd_send_nibble(2);
168
    for(i=0;i<=3;++i)
169
       lcd_send_byte(0,LCD_INIT_STRING[i]);
170
}
171

172

173
void lcd_gotoxy( BYTE x, BYTE y) {
174
   BYTE address;
175

176
   if(y!=1)
177
     address=lcd_line_two;
178
   else
179
     address=0;
180
   address+=x-1;
181
   lcd_send_byte(0,0x80|address);
182
}
183

184
void lcd_putc( char c) {
185
   switch (c) {
186
     case '\f'   : lcd_send_byte(0,1);
187
                   delay_ms(2);
188
                                           break;
189
     case '\n'   : lcd_gotoxy(1,2);        break;
190
     case '\b'   : lcd_send_byte(0,0x10);  break;
191
     default     : lcd_send_byte(1,c);     break;
192
   }
193
}
194

195
char lcd_getc( BYTE x, BYTE y) {
196
   char value;
197

198
    lcd_gotoxy(x,y);
199
    while ( bit_test(lcd_read_byte(),7) ); // wait until busy flag is low
200
    lcd.rs=1;
201
    value = lcd_read_byte();
202
    lcd.rs=0;
203
    return(value);
204
}
205

206
/* lcd_set_CG() Set User-defineable Characters: Standard-Displays have up to 8 different Characters (max. 8x8=64 Byte, CG means Custom-Graphics)
207
    input:  ChNum: Custom-Graphics Ram Address (0 .. 7), can be used e.g. by printf("%c", 0); for 1st CG or printf("\1"); for 2nd CG-Character
208
            Buffer: Address of a 8-Byte-Buffer containing the Pixel-Information: 1st Byte: Top Line (only 1st 5 Bits = Bit0..4 used)
209
    usage:  unsigned char UserChar[8] = {0x00,0x00,0x00,0x1F,0x11,0x15,0x11,0x1F }; // 8 Bytes Pixel-Data: e.g. a square with a dot inside
210
            lcd_set_CG(3, UserChar);                                                // set 4th CG-Ram to Pixel-Definition (8 user-defineable Characters possible (0 .. 7))
211
            printf(lcd_putc, "Hallo \3");                                           // printf 3rd char
212
*/
213
void lcd_set_CG(BYTE ChNum, BYTE *Buffer)
214
{ 
215
    BYTE b;
216
    lcd_send_byte(0, 0x40 | ((chnum & 0x07) << 3));     // Set CG-Address
217
    for (b=0;b<=7;b++)
218
        lcd_send_byte(1, Buffer[b ]);                    // Set 8 Bytes of Character-Data
219
}
220

221
/* lcd_cursor() Enable / Disable Cursor 
222
    inputs: On:     1: enable Cursor: lower 5 Pixel (='Underline') at current Cursor-Pos is always on
223
            Blink:  1: Character at current Cursor-Pos blinks: all Pixels ON (5x8) alternate with current Character
224
*/
225
void lcd_cursor(int1 On, int1 Blink)
226
{ 
227
    BYTE CursorCmd = 0x0C;  // Display on/off control: 0x08, + Display always ON: 0x04
228
    if (Blink)
229
        CursorCmd |= 0x01;  // Character Blinks at Cursor-Pos
230
    if (On)
231
        CursorCmd |= 0x02;  // Cursor ON
232
    lcd_send_byte(0, CursorCmd);                        // Set Cursor-Command
233
}


Und hier meine Version die nicht funzt:
1
///////////////////////////////////////////////////////////////////////////
2
////                             LCD_WSH.C                             ////
3
////                 Driver for common LCD modules                     ////
4
////                                                                   ////
5
////  lcd_init()   Must be called before any other function.           ////
6
////                                                                   ////
7
////  lcd_putc(c)  Will display c on the next position of the LCD.     ////
8
////                     The following have special meaning:           ////
9
////                      \f  Clear display                            ////
10
////                      \n  Go to start of second line               ////
11
////                      \b  Move back one position                   ////
12
////                                                                   ////
13
////  lcd_gotoxy(x,y) Set write position on LCD (upper left is 1,1)    ////
14
////                                                                   ////
15
////  lcd_getc(x,y)   Returns character at position x,y on LCD         ////
16
////                                                                   ////
17
////  lcd_set_CG(ChNum, *Buffer) Sets Custom-Graphics for User-Chars.  ////
18
////                ChNum:   User-Char 0 .. 7                          ////
19
////                *Buffer: 8 Bytes Pixel-Data. details: see below!   ////
20
////                                                                   ////
21
////  lcd_cursor(On, Blink) Cursor-Functionaliy details: see below!    ////
22
////                                                                   ////
23
///////////////////////////////////////////////////////////////////////////
24
////        (C) Copyright 1996,2003 Custom Computer Services           ////
25
//// This source code may only be used by licensed users of the CCS C  ////
26
//// compiler.  This source code may only be distributed to other      ////
27
//// licensed users of the CCS C compiler.  No other use, reproduction ////
28
//// or distribution is permitted without written permission.          ////
29
//// Derivative programs created using this software in object code    ////
30
//// form are not restricted in any way.                               ////
31
///////////////////////////////////////////////////////////////////////////
32
//// History:                                                          ////
33
//// 09-06-27   Martin Scharfetter: adapted for use of                 //// 
34
////            Werkschulheim Felbertal, Salzburg, AUSTRIA:            ////
35
////            16F876, 18F2550+BootLoader + defining Custom-Graphics: ////
36
////            added lcd_set_CG() for up to 8 defineable Pixel-Chars  ////
37
//// 09-06-28   Martin Scharfetter: added Cursor-Control lcd_cursor()  ////
38
///////////////////////////////////////////////////////////////////////////
39

40
// As defined in the following structure the pin connection is as follows:
41
//    PIC  LCD
42
//     D0  enable
43
//     D1  rs
44
//     D2  rw
45
//     D3  not connected
46
//     D4  D4
47
//     D5  D5
48
//     D6  D6
49
//     D7  D7
50
//
51
//   LCD pins D0-D3 are not used and PIC D3 is not used.
52

53

54
struct lcd_pin_map {                 // This structure is overlayed
55
           BOOLEAN enable;           // on to an I/O port to gain
56
           BOOLEAN rs;               // access to the LCD pins.
57
           BOOLEAN rw;               // The bits are allocated from
58
           BOOLEAN unused;           // low order up.  ENABLE will
59
           int     data : 4;         // be pin B0.
60
        } lcd;
61

62

63
#if defined(__PCH__)
64
    #if defined use_portb_lcd
65
    #byte lcd = 0xF81                   // This puts the entire structure
66
    #elif defined use_portc_lcd
67
    #byte lcd = 0xF82                   // This puts the entire structure
68
    #elif defined use_portd_lcd
69
    #byte lcd = 0xF83                   // This puts the entire structure
70
    #else 
71
    #error Port for LCD not defined: use '#define use_portX_lcd' before including LCD_WSH.C (X=>Port: b, c or d)!
72
    #endif
73
#else
74
    #if defined use_portb_lcd
75
    #byte lcd = 0x6                     // on to port B (at address 6)
76
    #elif defined use_portc_lcd
77
    #byte lcd = 0x7                     // on to port C (at address 7)
78
    #elif defined use_portd_lcd
79
    #byte lcd = 0x8                     // on to port D (at address 8)
80
    #else 
81
    #error Port for LCD not defined: use '#define use_portX_lcd' before including LCD_WSH.C (X=>Port: b, c or d)!
82
    #endif
83
#endif
84

85
#if defined use_portb_lcd
86
   #define set_tris_lcd(x) set_tris_b(x)
87
#elif defined use_portc_lcd
88
   #define set_tris_lcd(x) set_tris_c(x)
89
#elif defined use_portd_lcd
90
   #define set_tris_lcd(x) set_tris_d(x)
91
#endif
92

93

94
#define lcd_type 2           // 0=5x7, 1=5x10, 2=2 lines
95
#define lcd_line_one 0x00    // LCD RAM address for the second line
96
#define lcd_line_two 0x40    // LCD RAM address for the second line
97
#define lcd_line_three 0x10    // LCD RAM address for the third line
98
#define lcd_line_four 0x50    // LCD RAM address for the fourth line
99

100

101
BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
102
                             // These bytes need to be sent to the LCD
103
                             // to start it up.
104

105

106
                             // The following are used for setting
107
                             // the I/O port direction register.
108

109
struct lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; // For write mode all pins are out
110
struct lcd_pin_map const LCD_READ = {0,0,0,0,15}; // For read mode data pins are in
111

112

113

114
BYTE lcd_read_byte() {
115
      BYTE low,high;
116
      set_tris_lcd(LCD_READ);
117
      lcd.rw = 1;
118
      delay_cycles(1);
119
      lcd.enable = 1;
120
      delay_cycles(1);
121
      high = lcd.data;
122
      lcd.enable = 0;
123
      delay_cycles(1);
124
      lcd.enable = 1;
125
      delay_us(1);
126
      low = lcd.data;
127
      lcd.enable = 0;
128
      set_tris_lcd(LCD_WRITE);
129
      return( (high<<4) | low);
130
}
131

132

133
void lcd_send_nibble( BYTE n ) {
134
      lcd.data = n;
135
      delay_cycles(1);
136
      lcd.enable = 1;
137
      delay_us(2);
138
      lcd.enable = 0;
139
}
140

141

142
void lcd_send_byte( BYTE address, BYTE n ) {
143

144
      lcd.rs = 0;
145
      while ( bit_test(lcd_read_byte(),7) ) ;
146
      lcd.rs = address;
147
      delay_cycles(1);
148
      lcd.rw = 0;
149
      delay_cycles(1);
150
      lcd.enable = 0;
151
      lcd_send_nibble(n >> 4);
152
      lcd_send_nibble(n & 0xf);
153
}
154

155

156

157
void lcd_init() {
158
    BYTE i;
159
    set_tris_lcd(LCD_WRITE);
160
    lcd.rs = 0;
161
    lcd.rw = 0;
162
    lcd.enable = 0;
163
    delay_ms(15);
164
    for(i=1;i<=3;++i) {
165
       lcd_send_nibble(3);
166
       delay_ms(5);
167
    }
168
    lcd_send_nibble(2);
169
    for(i=0;i<=3;++i)
170
       lcd_send_byte(0,LCD_INIT_STRING[i]);
171
}
172

173

174
void lcd_gotoxy( BYTE x, BYTE y) {
175
   BYTE address;
176

177
   if(y=1)
178
     address=lcd_line_one;
179
   else if(y=2)
180
     address=lcd_line_two;
181
   else if(y=3)
182
     address=lcd_line_three;
183
   else if(y=4)
184
     address=lcd_line_four;
185
   else
186
     address=0;
187
   address+=x-1;
188
   lcd_send_byte(0,0x80|address);
189
}
190

191
void lcd_putc( char c) {
192
   switch (c) {
193
     case '\f'   : lcd_send_byte(0,1);
194
                   delay_ms(2);
195
                                           break;
196
     case '\n'   : lcd_gotoxy(1,2);        break;
197
     case '\b'   : lcd_send_byte(0,0x10);  break;
198
     default     : lcd_send_byte(1,c);     break;
199
   }
200
}
201

202
char lcd_getc( BYTE x, BYTE y) {
203
   char value;
204

205
    lcd_gotoxy(x,y);
206
    while ( bit_test(lcd_read_byte(),7) ); // wait until busy flag is low
207
    lcd.rs=1;
208
    value = lcd_read_byte();
209
    lcd.rs=0;
210
    return(value);
211
}
212

213
/* lcd_set_CG() Set User-defineable Characters: Standard-Displays have up to 8 different Characters (max. 8x8=64 Byte, CG means Custom-Graphics)
214
    input:  ChNum: Custom-Graphics Ram Address (0 .. 7), can be used e.g. by printf("%c", 0); for 1st CG or printf("\1"); for 2nd CG-Character
215
            Buffer: Address of a 8-Byte-Buffer containing the Pixel-Information: 1st Byte: Top Line (only 1st 5 Bits = Bit0..4 used)
216
    usage:  unsigned char UserChar[8] = {0x00,0x00,0x00,0x1F,0x11,0x15,0x11,0x1F }; // 8 Bytes Pixel-Data: e.g. a square with a dot inside
217
            lcd_set_CG(3, UserChar);                                                // set 4th CG-Ram to Pixel-Definition (8 user-defineable Characters possible (0 .. 7))
218
            printf(lcd_putc, "Hallo \3");                                           // printf 3rd char
219
*/
220
void lcd_set_CG(BYTE ChNum, BYTE *Buffer)
221
{ 
222
    BYTE b;
223
    lcd_send_byte(0, 0x40 | ((chnum & 0x07) << 3));     // Set CG-Address
224
    for (b=0;b<=7;b++)
225
        lcd_send_byte(1, Buffer[b ]);                    // Set 8 Bytes of Character-Data
226
}
227

228
/* lcd_cursor() Enable / Disable Cursor 
229
    inputs: On:     1: enable Cursor: lower 5 Pixel (='Underline') at current Cursor-Pos is always on
230
            Blink:  1: Character at current Cursor-Pos blinks: all Pixels ON (5x8) alternate with current Character
231
*/
232
void lcd_cursor(int1 On, int1 Blink)
233
{ 
234
    BYTE CursorCmd = 0x0C;  // Display on/off control: 0x08, + Display always ON: 0x04
235
    if (Blink)
236
        CursorCmd |= 0x01;  // Character Blinks at Cursor-Pos
237
    if (On)
238
        CursorCmd |= 0x02;  // Cursor ON
239
    lcd_send_byte(0, CursorCmd);                        // Set Cursor-Command
240
}

Die Adressen für die Zeilen des Displays sind laut Datenblatt für
Zeile1 $00-$0F
Zeile2 $40-$4F
Zeile3 $10-$1F
Zeile4 $50-$5F
, was ich auch am Anfang für lcd_line_one, etc. definiert habe.

Ich vermute dass in der Funktion lcd_gotoxy der Programmierfehler von 
mir liegt.
Kann mir wer helfen?

Danke!

MfG Emanuel
OP #2246948
Lesenswert?

Ok, danke für eure Antworten.

Obwohl ich kein guter C-Programmierer bin ist mir selbst das mit der 
Zuweisung und Abfrage in einer IF-Schleife ziemlich peinlich xD, sowas 
passiert mir nicht allzu oft...

Leider funktionierts aber noch immer nicht, also wenn ich im Programm 
goto_xy(1,3) schreibe, schreibts mir die Schrift immer in die 2. statt 
in die 3. Zeile. Jedoch wenn ich mehr als 16 Zeichen schreibe, also die 
maximale "länge" des Displays, wird der Satz oder was auch immer in der 
3. Zeile fortgesetzt.

Was mir noch aufgefallen ist:
1
#define lcd_type 2           // 0=5x7, 1=5x10, 2=2 lines

und das kann bei 4 zeilen dann wohl nicht mehr stimmen.
Verwendet wird lcd_type bei
1
BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
2
                             // These bytes need to be sent to the LCD
3
                             // to start it up.

mfg
Gast #2247034
Lesenswert?

Hi

>Was mir noch aufgefallen ist:
>#define lcd_type 2           // 0=5x7, 1=5x10, 2=2 lines
>und das kann bei 4 zeilen dann wohl nicht mehr stimmen.

Doch. Die Einstellung 1/2-zeilig im Controller hat nur sehr bedingt 
etwas mit der Anzahl der Displayzeilen zu tun. Es gibt 1x16 Displays, 
die 2-Zeilig initialisiert werden müssen und bei denen die Zeichen o..7 
eine Zeile und 8..15 die zweite Zeile sind.
Bei vierzeiligen Displays sind die Displayzeilen 0 und 2 die erste und 1 
und 3 die zweite Zeile.

>BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
>änder das mal auf folgende Zeile
>BYTE const LCD_INIT_STRING[4] = {0x28, 0xc, 1, 6};

kommt aus gleiche heraus:

0x20| 0x10<<2 = 00101000 = $28

MfG Spess
Gast #2247798
Lesenswert?

Blöde Frage -

Du hast nicht zufällt ein \n vor Deinem Text stehen ?

Ich meine nur, weil in Deiner lcd_putc routine noch fest zeile 2 bei \n 
angesprungen wird ?

(   case '\n'   : lcd_gotoxy(1,2);        break; )
OP #2247815
Lesenswert?

Das mit den 4 Zeilen funktioniert nun, danke an alle (bes. Spess)

NurEinGast schrieb:
> Blöde Frage -
>
> Du hast nicht zufällt ein \n vor Deinem Text stehen ?
>
> Ich meine nur, weil in Deiner lcd_putc routine noch fest zeile 2 bei \n
> angesprungen wird ?
>
> (   case '\n'   : lcd_gotoxy(1,2);        break; )

Jap das hab ich mir auch schon gedacht, hatte ich aber nicht stehen. Und 
dass wird das nächste..
wie kann ich das mit dem Zeilenumbruch nun mit 4 zeilen machen?

Am besten die Curserposition abfragen und je nach dem in die richtige 
Zeile setzen oder?

danke & mfg

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren