Forum: Mikrocontroller und Digitale Elektronik Erster UART-Versuch


von Donni D. (Gast)


Lesenswert?

Hey Leute,
Ich bin im Moment ein Arduino Nutzer, möchte das Dingen aber jetzt mal 
richtig programmieren da ich auf das Arduino-Zeug nichtmehr so Lust 
habe. Habe mir also Atmel Studio geladen, auch schon paar LED's blinken 
lassen und alles, wollte mich aber nun an den UART wagen. µC ist ein 
atmega328p. Als Programmer benutz ich auch das Arduino UNO Board, dass 
funktioniert auch alles. Hab mit dem Datenblatt eigentlich auch alles 
eingestellt bekommen, dachte ich. Hier zu meinem Problem:

Ich dachte eigentlich, dass meine BAUD auf 9600 eingestellt ist, aber 
dann empfange ich keine Zeichen (HTerm). Ich bekomme ständig FF 
gesendet, auf der BAUD-Rate 115200. Wenn ich auf 9600 stelle passiert 
nichts.. Jetzt bin ich mir nicht sicher ob ich meinen Code so einfach 
auf den Arduino hauen kann, wegen dem Bootloader und so.. Hab F_CPU auf 
16000000 gestellt, da ein 16mhz Quarz auf dem Arduino ist.

Hier aber mal mein Code:
1
#include <avr/io.h>
2
#include <avr/delay.h>
3
4
#define F_CPU 16000000L
5
#define BAUD 9600
6
#define MYUBRR F_CPU/16/BAUD-1
7
8
9
10
int main(void)
11
{
12
  
13
  UART_init(MYUBRR);
14
  
15
    while(1)
16
    {
17
    UART_transmit("a");
18
    _delay_ms(500);
19
    }
20
}
21
22
void UART_init( unsigned int ubrr ) 
23
{
24
  // BAUD-Rate
25
  UBRR0H = (unsigned char) (ubrr >> 8);
26
  UBRR0L = (unsigned char) ubrr;
27
  
28
  // Senden/Empfangen aktivieren
29
  UCSR0B = (1 << RXEN0) | (1 << TXEN0);
30
  
31
  // 2 Stop-Bits und 8 Data-Bits
32
  UCSR0C = (1 << USBS0) | (3 << UCSZ00);
33
}
34
35
void UART_transmit( int send ) 
36
{
37
  // Warte auf leeren Transmitter-Buffer
38
  while( !(UCSR0A & (1 << UDRE0)));
39
  UDR0 = send;
40
}

Wo habe ich Fehler gemacht?

von später (Gast)


Lesenswert?

Moin,

ich glaube die Zeile sollte

#define MYUBRR F_CPU/(16*BAUD)-1

geschrieben werden.

von Donni D. (Gast)


Lesenswert?

Ich hab sie geändert, funktioniert aber immernoch nicht.
Eigentlich bewirkt das 2 mal dividieren ja den gleichen Effekt wie 
einmal dividieren und einmal multiplizieren.
Ich habe jetzt mal alle BAUD-Raten probiert und bekomme mit folgenden 
Zeichen empfangen:
57600
115200
128000
256000
Immer bekomme ich 0xFF. Noch wer eine Idee?

von Steffen H. (avrsteffen)


Lesenswert?

Ich glaube du lädst UBRR0L mit dem "oberen" 8Bit und UBRR0H mit den 
"unteren" 8Bit?

Donni Donis schrieb:
1
 // BAUD-Rate
2
   UBRR0H = (unsigned char) (ubrr >> 8);
3
   UBRR0L = (unsigned char) ubrr;

..sollte es nicht eher so aussehen?
1
 // BAUD-Rate
2
   UBRR0H = (unsigned char) ubrr;
3
   UBRR0L = (unsigned char) (ubrr >> 8);


Gruß Steffen

von Donni D. (Gast)


Angehängte Dateien:

Lesenswert?

Hab es mal geändert gehabt, aber keine Besserung..
Ich hab den Teil so aus dem Datenblatt, im Anhang ist ein Bild davon.

Mir fällt grad auf das meine delay-Zeiten auch nicht stimmem, könnte da 
ein zusammenhang bestehen? Bin wie gesagt noch recht neu dabei, hatte 
vorher nur Arduino-Sprache benutzt..

von Steffen H. (avrsteffen)


Lesenswert?

Simulier es doch mal. Dann siehst du doch was passiert.

von Donni D. (Gast)


Lesenswert?

