Hallo, ich beschäftige mich gerade mit der Kommunikation zwischen ATmega8 und dem PC. Ich verwende das Starterkit aus dem Microcontroller.net Shop sowie den obersten Code aus dem UART-Kapitel im AVR-Tutorial (http://www.mikrocontroller.net/articles/AVR-Tutorial:_UART) Die einzige Anpassung habe ich beim Einstellen der Taktfrequenz des externen Takts vorgenommen, der bei 8Mhz liegt. Mein Problem ist, dass die Übertragung zum PC nur sporadisch funktioniert und äußerst fehleranfällig ist, wie z.B. auf dem angehängten Screenshot zu sehen ist. Die korrekte Übertragung müsste Test! in jeder Zeile liefern. Hat jemand von den Experten eine Idee, was hier das Problem sein könnte? Vielen Dank für Eure Hilfe! Stephan
Sieht mir entweder nach einem Wackelkontakt oder einem nicht stabilen Takt aus. Die Verwendung des internen 8Mhz RC-Schwingkreises könnte zb sowas erzeugen.
Solche Zeichenwildwüchse deuten oft auf einen Stringüberlauf hin. Aber da müsstest du schon deinen ganzen Quelltext zeigen. Ansonsten: Woher hast du den Wert für das UBRR Register? Selbst ausgerechnet? Im Datenblatt des Atmels sind sämtliche Werte für die gängigsten Quarze zu finden (+ Angabe zum prozentualen Fehler).
Vielen Dank erst mal! Hier der gesamte Quelltext:
1 | |
2 | .include "m8def.inc" |
3 | |
4 | .def temp = R16 |
5 | |
6 | .equ F_CPU = 8000000 ; Systemtakt in Hz |
7 | .equ BAUD = 9600 ; Baudrate |
8 | |
9 | ; Berechnungen |
10 | .equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1) ; clever runden |
11 | .equ BAUD_REAL = (F_CPU/(16*(UBRR_VAL+1))) ; Reale Baudrate |
12 | .equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000) ; Fehler in Promille |
13 | |
14 | .if ((BAUD_ERROR>10) || (BAUD_ERROR<-10)) ; max. +/-10 Promille Fehler |
15 | .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!" |
16 | .endif |
17 | |
18 | ; Stackpointer initialisieren |
19 | |
20 | ldi temp, HIGH(RAMEND) |
21 | out SPH, temp |
22 | ldi temp, LOW(RAMEND) |
23 | out SPL, temp |
24 | |
25 | ; Port D = Ausgang |
26 | |
27 | ldi temp, 0xFF |
28 | out DDRD, temp |
29 | |
30 | ; Baudrate einstellen |
31 | |
32 | ldi temp, HIGH(UBRR_VAL) |
33 | out UBRRH, temp |
34 | ldi temp, LOW(UBRR_VAL) |
35 | out UBRRL, temp |
36 | |
37 | ; Frame-Format: 8 Bit |
38 | |
39 | ldi temp, (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0) |
40 | out UCSRC, temp |
41 | |
42 | sbi UCSRB, RXEN ; RX (Empfang) aktivieren |
43 | |
44 | receive_loop: |
45 | sbis UCSRA, RXC ; warten bis ein Byte angekommen ist |
46 | rjmp receive_loop |
47 | in temp, UDR ; empfangenes Byte nach temp kopieren |
48 | out PORTD, temp ; und an Port D ausgeben. |
49 | rjmp receive_loop ; zurück zum Hauptprogramm |
Ich verwende nicht den internen RC-Oszillator sondern einen externen Quarz. Dieser müsste eigentlich die geforderte Genauigkeit liefern.
Hm, das passt aber nicht zu deiner Terminalausgabe - du sendest doch gar nichts?
Oh sorry, tut mir leid: Hab beim Kopieren im Eifer des Gefechts einen Codeteil unterschlagen. Hier nochmal der ganze Code:
1 | .include "m8def.inc" |
2 | |
3 | .def temp = r16 ; Register für kleinere Arbeiten |
4 | .def zeichen = r17 ; in diesem Register wird das Zeichen an die |
5 | ; Ausgabefunktion übergeben |
6 | |
7 | .equ F_CPU = 8000000 ; Systemtakt in Hz |
8 | .equ BAUD = 9600 ; Baudrate |
9 | |
10 | ; Berechnungen |
11 | .equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1) ; clever runden |
12 | .equ BAUD_REAL = (F_CPU/(16*(UBRR_VAL+1))) ; Reale Baudrate |
13 | .equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000) ; Fehler in Promille |
14 | |
15 | .if ((BAUD_ERROR>10) || (BAUD_ERROR<-10)) ; max. +/-10 Promille Fehler |
16 | .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!" |
17 | .endif |
18 | |
19 | ; Stackpointer initialisieren |
20 | |
21 | ldi temp, HIGH(RAMEND) |
22 | out SPH, temp |
23 | ldi temp, LOW(RAMEND) |
24 | out SPL, temp |
25 | |
26 | ; Baudrate einstellen |
27 | |
28 | ldi temp, HIGH(UBRR_VAL) |
29 | out UBRRH, temp |
30 | ldi temp, LOW(UBRR_VAL) |
31 | out UBRRL, temp |
32 | |
33 | ; Frame-Format: 8 Bit |
34 | |
35 | ldi temp, (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0) |
36 | out UCSRC, temp |
37 | |
38 | sbi UCSRB,TXEN ; TX aktivieren |
39 | |
40 | loop: |
41 | ldi zeichen, 'T' |
42 | rcall serout ; Unterprogramm aufrufen |
43 | ldi zeichen, 'e' |
44 | rcall serout ; Unterprogramm aufrufen |
45 | ldi zeichen, 's' |
46 | rcall serout ; ... |
47 | ldi zeichen, 't' |
48 | rcall serout |
49 | ldi zeichen, '!' |
50 | rcall serout |
51 | ldi zeichen, 10 |
52 | rcall serout |
53 | ldi zeichen, 13 |
54 | rcall serout |
55 | rcall sync |
56 | rjmp loop |
57 | |
58 | serout: |
59 | sbis UCSRA,UDRE ; Warten bis UDR für das nächste |
60 | ; Byte bereit ist |
61 | rjmp serout |
62 | out UDR, zeichen |
63 | ret ; zurück zum Hauptprogramm |
64 | |
65 | ; kleine Pause zum Synchronisieren des Empfängers, falls zwischenzeitlich |
66 | ; das Kabel getrennt wurde |
67 | |
68 | sync: |
69 | ldi r16,0 |
70 | sync_1: |
71 | ldi r17,0 |
72 | sync_loop: |
73 | dec r17 |
74 | brne sync_loop |
75 | dec r16 |
76 | brne sync_1 |
77 | ret |
Zum Thema Wackelkontakt: Hab jetzt mal alle unschönen Lötstellen nochmal nachgelötet, gebracht hats bisher leider nichts...
Das sieht nach Störungen aus, die nicht von der Software kommen. Ich würde an deiner Stelle die Hardware näher untersuchen, also den Aufbau des µC Boards und die Verbindung zwischen PC und µC. Bei COM14 vermute ich, dass zusätzlich ein USB-RS232 Wandler im Spiel ist. > Starterkit aus dem Microcontroller.net Shop Dieses? AVR Starterkit (inkl. USB Programmer) http://shop.embedded-projects.net/index.php?module=artikel&action=artikel&id=108 Dort kannst du den AVR aus der IC-Fassung entfernen und RXD-TXD an der Fassung brücken. Alle vom PC aus gesendeten Zeichen müssen dann fehlerfrei an den PC zurück kommen, wenn der Rest der Hardware OK ist (Loopback-Test).
Auch mal an allen Kabeln und Steckern wackeln. Ich hab zb einen USB Stick, den ich beim Einstecken etwas in eine Richtung 'verkanten' muss, sonst wird der Stick nicht korrekt erkannt. Nachweislich auf 5 Rechnern ausprobiert. Es liegt am Stick und dessen mechanischem Steckeraufbau.
@ Karl Heinz Buchegger (kbuchegg) (Moderator) >Ich hab zb einen USB Stick, den ich beim Einstecken etwas in eine >Richtung 'verkanten' muss, sonst wird der Stick nicht korrekt erkannt. >Nachweislich auf 5 Rechnern ausprobiert. Es liegt am Stick und dessen >mechanischem Steckeraufbau. Klingt nach Wackelkontakt oder kalter Lötstelle. Würde ich umgehend entsorgen.
Vielen Dank für die weiteren Tipps! Krapao schrieb: >> Starterkit aus dem Microcontroller.net Shop > > Dieses? > > AVR Starterkit (inkl. USB Programmer) > http://shop.embedded-projects.net/index.php?module... > > Dort kannst du den AVR aus der IC-Fassung entfernen und RXD-TXD an der > Fassung brücken. Alle vom PC aus gesendeten Zeichen müssen dann > fehlerfrei an den PC zurück kommen, wenn der Rest der Hardware OK ist > (Loopback-Test). Ja genau dieses Starterkit verwende ich! Den Loopback-Test habe ich durchgeführt -> Funktioniert! Wenn ich RXD und TXD brücke, dann kommen genau die eingegebenen Zeichen zurück (ohne Störungen)! (Ach ja, ein USB-RS232 ist auch im Spiel, aber an dem dürfte es ja dann auch nicht liegen,oder?) Die richtige Folgerung wäre doch eigentlich, dass irgendwas an der Ausgabe des Controllers nicht stimmt!?! Um Verbindungsfehler auszuschließen habe ich auch die entscheidenden Pins zwischen MAX232 und µC direkt verbunden... erfolglos... Oder der externe Quarz auf dem Board ist zu ungenau? Würde mich aber wundern, wenn das noch keinem zuvor aufgefallen wäre...
Hi >Oder der externe Quarz auf dem Board ist zu ungenau? Würde mich aber >wundern, wenn das noch keinem zuvor aufgefallen wäre... Unwahrscheinlich. Bist du Sicher, das der Quarzoszillator wirklich (per Fuse) aktiviert ist? MfG Spess
spess53 schrieb: > Unwahrscheinlich. Bist du Sicher, das der Quarzoszillator wirklich (per > Fuse) aktiviert ist? Ich sag mal zu 99% ja. Ich setz die Fuses übers AVR-Studio. Bei der Option SUT_CKSEL habe ich "Ext. Crystal/Resonator high Freq; Start-up time: 16 CK + 64ms" eingestellt. An den andren Fuses habe ich nichts verändert. Dies führt dann zu folgender Bitkombination: HIGH: 0xD9 LOW: 0x3F Diese wiederum entspricht den Empfehlungen im Tutorial... Weiß jetzt irgendwie nicht mehr weiter...
Mit dem Oszi mal angeschaut, was am Ende des Kabels ankommt? Stimmt das Timing für 9600 Baud? Ist da ein Wackler im Kabel? Gehts mit einem anderen Kabel?
Miss mal von Anschluß 2 und Anschluß 6 des MAX232 gegen Masse, ob da ca +10 Volt bzw. -10 Volt anstehen. Ich hatte auch mal so ein Fehlerbild wie Du und da lag es an dem MAX232. Von 10 Stück hatte einer eine Macke. MfG Paul
Also ich hab jetzt nochmal etwas rumgespielt und verschiedenste Sachen ausprobiert (auch Kabel z.T. erneuert etc.) und jetzt funktioniert es tatsächlich. Vielen Dank nochmal für eure Hilfe!
>Also ich hab jetzt nochmal etwas rumgespielt und verschiedenste Sachen >ausprobiert (auch Kabel z.T. erneuert etc.) und jetzt funktioniert es >tatsächlich. > >Vielen Dank nochmal für eure Hilfe! Und woran lag es jetzt?
So wie es aussieht war es tatsächlich ein Wackelkontakt an einer Lötstelle, wie bereits von ein paar Seiten vermutet wurde.
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.