UART empfängt nur <\0>

Gast #2892349
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
Gast #2892350
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.
Gast #2892353
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!
Gast #2892363
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren