Forum: Mikrocontroller und Digitale Elektronik UART Problem


von Matthias S. (Gast)


Lesenswert?

Hi,
Ich weiß, das Problem UART ist scho oft besprochen worden, aber ich 
komme einfach nicht weiter.

Ich habe einen ATMEGA8 auf dem STK600 mit einem externen Quarz 
(7.23728H4F - der ja eigentlich für UART Übertragungen geeignet sein 
soll) und Fusebits müssten alle passen.

Wenn ich jetzt ein einzelnes Zeichen mit dem uC übertrage, kommt auf dem 
Rechner ein anderes heraus.
Komischer Weiße passiert auch folgendes: Wenn ich zwei mal das selbe 
Zeichen übertrage kommt zweimal das selbe "falsche" Zeichen am PC an. 
Wenn ich jedoch die zwei gleichen Zeichen übertrage mit einem 
_delay_ms(100) dazwischen, kommen 2 unterschiedliche Zeichen am PC an. 
(Vielleicht hilft das...)

Hier mein Code:
1
#include <avr/io.h>
2
#include <stdlib.h>
3
#include <util/delay.h>
4
5
/* 
6
  UART-Init: 
7
Berechnung des Wertes für das Baudratenregister 
8
aus Taktrate und gewünschter Baudrate
9
*/
10
 
11
#ifndef F_CPU
12
/* In neueren Version der WinAVR/Mfile Makefile-Vorlage kann
13
   F_CPU im Makefile definiert werden, eine nochmalige Definition
14
   hier wuerde zu einer Compilerwarnung fuehren. Daher "Schutz" durch
15
   #ifndef/#endif 
16
 
17
   Dieser "Schutz" kann zu Debugsessions führen, wenn AVRStudio 
18
   verwendet wird und dort eine andere, nicht zur Hardware passende 
19
   Taktrate eingestellt ist: Dann wird die folgende Definition 
20
   nicht verwendet, sondern stattdessen der Defaultwert (8 MHz?) 
21
   von AVRStudio - daher Ausgabe einer Warnung falls F_CPU
22
   noch nicht definiert: */
23
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"
24
#define F_CPU 7372800UL  // Systemtakt in Hz - Definition als unsigned long beachten 
25
//#define F_CPU 16000000UL
26
                         // Ohne ergeben sich unten Fehler in der Berechnung
27
#endif
28
 
29
#define BAUD 9600UL      // Baudrate
30
 
31
// Berechnungen
32
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
33
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
34
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
35
 
36
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
37
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
38
#endif 
39
40
41
/* UART-Init Bsp. ATmega16 */
42
 
43
void uart_init(void)
44
{
45
  UCSRB |= (1<<TXEN);  // UART TX einschalten
46
  UCSRC |= (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);  // Asynchron 8N1 
47
 
48
  UBRRH = UBRR_VAL >> 8;
49
  UBRRL = UBRR_VAL & 0xFF;
50
}
51
52
int main(void) {
53
54
  DDRB &= ~(1 << PB0);  //Taster
55
  DDRD |= (1<<PD7);    //LED
56
  DDRD &= ~(1<<PD0);    //RxD
57
  DDRD |= (1<<PD1);    //TxD
58
  
59
  uart_init(); 
60
61
  while(1) {
62
        while (!(UCSRA & (1<<UDRE))) {}
63
        UDR = 'j';
64
65
      _delay_ms(10);
66
67
        while (!(UCSRA & (1<<UDRE))) {}
68
        UDR = 'j';
69
  }
70
71
  return 0;
72
}

irgendeine Idee?

von Karl H. (kbuchegg)


Lesenswert?

Matthias S. schrieb:
> Hi,
> Ich weiß, das Problem UART ist scho oft besprochen worden, aber ich
> komme einfach nicht weiter.

Dann kennst du ja auch die Standardantworten :-)

> Ich habe einen ATMEGA8 auf dem STK600 mit einem externen Quarz
> (7.23728H4F - der ja eigentlich für UART Übertragungen geeignet sein
> soll) und Fusebits müssten alle passen.

'Müssten' ist nicht gut genug.
Hast du kontrolliert ob der Quarz verwendet wird?

von Helmut -. (dc3yc)


Lesenswert?

Gib uns weitere Infos: welches Zeichen wird empfangen, wenn du was 
sendest? Verwendest du RS232 oder TTL-Signale zum Rechner?

