Forum: Mikrocontroller und Digitale Elektronik UART empfängt nur <\0>


von Christian (Gast)


Lesenswert?

Hallo,

habe mir hier aus dem Forum und aus dem Internet diverse Sourcecodes 
angeschaut und zusammengebaut, um vom atmega16 per UART an meinen PC 
einen String zu übertragen (in meinem Beispiel "Hello").

Ich bekomm aber nur <\0> oder "sinnlose" Buchstaben und Zeichen 
angezeigt (im HTerm, dem Terminalprogramm das ich zum Anzeigen 
verwende). Ich hab nun natürlich schon gelesen, dass die Baudrate und 
F_CPU richtig gesetzt werden müssen, damit man genau solche "falsche 
Zeichen" verhindern kann. Ich hab da folgenden Code verwendet:
1
#define F_CPU 16000000UL  // Systemtakt in Hz - Definition als unsigned long beachten
2
#define BAUD 14400UL      // Baudrate
3
// Berechnungen
4
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
5
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
6
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
7
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
8
#error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!
9
#endif
10
#include <util/setbaud.h>

Kompiliert wird mein Programm (verwende AVRStudio6). Hier wird über 
einen Parameter F_CPU sowieso nochmal gesetzt (-DF_CPU=16000000). Das 
sollte also passen. Nachdem beim Compilieren auch die #error - Nachricht 
nicht geworfen wird, hab ich gedacht, dass ich eigentlich die richtigen 
Parameter verwende. Der Code, den ich gefunden habe ist:
1
void uart_puts (const char *s)
2
{
3
  do
4
  {
5
    while (!(UCSRA & (1 << UDRE)))
6
    ;
7
8
    // UDR Schreiben startet die Übertragung
9
    UDR = *s;
10
  }
11
  while (*s++);
12
}
13
14
15
void uart_init (void)
16
{
17
  uint16_t ubrr = (uint16_t) ((uint32_t) F_CPU/(16*BAUD) - 1);
18
  
19
  UBRRH = (uint8_t) (ubrr>>8);
20
  UBRRL = (uint8_t) (ubrr);
21
  
22
  // UART Receiver und Transmitter anschalten
23
  // Data mode 8N1, asynchron
24
  UCSRB = (1 << RXEN) | (1 << TXEN);
25
  UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
26
27
  // Flush Receive-Buffer (entfernen evtl. vorhandener ungültiger Werte)
28
  do
29
  {
30
    UDR;
31
  }
32
  while (UCSRA & (1 << RXC));
33
}
34
static inline int uart_putc (const uint8_t c)
35
{
36
  // Warten, bis UDR bereit ist für einen neuen Wert
37
  while (!(UCSRA & (1 << UDRE)))
38
  ;
39
40
  // UDR Schreiben startet die Übertragung
41
  UDR = c;
42
43
  return 1;
44
}
Ich sende dann einfach über uart_puts("Hello").

Ich bin nun ein bisschen ratlos, warum trotz richtiger Baudrate (welche 
ich auch am Terminalprogramm so gewählt habe, nämlich 14400) und der 
F_CPU (welche ja auch lt. Compiler 16000000 sein sollte (mein ATMega16 
hängt auch an einem 16MHz Quarz)) die Zeichen falsch übertragen werden. 
Kann mir jemand einen Denkanstoß geben?

LG Christian

: Verschoben durch Moderator
von Hmm (Gast)


Lesenswert?

>Kann mir jemand einen Denkanstoß geben?
Nun, da das so ein "alltägliches" Problem ist, wäre es sinnvoll wenn Du 
Dir mal all die anderen Threads dazu anschaust. Es ist äusserst 
wahrscheinlich das der passende auch für Dich dabei ist.

von g457 (Gast)


Lesenswert?

> dass die Baudrate und F_CPU richtig gesetzt werden müssen

Hast Du F_CPU richtig(!) gesetzt?

> (mein ATMega16 hängt auch an einem 16MHz Quarz))

Hängt er da nur dran oder nutzt er ihn auch? Falls ja, wie? -> 
überprüfen!

von Sebastian (Gast)


Lesenswert?

Setze #define F_CPU 16000000UL mal testweise auf 1 MHz. Wie mein 
Vorredner andeutet könnte der AVR noch seinen internen 1 MHz 
Quarzoszillator nutzen.

Wenn du dann etwas sinnvolles empfängst musst du die Fuses auf externen 
Quarz umstellen.

von Programmierer (Gast)


Lesenswert?

Christian schrieb:
> #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden

vs.

Christian schrieb:
> uint16_t ubrr = (uint16_t) ((uint32_t) F_CPU/(16*BAUD) - 1);

Fällt dir was auf?

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.