Forum: Mikrocontroller und Digitale Elektronik Logikbausteine mit AVR realiesieren


von Dirk (Gast)


Lesenswert?

Hallo an alle,

ich bin recht neu auf dem Gebiet mit den Atmel Controller.

Ich habe vorher in der Schule mit Infinion Controller programmiert, was 
ich sehr einfach fand. Aber aller Anfang ist schwer.
Manchmal finde ich es aber schon umständlich, z.B. dass man den 
Stackpointer inizialisieren muß.

Ich arbeite meine Unterlagen mit Programmübungen durch. Aber manchmal 
weiß ich nicht weiter, da ich den vergleichbaren Befehl für den Atmel 
nicht finde.
Wie folgendes:

DJNZ = decrement and jump if not zero (gibt es sowas bei Atmel?)
Ich nehme diesen Befehl gerne für Zeitschleifen her. Hab ihn dann mit 
dem Atmel so realisiert:

loop:   dec r16
        brne loop
        .
        .
=========================================
Jetzt mein Hauptproblem:
Ich will Logikschaltungen wie bei einer SPS realisieren. Mit dem 
Infinion ging das ganz einfach:
Sagen wir ich habe drei Eingabe Pins (0, 1, 2 von Portd) und einen als 
Ausgabe (Bit 7 Portb).
        ______
0------=        =      ______
       =  UND   =-----=        =
1------=________=     =  ODER  =
                      =        =negiert----Bit7
2--------------negiert=________=


MOV C, PORTD  0      ;bei Infinion ist es normalerweise P1.0
ANL C, PORTD  1      ;UND Verknüpfung 0 und 1 Ergebnis = CarryBit
ORL C, /PORTD 2      ;ODER Verknüpfung, Portd 2 ist negiert
CPL C                ;Compliment CarryBit,
MOV PORTB 7, C       ;CarryBit auf Ausgang Bit 7 von Portb


Frage wie kann ich genauso einfach dieses mit dem Atmel 8515 
realisieren.
Im Tutorial unter Tastern habe ich schon was gefunden, aber das ist mehr 
als umständlich. Vorallem weil es vielleicht bei diesem Beispiel gerade 
noch überschaubar ist, aber wenn ich dieses um 5 Gatter erweitere kenn 
sich keiner mehr aus was überhaupt abgefragt wird, UND verknüpft wird 
usw....

Wie kann man einzelne Bits beim Atmel abfragen und das CarryBit 
complimentieren? Oder kann man da nur mit Registern arbeiten?

Vielen Dank im vorraus!


Gruß
Dirk

von Karl H. (kbuchegg)


Lesenswert?

Dirk wrote:
>
> Wie kann man einzelne Bits beim Atmel abfragen

Du meinst von einem Port?

Mittels cbis und sbis, aber das hilft dir nicht viel.
AVR sind Risc Prozessoren, für fast alles muss der entsprechende Wert in 
einem Register vorliegen.

von Falk B. (falk)


Lesenswert?


von Dirk (Gast)


Lesenswert?

Ok verstehe, muß also immer alles als Registerwerte angeben. Damit kann 
ich leben.

Kann mir vielleicht bitte jemand das obige Programm so umschreiben, dass 
es in einem AVR funktioniert?

Komme einfach nicht drauf. Wollte es auch immer mit der Carry Abfrage 
machen, aber irgendwie checke ich es nicht.

Wäre wirklich nett...

von Uhu U. (uhu)


Lesenswert?

RISC-Prozessoren in ASM zu programmieren, ist nicht der reine Genuß. Die 
sind eigentlich dafür gedacht, in einer höheren Programmiersprache 
gefüttert zu werden.

Den Assembler gibts nur so dazu.

von mr.chip (Gast)


Lesenswert?

Warum arbeitest du nicht einfach mal das (auf dieser Webseite 
angebotene) Tutorial durch? Danach dürften sich deine Fragen von selbst 
in Luft auflösen.

> Den Assembler gibts nur so dazu.

Schadet aber jedenfalls nicht, wenn man sich mal damit befasst hat :-)

von Gerhard (Gast)


Lesenswert?

Ne mein Lieber.