So, hab es mal simuliert und glaube den Fehler gefunden zu haben. 
Erstmal das Problem mit den ddelay-Zeiten. Hatte ausversehen die 
includes vor den difnes, jetzt geht das schonmal.

Die 9600er BAUD läuft an sich auch, aber nur wenn ich der 
UART_init-Methode direkt "103" übergebe (Ist der Wert der rauskommen 
muss). Wenn ich jedoch MYUBRR übergebe klappt es wieder nicht.. aber die 
wird doch richtig berechnet odern icht?

von Michael H. (mha1)


Lesenswert?

Du setzt für die Kommunikation 8N2 (2 Stopbits). Hast Du das auch 
Empfängerseite so eingestellt ? Typisch wäre eher 8N1 (1 Stopbit).

UCSR0C = (3 << UCSZ00);

Die Funktion UART_transmit würde ich mit einem char als Parameter 
deklarieren.

void UART_transmit( char send )

Als mögliche Ursache fallen mir sonst noch verstellte Fuses ein. Wenn 
diese falsch eingestellt sind, kann die aktuelle Taktrate der Prozessors 
ganz anders als erwartet sein (1 MHz, 2 MHz, 8 MHz, ...). Damit wäre 
auch die eingestellte Baudrate eine andere. Die Fuses sind abhängig vom 
verwendetet ATMega Baustein auf dem Arduino und daher abängig vom 
Arduino Board.

von Donni D. (Gast)


Lesenswert?

Hab das mal gemacht mit dem char und jetzt funktioniert auch erstmal 
alles, auch mit den 2 StopBits.
Hier nochmal der Code:
1
#define F_CPU 16000000UL
2
#define BAUD 9600
3
#define MYUBRR F_CPU/16/BAUD-1
4
5
#include <avr/io.h>
6
#include <avr/delay.h>
7
8
int main(void)
9
{
10
  
11
  UART_init(103);
12
  
13
    while(1)
14
    {
15
    UART_transmit('a');
16
    _delay_ms(500);
17
    }
18
}
19
20
void UART_init( unsigned int ubrr ) 
21
{
22
  // BAUD-Rate
23
  UBRR0H = (unsigned char) (ubrr >> 8);
24
  UBRR0L = (unsigned char) ubrr;
25
  
26
  // Senden/Empfangen aktivieren
27
  UCSR0B = (1 << RXEN0) | (1 << TXEN0);
28
  
29
  // 2 Stop-Bits und 8 Data-Bits
30
  UCSR0C = (1 << USBS0) | (3 << UCSZ00);
31
}
32
33
void UART_transmit( char send ) 
34
{
35
  // Warte auf leeren Transmitter-Buffer
36
  while( !(UCSR0A & (1 << UDRE0)));
37
  UDR0 = send;
38
}
Jetzt übergebe ich an die init-Methode ja die 103, dann geht alles. Wenn 
ich MYUBRR übergebe, geht nichts.. Woran kann das liegen?

von Praktiker (Gast)


Lesenswert?

Donni Donis schrieb:
> Woran kann das liegen?

Wahrscheinlich werden in der UART_init im zweiten Fall falsche Werte in 
die Register geschrieben. Was packt der Prozessor denn dann z.B. in 
UBRR0H und UBRR0L. Das sollte dir der Simulator verraten.

von Fabian O. (xfr)


Lesenswert?

In C musst Du jede Funktion deklarieren, bevor Du sie verwendest. Das 
heißt, Du musst entweder UART_init() und UART_transmit() vor main() 
definieren, oder Du deklarierst vor main() ihren Prototyp:
1
// ...
2
3
void UART_init( unsigned int ubrr );
4
void UART_transmit( char send );
5
6
int main(void)
7
{
8
  // ...
9
}
10
11
void UART_init( unsigned int ubrr ) 
12
{
13
  // ...
14
}
15
16
void UART_transmit( char send ) 
17
{
18
  // ...
19
}

Nur dann weiß der Compiler den korrekten Datentyp, den er der Funktion 
übergeben muss und wandelt ihn ggf. richtig um. Vor solchen Fällen warnt 
der Compiler aber auch (sofern Du mit dem Schalter -Wall kompilierst, 
falls nicht: Unbedingt setzen!). Nimm Compiler-Warnungen ernst, sie sind 
in den allermeisten Fällen wichtig.

von Donni D. (Gast)


Lesenswert?

Fabian, daran lags :)
Jetzt funktioniert das senden schonmal :)
Vielen Dank für die Hilfe von euch! Super Forum :)
Werde mich nachher mal um das Empfangen kümmern und gucken ob da alles 
klappt, wenn nicht, melde ich mich noch einmal! :)

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.