Forum: Mikrocontroller und Digitale Elektronik Anzeige LCD-I2C / Multitasking und Tasterentprellung von Peter


von Achim S. (achims)


Lesenswert?

Hallo
ich verwende die Tasterentprellung von Peter, eine Timer mit 1 ms zur 
Anzeige mit LED, 10 ms für Entprellung, Kommunilkation über den I2C Bus 
mit einer Anzeige 4x16. Habe das wichtigste im Code:
1
int main(void)
2
  {
3
  timer_init();
4
5
  DDRA=0b00000100;              // Port A 1x auf Ausgang schalten
6
  DDRC=0b01100000;              // Port C 2x auf Ausgang schalten
7
  
8
  KEY_DDR&=~ALL_KEYS;
9
  KEY_PORT|=ALL_KEYS;
10
  
11
  PORTC |= (1<<PC5);              // Port A beim einschalten Ausgänge aus
12
  PORTC |= (1<<PC6);
13
  
14
  //char Buffer[20];
15
  i2c_init();                          // Starte I2C Bus
16
  lcd_init();                          // Starte I2CLCD
17
  lcd_light(0);                // 0=Licht an, 1=Licht aus
18
  // Display Befehle
19
  lcd_command(LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKINGOFF);
20
  // Display ON/OFF / Cursor ON/OFF / Blinken ON/OFF
21
  startanzeige();
22
  
23
  _delay_ms(5000);  
24
  
25
  
26
  lcd_command(LCD_CLEAR);            // Leere Display
27
  _delay_ms(2);              // warte 2ms
28
  
29
  sei();
30
  
31
  
32
  while(1)              // Programmschleife
33
    {
34
    if(flag_1ms)
35
      {
36
      flag_1ms=0;
37
      led_blinken1();        // Aufruf Unterprogramm
38
      }
39
    
40
    if(get_key_press(1<<KEY_2))    // nur Taste press
41
    {                // LED an
42
      PORTC &= ~(1<<PC5);
43
    }
44
    
45
    if(get_key_press(1<<KEY_3))    // nur Taste press
46
    {                // LED aus
47
      PORTC |= (1<<PC5);
48
    }
49
    
50
    if(get_key_short(1<<KEY_1))    // kurz schalten immer zusammen mit long
51
    {
52
      PORTC &= ~(1<<PC6);          // LED an
53
    }
54
55
    if(get_key_long(1<<KEY_1))    // Lang schalten immer mit short
56
    {
57
      PORTC |= (1<<PC6);      // LED aus
58
    }
59
//////////////////////////////////////////////////////
60
    
61
    lcd_printlc(1,2,"Anzeige 1t");
62
63
//////////////////////////////////////////////////////
64
    
65
  }
66
}
Durch Startanzeige wird ein kurzer Text zur Begrüssung auf dem Display 
dargestellt.

lcd_printlc(1,2,"Anzeige 1t");

Das Problem ist dieser Anweisung. Ohne diese Teil habe ich gut laufendes 
Programm. Es wird mir durch dieses Teil immer ein Takt angezeigt und ich 
weiss das alles läuft.
1
void led_blinken1()
2
  {
3
  led1++;
4
  if(led1==500)
5
    {
6
    PORTA &= ~(1<<PA2);        // Schaltet Pin
7
    }
8
  else
9
    {
10
    if(led1==1000)
11
      {
12
      PORTA |= (1<<PA2);      // Schaltet Pin
13
      led1=0;
14
      }
15
    }
16
  }

Sobald ich die letzte Anweisung drin habe, wird das Programm sehr 
langsam.
Ich weis das ein Display Zeit braucht zur Anzeige. Jetzt braucht es ca. 
10x so lang.

Wie kann ich das ändern? Suche eine Idee dazu. Es geht in die Richtung 
Multitasking und Anzeige bzw. I2C Bus.

AT1284p,C,16Mhz
achim

von Karl M. (Gast)


Lesenswert?

Hallo Achim,

was wichtigste zeigt du nicht: die LCD Lib mit allen Methoden.

lcd_printlc(..) usw.

