www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik UART falsche Zeichen


Autor: Ange (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich versuche bei einem Atmega128 Zeichen über die UART-Schnittstelle zu 
senden, es werden Zeichen auf dem Hyperterminal angezeigt (richtige 
Anzahl),
aber leider nicht die richtigen.
An was kann das liegen?


#ifndef F_CPU
  #define F_CPU 10000000
#endif

/* UART baud rate */
#define UART_BAUD  9600

int main (void){
  //2 Stopbits, 8 bit Daten, Parity: No
  UCSR0C |= (1<<USBS)|(1<<UCSZ01)|(1<<UCSZ00)|(0<<UPM01)|(0<<UPM00);
  UBRR0L =64; //Baudrate 9600 bei 10 MHz
  UCSR0B |= (1<<TXEN1);


  for(;;){
    USART_transmit('a');
    _delay_ms(500);
    USART_transmit('b');
    _delay_ms(500);
    USART_transmit('c');
    _delay_ms(500);
  }
}
void USART_transmit(unsigned char a){
  while(!(UCSR0A &(1<<UDRE0))){}
  UDR0 = a;
}

Gruß
Angelika

Autor: Niels Hüsken (monarch35)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"falsche Zeichen" sind ein eindeutiger Hinweis auf falsche 
Parametrierung der seriellen Schnittstelle, meistens verursacht durch 
unstimmige Baudraten.

Überprüfmal ob der Systemtakt 10Mhz und der UBRR0L-Wert korrekt ist. 
Ausserdem solltest du UBRR0H auch initialisieren.

Zudem kommt mir jedoch der Parameter "2 Stoppbits" merkwürdig, weil 
unüblich vor. Eine "normale" serielle Parametrierung sieht meistens 
"8,N,1" vor. (8 Datenbits,No Parity, 1Stoppbit)

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#ifndef F_CPU
  #define F_CPU 10000000
#endif

/* UART baud rate */
#define UART_BAUD  9600

Das ist ja alles recht schön - allerdings solltest du dann auch die 
Werte für das Baudratenregister daraus berechnen, sonst macht es wenig 
sind.
Bleibt als weitere Fehlerquelle zu dem schon gesagten noch, ob der Chip 
wirklich mit dem 10MHz-Quarz getaktet wird oder noch mit dem internen 
Clock läuft.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
_delay_ms(500) geht mit 10 MHz nicht. Mit der Frequenz gehen max. 26,2 
ms. Schau mal in die libc-Doku.

Baudrate checken, Takt checken, Einstellungen im Terminal checken...

An den zwei Stopbits kann es jedenfalls eigentlich nicht liegen.

Autor: mef (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ein Oszi hilft ungemein, damit kannst Du leicht überprüfen, ob der 
Fehler bei Hypereterm liegt (z.B. falsches Frameformat eingestellt) oder 
bei deinem µC (z.B. falsches Baudrate). Vllt. kennst Du ja jemanden, der 
Dir eines leihen kann. Es ist auf jeden Fall empfehlenswert, weil es 
Grübelzeit spart. ;-)

Solltest Du ein Ozsi haben, danke daran, dass das kleinste Bit zuerst 
übertragen wird und daher auf dem Oszi ganz rechts zu sehen ist, während 
das 128er-Bit z.B. ganz links steht.

Ansonsten:

* Probier' es doch mal mit einer anderen Baudrate, z.B. 2400Bd
* Vllt. haben einige Register nocht falsche Werte?
  Schreib' doch mal explizit noch UBRR0H = 0 oder das U2X0-Bit auf 0.
* Stimmt das Frameformat und die Baudrate bei Hyperterm.
* Welche Zeichen kommen denn an. Schick' doch mal Zeichen von 0x00-0xff 
vllt. bildet sich ein Schema, durch das Du auf den Fehler schliessen 
kannst.
* Atmel bietet zu einigen Controllern auch Bibliotheken, darunter auch 
UART. Vergleich doch mal die Atmel-Sourcen mit Deinen.

Ich hatte ähnliche Probleme und habe dazu auch schon einige 
Forenbeiträge gelesen und irgendwie lag es IMMER an der Baudrate ;-)

Grüße mef

PS: Ich hatte gestern 2 Stunden mal wider an meinen UART-Sourcen 
herumdebuggt, weil sie "plötzlich" nicht mehr gingen. Irgendwann fiehl 
mir dann auf, daß ich anstelle von uart_putchar('A') ausversehen 
uart_putchar("A") geschrieben hatte... 
SMILEY_DER_SEINEN_KOPF_AUF_DEN_TISCH_HAUT So, das musste ich jetzt 
unbedingt noch loswerden ;-)

Autor: mef (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Niels Hüsken: Die Stopbits dürften eigentlich keine Probleme machen. 
Wenn der µC die Frames mit so langen Pausen schickt, kann der Empfänger 
nicht unterscheiden, ob nun 1 oder 2 Stopbits verwendet werden. Macht 
auch in diesem Fall kein Unterschied, weil die Bits sich vom Idle-Pegel 
nicht unterscheiden.

Grüße mef

Autor: Niels Hüsken (monarch35)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich sagte ja auch lediglich, daß die Verwendung zweier Stoppbits 
unüblich ist. Problematisch wirds auf jeden Fall, wenn der Empfänger 
zwei Stoppbits erwartet, aber nur Eines kommt.

Auf jeden Fall möchte ich nochmal hervorheben, daß die initialisierung 
des UBRR0H-Registers fehlt. Das wäre äusserst wichtig, daß das passiert. 
Das delay_ms() falsch parametriert ist, interessiert hier nen Toten.

Autor: Angelika Voß (ange)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Nils
mal eine Frage wie kann ich den Systemtakt feststellen? Ich habe hier 
ein begonnenes Projekt übernommen, im Datenblatt ist ein Takt von 16 MHz 
angegeben
Stopbit habe ich auf 1 geändert
UCSR0C |= (0<<USBS0)|(1<<UCSZ01)|(1<<UCSZ00)|(0<<UPM01)|(0<<UPM00);
UBRR0H = 0  beschrieben

@mef
habe leider kein Oszi
unterschiedliche Baudraten habe ich auch ausprobiert

Autor: Niels Hüsken (monarch35)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Angelika:
Das "e" ist kein Tippfehler. Mein Name ist "Niels" :)
Um den Systemtakt festzustellen gibt es mehrere Möglichkeiten:
Fusebits auslesen und schauen, was konfiguriert ist. Ist ein externer 
Taktgeber konfiguriert, müsste also ein Quarz oder ein Ozillator 
angeschlossen sein, auf dem die Taktfrequenz draufsteht.

Ist über die Fuses ein interner Taktgeber konfiguriert, müsste hier 
beistehen, wie schnell der klappert. In diesem Fall ist häufig jedoch 
die Taktfrequenztolleranz ausserhalb die der für seriellen Übertragung 
nötigen präzision. Ein externer Taktgeber ist auf jeden Fall von nöten.

Bitte schau auch bezüglich des UBRR0H-Registers in die Dokumentation des 
Mega128. Die Reihenfolge in der man die UBRR0H und UBRR0L beschreibt ist 
wichtig. Ich habe sie nur gerade nicht im Kopf.

Autor: mef (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hätte jetzt einfach auf den Quarz geschaut und überprüft, ob die 
Fuses richtig gesetzt sind. Es gibt IMO eine Fuse, die angibt, ob die 
interne oder externe Taktquelle verwendet werden soll. Ich habe gelesen, 
daß die Interne Taktquelle nicht für UART geeignet ist, weil zu ungenau 
(temperaturabhängig, usw.). Apropos Fuses, vllt. ist bei Dir auch die 
Fuse für die Kompatiblität zum ATMega103 gesetzt. Vielleicht macht das 
auch Probleme.

Grüße aus Ulm

Autor: mef (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
im Datenblatt wird zuerst High geschrieben

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mef wrote:

> (temperaturabhängig, usw.). Apropos Fuses, vllt. ist bei Dir auch die
> Fuse für die Kompatiblität zum ATMega103 gesetzt. Vielleicht macht das
> auch Probleme.

Eher unwahrscheinlich.
Wenn die 103-Fuse falsch steht, stürzt der Prozessor beim ersten
Funktionsaufruf ab, weil der Stack nicht dort liegt wo er sollte.

Das Wahrschinlichste ist immer noch Takt und daher die
Baudrate.
Wenn man mit den Fuses nicht klarkommt, kann man auch folgendes
machen: Mittels _delay_ms einfach mal eine LED im Sekundentakt
blinken lassen. Den Unterschied zwischen 10Mhz und 1Mhz internem
Takt kann man deutlich sehen.

Autor: Angelika Voß (ange)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Niels ;-)
also auf der Platine ist ein Quartz auf dem steht 16.000H6D
ich nehme an 16 Mhz
das mit zuerst UBRR0H und dann UBRR0L beschreiben ist richtig
was die Fusebits betrifft, die habe ich gestern auf alle möglichen Arten 
versucht auszulesen. Das Problem:
Ponyprog kann ich nicht verwenden, mein Spi-Adapter ist über die 
Parallele Schnittstelle(stk200), das wird nicht unterstützt.
Mit Averdude GUIscheint zwar irgendetwas gelesen zu werden
... reading efuse memory..
...writing outputfile "con"
nur das outputfile kann ich nicht finden

was nun?
Gruß
Angelika

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Angelika Voß wrote:
> @ Niels ;-)
> also auf der Platine ist ein Quartz auf dem steht 16.000H6D
> ich nehme an 16 Mhz

Das heist noch lange nicht, dass der auch verwendet wird.
Einfacher Test: Mittels _delay_ms (welches den delay aus
der angegebenen Taktfrequenz F_CPU berechnet) eine Blinkschleife
bauen und nachsehen ob die Zeiten stimmen können.
Einfach 100 mal _delay_ms(10) aufrufen und LED umschalten.
Ist der Wert für F_CPU korrekt, dann blinkt deine LED alle
1 Sekunde. Läuft der interne Oszillator dann blinkt sie alle
16 Sekunden. Ist deutlich unterscheidbar.

Aber ich muss mich schon wundern.
Wenn du einen 16Mhz Quarz hast, dann solltest du nicht lügen
und hier

#ifndef F_CPU
  #define F_CPU 10000000
#endif

10Mhz angeben. Sicher ist sicher. Solche Zahlen sollten immer
stimmen (auch wenn die tatsächliche Frequenz zb. im AVR-Studio
noch mal eingegeben werden kann). Das hat zwar jetzt keine
Auswirkungen auf deine UART (weil da momentan die Baudrate nicht
von der F_CPU abgeleitet wird), aber es geht ums Prinzip.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Karl heinz Buchegger (kbuchegg)

>machen: Mittels _delay_ms einfach mal eine LED im Sekundentakt
>blinken lassen. Den Unterschied zwischen 10Mhz und 1Mhz internem
>Takt kann man deutlich sehen.

Ja, aber auch nur, wenn man es richtig macht.

http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

MFG
Falk

Autor: Niels Hüsken (monarch35)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Angelika
Vergiss die gui. Die macht desöfteren schonmal probleme. Geh auf 
Kommandozeile und starte avrdude im interactive-mode.

> avrdude -p m128 -c stk200 -t -F

und dann kannst du mit "read lfuse" und "read hfuse" die Fuses auslesen. 
Den Hexadizimalcode musst du in Binär umwandeln (Windows-Taschenrechner) 
und kannst dann Anhand der Fuses-Tabelle in der Atmel-Doku die einzelnen 
Flags bestimmen. Wichtig für die Taktangabe sind die flags für CKSEL und 
CKOPT.

Eine "1" als "High" bedeutet übrigens "unprogrammed"

Autor: Angelika Voß (ange)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Karl heinz Buchegger
ich habe hier 2 Boards und konnte mit der Wartefunktion (danke @Falk) 
herausfinden:
Board1 blinkt bei F_CPU von 16 MHz im Sekundentakt
Board2 ist langsamer
@ Niels
na dann werd ich mich mal an das Auslesen der Fuses machen