Der Assembler, bzw. der Maschinencode, welcher aus ihm erzeugt wird, ist 
das Maß aller Dinge für diesen Prozessor. Nur diesen kann er 
"verstehen" und abarbeiten.

Jedes Compilat aus einer Hochsprache ist ein Kompromiß zwischen 
Speicherbedarf / Geschwindigkeit auf der einen Seite und 
Lesbarkeit/Verständlichkeit für den Menschen und Effizienz beim 
Programmieren auf der anderen Seite.

Zwar könnte man sagen, daß viele RISC-Befehlssätze schon mit Hinblick 
auf Hochsprachen-Compiler entwickelt und optimiert wurden, allerdings 
bedeutet das keineswegs, daß man diese RISC-Befehlssätze als Mensch 
nicht effizient einsetzen könnte. Ganz im Gegenteil. Gerade beim Atmel 
AVR ist genau all das da, was man sich als "Assembler-Programmierer" 
wünscht. Schleifen, "case"-Anweisungen, Bit-Operationen, all das läßt 
sich in AVR-Assembler sehr schön intuitiv umsetzen. Ich empfinde es 
sogar als hilfreich und nicht als Einschränkung, daß nur rund 100 
Befehle zur Verfügung stehen.

Wenn es um Schnelligkeit und Speichereffizienz geht, dagegen 
Entwicklungsaufwand und Portierbarkeit eine eher untergeordnete Rolle 
spielen, (Großserie zum Beispiel), dann ist Assembler genau das, was du 
willst.

von Karl H. (kbuchegg)


Lesenswert?

Um auf die Anfrage, das ganze mal in Assembler umzusetzen zurückzukommen

Das hier ist nicht der Weisheit letzter Schluss, sondern nach einem 
Schema programmiert:

Ich fang damit an, mir eine verbindliche Registerzuordnung zu 
definieren:

    R16 enthält immer den einen Operanden
    R17 enthält immer den anderen Operanden
    R16 enthält immer das Ergebnis der Operation
    R19 ist ein temporäres Register, das während des Einlesens/Ausgebens
        benutzt werden kann

In jedem Register gilt nur das Bit 0, weil da ja nur Logik im Spiel ist.

   zusätzlich beenutze ich noch R20, das immer das Bitmuster für
   1 enthält, bei manchen Operationen, bei denen keine Konstante
   angegeben werden kann (EOR) mag sich das als nützlich erweisen.

*************
Die Negierung ist damit leicht: Bit 0 in R18 wird umgedreht. Das ist
   ganz einfach ein

      EOR  R16, R20

*************
Eine UND Verknüpfung ist damit auch simpel:

      AND  R16, R17

*************
Und ein Oder ditto

      OR  R16, R17

*************
Bleibt nur nach das Abfragen eines Pins. Einlesen findet immer nach R19 
statt. Dort wird das interessierende Bit freigestellt und je nachdem ob 
dann 0 oder nicht 0 übrigbleibt, wird das Zielregister auf 0 oder 1 
gesetzt.

      CLR   Zielregister       ; Zielregister mal auf 0
      SBIC  gewünschter Port, gewünschter Pin
      BREQ  Fertig
      LDI   Zielregister, 1
Fertig:

***********
Ausgabe eines Pins mach ich mir ebenfalls als Baustein. Wenn R16 0 ist, 
wird der Zielpin auf 0 gesetzt, ansonsten auf 1

      CPI   R16, 0
      BREQ  SetZero
      SBI   ZielPort, gewünschter Pin
      RJMP  Fertig
SetZero:
      CBI   ZielPort, gewünschter Pin
Fertig:


Damit hab ich meinen Baukasten, mit dem sich Operationen 
zusammenstoppeln lassen. Wenn du etwas mehr Übung hast, könnte man für 
die Operationen Makros definieren, dann wird auch der Schreibaufwand für 
das eigentliche Programm kleiner.
Noch die Ports für Ein/Ausgabe richtig initialisieren und es kann 
losgehen.


So in etwa würd ich an die Aufgabe rangehen.


0------=        =      ____
       =  UND   =-----=        =
1------=________=     =  ODER  =
                      =        =negiert----Bit7
2--------------negiert=________=


Alles soll sich am Port D abspielen. PD0, PD1, PD2 sind Eingang, 
brauchen also nichts spezielles, PD7 ist Ausgang
1
       SBI  DDRD, PD7
2
       LDI  R20, 1     ; eine 1 ins Register R20 bringen
3
4
Loop:
5
; PD0 einlesen
6
      CLR   R16
7
      SBIC  PIND, PD0
8
      BREQ  Fertig
9
      LDI   R16, 1
10
Fertig:
11
12
; PD1 einlesen
13
      CLR   R17
14
      SBIC  PIND, PD1
15
      BREQ  Fertig1
16
      LDI   R17, 1
17
Fertig1:
18
19
; PD0 und PD1
20
      AND   R16, R17
21
22
; PD2 einlesen
23
      CLR   R17
24
      SBIC  PIND, PD1
25
      BREQ  Fertig2
26
      LDI   R17, 1
27
Fertig2:
28
29
; PD2 negieren
30
      EOR   R17, R20
31
32
; Ergebnis von PD0 und PD1 (steht noch in R16) ODER PD2 negiert
33
      OR    R16, R17
34
35
; Ergebnis bisher negieren
36
      EOR   R16, R20
37
38
; damit ist das Gesamt Ergebnis in R16, auf PD7 ausgeben
39
      CPI   R16, 0
40
      BREQ  SetZero
41
      SBI   PORTD, PD7
42
      RJMP  Fertig3
43
SetZero:
44
      CBI   PORTD, PD7
45
Fertig3:
46
47
      rjmp  Loop

Wie gesagt, das ist jetzt nach einem Baukastenschema zusammengesetzt. Da 
kann man sicher noch vereinfachen. Vor allem die Ein/Ausgabeoperationen, 
da ist noch Handlungsbedarf. Vielleicht fällt ja jemandem etwas besseres 
ein, welches in das Baukastensystem passt. Aber im Grunde müsste das so 
funktionieren.

von Dirk (Gast)


Lesenswert?

Danke Karl heinz, dass Du Dir die Arbeit gemacht und mir ein 
Beispielprogramm gepostet hast.
Boa, dass is beim AVR dann doch ganz schön kompliziert. Vorallem wenn 
ich jetzt größere Netzwerke aufbauen möchte oder was ändern will....
Irgendwann will ich ja auch mal kompliziertere Sachen wie eine 
Heizungssteuerung mit Display etc. programmieren. Aber ich glaube da ist 
es für mich noch ein langer Weg...

Ist es vielleicht für mich doch besser jetzt in C weiterzulernen?
Habe heute angefangen das AVR-GCC-Tutorial durchzulesen. Hatte früher in 
der Schule C++, kenntnisse also solala.
Wie hätte sowas in C ausgesehen?

von Thilo M. (Gast)


Lesenswert?

Assembler ist eine sehr feine Sache um die Hardware kennenzulernen. Ich 
würde einiges damit machen um die Architektur und die Feinheiten des AVR 
kennenzulernen.
Für ganze Steuerungen mit Display usw. bietet sich C natürlich gradezu 
an.

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

Schreibs einfach in C, dann läufts auf 8051 und AVR:
1
#include <io.h>
2
#include "mydefs.h"
3
4
5
#define IN_A            SBIT( PINB,  0 )
6
#define IN_B            SBIT( PINB,  1 )
7
#define IN_C            SBIT( PINB,  2 )
8
#define OUT_Y           SBIT( PORTB, 7 )
9
#define OUT_Y_DDR       SBIT( DDRB,  7 )
10
11
#if 0
12
0------=        =      ______
13
       =  UND   =-----=        =
14
1------=________=     =  ODER  =
15
                      =        =negiert----Bit7
16
2--------------negiert=________=
17
#endif
18
19
20
void logic( void )
21
{
22
  OUT_Y_DDR = 1;                // pin direction = output
23
24
  for(;;){
25
    OUT_Y = !(                  // Y = NOT
26
              (IN_A && IN_B)    // A AND B
27
              ||                // OR
28
              !IN_C             // NOT C
29
             );
30
  }
31
}


Peter

von Karl H. (kbuchegg)


Lesenswert?

Dirk wrote:
> Boa, dass is beim AVR dann doch ganz schön kompliziert.

