Forum: Mikrocontroller und Digitale Elektronik Intterrupt vs. Polling bei bidirektionalem Datenverkehr


von Matze (Gast)


Lesenswert?

Hallo zusammen,

in meinem nächsten Projekt möchte ich gerne eine Alarmmeldeanlage 
realisieren, die mir via GSM-Modem den Alarmstatus per SMS übermittelt. 
Mein ATmega 1280 untersucht kontinuierlich die seriellen Daten der 
Maschine und soll bei einer Fehlermeldung eine Nachricht versenden. 
Zudem möchte ich per SMS über mein Mobilfunktelefon Befehle an mein 
GSM-Modem schicken, der uC soll diesen verarbeiten und über den USART an 
die Maschine weiterleiten

Im Forum habe ich bereits ähnliche Beiträge gefunden, allerdings haben 
sie mir bisher nur bedingt weiter geholfen.

Mein erster Gedanke war, dass ich das überprüfen der RS232-Daten mittels 
While-Schleife realisiere. Also in etwa so:


uint8_t UART_GETC (void)
{
    while (!(UCSR0A & (1<<RXC0)));
    return UDR0;
}


void main()
{

uint8_t char c;

  while( 1 ) {

    c = UART_GETC();

    if( c == Terminator )    // Terminator bspw. 0x0D

// es folgt eine Reihe an If-else-Anweisungen, die die Zeichen 
untersuchen

}
}

Allerdings gehört in eine Hauptprogrammschleife nichts, was die 
Ausführung dieser grundsätzlich verhindern kann. Und genau das mache ich 
ja beim verwenden des Interrupts.

Das Programm soll ja nun beim Auftreten einer Fehlermeldung reagieren 
und mittels einer Funktion Send_SMS() eine Benachrichtigung an mein 
Handy versenden. Zudem will ich ja auch die Maschine ansteuern. Wenn ich 
auf zwei USARTs angewiesen bin, wäre es da nicht sinnvoller mit zwei 
Interruptroutinen zu arbeiten?

Also…

ISR (USART0_RXC0_vect)  // Maschine uC
{
unsigned char data = UDR0;
}

und…

ISR (USART1_RXC1_vect)  // uC Modem
{
unsigned char data  = UDR1;
}

Ich empfange kontinuierlich Daten von der seriellen Schnittstelle und 
werte diese aus. Sende ich jetzt ein Befehl mittels Handy, wird diese 
Routine unterbrochen und ich lese am USART1 Zeichen für Zeichen des 
Befehls ein, speichere ihn zwischen, oder leite ihn einfach an den UART0 
weiter.

// Zeichen von Modem empfangen