Autor: mef (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sollte Dein µC doch nicht mit 10Mhz laufen, dann stimmen die Werte im 
UBRR-Register nicht mehr. Im Datenblatt stehen meistens Tabellen mit 
passenden Werten, Baudraten und Fehlerraten. Ich würde das gleich mal 
anpassen und schauen ob's jetzt geht, vielleicht war das schon der 
Fehler und Du sparst Dir das mit den Fuses.

Für 16Mhz und 2400bd bei 0% Fehler: UBBRxH = 3 und UBBRxL = 64

UBBR berechnet man so: F_OSC / (16*Baudrate) - 1
*   Der Faktor 16, weil die UART 16-fach sampled (sagt man das so?).
*   - 1 weil IMO bis 0 runtergezählt wird.aDo je nach Prozessortakt 
keine ganzen Zahlen herauskommen hat man einen gewissen Fehler, der 0.2% 
nicht überschreiten sollte.

Grüße mef

Autor: Angelika Voß (ange)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@mef
das habe ich schon versucht, leider kein Erfolg

@Niels
bei den zwei Atmega128-Boards mit verschiedener Einstellung hat
das Auslesen der Fusebits hat fogendes ergeben:

        Low Fuse Byte:      High Fuse Byte:   Extendet Fuse Byte:
Board1  00000100            11011001          11111111
Board2  11101110            10000001          11111111

nun werde ich mal das Datenblatt studieren

Autor: Angelika Voß (ange)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich werd' aus dem Datenblatt nicht schlau,
nun habe ich aber getestet von Board2 über serielle Schnittstelle Daten 
an den Rechner zu schicken
Einstellungen: CPU-Takt:  16MHz
               Baudrate:  9600
               8N1
Fusebits wie oben beschrieben,
es funktioniert!!
macht es nun Sinn die EInstellungen der Fusebits von Board2 auf Board1 
zu übertragen?

@Niels lautet der Befehl für das Schreiben z.B. write hfuse?

Autor: Niels Hüsken (monarch35)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Angelika

> write hfuse 0 <byte>

für <byte> beispielsweise 0xa0... Die '0' bedeutet, das offset 0 von der 
basis beschrieben werden soll.

Board1 hat CKSEL 0100 CKOPT 1
und Board2 CKSEL 1110 CKOPT 0

Bei Board 1 bedeutet das laut Tabelle 6 auf Seite 37/38, daß interne 
Resonator auf 8Mhz (tabelle 13) schwingt.

Bei Board 2 ist der externe Crystal-Resonator ab 1Mhz aufwärts 
selektiert  (Tabelle 8) und konfiguriert.

Wenn die Boards auf den externen 16Mhz laufen soll, solltest du auf 
Board1 die Einstellungen von Board2 übernehmen.... sowohl lfuse, als 
auch hfuse

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Angelika Voß wrote:
> Ich werd' aus dem Datenblatt nicht schlau,

Datenblatt, Seite 288

Fuse Low Byte

    Name        Bit     Default
   -----------------------------
    BODLEVEL    7         1
    BODEN       6         1
    SUT1        5         1
    SUT0        4         0
    CKSEL3      3         0
    CKSEL2      2         0
    CKSEL1      1         0
    CKSEL0      0         1


Board1  00000100
Board2  11101110


Bei deinem Board1 sind die CKSEL Bits also so 0100.
Laut Tabelle 6 auf Seite 38, bedeutet dies, dass der
interne RC-Oszillator aktiv ist.

Bei deinem Board2 sind die CKSEL Bits 1110
Laut derselben Tabelle heist das, das dort ein externer
Quarz (external Crystal) verwendet wird.

Die Einstellung external Crystal ist die, die du haben willst.
Kein Wunder dass dein Board1 nicht die vorgegebene Baudrate
erreicht. Der Prozessor arbeitet nicht mit dem Quarz, sondern
läuft immer noch auf dem internen Oszillator.

Autor: Angelika Voß (ange)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heiz Buchegger
vielen Dank es wird mir klarer,
wenn ich nun auch die Einstellung für SUT1..0 von Board2, also laut 
Datenblatt bei CKSEL0 auf 0 somit auf "Chystal Oscillator, fast rising 
power", übernehmen würde, wäre ich damit wahrscheinlich im grünen 
Bereich.
Brownout(Spannungseinbruch)-Detektor ist bei Board2 ausgeschaltet.
d.h. ich kann die Einstellung für Fuse Low Byte (11101110) von Board2 
übernehmen.
ich hoffe das stimmt so,
nun noch eins, wie kann ich das im Interaktive Terminal Mode von Avrdude 
eingeben?

Autor: Niels Hüsken (monarch35)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Angelika Voß wrote:

> nun noch eins, wie kann ich das im Interaktive Terminal Mode von Avrdude
> eingeben?

Die Antwort auf diese Frage hatte ich bereits ein Post vor Herrn 
Bucheggers Posting gegeben.

Autor: Angelika Voß (ange)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ist das dann so ok?
averdude -p m128 -u -c stk200 -t -F
und dann:
averdude> d lfuse
averdude> w lfuse 0 0xee

Autor: Niels Hüsken (monarch35)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Angelika Voß wrote:

> averdude> w lfuse 0 0xee

sollte passen. Die hfuse nicht vergessen! Die beinhaltet nämlich CKOPT.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Niels Hüsken wrote:

> vor Herrn Bucheggers Posting gegeben.

Einfach nur 'Karl Heinz' oder noch einfacher 'Heinz'.
Herr Buchegger, das ist mein Vater :-)

Autor: Angelika Voß (ange)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ist klar,
ich habe hfuse und lfuse geändert,
und das Testprogramm laufen lassen, dass Daten über serielle 
Schnittstelle an den Rechner sendet. Es funktioniert auf beiden Boards!!
Die Werte werden korrekt auf dem Hyperterminal angezeigt.
Ich danke euch allen für euren freundlichen Rat.
Angelika

Autor: Niels Hüsken (monarch35)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:

> Einfach nur 'Karl Heinz' oder noch einfacher 'Heinz'.
> Herr Buchegger, das ist mein Vater :-)

Ist schon klar. Die Nettiquette sagt eindeutig "Im de-Usenet duzt man 
sich". Deshalb gehe ich eigentlich auch immer davon aus, daß das "du" 
okey ist.

Das hier sollte sich allerdings absichtlich etwas "literarisch" 
anhören.... mache ich in R/L mit meinen Freunden auch öfter so :)

Autor: Angelika Voß (ange)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Herr Niels ;)
ich hoffe ich bin Ihnen da nicht über den großen Zehen geschlappt
auf jeden Fall viele Grüsse

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.