von Karl H. (kbuchegg)


Lesenswert?

Matthias S. schrieb:

> Ich habe einen ATMEGA8 auf dem STK600 mit einem externen Quarz
> (7.23728H4F


> #define F_CPU 7372800UL  // Systemtakt in Hz - Definition als unsigned

Ziffernsturz! (bzw. da fehlt eine 2, dafür ist eine 0 zu viel)
Was steht wirklich auf deinem Quarz drauf?

von H.Joachim S. (crazyhorse)


Lesenswert?

7.23728H4F
#define F_CPU 7372800UL

Das sind schon mal 2%, kann schon eng werden.
Ich nehme aber mal an, dass du dich ober nur verschrieben hast.

Ohne jetzt alles durchzugehen, es müsste am Ende so aussehen (list-File)

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600
UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x2F;

Ja ich weiss, so macht man es nicht :-), der Wizard aber.

von Matthias S. (Gast)


Lesenswert?

Jep ich hab mich oben verschrieben am Quarz steht: 7.3728H4F.

Der Quarz müsste schon verwendet werden, ich hab das mit dem 
Testprogramm aus der "AVR Checklist" getestet, außerdem hab ich das 
ganze schon auf dem Steckbrett mit eigener Schaltung gehabt und da wird 
der uC auch mit dem Quarz getaktet und alles funkt bis auf den UART. 
(bin aber jetzt für den UART doch aufs STK600 zurückgekehrt, bis er 
funkt)

RS232 oder TTL? Wie meinen? und wie kann ich das Überprüfen? Ich habs 
zwischendurch scho mal mit nem Oszi gemessen und da kommt eigentlich 
genau das raus was der PC anzeigt...

wenn ich ein 'h' sende kommt ',' raus, und bei 'a' kommt 'h' raus.

und bei meinem Baudraten rechner kommt bei der Frequenz des Quarzes (die 
auch im Code steht) genau 0% Fehler heraus...

mfg Matthias

von Matthias S. (Gast)


Lesenswert?

@H.joachim Seifert: wo seh ich das List-File oder ist das einfach der 
Code vom Wizard?

von Matthias S. (Gast)


Lesenswert?

und noch etwas zum Thema falsche Baud Rate: Ich habs schon mit mehreren 
Einstellungen und Quarzen probier: (intern, externer 4MHZ, Clock vom 
Oszi und immer mehr oder weniger das selbe. Schließlich bin ich zu 
diesem Quarz, weil er die besten Fehlertoleranzen hat (laut 
Baud-Raten-Rechner und priv. Bauteilbestand ;)

von g457 (Gast)


Lesenswert?

Hast Du die jeweiligen Einstellungen auch überprüft? Da [1] gibts neben 
zahlreichen anteren Tipps auch ein kurzes Beispieltestprogrämmchen.

HTH

http://www.mikrocontroller.net/articles/AVR_Checkliste#UART.2FUSART

von H.Joachim S. (crazyhorse)


Lesenswert?

Wenn du deinen Compiler anschmeisst, gibts normalerweise ein list-file.
Da kann man dann mal reinschauen.

von Karl H. (kbuchegg)


Lesenswert?

g457 schrieb:
> Hast Du die jeweiligen Einstellungen auch überprüft? Da [1] gibts neben
> zahlreichen anteren Tipps auch ein kurzes Beispieltestprogrämmchen.
>
> HTH
>
> http://www.mikrocontroller.net/articles/AVR_Checkliste#UART.2FUSART

Ich denke das ihm das in diesem Fall ausnahmsweise nicht viel helfen 
wird. Meine Vermutung geht dahin, dass seine Taktfrequenz, aus welchem 
Grund auch immer, ein klein wenig daneben liegt, so dass man diesen 
Unterschied nicht sehen wird.

Ev. ist der Mega sogar noch auf 8Mhz intern gefust. Die Differnz zu 
7.3Mhz wird man mit freiem Auge nicht mehr sehen können. Meine 
Vorgehensweise wäre: Fuses doppelt und dreifach kontrollieren. 2tes oder 
3tes Augenpaar einen Blick drauf werfen lassen.
Gezielt den µC auf 1Mhz intern umfusen. Mittels _delay kontrollieren, ob 
das auch wirklich so ist. Dann auf externen QUarz fusen, wieder 
kontrollieren. Gegentest machen: Quarz rausziehen

von Matthias S. (Gast)


Lesenswert?

@H.joachim Seifert
Ich benutz AVRStudio4 und irgendwie find ich das List file nicht.

von Matthias S. (Gast)


Lesenswert?

Fusebits (so wies im AVR Studio drin steht):

SUT_CKSEL: Ext. Crystal/Resonator Medium Freq.; Start-up time: 1K CK + 
0ms
HIGH: 0xD9
LOW: 0xEC

von g457 (Gast)


Lesenswert?

Wenn man länger zusieht (mit der Stoppuhr in der Hand), dann sollte man 
7.4MHz und 8MHz schon auseinandernhalten können :-)

