Hallo zusammen,
ich versuche gerade mich ein wenig mit dem UART bzw. USART vertraut zu
machen. Ich habe ein paar Beispiele im Internet gesucht und konnte diese
auch nachvollziehen und habe mich dann dazu zu entschlossen die Theorie
in die Praxis zu übertragen.
Hier kommt mein Programmcode:
main.c
Zum Einsatz kommt bei mir ein ATmega8L auf einem STK500 (wobei ich einen
AVR ISP MK II als Programmiergerät einsetze da ich nur einen
USB-zu-Seriell Adapter habe). Der ATmega8 erhält seinen Takt von einem
externen 8MHz Quarz (entsprechende Fuses: Low: 0xFD, High: D9). Als
USB-zu-Seriell Adapter verwende ich einen Keyspan USA-19HS.
Wie man im Programm sehen kann werden alle ASCII-Zeichen hintereinander
über den UART übertragen. Der UART Modus ist 19200 Baud 8N1.
Leider empfange ich am Computer nur Kauderwelsch, siehe Foto:
https://dl.dropboxusercontent.com/u/6454333/mikrocontoller.net/uart_rcv01.png
Ich habe auch noch eine Messung mit meinem Logic Sniffer durchgeführt:
https://dl.dropboxusercontent.com/u/6454333/mikrocontoller.net/uart_measure01.png
In der Messung kann man sehen, dass die 117 (u), 118 (v), 119 (w) usw.
übertragen werden.
Ich bin mit meinem Latein am Ende, was läuft hier falsch?
Vielen Dank und viele Grüße
konze
Hallo!
Wahrscheinlich ein Baudraten Fehler.
Wenn Du dir die Länge der Bits im Logic Sniffer ansiehst, sind diese
dann 52µs? Ich kann das nur schlecht erkennen auf deinem Plot.
Wenn ja, dann ist das Problem am PC!
Konstantin Lübeck schrieb:> ändert sich> nichts. Im Makefile ist die Taktrate auch nochmal angegeben.
Dann schmeiss sie überall anders raus.
Wenn du dieselbe Angabe mehrfach im System hast, dann bringt dir das im
besten Fall nichts. Im schlechtesten Fall stimmen die einzelnen Angaben
nicht überein und du suchst dir einen Wolf.
Ich sehe HIER jetzt kein Problem mit:
>#ifndef F_CPU>#define F_CPU 8000000UL>#endif
Solange F_CPU im makefile angegeben ist, passiert hier ja nichts.
Außerdem hat er ja eh einen 8Mhz Quarz.
Prinzipiell kann man sicher aber überlegen, ob man es so machen will.
> Wie man im Programm sehen kann werden alle ASCII-Zeichen hintereinander
Um nachprüfbare Ergebnisse zu erhalten, sende erst mal nur immer
dasselbe Zeichen. Dann kann man auch mal mit dem Oskar messen bzw.
gewinnt ev. aus dem was am PC ankommt eine gewisse Idee, was falsch sein
könnte.
Sepp schrieb:> Ich sehe HIER jetzt kein Problem mit:
Wir sehen massenhaft Probleme mit dieser Form hier im Forum.
>>#ifndef F_CPU>>#define F_CPU 8000000UL>>#endif>> Solange F_CPU im makefile angegeben ist, passiert hier ja nichts.
WENN F_CPU im makefile angegeben ist.
Und wenn nicht?
Dann wird hier stillschweigend eine Taktfrequenz angenommen.
Im nächsten C-File steht
1
#ifndef F_CPU
2
#define F_CPU 4000000UL
3
#endif
Solange er im makefile diese ganzen #ifndef durch eine eigene Angabe mit
zb 16Mhz ausser Kraft setzt, funktioniert alles wie gewollt. Aber wehe
er vergisst auf die Angabe im makefile. Dann gibt es keine Fehlermeldung
und diverse Programmteile (zb Delays, UART, LCD, ...) rechnen im
schlimmsten Fall mit ihren jeweiligen Privatwerten für F_CPU, die nicht
übereinstimmen müssen.
Es ist besser, wenn eine im makefile fehlende F_CPU Angabe einen Fehler
verursacht, als wie wenn sich der Compiler anhand diverser 'Altlasten'
aus kopiertem Code irgendwelche F_CPU Angaben aus den Fingern saugt.
Dafür zu sorgen, dass im Falle eines Programmiererversäumnisses es zu
einer Fehlermeldung kommt, ist durchaus eine Form des defensiven
Programmierens.
Karl Heinz Buchegger schrieb:> gewinnt ev. aus dem was am PC ankommt eine gewisse Idee, was falsch sein> könnte.
Es hat mit Sicherheit was mit dem Timing (sprich tatsächliche
Taktfrequenz zu F_CPU Angaben, bzw. Einstellung auf dem PC) zu tun.
Der Serial/USB Wandler da drinnen ist dann momentan auch nur eine
potentielle Fehlerquelle mehr.
Vielen Dank für eure Unterstützung, ich denke ich habe den Fehler
gefunden. Aber ich weiß noch nicht wie ich diesen Beheben kann.
***Derzeitiges Setup:***
Ich habe ein paar Veränderungen an meinem Programm gemacht, sodass ich
die Übertragung von Hand auslösen kann und dass immer das gleiche
Zeichen übertragen wird. Zudem habe ich aus allen Dateien #define F_CPU
entfernt, da diese schon im Makefile gesetzt wird. Mein Programm sieht
nun wie folgt aus:
main.c
An der Hardware habe ich fast nichts verändert, ich habe das 8MHz Quarz
gegen ein 16MHz Quarz ersetzt. Im Makefile habe ich somit F_CPU auf
16000000UL gesetzt.
Die Ausgabe des Compilers sieht wie folgt aus:
***FEHLERQUELLE:***
Nun habe ich nochmal mit meinem Logic Sniffer eine Messung durchgeführt
und bin bei 9600 Baud auf das folgende Ergebnis gekommen:
https://dl.dropboxusercontent.com/u/6454333/mikrocontoller.net/uart_measure_9600_baud.png
Laut Wikipedia beträgt die Bitzeit bei einer Baudrate von 9600: 104us
(Quelle: http://de.wikipedia.org/wiki/UART). Bei meiner Messung bin ich
aber auf eine Bitzeit von 454us gekommen, also mehr als 4 mal so lang.
Checklist 3.2:
+ Int. Oszillator wird nicht verwendet sondern 16MHz Quarz.
+ Habe nur 8MHz und 16MHz zur Hand.
+ Taktrate wird genau angegeben über F_CPU während des Kompilierens.
+ entfällt, s.o.
+ Fuses sind folgendermaßen eingestellt: High: 0xd9, Low: 0xff (ext.
crystal / resonator high freq.; start-up time 16K CK + 64ms) siehe:
http://www.engbedded.com/fusecalc/
+ CLKDIV gibt es nicht beim ATmega8.
+ entfällt, s.o.
+ Wenn ich das Quarz während der Laufzeit entferne, geht nichts mehr =>
Quarz wird somit als Taktquelle verwendet.
+ Hier liegt der Fehler, aber ich weiß nicht wo?
+ URSEL bit ist gesetzt.
+ Habe ich gelesen und verstanden
Sonstige Fehlerquellen:
+ Datenübertragung "funktioniert" (Wenn ich den Taster drücke wird etwas
gesendet, ansonsten ist es still)
+ Ich gehe davon aus dass das STK500 das regelt.
+ PD0 auf RX und PD1 auf TX.
+ Ja, alle Programme wurden auf die Baudrate 9600 und 8N1 gestellt.
+ Ich kann mit dem USB-zu-Seriell Adapter ohne Probleme eine AVR auf dem
STK500 programmieren => USB-zu-Seriell funktioniert.
+ Nein.
+ Welche Pins sind gemeint? Ein D-Sub 9 habe nur 9 Pins + Masse über das
Gehäuse.
Ich hoffe ich habe keine Details übersehen.
Viele Grüße
konze
Nachtrag:
Ich habe soeben das folgende Programm auf den ATmega8 geladen:
1
/* main.c */
2
3
#include<avr/io.h>
4
#include<util/delay.h>
5
6
intmain(void){
7
8
/* set PB0 as input */
9
DDRB=~0x01;
10
PORTB=0x01;
11
12
/* set PD0-1 as output */
13
DDRD=0xff;
14
PORTD=~0x00;
15
16
/* set PC0-1 as output*/
17
DDRC=0x03;
18
PORTC=~0x02;
19
20
while(1){
21
if((PINB&0x01)==0){
22
break;
23
}
24
}
25
26
PORTC=~0x01;
27
28
while(1){
29
PORTD=0xff;
30
_delay_ms(1000);
31
PORTD=0x00;
32
_delay_ms(1000);
33
}
34
35
return0;
36
}
Fuses und Hardware wie eben.
Wenn ich mit meinem Logic Sniffer die Zeit messe zwischen positiver und
negativer Flanke an PD0 dann beträgt die Dauer nicht 1s sondern 4,5.
Dies ist fast genau der selbe Faktor wie er auch bei den Zeiten am UART
auftritt. Ich hoffe dies dient zu Lösung des Problems.
Viele Grüße
konze
Konstantin Lübeck schrieb:> Laut Wikipedia beträgt die Bitzeit bei einer Baudrate von 9600: 104us> (Quelle: http://de.wikipedia.org/wiki/UART). Bei meiner Messung bin ich> aber auf eine Bitzeit von 454us gekommen, also mehr als 4 mal so lang.
Das entspricht ziemlich genau einer anderen gebräuchlichen
Quarzfrequenz, nämlich 3,6864 MHz. Also Lupe raus holen, und nochmal
schauen, was tatsächlich auf dem Quarz steht.
Nachtrag: Ich bin nicht wirklich vertraut mit dem STK500, aber ist
3,6864 MHz nicht auch die Standardeinstellung des STK500-Taktgenerators?
Also auch noch mal checken, ob das STK500 richtig für die Verwendung
eines Quarzes konfiguriert ist. Ja, ich weiß, dein Quarz-Zieh-Test
scheint das zu belegen, die Symptome sprechen aber dagegen.
Ich habe den Fehler gefunden:
Auf dem STK500 gibt es einen Jumper OSCSEL dieser hat zwei Positionen 0
und 1.
Wenn man den Jumper auf 1 steckt, dann wird eine vom STK500 generierte
Frequenz angelegt nämlich: 3,6864 MHz.
Wenn man den Jumper auf 0 steckt, dann wird das Quarz welches man in den
Sockel CRYSTAL gesteckt als Taktquelle verwendet.
Ich hatte die ganze Zeit den OSCSEL Jumper in der falschen Stellung.
Jetzt Funktioniert alles wunderbar.
Viele Dank an alle!
konze