Halb so wild. letztendlich ist das nur Programmierbaustein an 
Programmierbaustein gesetzt. Noch ein paar Makros drübergestülpt, und es 
sieht so aus
1
Loop:
2
     READ_PORT   PIND, PD0
3
     MOV         R16, R17
4
5
     READ_PORT   PIND, PD1
6
7
     AND_VALUES                    ; I)   PD0 & PD1
8
9
     READ_PORT   PIND, PD2
10
11
     NEGATE                        ; II)  !PD2
12
     OR_VALUES                     ; III) ( PD0 & PD1 ) | !PD2
13
14
     NEGATE                        ; IV)  !( ( PD0 & PD1 ) | !PD2 )
15
16
     WRITE_PORT  PORTD, PD7        ; V) PD7 = !( ( PD0 & PD1 ) | !PD2 )
17
18
     rjmp Loop

Und das liest dich dann schon vieeel einfacher.
Und wer weiß, wenn du mehr Erfahrung hast, könnte man ja auch einen 
kleinen 'Compiler' schreiben, der aus PD7 = !( ( PD0 & PD1 ) | !PD2 ) 
genau obige Sequenz erzeugt. Wär ne schöne Fingerübung um mal wieder was 
in Compilerbau zu tun.

> Vorallem wenn
> ich jetzt größere Netzwerke aufbauen möchte oder was ändern will....

Das wäre bei deinem Infinion auch nicht anders.
Immer im Auge zu behalten, welche Operation nun als letztes das Carry 
Bit beeinflusst hat und wie sich die Operationen gegenseitig 
beeinflussen, ...

Letztendlich gehts ja sowieso immer nur darum, den Überblick zu 
behalten, welche Operation mit welcher anderen Operation interagiert.

Würde auch sagen: Schreibs in C.
Da kümmert sich der Compiler um die kleinen Details, und du hast viel 
mehr Freiheiten

Ideal wäre es natürlich, wenn man für sowas eine graphische 
Programmiersprache hätte.
Man zieht die ganzen Gatter (und sonstige Bausteine) auf eine 
Arbeitsfläche, verbindet Ausgang mit Eingang entsprechend der Logik und 
ein Compiler erzeugt dafür den Code, bzw. ein Interpreter arbeitet in 
einer Schleife am µC die ganze Logik durch.
Aber für ein Einzelstück lohnt sich sowas klarerweise nicht.

von Dirk (Gast)


Lesenswert?

Vielen Dank an euch alle, dass ihr mir immer so schnelle und informative 
Antworten gebt!

Auf den ersten Blick finde ich, dass es in C viel Ausagekräftiger ist. 
Man weiß sofort um was es geht.

Peter wrote:
>Schreibs einfach in C, dann läufts auf 8051 und AVR:
Diesen Vorteil sehe ich natürlich auch, ich dachte nur ich fange jetzt 
erstmal in Assembler an, damit ich evtl. spätere Fehler die in C 
auftauchen verstehe.

Karl heinz wrote:
>Ideal wäre es natürlich, wenn man für sowas eine graphische
Programmiersprache hätte.
Ja so wie bei der Siemens Logo!. Aber die kostet halt richtig Asche, 
deswegen will ich mich ja in die AVR´s einarbeiten.

Mein Ziel ist es, A/D-Wandler, Sensoren, LCD´s und Motoren mit Hilfe des 
AVR ansteuern zu können. Deswegen hätte ich eine Bitte, aus eurer 
Erfahrung könnt ihr mir bestimmt sagen, wie ich zum Ziel komme.
Gibt es besondere Bücher (welche?) die zu empfehlen sind? Oder ein Art 
"Kochrezept" wie:
1. C Programmierung lernen (mit Buch xy oder www.Seite xy)
2. AVR-GCC Tutorial komplett durcharbeiten
3. Programmbeispiele auf Seite www.xy.. durcharbeiten
usw..

Ich habe das AVR-GCC Tutorial noch nicht ganz durch, aber was kann ich 
danach? Ich denke es wirft danach immer noch viele Fragen auf. Ich würde 
gerne ein Buch haben, dass ganz einfach anfängt. C für Mikrocontroller, 
dass dann immer mehr und mehr Komponenten behandelt und viele praktische 
Beispiele beinhaltet. Wirklich von 0 auf! Ich weiß es gibt so viele 
elektronische Bauteile die man behandeln könnte, aber die gängisten 
sollten es halt sein (Tempfühler bzw. Analoge Messwerte verarbeiten, 
Schrittmotor, LCD- Display, Eingabe über ein Display z.B. Zeitschaltuhr, 
usw...)

