Forum: Mikrocontroller und Digitale Elektronik Atmega128 UART Problem


von Florian S. (didi34)


Lesenswert?

Ich habe ein Programm mit Hilfe das Tutorials programmiert, welches den 
berühmten String "HALLO WELT" sendet. Ich empfange aber nichts. Habe 
auch schon mit dem Oszi gemessen, es kommt gar nichts, sollte also kein 
Baudraten-Fehler sein. Vielleicht sind die Register falsch. Ich habe das 
Programm aus dam Tutorial, welches aber für den Atmega8 ist. Der hat nur 
eine UART-Schnittstelle, Der Atmega128 hat zwei also habe ich den Code 
geändert. Vielleicht ist da ein Fehler passiert. Hoffentlich kann mir 
jemand helfen.
1
/* 
2
  UART-Init: 
3
Berechnung des Wertes für das Baudratenregister 
4
aus Taktrate und gewünschter Baudrate
5
*/
6
 
7
#ifndef F_CPU
8
/* In neueren Version der WinAVR/Mfile Makefile-Vorlage kann
9
   F_CPU im Makefile definiert werden, eine nochmalige Definition
10
   hier wuerde zu einer Compilerwarnung fuehren. Daher "Schutz" durch
11
   #ifndef/#endif 
12
 
13
   Dieser "Schutz" kann zu Debugsessions führen, wenn AVRStudio 
14
   verwendet wird und dort eine andere, nicht zur Hardware passende 
15
   Taktrate eingestellt ist: Dann wird die folgende Definition 
16
   nicht verwendet, sondern stattdessen der Defaultwert (8 MHz?) 
17
   von AVRStudio - daher Ausgabe einer Warnung falls F_CPU
18
   noch nicht definiert: */
19
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"
20
#define F_CPU 4000000UL  // Systemtakt in Hz - Definition als unsigned long beachten 
21
                         // Ohne ergeben sich unten Fehler in der Berechnung
22
#endif
23
 
24
#define BAUD 9600UL      // Baudrate
25
 
26
// Berechnungen
27
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
28
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
29
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
30
 
31
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
32
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
33
#endif 
34
#include <avr/io.h> 
35
//#define F_CPU 1000000 /* evtl. bereits via Compilerparameter definiert */
36
//#define BAUD 9600
37
#include <util/setbaud.h>
38
void uart_init(void)
39
{
40
  UBRR1H = UBRR_VAL >> 8;
41
  UBRR1L = UBRR_VAL & 0xFF;
42
 
43
  UCSR1B |= (1<<TXEN);  // UART TX einschalten
44
  UCSR1C = (1<<UMSEL1)|(1<<UCSZ1)|(1<<UCSZ0);  // Asynchron 8N1 
45
}
46
/* ATmega16 */
47
int uart_putc(unsigned char c)
48
{
49
    while (!(UCSR1A & (1<<UDRIE1)))  /* warten bis Senden moeglich */
50
    {
51
    }                             
52
 
53
    UDR1 = c;                      /* sende Zeichen */
54
    return 0;
55
}
56
 
57
 
58
/* puts ist unabhaengig vom Controllertyp */
59
void uart_puts (char *s)
60
{
61
    while (*s)
62
    {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen(Terminator)" */
63
        uart_putc(*s);
64
        s++;
65
    }
66
}
67
int main()
68
{
69
  uart_init();
70
  while( 1 ) 
71
  {
72
73
  uart_puts("HALLO WELT");
74
}
75
76
}

von Stefan E. (sternst)


Lesenswert?

1) UMSEL1 willst du sicher nicht haben.

2) Zustand der M103C-Fuse?

von Florian S. (didi34)


Lesenswert?

>1) UMSEL1 willst du sicher nicht haben.

Was soll ich statt dem nehmen?

>2) Zustand der M103C-Fuse?

M103C ist nicht gesetzt.

von Uwe (de0508)


Lesenswert?

Hallo Florian,

hast Du das passende Datenblatt [1] offen ?

Dann findest Du mit dem Setzen von UMSEL1 in UCSR1C, das der"Synchronous 
Operation" eingeschaltet ist.


Link
[1] www.atmel.com/Images/doc2467.pdf

von Oliver J. (skriptkiddy)


Lesenswert?

>while (!(UCSR1A & (1<<UDRIE1)))  /* warten bis Senden moeglich */
Das Flag, welches du eigentlich pollen willst, heißt UDRE1 und nicht 
UDRIE1.
Sollte aber keine Rolle spielen, weil beide 5 sind.

von Florian S. (didi34)


Lesenswert?

Das heißt ich soll es einfach nicht setzen oder?

von Oliver J. (skriptkiddy)


Lesenswert?

Florian Schuller schrieb:
> Das heißt ich soll es einfach nicht setzen oder?
Ja.

von John (Gast)


Lesenswert?

UCSR1B |= (1<<TXEN);  // UART TX einschalten

Hier fehlt noch was!
Damit du empfangen kannst musst du auch den Empfänger auf enable setzen 
:D
Also:

UCSR1B |= (1<<RXEN1) |(1<<TXEN1);  // Enable RX, TX

von John (Gast)


Lesenswert?

ups du willst ja nur senden, dann vergiss das oben...

von Thomas R. (Gast)


Lesenswert?

Kann jemand bestätigen, dass der Code hier funktioniert??? Will einen 
Fehler in der Software ausschließen.

Habe den Code so übernommen und nur die Baudrate (19200) und die 
Taktfrequenz (8MHz) angepasst. Für meine Zwecke benötige ich nur die 
Sendefunktion (UART1).

von Holli (Gast)


Lesenswert?

Hat jemand den vorgegeben Beispielcode so umkonfiguriert, dass sowohl 
das Senden, als auch das Empfangen möglich ist?

Zurzeit kann ich nur über die UART-Schnittstelle Senden.

von Karl H. (kbuchegg)


Lesenswert?

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART
http://www.mikrocontroller.net/articles/AVR-Tutorial:_UART

Aber Vorsicht.
Die Tutorien sind für einen anderen AVR geschrieben. Das Prinzip ist 
zwar dasselbe, die Registernamen heissen aber leicht anders. Unter 
anderem, weil der M128 2 UARTS hat.

: Bearbeitet durch User
von Holli (Gast)


Lesenswert?

Danke erstmal für die links. Diese habe ich bereits verwendet. Ich kann 
senden, als auch einzelne Zeichen empfangen.

Mein Ziel ist es nun, die Einstellungen und Informationen des 
Bluetooth-Moduls über den ATI-Befehl auszulesen.

Kann mir jemand Tipps geben, wie ich da am besten vorgehe?

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.