ISR (USART1_RXC1_vect) {
unsigned char x  = UDR1;
void putch() = x;

// void putch (unsigned char x) {
// while (!(UCSR0A & (1 << UDRE0)));
// UDR0 = x;
// }

In meiner Main würde ich also zunächst die entsprechenden AT-Kommandos 
an mein Modem zur Initialisierung schicken (aufwecken, Pin-Eingabe, 
etc). Das Sperren und Freigeben der globalen Interrupts wäre hier noch 
nicht nötig.

Wenn das Modem Sende und Empfangsbereit ist, initialisiere ich USART0 
und USART1 und springe in meine Hauptprogrammschleife, die die seriellen 
Daten am USART0 untersucht. Wenn bspw. eine Fehlermeldung detektiert 
wird sende ich mit Hilfe der Funktion Send_SMS() eine Nachricht. Hierbei 
müsste ich vor dem Ausführen der Funktion die globalen Interrupts 
deaktivieren und nach Ausführung wieder aktivieren, oder? Nicht das mir 
da der USART1 dazwischenfunkt.

Ich bin mir nicht sicher was ich in diesem Fall tun soll! Das 
Untersuchen der Daten mittels Polling und Empfangen von Befehlen mittels 
Interrupt, löst das nicht ne Art Kollision aus?

Wie ihr seht, verwirrt mich das Ganze etwas und ich wäre froh, wenn mir 
diesbezüglich jemand weiterhelfen könnte. Über Tipps und Hinweise würde 
ich mich freuen!

Viele Grüße,
Matze

von oldmax (Gast)


Lesenswert?

Hi
Also, ich habe bisher nur mit Atmega8 und Assembler gearbeitet, aber 
vielleicht hilft dir trotzdem diese Info.
Ich habe einen kleinen Speicherbereich von ca. 30 Bytes als Buffer 
deklariert. Kommt in der ISR - Empfang ein Zeichen an, wird er in den 
Buffer eingetragen und ein Schreibzeiger erhöht. Erwischt er die 
Buffergrenze setze ich ihn wieder auf 0, damit habe ich einen 
Ringspeicher. Im Programm vergleiche ich nun diesen Schreibzeiger mit 
einem Lesezeiger. Sind diese beiden unterschiedlich, weiß ich, das ein 
Zeichen angekommen ist. Also werte ich es aus und führe den 
Schreibzeiger nach. Das Programm hat alle Zeit der Welt für die 
Bearbeitung und die Routinen werden auch nur aktiv, wenn es notwendig 
ist.
Ich denke, das auch du in ähnlicher Form vorgehen kannst.
Gruß oldmax

von Lehrmann M. (ubimbo)


Lesenswert?

Matze schrieb:
> Allerdings gehört in eine Hauptprogrammschleife nichts, was die
> Ausführung dieser grundsätzlich verhindern kann. Und genau das mache ich
> ja beim verwenden des Interrupts.

Dann wäre ja jeder Interrupt sinnlos ...

Man muss die Interrupts natürlich immer intelligent maskieren. Das gilt 
gerade dann, wenn man zeitkritische Anwendung hat. Es ist ja nicht so, 
dass Interrupts die während der ISR auftreten verloren gehen. Diese 
werden dann halt leicht zeitverzögert nach Ablauf der ersten ISR 
ausgeführt.

Alles von dir ansgesprochene solle in ISR(s) von statten gehen.

von Huch (Gast)


Lesenswert?

Es ist ein bischen schwierig Dir bei diesem Stand Deiner Kenntnisse 
weiterzuhelfen.

Da sind: Der globale Interrupt, die einzelnen Interrupts, 
Initialisierungen, Texterkennung, Nebenläufigkeit.

Es ist ratsam erstmal mit einzelnen Aspekten zu beginnen um die 
Kenntnisse zu erwerben die Du für das Gesamtprojekt brauchst.

Um Dir aber eine Sorge zu nehmen: An sich ist es möglich das Projekt zu 
verwirklichen. Wenn man es "richtig" macht ist das kein Problem.

Um gleich auf Interrupts und ihren Einfluss auf das Hauptprogramm 
einzugehen:
Interrupts werden prinzipiell so kurz wie irgend möglich programmiert.
Stell Dir vor, dass es so etwas wie einen Zyklus gibt. Er besteht aus 
dem Ereignis, das den Interrupt auslöst, dessen Bearbeitung im Interrupt 
(so kurz wie möglich, wie gesagt) und der Bearbeitung der Daten wie sie 
im Interrupt hereingekommen sind im eigentlichen Hauptprogramm.
Die Summe der Verarbeitungszeiten im Interrupt und im Hauptprogramm darf 
höchstens gross sein wie die Ereignisse auftreten.
Dabei hat man aber verschiedene Variationsmöglichkeiten um die Zeit 
günstig zu verteilen. Buffer usw.
Im Interrupt selbst verarbeitet man in der Regel keine Daten, vergleicht 
nichts oder macht sonst irgendwas mit den Daten. (Das ist mehr eine 
Faustregel als ein Gesetz. Für den Anfänger aber sollte es erstmal 
Gesetz sein).
Der Interrupt soll eigentlich nur Eingangsdaten wegspeichern und dem 
Hauptprogramm mitteilen, das solch ein Interrupt aufgetreten ist. Das 
Hauptprogramm selbst liest dann die vorher gespeicherten Daten und 
interpretiert sie.
Durch die Regel, das die "Zykluszeit" ausreichen muss ist auch 
sichergestellt, das eine Unterbrechung durch den Interrupt die 
Gesamtfunktion nicht negativ beeinflusst. Selbst wenn das Hauptprogramm 
gerade einen Text vergleicht, schadet das nichtst, denn es hat ja Zeit 
genug, die gerade eingetroffenen Daten erstmal_ _vorläufig zu 
ignorieren und mit denen weiterzumachen die es gerade am Wickel hat.

Dieser kurze Überblick soll Dir zeigen, dass man systematisch an das 
Problem herangehen kann, das es aber andererseits auch nicht wirklich 
trivial ist.

Ich würde Dir daher wärmstens empfehlen, erstmal einfache Dinge zu 
programmieren und damit herumzuspielen. Z.B. könntest Du mal in einem 
Interrupt eine LED blinken lassen. Im Hauptprogramm die Anzahl zu zählen 
und evtl. auszugeben.

Anfänger neigen dazu im Interrupt der Texte empfängt, schon die Texte 
oder wenigstens das Textende zu erkennen. Das erste ist nicht sinnvoll, 
das zweite kann man machen ist aber meist unnötig.

Der zweite Schritt wäre einfach mal einen Textempfang und Senden via 
Interrupt zu programmieren und einfache Befehle im Hauptprogramm zu 
erkennen.

Eine Rundumerklärung wäre an dieser Stelle einfach viel zu umfangreich. 
Du musst Dich dem Thema Schritt für Schritt nähern. Bei den 
Einzelschritten sind wir Dir hier gerne behilflich.

Viel Erfolg.

von Huch (Gast)


Lesenswert?

Ich sehe gerade, das Du anscheinend Deinen ersten Post wesentlich 
editiert hast, während ich dabei war die Antwort zu schreiben. Das ist 
ungünstig, da es die Antwort entwertet.

von Huch (Gast)


Lesenswert?

Ich hoffe ich habe mich da nicht geirrt. Aber irgendwie kam mir der Post 
verändert vor.

>Allerdings gehört in eine Hauptprogrammschleife nichts, was die
>Ausführung dieser grundsätzlich verhindern kann. Und genau das mache ich
>ja beim verwenden des Interrupts.

Das ist überhaupt kein Problem, solange die Bedingung der "Zykluszeit" 
nicht verletzt wird.

Deine skizzierten Interruptroutinen sind soweit OK. Aber die hier von 
olmdax angeregte Verwendung eines Ringpufferst ist zu empfehlen.

von Matze (Gast)


Lesenswert?

Hallo zusammen,
vielen Dank für die Antworten. Vor allem der Beitrag von Huch, hat mir 
doch sehr weiter geholfen. Ok, die Interrupts verwende ich also nur um 
die Eingangsdaten wegzuspeichern.

ISR(USART1_RXC_vect) {

char array [20];
int counter = 0;
uint_8 data;
uint_8 StringLaeng = 20;
data = UDR;

array [counter] = data;
counter++;
If (counter < StringLaeng – 1)
counter = 0;
}

Ich empfange also den ankommenden Befehl (20 Zeichen lang), im Falle 
einer empfangenen SMS, und speichere die einzelnen Zeichen in einem 
Buffer. Das geschieht alles noch in der IR. Nun soll eine Funktion das 
Array bzw. die einzelnen Zeichen auslesen und und an den UART0 
weiterleiten. Wäre für die Analyse der seriellen Daten eine IR ebenfalls 
sinnvoll? Verständnisfrage: Wenn ich aber permanent Zeichen via 
Interrupt empfange, gibts da nicht Probleme wenn eine SMS eintrifft?

> Es ist ja nicht so,
> dass Interrupts die während der ISR auftreten verloren gehen. Diese
> werden dann halt leicht zeitverzögert nach Ablauf der ersten ISR
> ausgeführt.

Ich meine, wir haben dann ja ne extrem hohe Zeitverzögerung, wenn ich 
meine Prüfroutine anstatt Polling mit IR durchführen würde. Ich empfange 
ja permanent Zeichen. Denkfehler meinerseits?

Wie ich das jetzt verstanden habe soll ich sowohl für die Prüfroutine 
(Polling), als auch für die IR (Empfangen eines Befehls) eine Art 
Ringpuffer anlegen, um bei einer IR, getriggert durch eine SMS, ich in 
meiner Main die restlichen Zeichen noch abarbeiten kann.

Eine Frage habe ich noch: Wie kann ich den bspw. die SMS am besten 
Versenden? Wenn ich in meiner Main eine Fehlermeldung entdecke, muss ich 
ja ebenfalls ein Art Interrupt verwenden, oder? D.h., ich muss dies 
mittels Software-Interrupt einläuten. Wie provoziere ich so ein Software 
Interrupt?

Vielen Dank nochmal für die Antworten, ich weiß das wirklich sehr zu 
schätzen. VG

von Matze (Gast)


Lesenswert?

Könnte mir zum letzten Beitrag vielleicht nochmal jemand weiterhelfen? 
Vielen Dank!

Da muss natürlich noch das data = UDR1 rein.

> ISR(USART1_RXC_vect) {

> char array [20];
> int counter = 0;
> uint_8 data;
> uint_8 StringLaeng = 20;
> data = UDR;

  data = UDR1
> array [counter] = data;
> counter++;
> If (counter < StringLaeng – 1)
> counter = 0;
> }

von Remote O. (remote1)


Lesenswert?

Matze schrieb:
> Könnte mir zum letzten Beitrag vielleicht nochmal jemand weiterhelfen?
> Vielen Dank!

Das was in deinem Beitrag steht ist schon einmal grundsätzlich falsch - 
sry.

All deine Variablen sind lokal in der ISR angelegt. Das heißt, das bei 
jedem Aufruf der ISR diese "neu erstellt" werden, da sie beim Verlassen 
der ISR wieder freigegeben werden. Heißt also, dass ein Großteil deiner 
Variablen global angelegt werden muss und zudem auch noch volatile.
Schau dir doch in der Artikelsammlung einfach mal die Verwendung des 
UART an (AVR-GCC-Tutorial/Der UART: Interruptbetrieb). Da hatte ich 
auch einmal ein Beispiel zum Empfang von Zeichen via Interrupt 
eingestellt.

von Matze (Gast)


Lesenswert?

Hi Remote one,
Danke für die Antwort...Kurze Frage, hab ich das vom vorletzten Beitrag 
grundsätzlich richtig verstanden?

> Ich empfange also den ankommenden Befehl (20 Zeichen lang), im Falle
> einer empfangenen SMS, und speichere die einzelnen Zeichen in einem
> Buffer. Das geschieht alles noch in der IR. Nun soll eine Funktion das
> Array bzw. die einzelnen Zeichen auslesen und und an den UART0
> weiterleiten. Wäre für die Analyse der seriellen Daten eine IR ebenfalls
> sinnvoll? Verständnisfrage: Wenn ich aber permanent Zeichen via
> Interrupt empfange, gibts da nicht Probleme wenn eine SMS eintrifft?

> Es ist ja nicht so,
> dass Interrupts die während der ISR auftreten verloren gehen. Diese
> werden dann halt leicht zeitverzögert nach Ablauf der ersten ISR
> ausgeführt.

> Ich meine, wir haben dann ja ne extrem hohe Zeitverzögerung, wenn ich
> meine Prüfroutine anstatt Polling mit IR durchführen würde. Ich empfange
> ja permanent Zeichen. Denkfehler meinerseits?

> Wie ich das jetzt verstanden habe soll ich sowohl für die Prüfroutine
> (Polling), als auch für die IR (Empfangen eines Befehls) eine Art
> Ringpuffer anlegen, um bei einer IR, getriggert durch eine SMS, ich in
> meiner Main die restlichen Zeichen noch abarbeiten kann.

Eine Frage habe ich noch: Wie kann ich den bspw. die SMS am besten
Versenden? Wenn ich in meiner Main eine Fehlermeldung entdecke, muss ich
ja ebenfalls ein Art Interrupt verwenden, oder? D.h., ich muss dies
mittels Software-Interrupt einläuten. Wie provoziere ich so ein Software
Interrupt?

von Remote O. (remote1)


Lesenswert?

Also, ich hab jetzt nicht alles genau gelesen, aber 20 Zeichen sind 
schon sehr wenig. Wenn eine SMS ankommt, merkst du das ja durch den 
Empfang von entsprechenden Steuerstrings des Mobiltelefons oder des GSM 
Modems. D.h. du sammelst via Interrupt alle empfangenen Zeichen ein und 
vergleichst bei vollständigem Empfang in einer State Machine und führst 
entsprechende Aktionen durch, z.B. SMS abrufen. Je nach Typ des 
Mobiltelefons / GSM Modems kommen da aber nicht nur die Klartextzeichen 
an, sondern noch jede Menge Overhead (TelNr. etc.). Also schon einmal 
mehr als 20 Zeichen.

Das Senden einer SMS ist schon wieder eine neue Aufgabe. D.h., wenn du 
in deiner State Machine festgestellt hast, dass ein Fehler aufgetreten 
ist, dann wird eine Textnachricht versendet. Das kann eigentlich im 
Hauptprogramm geschehen. Es ist ja egal, ob du dafür 100ms mehr oder 
weniger benötigst. Die größte Zeit geht bei der Vermittlung verlogen. Zu 
Silvester kann das auch mal einen halben Tag dauern ;)