man kann auch eine nicht blockierende LCD Ausgabe programmieren, in dem 
man alle LCD-Ausgaben und deren ASCII-Zeichen in einem shadow Puffer 
ablegt.
Über einem Timerinterrupt wird im Hintergrund, z.B. alle 1ms, jeweils 
nur ein Zeichen fortlaufend aus dem shadow Puffer auslesen und dann 
direkt in das LCD geschrieben.
Man muss aber die LCD Bereichsgrenzen überprüfen und am LCD-Zeilen einen 
Zeilenumbruch machen.
Die LCD.Char( ch ) und LCD.SetCursor( Y, X ) Routinen brauchen dann 
keine Wartezeiten mehr. Andere LCD Methoden verwende ich i.a. nicht.

von Falk B. (falk)


Lesenswert?

@ Karl M. (Gast)

>was wichtigste zeigt du nicht: die LCD Lib mit allen Methoden.

Hat keine Methoden, weil es kein C++ ist. Ausserdem ist die 
nebensächlich.

>lcd_printlc(..) usw.

>man kann auch eine nicht blockierende LCD Ausgabe programmieren,

Kann man, ist hier aber nicht das Problem. Die Ausgaben sind so oder so 
recht schnell. Der Achim bremst sich (mal wieder) selber aus.

von Karl M. (Gast)


Lesenswert?

Es könnte sich bei der LCD Routinen um eine I2C Implementierung handeln.

Vielleicht diese hier ?
http://computerheld.de/i2clcd/
https://www.mikrocontroller.net/attachment/82786/i2clcd.c
https://www.mikrocontroller.net/attachment/98515/i2clcd.h

von Falk B. (falk)


Lesenswert?

@Achim Seeger (achims)

>mit einer Anzeige 4x16. Habe das wichtigste im Code:

Nein. Du bist eigentlich lange genug in diesem Forum unterwegs, daß du 
wissen solltest, daß man besser VOLLSTÄNDIGEN Querlltext als Anhang 
mitgibt. Dein Quelltext oben ist OK, der Fehler liegt woanders.

von Karl M. (Gast)


Lesenswert?

Hallo Falk,

JA ich meinte auch nicht C++ mit Methoden, sondern nur die zur LCD Lib 
gehörigen Funktionen/ Proceduren.

Wo bremst er sich aus ?
Ich sehe es noch nicht.
Ausser die get_key_press() kann man als if () .. else if ()  schreiben.

von Falk B. (falk)


Lesenswert?

@Karl M. (Gast)

>JA ich meinte auch nicht C++ mit Methoden, sondern nur die zur LCD Lib
>gehörigen Funktionen/ Proceduren.

Dann schreib das doch einfach.

>Wo bremst er sich aus ?

In dem Teil, der nicht sichtbar ist.

>Ich sehe es noch nicht.

Ich schon, denn ich kenn den Achim ;-)

>Ausser die get_key_press() kann man als if () .. else if ()  schreiben.

von Achim S. (achims)


Lesenswert?

