Hallo Leute, ich habe nun auch mal einen kleinen UART geschrieben. Er funktioniert leider nicht ganz. Er empfängt recht häufig falsche Zeichen. Das "falsche" Zeichen äußert sich in einem bit-versatz bzw. er "dichtet" sich ein paar bits dazu. Es hängt allerdings auch vom Zeichen selbst ab. Wenn ich z.b. ein 'h' sende (binär : 01101000) empfängt er es immer richtig. Ein 'a' hingegen (binär : 01100001) wird fast immer falsch empfangen. Wenn jemand Lust und Zeit hat kann er sich ja gerne mal die Komponente antun. hier mal der quellcode des empfängers. Wenn jemand eine idee hat warum es hapert, bzw. anderweitige verbesserungsvorschläge hat, immer her damit :-) -------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; -- Uncomment the following lines to use the declarations that are -- provided for instantiating Xilinx primitive components. --library UNISIM; --use UNISIM.VComponents.all; entity uart_rx is port (clk : in std_logic; res : in std_logic; rx_in : in std_logic; baud_clk_16 : in std_logic; busy : out std_logic; out_buffer : out std_logic_vector (7 downto 0); trg : out std_logic); end uart_rx; architecture behave of uart_rx is signal state : std_logic_vector (3 downto 0); signal count : std_logic_vector (3 downto 0); signal baud_clk_16_z1 : std_logic; signal rx_buffer : std_logic_vector (7 downto 0); signal err : std_logic; signal trg_out : std_logic; signal rx_in_z1 : std_logic; signal rx_in_z2 : std_logic; signal rx_in_z3 : std_logic; --signal rx_in_z4 : std_logic; begin trg <= trg_out; process (clk,res, baud_clk_16_z1, baud_clk_16, state, count, rx_in_z3, rx_in_z2, rx_in_z1, rx_in, rx_buffer) begin if res = '1' then state <= (others => '0'); count <= (others => '0'); rx_buffer <= (others => '0'); baud_clk_16_z1 <= '0'; err <= '0'; trg_out <= '0'; elsif clk'event and clk = '1' then baud_clk_16_z1 <= baud_clk_16; --rx_in_z4 <= rx_in_z3; if baud_clk_16_z1 = '0' and baud_clk_16 = '1' then rx_in_z1 <= rx_in ; rx_in_z2 <= rx_in_z1; rx_in_z3 <= rx_in_z2; count <= count + '1'; if state = X"0" then if rx_in_z3 = '0' then --count <= count + '1'; if count = X"F" then state <= X"1"; --count <= (others => '0'); end if; else count <= (others => '0'); end if; else if count = X"8" then case state is when X"1" => rx_buffer (0) <= rx_in_z3; state <= X"2"; when X"2" => rx_buffer (1) <= rx_in_z3; state <= X"3"; when X"3" => rx_buffer (2) <= rx_in_z3; state <= X"4"; when X"4" => rx_buffer (3) <= rx_in_z3; state <= X"5"; when X"5" => rx_buffer (4) <= rx_in_z3; state <= X"6"; when X"6" => rx_buffer (5) <= rx_in_z3; state <= X"7"; when X"7" => rx_buffer (6) <= rx_in_z3; state <= X"8"; when X"8" => rx_buffer (7) <= rx_in_z3; state <= X"9"; when X"9" => if rx_in_z3 = '1' then out_buffer <= rx_buffer; err <= '0'; trg_out <= '1'; else out_buffer <= (others => '0'); err <= '1'; end if; state <= X"0"; when others => NULL; end case; end if; end if; end if; if trg_out = '1' then trg_out <= '0'; end if; end if; end process; end architecture; ----------------------------------------------------------------------- gruß rene
> if state = X"0" then > if rx_in_z3 = '0' then > --count <= count + '1'; > if count = X"F" then > state <= X"1"; > --count <= (others => '0'); > end if; > else > count <= (others => '0'); > end if; Erstze das mal durch if state = X"0" then if rx_in_z3 = '0' then count <= "0000"; state <= X"1"; end if; MfG Falk
danke für den tip. werde es heute abend mal ausprobieren. obwohl mir noch nicht so ganz klar ist warum es daran liegen könnte. ich muß ja erst ein rx-bit (16x baud_clk_16) abwarten nachdem ich die 0 erkannt habe, oder sehe ich da was falsch ?! gruß rene
Hallo Falk, ich habs mal ausprobiert, aber es funktioniert leider nicht. Mir ist nicht so ganz klar wieso das mit dieser Änderung laufen könnte. Ich muß doch erst mein Start-Bit abwarten (also 16 baud_clk_16 pulse zählen), bevor ich die eigentlichen nutzdaten in mein register packe ? oder meintest du das so, das man noch einen zusätzlichen zustand einfügen muß für das start-bit ? gruß rene
@TheMason >Ich muß doch erst mein Start-Bit abwarten (also 16 baud_clk_16 pulse >zählen), bevor ich die eigentlichen nutzdaten in mein register packe ? Ja. Aber mit der fallenden Flanke von rx_in_z3 musst du deinen Zähler rücksetzen. Danach läuft er frei durch. >oder meintest du das so, das man noch einen zusätzlichen zustand >einfügen muß für das start-bit ? Ja. MfG Falk
nach Erkennung des Startbits musst du 1,5 bitzeiten bis zur Abtastung des ersten Bits warten, damit der Pegel auch in der Mitte der Bits abgefragt wird. Ansonsten fragst Du die Bits immer am Anfang ab und das kann schon mal Fehler geben. Gruß Jörg
Eines der Hauptprobleme, die es mit FPGAs gibt, sind asynchrone Signale von aussen. Die MÜSSEN immer erst mal synchronisiert werden (ich hätte auch schreiben können: die SOLLTEN immer erst mal synchronisiert werden, aber aus der alltäglichen Erfahrung ist ein zwingendes MUSS immer besser). Denn ein asynchrones Signal geht z.B. auf mehrere LUTs/FFs im FPGA und kommt da aufgrund von Laufzeitunterschieden nicht bei allen gleichzeitig an. Daher weiß das halbe FPGA dann schon von dem neuen Zustand, die andere Hälfte bekommt die Änderung erst zum nächsten Takt mit. Und dann gibt es solche Effekte, dass das Design so ein paar Minuten oder Zeichen lang gut funktioniert, dann gehts mal schief, dann funktionierts wieder ne Zeit lang usw. usf. Du hast gleich zwei solcher Signale in deinem Design: rx_in : in std_logic; baud_clk_16 : in std_logic; Schau dir das mal genauer an. Irgendwo dort liegt der Hund begraben (garantiert!). Als Anhang habe ich ein kampferprobtes SIO-Design, schau dir mal die Entprellung des RX-Signals an (so gehts, auch garantiert!). BTW: die sensitivity-List des Process braucht nur zwei Signale: process (clk,res) Denn eine Änderung irgendeines anderen Signals aus deiner Liste führt nicht zu einer Ausgangs- oder Signaländerung. Das ist aber eh' nur für die Simulation interessant (reduziert die Simulationszeit), der Synthesizer schmeisst die Dinger sowieso weg. Gruß Lothar
@lothar aber durch: > elsif clk'event and clk = '1' then > baud_clk_16_z1 <= baud_clk_16; > > --rx_in_z4 <= rx_in_z3; > > if baud_clk_16_z1 = '0' and baud_clk_16 = '1' then > > rx_in_z1 <= rx_in ; > rx_in_z2 <= rx_in_z1; > rx_in_z3 <= rx_in_z2; wird rx_in doch einsynchronisiert (es wird sonst nirgends das signal rx_in verwendet !). außerdem ist baud_clk_16 auch synchron zum clk (da dieser von clk abgeleitet wird). oder sehe ich da was falsch ?! gruß rene ps. danke für deine rs232-komponente. werde mir diese mal genauer anschauen. ist ja bald wochenende :-))
@TheMason >wird rx_in doch einsynchronisiert (es wird sonst nirgends das signal >rx_in verwendet !). außerdem ist baud_clk_16 auch synchron zum clk (da >dieser von clk abgeleitet wird). >oder sehe ich da was falsch ?! Du siehst das vollkommen richtig. Alles im grünen Bereich. Dein Problem liegt höchstwahrscheinlich in der State Machine. MFG Falk
ich glaub mir schwant was böses ... ich habe vermutung das ihr beide recht habt. mir ist nämlich gerade aufgefallen, das : > if baud_clk_16_z1 = '0' and baud_clk_16 = '1' then > > rx_in_z1 <= rx_in ; > rx_in_z2 <= rx_in_z1; > rx_in_z3 <= rx_in_z2; zwar meinen rx_in einsynchronisiert, ABER : eben nur mit dem baud_clk_16 und nicht mit meinem systemtakt clk. dadurch kann natürlich meine statemachine nicht richtig funktionieren. schmärz lass nach ... es ist denke ich ein problem des einsynchronisierens (falscher sync-clk) und der statemachine (durch zu langsam einsynchronisiertes signal) kann es sein das es das ist ? (ich muß das gleich zuhause mal testen) gruß rene
@TheMason >mir ist nämlich gerade aufgefallen, das : >zwar meinen rx_in einsynchronisiert, ABER : eben nur mit dem baud_clk_16 >und nicht mit meinem systemtakt clk. dadurch kann natürlich meine Das ist schon OK, deine State Machine reagiert ja auch nur im baud_clk_16 Takt, da müssen die Eingangssignale nicht schneller abgetastet werden. >es ist denke ich ein problem des einsynchronisierens (falscher sync-clk) >und der statemachine (durch zu langsam einsynchronisiertes signal) >kann es sein das es das ist ? (ich muß das gleich zuhause mal testen) Hier ist das kein Problem. MFG Falk
@lothar also ich habe mir mal deine einsychronisierung in meinen uart eingebaut. (um rx_in zu entprellen). es funktioniert. wobei mir noch nicht so ganz klar ist warum dem so ist. ob ich nun mit baud_clk_16 einclocke oder mit dem systemtakt sollte für den weiteren verlauf der statemachine doch unerheblich sein, oder ? und da das signal ja mehrfach abgetastet wird dürfte es doch spätestens nach dem 4. takt sauber anliegen. das einzige was ich bei meiner lösung nicht gemacht habe das ich mein rx-input aus allen 4 flip-flops generiere, sondern nur aus 2 flip-flops, und dies auch nur für die startbedingung (fallende flanke an rx). ich wollte außerdem fragen ob ich dein einsynchronisieren so übernehmen und öffentlich verwenden darf. ich würde meine komponente gerne ausbauen und hier in der Codesammlung "verewigen". ist das mit einem entsprechenden vermerk auf dich ok ? gruß rene
@TheMason >ich wollte außerdem fragen ob ich dein einsynchronisieren so übernehmen >und öffentlich verwenden darf. ich würde meine komponente gerne ausbauen Ersten sehe ich keine Code und zweites gibt darauf kein Patent ;-) >und hier in der Codesammlung "verewigen". ist das mit einem >entsprechenden vermerk auf dich ok ? Wen meinst du mit "dich?". Das Entprellen ist prinzipiell nicht falsch, wird aber meist nicht gebraucht. Die Abtastung mit baud_clk_16 wirkt schon entprellend genug. Ausserdem verwenden alle professionellen UARTs auch nur die mit baud_clk_16 abgetasteten Werte (und bilden die Mehrheitseintscheidung aus Abtastwert 7,8 und 9. Wenn du dann noch das Startbit sowie Stopbit prüfst ist wasserdicht. MfG Falk
@falk es ging sich mir eigentlich nur um den code-schnipsel aus lothars rs232-komponente : > process (RESET, CLK) > begin > if (RESET='1') then > RX_SR <= "0000"; > elsif (rising_edge(CLK)) then > RX_SR <= RX_SR(2 downto 0) & RX; > if (RX_SR = "1000") then RX_Entprellt <= '0'; end if; > if (RX_SR = "0111") then RX_Entprellt <= '1'; end if; > end if; > end process; diesen teil wollte ich verwenden, da damit mein uart funktioniert (wie gesagt ich habe auch noch nicht ganz verstanden warum es damit funktioniert, aber das werde ich schon noch rauskriegen) ich weiß das das nichts wildes ist oder etwaige patentrechtsverletzungen damit verbunden wären, möchte aber anstandshalber nachfragen ob es ok wäre, damit ich in der code-sammlung auchmal einen beitrag in form eines eigen geschriebenen uarts leisten kann. :-) daher die frage (die an lothar gerichtet war :-) >Das Entprellen ist prinzipiell nicht falsch, >wird aber meist nicht gebraucht. Die Abtastung mit baud_clk_16 wirkt >schon entprellend genug. Ausserdem verwenden alle professionellen UARTs >auch nur die mit baud_clk_16 abgetasteten Werte (und bilden die >Mehrheitseintscheidung aus Abtastwert 7,8 und 9. Wenn du dann noch das >Startbit sowie Stopbit prüfst ist wasserdicht. mir ist klar das es so funktionieren müsste, tut es aber leider nicht. und einen grund für das nicht-funktionieren habe ich leider auch keinen. werde das nochmal genauer autesten müssen damit ich nicht dumm sterbe :-) dank auch an dich falk für deine kompetenten beiträge und deine prompte hilfe gruß rene
@TheMason: Nimm den Code ruhig, wenn da was geschützt wäre, hätte ich es
nicht veröffentlicht.
Was ich damit mache, ist ein gelatchtes Signal (RX_Entprellt), das den
Zustand nur ändert, wenn eine richtige Flanke am Eingang anliegt.
Ehrlich gesagt ist mir auch nicht ganz klar, wieso das jetzt
funktioniert. Evtl. liegt es an der zusätzlichen Latency von 2
Taktzyklen.
Mit dem synchronisieren meinte ich eigentlich deinen baud_clk_16_z1, der
war aus dem Code nicht als taktsynchron zu erkennen. Erst durch deine
Bemerkung mit dem Ableiten aus dem clk wird das klar:
> außerdem ist baud_clk_16 auch synchron zum clk (da dieser von clk abgeleitet
wird).
Ich mag solche Unklarheiten nicht. Deshalb habe ich mir deinen Code
nochmal angeschaut (für was gibts Mittagspausen?).
Prinzipiell tut sich dein UART etwas schwer mit dem Start:
1 | count <= count + '1'; |
2 | |
3 | if state = X"0" then |
4 | if rx_in_z3 = '0' then -- solange Startbit aktiv (= 0)!!! |
5 | if count = X"F" then -- was passiert, wenn das Startbit mal |
6 | state <= X"1"; -- nur 15 Takte lang aktiv ist?? |
7 | end if; -- -> das Startbit wird ignoriert |
8 | else -- und auf einem nachfolgenden Bit gestartet |
9 | count <= (others => '0'); |
10 | end if; |
Hier würde ich sofort nach dem Erkennen eines Startbits (fallende Flanke) einen zusätzlichen Zustand einlegen, der auf das erste Bit wartet. >Es hängt allerdings auch vom Zeichen selbst ab. Wenn ich z.b. ein 'h' >sende (binär : 01101000) empfängt er es immer richtig. Ein 'a' hingegen >(binär : 01100001) wird fast immer falsch empfangen. Und jetzt wirds klar: bei einem 'a' kommt nach dem Startbit='0' gleich eine '1' (LSB zuerst) --> Fehlstart (oft, meistens?). Ich denke, dass z.B. ein c, e, g, i... auch öfter mal falsch kommt. Mit einem b, d, f, h, j... gehts dagegen. Eine kleine Änderung in deinem Code könnte da helfen:
1 | count <= count + '1'; |
2 | |
3 | if state = X"0" then |
4 | if rx_in_z3 = '0' then |
5 | if count = X"8" then -- halbe Bitzeit vom Startbit abgewartet |
6 | state <= X"11"; -- -> jetzt noch ein Bit abwarten |
7 | end if; |
8 | else
|
9 | count <= (others => '0'); |
10 | end if; |
11 | else
|
12 | if count = X"8" then |
13 | case state is |
14 | when X"11" => state <= X"1"; -- ein Bit warten |
15 | when X"1" => rx_buffer (0) <= rx_in_z3; state <= X"2"; |
16 | when X"2" => rx_buffer (1) <= rx_in_z3; state <= X"3"; |
17 | when X"3" => rx_buffer (2) <= rx_in_z3; state <= X"4"; |
18 | when X"4" => rx_buffer (3) <= rx_in_z3; state <= X"5"; |
19 | when X"5" => rx_buffer (4) <= rx_in_z3; state <= X"6"; |
20 | when X"6" => rx_buffer (5) <= rx_in_z3; state <= X"7"; |
21 | when X"7" => rx_buffer (6) <= rx_in_z3; state <= X"8"; |
22 | when X"8" => rx_buffer (7) <= rx_in_z3; state <= X"9"; |
23 | when X"9" => if rx_in_z3 = '1' then |
24 | out_buffer <= rx_buffer; |
25 | err <= '0'; |
26 | trg_out <= '1'; |
27 | else
|
28 | out_buffer <= (others => '0'); |
29 | err <= '1'; |
30 | end if; |
31 | state <= X"0"; |
32 | when others => NULL; |
33 | end case; |
34 | |
35 | end if; |
Wäre interessant, obs das war. Lothar
@lothar erstmal danke für das snippet. muß wohl eben anmerken das der code den ich zu anfang gepostet habe schon nicht mehr aktuell ist. >if rx_in_z3 = '0' then > if count = X"F" then > state <= X"1"; > end if; >else war nur der erste schuß. ich habe recht schnell gemerkt das das nicht funktionieren kann. daher habe ich in meinem aktuell verwendeten code (habe diesen gerade nur zuhause rumfliegen) in etwa das verwendet : if rx_in_z3 = '0' and rx_in_z2 = '1' then count <= X"0"; state <= X"1"; end if; um die fallende flanke zu erkennen. daraufhin verzweige ich in zustand 1 der (und das ist auch wieder neuer code) bis zur bit-mitte wartet (also count = X"8") und dann das start-bit erneut prüft. ist dieses bit = 0, so gehe ich in zustand 2 der mir meine bits reinschiebt (auch immer nur in der bit-mitte). habe ich stattdessen ein start-bit von 1 gehe ich zurück nach zustand 0. und genau dieser code (ich poste ihn heute abend, damit wir nicht über alten code reden) funktioniert NUR dann wenn ich deine entprellung nehme. bei der methode die ich verwendet habe (4-flip-flops die per baud_clk_16 getaktet werden) empfange ich nichts. irgendwie finde ich das merkwürdig, zumal (wie falk ja schon sagte) ich das signal ja auch mit baud_clk_16 einsynchen kann ... gruß rene
@TheMason: mit welchem Takt synchronisierst du das RX_IN-Schieberegister? Mit baud_clk_16 oder (dem wesetlich schnelleren) clk? Nur auf ein einziges FF zu verwenden wie in
1 | if rx_in_z3 = '0' and rx_in_z2 = '1' then -- steigende Flanke, rx_in_z3 ist älter |
bringt dir sicher auch interessante Effekte. Das wird jetzt ein statistisches Problem: wenn du nicht so richtig schöne störfreie Signale hast, kann dir ein kurzer 1- oder 0-Spike in rx_in_z1 eingelesen werden und voila: zwei Takte später erkennst du eine Flanke und legst schon mal los. Ich umgehe sowas über das 4-Bit Schieberegister. Dein Code müsste ohne Schieberegister demnach etwa so aussehen (als 3-Bit-SR):
1 | if rx_in_z3 = '0' and rx_in_z2 = '1' and rx_in_z1 = '1' then -- steigende Flanke |
Am Rande: Ruhepegel ist normalerweise '1' auf der RX-Strippe. Ich denke dein Code zuhause wartet auf die fallende Flanke des Startbits. Im Text hast du es jedenfalls schon richtig beschrieben.
@lothar ich habe es mit beiden takten ausprobiert, klappte in keinem der fälle :-( aber was du meintest mit den spikes und dem 4-bit-sr ist denke ich mein problem. ich habe mal bei einer spi-komponente die nicht laufen wollte meine bedingung (steigende oder fallende flanke) einfach mal über 3 ff anstatt über 2 gemacht und dann lief es auch. ich vermute das ich hier ein ähnliches problem habe bzw. das das das selbe problem ist.
@Lothar >Nur auf ein einziges FF zu verwenden wie inif rx_in_z3 = '0' and rx_in_z2 >= '1' then -- steigende Flanke, rx_in_z3 ist älter >bringt dir sicher auch interessante Effekte. >Das wird jetzt ein statistisches Problem: wenn du nicht so richtig >schöne störfreie Signale hast, kann dir ein kurzer 1- oder 0-Spike in >rx_in_z1 eingelesen werden und voila: zwei Takte später erkennst du eine >Flanke und legst schon mal los. Und bricht bei der Prüfung des Startbits wieder ab. MFG Falk
so ! nun hab ich das problem gefunden. durch eine schusseligkeit hab doch tatsächlich statt if rx_in_z3 = '1' and rx_in_z2 = '0' then if rx_in_z3 = '0' and rx_in_z2 = '1' then zur erkennung der fallenden flanke verwendet ... :-( konnte ja nicht funktionieren. kaum macht mans richtig. jetzt klappts auch wenn ich auf baud_clk_16 einsynche. gruß rene
Ein paar kleine Anmerkungen. > process (clk,res, baud_clk_16_z1, baud_clk_16, state, count, rx_in_z3, >rx_in_z2, rx_in_z1, rx_in, rx_buffer) In einenm getakteten Prozess braucht man nur den Takt und das asynchrone Reset in der Sensitivity List. > baud_clk_16_z1 <= baud_clk_16; > if baud_clk_16_z1 = '0' and baud_clk_16 = '1' then Ist prinzipiell richtig, besser ist es aber, gleich im Baudgenerator ein entsprechendes Signal zu generieren (Clock enable, einen Takt breit). Macht das Ganze übersichtlicher. > if state = X"0" then > if rx_in_z3 = '0' and rx_in_z2 = '1' then > count <= (others => '0'); > state <= X"1"; > else > count <= (others => '0'); > end if; In beiden Zweigen ist die Zuweisung an count identisch. Also rausnehmen, der Übersicht wegen. > if trg_out = '1' then > trg_out <= '0'; > end if; Das soll sicher der Trigger für die nachfolgende Schaltung sein, dass ein neues Datenbyte angekommen ist. Das macht man sinnvollerwise anders. Man setzt ein Flag (Data available) und wartet auf das Handschake der Zielschaltung (Acknowledge). Dann löscht man das Flag wieder. Wenn das Flag nicht bis zum nächsten empfangenen Zeichen gelöscht wurde (State "a"), dann gibts nen Buffer Overflow. Ausserdem solltest du für die States Namen verwenden, keine Zahlen. Dadurch hat der Compiler die Chance, die für die Zielarchitektur günstige Kodierung zu wählen (Binär, One-Hot, Gray etc.) Ausserdem wird es wieder lesbarer. type state_type is (s_wait, s_start, s_0, s_1, s_2, s_3, s_4, s_5, s_6, s_7, s_stop); signal state: state_type; Aber alles in allem, gute Leistung, hast dich durchgekämpft. MfG Falk
@falk danke für die hinweise. habe diesen code nur mal schnell rausgekramt. da waren dann noch so sachen drin, die den code nicht gerade "schön" machen, aber das ist alles in arbeit. danke auch für das lob :-) aber eine gute leistung ist das nicht wenn man lediglich aus schusseligkeit auf die falsche flanke reagiert und da tagelang dran rumsucht ... :-(( vor allem weil ein uart ja echt simpel ist, und wenn man sich dann selbst so ein blödes "stop-bit" einbaut und es dann nicht findet .... da frage ich mich dann schon wie ich es geschafft habe einen kleinen audio-prozessor zu schreiben (der dann auch noch funktioniert :-)) wenn ich bei solch blöden sachen schon ins trudeln komme ... dank und gruß rene
@TheMason: Freut mich, dass es doch noch geklappt hat, so kurz vorm Einschlafen. Dann war das doch kein Versehen mit der Flanke, ich dachte da schon an einen Tippfehler (wie weiter oben schon am Rande vermerkt). Aber keine Sorge, den Fehler machst du nicht nochmal. Die Flankengeschichte ist jetzt im Gehirn abgespeichert. Gruß Lothar
@lothar es war doch ein tipp-fehler (statt rx_in_z3 = '1' and rx_in_z2 = '0' habe ich rx_in_z3 = '0' and rx_in_z2 = '1' verwendet). also schusseligkeit. das mit der flanken-erkennung hatte ich ja schon verstanden, nur halt eben einen dämlichen flüchtigkeitsfehler gemacht, der mich dann tage und nerven gekostet hat. an dich auch noch einen recht herzlichen dank für deine komponente. das einsynchen so zu machen find ich recht elegant (schön einfach). werde mir das mal merken. einfach und effektiv. gruß rene
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.