Du solltest dir also erst einmal einen Plan machen, was du alles willst. 
Danach musst du abschätzen wie schnell das erledigt werden muss (Empfang 
so schnell wie mgl., damit neues Zeichen eintreffen kann, Senden kann 
auch mal dauern - also Hauptprogramm).
Wenn ich das richtig verstanden habe, dann willst du einfach auf 
einkommende SMS in einer gesonderten Art und Weise reagieren
Auch wenn ich den ein oder anderen jetzt nerve, aber ich habe zu einem 
ähnlichen Thema mal einen Artikel verfasst:
Versenden von SMS mittels Mobiltelefon
Da du lernbegierig bist, solltest du das nicht einfach so verwenden, 
sondern versuchen das selbst zu machen.
Fang am Besten mit mehreren kleinen Programmen an:
 Zeichen empfangen via Interrupt
 SMS Versenden
 SMS dekodieren
 etc.
Am Ende spielt dann alles schön zusammen ;)

von Matze (Gast)


Lesenswert?

Hallo Remote One,
vielen Dank für deine Antwort, ich werde mich rein knien und deine 
hilfreichen Tipps/Hinweise aufarbeiten. Ich hab halt immer noch das 
Problem, dass ich mir die Ausführung der SMS-Routine zu lange vorstelle. 
Ich meine, wenn ich ein Fehlermeldung detektiere und dann eine SMS 
versenden will, müssen ja weiterhin die seriellen Daten untersucht 
werden. Und genau dieser "Konflikt" macht mir bisher noch etwas 
Kopfzerbrechen.
Bei Fragen werde ich mich natürlich nochmals melden. Vielen Dank nochmal 
für die Antworten!
Euch und Dir natürlich einen guten Rutsch ins neue Jahr!
Gruß,
Matze