Sorry Karl und Falk
habe fast alles reingestellt. Was fehlt sind die Routinen von Peter aus 
den Beiträgen "Entprellen" und den Libs von Peter zum I2C Bus.
Im Grunde handelt sich um die Tasterentprellung mit einer Erweiterung 
zum Bus. Diese Datein sind alle frein im Netz und von mir und vielen 
anderen verwendet. Habe auch weiter im Netz gesucht und was gefunden.
1
void anzeige()
2
  {
3
    lauf++;
4
  if(lauf==50)
5
    {
6
      
7
      itoa( anz, Buffer, 10 );    // Zeile 1
8
      lcd_printlc(3,1,"Wert ");
9
      lcd_printlc(3,9,Buffer);
10
      lauf=0;    
11
    }
Im Programm erfolgt der Aufruf damit:
1
                anzeige();  
2
    _delay_ms(1);
Als anz habe ich einen Wert genommen um zu testen ob eine Anzeige 
erfolgt.
Damit erfolgt ein Blinken der Kontroll LED und die Anzeige wird nur bei 
jedem 50 Aufruf durchgeführt. Damit scheint beides zu laufen.
Vielleicht hat jemand eine bessere Idee

von Falk B. (falk)


Lesenswert?

@ Achim Seeger (achims)

>habe fast alles reingestellt.

Ist es denn soooo schwer, einfach das gottverdammte Proggramm als Anhang 
hier zu posten? Überfordern dich drei Clicks?

> Was fehlt sind die Routinen von Peter aus
>den Beiträgen "Entprellen" und den Libs von Peter zum I2C Bus.

Die braucht keiner, denn die sind meist korrekt, wenn du nicht 
unqualifiziert dort drin rumgeändert hast.

Was z.B. fehlt ist in DEINEM Programm die globalen Variablen, u.a. led1, 
denn du Künstler hast bis heute nicht verstanden, wie man lokale 
Variabeln sinnvoll benutzt.

>Im Grunde handelt sich um die Tasterentprellung mit einer Erweiterung
>zum Bus. Diese Datein sind alle frein im Netz und von mir und vielen
>anderen verwendet. Habe auch weiter im Netz gesucht und was gefunden.

Ja und? Glaubst du durch wildes Zusammenkopieren findest du den Fehler 
in DEINEM Quelltext?

>Vielleicht hat jemand eine bessere Idee

Ja, hör endlich auf sinnlose Fragmente zu posten und fang endlich mal an 
gescheit zu kommunizieren. Wenn man hier nach dem VOLLSTÄDNIGEN 
Quelltext fragt hat das seinen Grund!

(Warum tu ich mir das eigenlich an?)

von Achim S. (achims)


Lesenswert?

Der komplette Code:
1
#define F_CPU 16000000UL  // Angabe der Quarzfrequenz, wichtig für die Zeit
2
#include <avr/io.h>      // Einbindung Datein
3
#include <avr/interrupt.h>
4
#include <stdint.h>
5
#include <util/delay.h>
6
#include <stdbool.h>
7
#include <avr/pgmspace.h>
8
#include "main.h"
9
#include "i2clcd.h"
10
#include "i2cmaster.h"
11
#include <stdlib.h>
12
13
#define PCF8591w   0x90
14
#define PCF8591r   0x91
15
16
volatile int16_t led1=0;
17
volatile int8_t lauf=0;
18
volatile int8_t anz=123;
19
char Buffer[20];
20
///////////////////////////////////////////////////////
21
volatile int8_t wait;
22
volatile int8_t flag_1ms;
23
volatile uint8_t key_state;
24
volatile uint8_t key_press;
25
volatile uint8_t key_rpt;
26
//////////////////////////////////////////////////////
27
#define KEY_DDR    DDRA                         // Datenrichtung A
28
#define KEY_PORT   PORTA                        // Angabe Port A
29
#define KEY_PIN    PINA                         // Angabe PIN A
30
#define KEY_1       3                           // PA 3
31
#define KEY_2       5                           // PA 5
32
#define KEY_3       7                           // PA 7
33
#define ALL_KEYS (1<<KEY_1|1<<KEY_2|1<<KEY_3)
34
#define REPEAT_MASK (1<<KEY_1|1<<KEY_2)
35
#define REPEAT_START 50                          // after 500ms
36
#define REPEAT_NEXT 20                           // every 200ms
37
///////////////////////////////////////////////////
38
void startanzeige()            // Titelbild
39
  {
40
  lcd_command(LCD_CLEAR);
41
  _delay_ms(2);
42
  lcd_printlc(1,2,"Versuch1n-I2C");
43
  lcd_printlc(2,2,"P30 + P64 + D2");
44
  lcd_printlc(3,2,"AT1284 und LCD");
45
  lcd_printlc(4,4,"bei achim S");
46
  //_delay_ms(2000);
47
  }
48
//////////////////////////////////////////////////
49
50
51
/////////////////////////////////////////////////////
52
ISR (TIMER0_COMPA_vect)                // wait1=1ms,
53
  {
54
  static uint8_t ct0,ct1,rpt;
55
  uint8_t i;
56
  //if (flag_1ms)
57
    //{
58
    // Laufzeit der Tasks >2ms, Fehlersignalisierung auf PA6, Programm stoppen
59
    //PORTA &= ~(1<<PA6);        // Schaltet Pin
60
    //while(1);        // Endlosschleife, stoppt Programm
61
    //}
62
  flag_1ms=1;
63
  if(wait<=9)                                // bei 9 sind es 10ms
64
    {
65
    wait++;
66
    }                      // erhöht
67
  else                    // wenn dann ...
68
    {
69
    wait=0;                  // setzt wait auf 0
70
    i=key_state ^~KEY_PIN;
71
    ct0=~(ct0&i);
72
    ct1=ct0^(ct1&i);
73
    i&=ct0&ct1;
74
    key_state^=i;
75
    key_press|=key_state&i;
76
    if((key_state & REPEAT_MASK)==0)
77
    rpt=REPEAT_START;
78
    if(--rpt==0)
79
      {
80
      rpt=REPEAT_NEXT;
81
      key_rpt|=key_state & REPEAT_MASK;
82
      }
83
    }
84
  }
85
//////////////////////////////////////////////////////
86
uint8_t get_key_press(uint8_t key_mask)
87
  {
88
  cli();
89
  key_mask &=key_press;
90
  key_press^=key_mask;
91
  sei();
92
  return key_mask;
93
  }
94
/////////////////////////////////////////
95
uint8_t get_key_rpt(uint8_t key_mask)
96
  {
97
  cli();
98
  key_mask &=key_rpt;
99
  key_rpt^=key_mask;
100
  sei();
101
  return key_mask;
102
  }
103
///////////////////////////////////////////////////////
104
uint8_t get_key_short(uint8_t key_mask)
105
  {
106
  cli();
107
  return get_key_press(~key_state & key_mask);
108
  }
109
///////////////////////////////////////////////////////
110
uint8_t get_key_long(uint8_t key_mask)
111
  {
112
  return get_key_press(get_key_rpt(key_mask));
113
  }
114
//////////////////////////////////////////////////////
115
void led_blinken1()
116
  {
117
  led1++;
118
  if(led1==500)
119
    {
120
    PORTA &= ~(1<<PA2);        // Schaltet Pin
121
    }
122
  else
123
    {
124
    if(led1==1000)
125
      {
126
      PORTA |= (1<<PA2);      // Schaltet Pin
127
      led1=0;
128
      }
129
    }
130
  }
131
132
//////////////////////////////////////////////////////
133
void anzeige()
134
  {
135
    lauf++;
136
  if(lauf==50)
137
    {
138
      
139
      itoa( anz, Buffer, 10 );    // Zeile 1
140
      lcd_printlc(3,1,"Wert ");
141
      lcd_printlc(3,9,Buffer);
142
      
143
      lauf=0;
144
      
145
    }
146
  
147
/////////////////////////////////////////////////////
148
void timer_init()
149
  {                        // Timer 0 konfigurieren
150
  TCCR0A = 0;                  // CTC Modus
151
  TCCR0B = (1<<WGM01)|(1<<CS01)|(1<<CS00);  // Prescaler 64
152
  TCNT0=1;
153
  OCR0A=249;
154
  TIMSK0|=(1<<OCIE0A);            // Interrupt erlauben
155
  }
156
////////////////////////////////////////////////////
157
int main(void)
158
  {
159
  timer_init();
160
161
  DDRA=0b00000100;              // Port A 1x auf Ausgang schalten
162
  DDRC=0b01100000;              // Port C 2x auf Ausgang schalten
163
  
164
  KEY_DDR&=~ALL_KEYS;
165
  KEY_PORT|=ALL_KEYS;
166
  
167
  PORTC |= (1<<PC5);              // Port A beim einschalten Ausgänge aus
168
  PORTC |= (1<<PC6);
169
  
170
  //char Buffer[20];
171
  i2c_init();                          // Starte I2C Bus
172
  lcd_init();                          // Starte I2CLCD
173
  lcd_light(0);                // 0=Licht an, 1=Licht aus
174
  // Display Befehle
175
  lcd_command(LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKINGOFF);
176
  // Display ON/OFF / Cursor ON/OFF / Blinken ON/OFF
177
  startanzeige();
178
  
179
  _delay_ms(5000);  
180
  
181
  
182
  lcd_command(LCD_CLEAR);            // Leere Display
183
  _delay_ms(2);              // warte 2ms
184
  
185
  sei();
186
  
187
  
188
  while(1)              // Programmschleife
189
    {
190
    if(flag_1ms)
191
      {
192
      flag_1ms=0;
193
      led_blinken1();        // Aufruf Unterprogramm
194
      }
195
    ////////////////////////////// Test mit delay
196
    // _delay_ms(2);
197
    //////////////////////////////
198
    
199
    if(get_key_press(1<<KEY_2))    // nur Taste press
200
    {                // LED an
201
      PORTC &= ~(1<<PC5);
202
    }
203
    
204
    if(get_key_press(1<<KEY_3))    // nur Taste press
205
    {                // LED aus
206
      PORTC |= (1<<PC5);
207
    }
208
    
209
    if(get_key_short(1<<KEY_1))    // kurz schalten immer zusammen mit long
210
    {
211
      PORTC &= ~(1<<PC6);          // LED an
212
    }
213
214
    if(get_key_long(1<<KEY_1))    // Lang schalten immer mit short
215
    {
216
      PORTC |= (1<<PC6);      // LED aus
217
    }
218
    
219
    anzeige();
220
    
221
    _delay_ms(1);
222
    
223
  }
224
}

von Falk B. (falk)


Lesenswert?

@Achim Seeger (achims)

>Der komplette Code:

Wie oft schrieb ich von ANHANG?
(Hoffnunslos . . . )

Hier fehlt eine }, das Programm kann so nicht fehlerfrei kompiliert 
werden.
1
void anzeige()
2
  {
3
    lauf++;
4
  if(lauf==50)
5
    {
6
      
7
      itoa( anz, Buffer, 10 );    // Zeile 1
8
      lcd_printlc(3,1,"Wert ");
9
      lcd_printlc(3,9,Buffer);
10
      
11
      lauf=0;
12
      
13
    }

Dein Einrückungsstil des Quelltextes ist mal wieder sehr speziell und 
einfach schlecht! Mach es so wie der Rest der Welt, dann hast du auch 
weniger Probleme.

Ausserdem ist es reichlich unsinnig, auf der einen Seite einen 1ms Timer 
laufen zu lassen und ein flag_1ms zu nutzen und dann zusätzlich noch ein 
_delay_ms(1) in die Hauptschleife zu schreiben. Konntest du dich nicht 
entscheiden? Damit dauert dein Durchlauf 2ms statt einer und deine LED 
blinkt mit 0,5 Hz statt 1Hz. Ist es das, was du siehst?

Deine Timerinitialisierung stimmt nicht.

>/////////////////////////////////////////////////////
>void timer_init()
>  {                        // Timer 0 konfigurieren
>  TCCR0A = 0;                  // CTC Modus
>  TCCR0B = (1<<WGM01)|(1<<CS01)|(1<<CS00);  // Prescaler 64

FALSCH! WGM01 liegt in TCCR0A.

>  TCNT0=1;

Braucht keiner

>  OCR0A=249;
>  TIMSK0|=(1<<OCIE0A);            // Interrupt erlauben
>  }

Eher so.
1
                        // Timer 0 konfigurieren
2
void timer_init() {
3
  TCCR0A = (1<<WGM01);            // CTC Modus
4
  TCCR0B = (1<<CS01)|(1<<CS00);  // Prescaler 64
5
  OCR0A=249;
6
  TIMSK0|=(1<<OCIE0A);            // Interrupt erlauben
7
}

Trotzdem müsste das Flag mit nahezu 1ms kommen, auch bei der falschen 
Initialisierung. Merkwürdig. Das Programm sieht OK aus. Was geht denn 
KONKRET nicht? Die LED sollte mit 0,5 Hz (2s) blinken.

von Karl M. (Gast)


Lesenswert?

Hallo,

hier noch eine Kleinigkeit zur Tastenenprellen im 10ms Timerinterrupt.

Diese Variable ct0, ct1 sind nicht initialisiert.
Sie, also beide, müssen mit 255 = 0xff initialisiert werden.
1
ISR (TIMER0_COMPA_vect)                // wait1=1ms,
2
  {
3
  static uint8_t ct0,ct1;
4
  static uint8_t rpt;

von Achim S. (achims)


Lesenswert?

Hallo Falk
bin am schaun was du schreibst.
Der Einrückstil kommt durch das übertragen, es verändert die Sachen.
} ist jetzt drin. ergab eine Warnung
In der jetzigen Fassung läuft das Programm. Ob 1 oder 2 ms habe nicht 
getestet. In der Fassung weiter oben hat die Anzeige des I2C Bus und der 
1ms Takt ca. 10 x länger gedauert. Die Anzeige auf dem Display kam 
saulangsam.
Das mit dem Timer werde ich sofort checken. Der Timer stammt aus 
"Multitasking" und auch die zusätzliche 1ms delay im programm.
Brauch nicht jedes Teilprogramm neuerfinden

von Falk B. (falk)


Lesenswert?

@ Achim Seeger (achims)

>Der Einrückstil kommt durch das übertragen, es verändert die Sachen.

Dann mach aus deinen echten Tabs echte Leerzeichen. Das können die 
meisten Editoren.

>} ist jetzt drin. ergab eine Warnung

WELCHE???!!!!!

Warum gab es vorher keine Warung? Oder hast du die nur ignióriert? Glaub 
ich nicht, denn ohne die Klammer ist das Programm unkompilierbar, auch 
niciht mir Warnung. Oder du murkst mal wieder rum und zeigst uns nicht 
deinen echten Originalquelltext sondern irgendwelche Kopien.

>In der jetzigen Fassung läuft das Programm. Ob 1 oder 2 ms habe nicht
>getestet. In der Fassung weiter oben hat die Anzeige des I2C Bus und der
>1ms Takt ca. 10 x länger gedauert. Die Anzeige auf dem Display kam
>saulangsam.

Dann ist was anderes faul. Faktor 10 erklärt das nicht.

>Das mit dem Timer werde ich sofort checken. Der Timer stammt aus
>"Multitasking" und auch die zusätzliche 1ms delay im programm.
>Brauch nicht jedes Teilprogramm neuerfinden

Aber man sollte es halbwegs verstehen, was man da zusammenkopiert . . . 
8-(

von Achim S. (achims)


Lesenswert?

Es ist der ori Text. Hatte aber noch Code drin aus der Arbeitsversion 
der auskommentiert war. Vielleicht hat sich was rein gemogelt und 
übersehen.
Wahrscheinlich hatte ich die reihenfolge verändert. Erst die pause und 
dann der Aufruf. Kann es nicht mehr eindeutug nachvollziehen, da ich die 
alten Teile gelöscht habe.
Warum soll ich keine Programme oder Teile wiederverwenden? Bestimmte 
Teile haben sich bewährt und laufeb Fehlerfrei.
Petres Code z.B. läuft sehr gut. Es gibt ganze Seiten mit den Hinweisen 
anderer über den Modularen Aufbau und verwendung von Unterprogrammen.
achim

von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

@ Achim Seeger (achims)

>Es ist der ori Text.

Ori? Von den Maori?

>Hatte aber noch Code drin aus der Arbeitsversion
>der auskommentiert war. Vielleicht hat sich was rein gemogelt und
>übersehen.

Na toll!

>Wahrscheinlich hatte ich die reihenfolge verändert. Erst die pause und
>dann der Aufruf. Kann es nicht mehr eindeutug nachvollziehen, da ich die
>alten Teile gelöscht habe.

Noch besser.

>Warum soll ich keine Programme oder Teile wiederverwenden? Bestimmte
>Teile haben sich bewährt und laufeb Fehlerfrei.

Darum geht es nicht. Wenn man Teile zusammenkopiert bzw. 
wiederverwendet, sollte man wissen was man tut.

Test mal das Programm in Anhang. F_CPU gehört in main.h, nicht in 
einzelne .c Dateien!

von Achim S. (achims)


Lesenswert?

Hallo Falk
habe das Programm gleich getestet. Geht ohne Fehler und Warnung.
Zusätzlich habe ich noch das eingebaut
1
if(get_key_press(1<<KEY_2))    // nur Taste press
2
        {                // LED an
3
        PORTC &= ~(1<<PC5);
4
        anz=anz+5;
5
        if (anz>255)
6
          {
7
          anz=255;
8
          }
9
        }
10
      if(get_key_press(1<<KEY_3))    // nur Taste press
11
        {                // LED aus
12
        PORTC |= (1<<PC5);
13
        anz=anz-5;
14
        if (anz<0)
15
          {
16
          anz=0;
17
          }      
18
        }
Damit kann ich anz von 0 bis 255 durchschalten und die Werte auf dem 
Display ausgeben. Als Anwendung z.B. Spannungsausgabe mit dem PCF8591 
und Anzeige. Die Tasterabfragen habe ich noch als Kontrolle drin. 
Begrenzung geht auch
Danke für deine Hilfe
achim

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.