Ich sehe mir immer wieder gerne die Seite http://www.mikrocontroller.com 
an. Und ich muß staunen wie man sowas machen kann. Nicht das Löten und 
zusammenbauen sondern, ein Programm dafür zu schreiben. Wenn ich mir 
dann in C so ein Programm anschaue kapier ich garnix..

von Uhu U. (uhu)


Lesenswert?

Dirk wrote:
> Peter wrote:
>>Schreibs einfach in C, dann läufts auf 8051 und AVR:
> Diesen Vorteil sehe ich natürlich auch, ich dachte nur ich fange jetzt
> erstmal in Assembler an, damit ich evtl. spätere Fehler die in C
> auftauchen verstehe.

Schreibs in C und laß dir den ASM-Code ausgeben. Dann siehst du, wie der 
Compiler die C-Anweisungen in Maschinencode umsetzt.

So lernst du, was der Compiler macht und gleichzeitig den Assembler - so 
hab ichs schon für einen ganzen Sack voll verschiedener Prozessoren 
gemacht...

von Tabelle (Gast)


Lesenswert?

Wenn man will, kann man das ja auch mit ner Tabelle machen. In C (z.B.) 
geht das sehr schön.

Angenommen, ich will ein 2fach NAND programmieren.
Wahrheitstabelle:

Nr Eingang Ausgang

0  00      1
1  01      1
2  10      1
3  11      0

Jetzt könnte man folgendes Programmieren:

void main(void)
{
  char data[] = {1, 1, 1, 0};
  char inputcode;
  char outputcode;
  while(1)
  {
    inputcode = (dein eingangsport, ggf. noch bits maskieren)
    outputcode = data[inputcode];
    (dein ausgangsport) = outputcode;
  }
}

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Karl heinz Buchegger wrote:
> da ist noch Handlungsbedarf. Vielleicht fällt ja jemandem etwas besseres
> ein, welches in das Baukastensystem passt. Aber im Grunde müsste das so
> funktionieren.

...

> In jedem Register gilt nur das Bit 0, weil da ja nur Logik im Spiel ist.
>
>    zusätzlich beenutze ich noch R20, das immer das Bitmuster für
>    1 enthält, bei manchen Operationen, bei denen keine Konstante
>    angegeben werden kann (EOR) mag sich das als nützlich erweisen.
>
> *************
> Die Negierung ist damit leicht: Bit 0 in R18 wird umgedreht. Das ist
>    ganz einfach ein
>
>       EOR  R16, R20

Wenn man nur auf Bit 0 schaut, geht auch einfach
        INC  R16   oder
        DEC  R16   oder
        COM  R16
und R20 wird nicht belegt.

> Bleibt nur nach das Abfragen eines Pins. Einlesen findet immer nach R19
> statt. Dort wird das interessierende Bit freigestellt und je nachdem ob
> dann 0 oder nicht 0 übrigbleibt, wird das Zielregister auf 0 oder 1
> gesetzt.

        CLR   Zielregister       ; Zielregister mal auf 0
        SBIC  gewünschter Port, gewünschter Pin
        INC   Zielregister       ; Zielregister auf 1
oder
        IN    Zielregister       ; Alle Pins lesen
        BST   gewünschter Pin    ; T = gewünschter Pin
        BLD   Zielregister, 0    ; Zielregister.0 = T

> Ausgabe eines Pins mach ich mir ebenfalls als Baustein. Wenn R16 0 ist,
> wird der Zielpin auf 0 gesetzt, ansonsten auf 1
        SBRC  R16, 0
        SBI   ZielPort, gewünschter Pin
        SBRS  R16, 0
        CBI   ZielPort, gewünschter Pin
oder
        BST   R16, 0               ; T = R16.0
        IN    R?, ZielPort
        BLD   R?, gewünschter Pin
        OUT   ZielPort, R?

Johann

von Dirk (Gast)


Lesenswert?

Ok, danke nochmal für die Problemlösungen in Assembler.