von Remote O. (remote1)


Lesenswert?

Matze schrieb:
> Ich meine, wenn ich ein Fehlermeldung detektiere und dann eine SMS
> versenden will, müssen ja weiterhin die seriellen Daten untersucht
> werden. Und genau dieser "Konflikt" macht mir bisher noch etwas
> Kopfzerbrechen.

Angenommen du arbeitest mit 19200baud / 8n1. Dann überträgst du 1920 
Zeichen pro Sekunde. Ein Zeichen benötigt also ca. 0,5ms.
Wenn ein kompletter Datensatz angekommen ist, wird dieser ausgewertet 
und dann ein neuer erwartet. Während der Auswertung dürfen keine neuen 
Daten mehr ankommen oder werden einfach ignoriert (zumindest bei FIFO).
Du musst also gewährleisten, dass deine State Machine so schnell wie 
möglich durcharbeitet und den Zeichenpuffer (FIFO) wieder freigibt für 
einen neuen Datensatz. Wenn der Vergleich erst einmal durch ist und der 
Puffer wieder freigegeben ist, hast du parallel zum Empfang des neuen 
Datensatzes ja "unendlich" viel Zeit deine SMS zu versenden. Das Senden 
der SMS wird dann eben manchmal durch den Empfang eines neuen Zeichens 
unterbrochen - ist ja aber nicht weiter schlimm.