Aber ich hab noch eine mögliche Fehlerquelle gefunden:

> #ifndef F_CPU
[..]
> #define F_CPU 7372800UL
[..]
> #endif

Ist das F_CPU möglicheweise schon (mit einem falschen Wert) definiert?

von Julian O. (juliano)


Lesenswert?

Ist der Quarz zufällig gesockelt? Ich nehme den Quarz ganz gerne raus um 
zu checken ob er verwendet wird. Läuft der uC ohne Quarz nicht mehr los 
(bzw. lassen sich die Fuses z.B. nicht mehr auslesen) wird der Quarz 
verwendet und die Fuse-Einstellung stimmt

von Karl H. (kbuchegg)


Lesenswert?

g457 schrieb:

> Ist das F_CPU möglicheweise schon (mit einem falschen Wert) definiert?


Ja, das ist gut. Könnte sein.
Auf die mögliche Fehlerquelle wird ja auch im Kommentar in diesem Block 
hingewiesen.

-> Beim Compilileren müsste man die Warnung sehen!
Sieht man sie nicht, kommt dieser #define gar nicht zum Zug.

Es gibt auch Leute, die mit einer derartigen #ifdef Absicherung extrem 
unglücklich sind. Eben genau aus diesem Grund.

von Matthias S. (Gast)


Lesenswert?

@g457: Es war wirklich die definition von F_CPU falsch. Aber wo wird die 
noch gesetzt? In den Project Options habe ich nichts eingetragen und 
sonst auch nicht...

von Hc Z. (mizch)


Lesenswert?

Matthias S. schrieb:
> HIGH: 0xD9
> LOW: 0xEC

Das ist für einen Quarz im Bereich von 0,9 bis 3 MHz (CKSEL3..1 = 110, 
CKOPT = 1) gültig, also nicht für den eingesetzten.  Es dürfte 
wahrscheinlich nicht der eigentliche Grund sein (schwingt meistens 
trotzdem auf der Sollfrequenz), aber unsauber ist es schon.

von Micha B. (mbcontrol)


Lesenswert?

Matthias S. schrieb:
> Fusebits (so wies im AVR Studio drin steht):
>
> SUT_CKSEL: Ext. Crystal/Resonator Medium Freq.; Start-up time: 1K CK +
> 0ms
> HIGH: 0xD9
> LOW: 0xEC

Probier doch mal ...
SUT_CKSEL: Ext. Crystal/Resonator High Freq; Start-up time: 16K CK + 
64ms

Gruß MB

von Karl H. (kbuchegg)


Lesenswert?

Matthias S. schrieb:
> @g457: Es war wirklich die definition von F_CPU falsch. Aber wo wird die
> noch gesetzt? In den Project Options habe ich nichts eingetragen und
> sonst auch nicht...

Dann musst du in Zukunft deinen Compiler-Output besser studieren.

#include <util/delay.h>


delay.h schreibt (genau wie dein Code) eine Warnung hin, dass F_CPU 
nicht definiert wurde und definiert sich selber eines.

Die Definition von F_CPU ist ein ständiges Ärgernis.
Du solltest dir angewöhnen, diese Einstellung ausschliesslich und nur 
über die Project Options zu machen. Nur dort kannst du gewährleisten, 
dass die immer und überall übereinstimmt!

Und am besten wäre ganz am Anfang im Hauptfile
1
#ifndef F_CPU
2
#error "F_CPU: Bitte in den Project Options die Taktfrequenz eintragen"
3
#endif
4
5
#include <avr/io.h>
6
....

dann hätte dieser Spuk schnell ein Ende.

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.