Ich habe jetzt für mich rausgefunden, dass ich alles weitere in C machen 
werde. Bei den ersten Versuchen bin ich schneller und einfacher zum Ziel 
gekommen.

Auf dieser Seite habe ich Beispielprogramme gefunden:
http://www.blafusel.de/books/avr.html (Download |= (1<<Übungsdateien);-)
Manche Programme haben Fehler. Ist aber eine gute Übung diese 
auszubessern.
Am Anfang steht immer dabei, was das Programm können soll. Somit hat man 
auch gleich eine Aufgabenstellung und kann später sein Programm 
vergleichen.

Und das wichtigste, man hat Erfolgserlebnisse und das entschädigt für 
die ganze Zeit die man sich in das Thema reingelesen hat.

Ich lerne am schnellsten, wenn ich ein Programm schon fertig habe und es 
im AVR-Studio mit "Step Into (Taste-F11)" analysiere. Nennt man dieses 
Teil eingentlich Debugger?

Werde jetzt meine Beispielprgramme mit Hilfe des AVR-GCC Tutorial 
durcharbeiten und hoffe, dass ihr mir bei Problemen weiter so gut helfen 
werdet.

PS: für alle die schon beim ersten Programm(LED2) verzweifeln warum es 
im AVR-Studio nicht geht. Einfach wie unten abändern oder besser noch 
von dieser Seite markieren und kopieren.
==============================================================

/* Laesst eine LED an PB0 und PB7 im wechsel endlos blinken
 *
 */

#include <avr/io.h>               //Header-Datei für Aus- und Eingabe
#include <util/delay.h>           // Header_Datei für das Unterprogramm,
                                  //das mit _delay_ms() aufgerufen wird

int main()
{
  DDRB = 0xFF;                  // PORTB als Ausgang definieren
  while (1)                     //"Grundschleife"
  {
    PORTB = 0b00000001;         // LED an PB0 ein, Bsp. als Binärzahl
    _delay_ms (250);            // 250 Millisekunden Schleife
    PORTB = 0x80;               // LED an PB7 ein, Bsp. als Hexzahl
    _delay_ms (250);
  }
  return 0;
}
==============================================================

Eine Frage habe ich noch, es sind ja keine 250 Milisekunden wenn ich mir 
die "Stop Watch" später anschaue.
Hat jemand eine bessere Schleife, die man vielleicht vor "MAIN" 
schreibt, die dann wirklich von 0 bis XX ms annähernd stimmt?
Oder ist das immer ein Problem zwecks unterschiedlicher Zykluszeit der 
einzelnen MCs.

von Karl H. (kbuchegg)


Lesenswert?

Dirk wrote:


> Ich lerne am schnellsten, wenn ich ein Programm schon fertig habe und es
> im AVR-Studio mit "Step Into (Taste-F11)" analysiere. Nennt man dieses
> Teil eingentlich Debugger?

Ja

> Oder ist das immer ein Problem zwecks unterschiedlicher Zykluszeit der
> einzelnen MCs.

Die Wartezeiten von _delay_xx stimmen nur dann, wenn der Optimizer des 
Compilers eingesetzt wird. Dies deshalb, da die Wartezeit durch 
Verbraten von Taktzyklen durch Schleifenkonstrukte erreicht wird. Das 
funktinioniert aber nur dann, wenn genau bekannt ist, was der Compiler 
aus einer C-Schleife genau erzeugt. Das ist aber unterschiedlich, wenn 
der Compiler optimieren darf oder nicht. Die Berechnung der notwendigen 
Schleifenwieerholungen wurde daher so gemacht, dass es dann passt, wenn 
der Compiler optimieren darf.


Ist aber in der Praxis weit weniger ein Problem als es sich jetzt 
anhört. Vor allem deswegen, weil man solch lange Wartezeiten nicht mit 
_delay_xx machen wird, sondern über irgendwelche Timerkonstruktionen. 
_delay_xx blockiert dir sonst nämlich die ganze Maschine und spätestens 
wenn dein Rechner mehrere Aufgaben quasi gleichzeitig erledigen soll, 
ist der Einsatz von _delay_xx sowieso kontraproduktiv (ausser vielleicht 
für ganz kurze Wartezeiten)

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.