Nun ist es so, dass viele Mobiltelefone einen Datensatz mit \r\n 
abschließen. Du weißt ja aber schon bei dem \r, dass das Ende des 
Datensatzes erreicht ist. Also wäre es nicht so schlimm, wenn du das 
nachfolgende Zeichen nicht empfängst. Du hast also ca. 1ms Zeit um den 
Vergleich durchzuführen. Angenommen du arbeitest mit einem Atmel auf 
16MHz - dann dauert ein Takt 62,5ns. Bei einer Befehlsausführungszeit 
von 1 Befehl je Takt (zumindest die einfachen) wären dass 16000 Befehle 
die du überschlagsmäßig ausführen kannst. Selbst wenn du "nur" von den 
0,5ms ausgehst und evtl. von 2 Takten je Befehl - ist das immer noch 
jede Menge.
Sollte das nicht reichen, kannst du immer noch die Baudrate runter 
drehen (9800 / 8n1 ist auch noch weit verbreitet).

Wenn ich mich nicht verrechnet habe und völligen Stuss erzählt habe, 
dann brauchst du dir da keine Gedanken machen. Ich konnte bei mir bis 
dato zumindest auch noch nie ein solches Problem erkennen.

In dem Sinne, gesundes Neues und lass es dir mal durch den Kopf gehen ;)

von Matze (Gast)


Lesenswert?

Hallo zusammen,
zunächst einmal, wenn auch etwas verspätet, noch ein frohes Neues!
ich hab mein Projekt nun in kleinere Aufgaben zerstückelt, so wie es ihr 
gesagt habt. GSM-Initialisierung, SMS-Senden, etc.

Ich hätte da noch eine Frage: Wenn eine Alarmmeldung auftritt möchte ich 
gerne in die SMS den Alarmtyp+die Uhrzeit in der er aufgetreten ist. 
Also ich hätte das jetzt per AT+CCLK? vom Modem abgefragt. Hat von euch 
vielleicht jemand ne andere Idee, wie man das am geschicktesten lösen 
könnte? In C gibts ja noch die Headerdatei <time.h>, die allerdings 
nicht in der libc ist.

von Remote O. (remote1)


Lesenswert?

Matze schrieb:
> Hat von euch
> vielleicht jemand ne andere Idee, wie man das am geschicktesten lösen
> könnte? In C gibts ja noch die Headerdatei <time.h>, die allerdings
> nicht in der libc ist.

Die geschickteste Antwort hast du selbst geliefert (zumindest wenn die 
Zeit im Mobiltelefon richtig eingestellt ist). Alles andere (DCF77, RTC 
...) wäre viel zu aufwendig.

Die <time.h> kannst du glaube ich für eine richtige Zeitangabe 
vergessen. Ich kenne die jetzt nicht unbedingt, aber 
höchstwahrscheinlich liefern die dortigen Funktionen lediglich die 
aktuelle Rechenzeit. Also die Systemzeit beim PC. So etwas funktioniert 
natürlich nicht bei einem µC.

von Matze (Gast)


Lesenswert?

Das blöde ist nur, dass nach einem Reset oder Unterbrechen der 
Stromversorgung ich die Uhrzeit immer wieder neu einstellen muss und 
mein Programm ja nicht weiß, wie viel Uhr es gerade ist. Wenn ich mein 
Programm starte, muss ich ja immer die Uhrzeit via AT-Befehl AT+CCLK=... 
eingeben. Gibt es da ein Befehl der die Uhrzeit aktualisiert bzw. 
updatet?
VG

von Uhrzeit (Gast)


Lesenswert?

Also mir ist ein derartige Lösung nicht bekannt. Evtl. musst du dass 
dann halt mit dem uC regeln...

von Remote O. (remote1)


Lesenswert?

Matze schrieb:
> Wenn eine Alarmmeldung auftritt möchte ich
> gerne in die SMS den Alarmtyp+die Uhrzeit in der er aufgetreten ist.

Ist eigentlich unsinnig, da der Empfänger ja sieht, wann die SMS 
eingegangen ist.

Matze schrieb:
> Das blöde ist nur, dass nach einem Reset oder Unterbrechen der
> Stromversorgung ich die Uhrzeit immer wieder neu einstellen muss und
> mein Programm ja nicht weiß, wie viel Uhr es gerade ist. Wenn ich mein
> Programm starte, muss ich ja immer die Uhrzeit via AT-Befehl AT+CCLK=...
> eingeben. Gibt es da ein Befehl der die Uhrzeit aktualisiert bzw.
> updatet?

Dann schalte dein Modem eben nicht komplett ab. Bei den Mobiltelefonen 
läuft beim Ausschalten auch die Uhr weiter. Du musst einfach etwas an 
deinem Konzept ändern. Bring doch erst einmal dein Projekt voran. Die 
Zeiteinstellung ist glaube ich dein geringstes Problem.

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.