Forum: Mikrocontroller und Digitale Elektronik UART in C - Problem


von Freddy (Gast)


Lesenswert?

Hallo. :)

einfache Frage, folgender CODE:
1
/*
2
 * UART_Test.c
3
 *
4
 * Created: 08.04.2014 14:17:40
5
 *  Author: Freddy
6
 */
7
#define F_CPU 16000000
8
9
#include <avr/io.h>
10
#include <stdlib.h>
11
#include <util/delay.h>
12
13
14
15
int main(void)
16
{
17
  init_uart();
18
    while(1)
19
    {
20
    send_uart();
21
    _delay_ms(1000);
22
    }
23
}
24
25
void init_uart(){
26
  
27
  //setze BAUD-Wert
28
  UBRRL =  103;  //9600
29
  
30
  //Frame Format konfigurieren: 8n1
31
  //Tx und Rx aktivieren
32
  UCSRB = (1<<RXEN) | (1<<TXEN);
33
  UCSRC = (1<<UCSZ1) | (1<<UCSZ0) | (0<<UMSEL);
34
}
35
36
void send_uart(){
37
  
38
  while (!(UCSRA & (1<<UDRE)))
39
  {
40
  }
41
  UDR = 'x';
42
}

Wenn ich mein PC dran hänge, dann kommt im 1s - Takt zweimal eine Null.. 
Warum? Das sollte doch alles passen oder?

Hab die RegisterKonfiguration aus dem Datenblatt.

Danke! Viele Grüße!

von Karl H. (kbuchegg)


Lesenswert?

Welcher µC?


Die hier
> #define F_CPU 16000000
stimmen und sind auch geprüft? Macht dein µC tatsächlich 16Mhz?

von Hubert G. (hubertg)


Lesenswert?

Kontroller?
Fehler beim beschreiben des UCSRC? UMSEL fehlt.

von Thomas E. (thomase)


Lesenswert?

Hubert G. schrieb:
> Kontroller?
> Fehler beim beschreiben des UCSRC? UMSEL fehlt.
Nein. URSEL!
Aber raten wir doch erstmal, was für ein Controller das ist.

( ) Atmega8
( ) Atmega16
( ) Atmega32

Die URSEL-befreiten haben ja UMSEL0 und UMSEL1.

mfg.

: Bearbeitet durch User
von Freddy (Gast)


Lesenswert?

Ja tut mir leid, das habe ich vergessen.

Ist ein Atmega8 :)

Das URSEL ist standart mäßig 1 und das UMSEL 0... beide werte stimmen 
mit dem was ich konfigurieren möchte überein.

Ich möchte eine 8n1 bei 9600 b/s einrichten :)


Wegen der Frequenz, auf das Herz genau vlt nicht, aber mit dem Oszi 
gemessen lieg ich 50Hz daneben..

Grüße!

von Karl H. (kbuchegg)


Lesenswert?

Freddy schrieb:
> Ja tut mir leid, das habe ich vergessen.
>
> Ist ein Atmega8 :)
>
> Das URSEL ist standart

standard

> mäßig 1

wo findet sich das in deinem Code wieder?

Wenn du UCSRC einen neuen Wert zuweist, hast du URSEL definitiv nicht 
angegeben. Das musst du aber, denn sonst gilt diese Zuweisung als 
Zuweisung an UBRRH.

von g457 (Gast)


Lesenswert?

> Das URSEL ist standart mäßig 1

Fehlt trotzdem. Im Zweifelsfalls einfach das Datenplatt nochmals lesen.

HTH

von Freddy (Gast)


Lesenswert?

1
UCSRC = (1<<UCSZ1) | (1<<UCSZ0) | (0<<UMSEL) | (0<<UMSEL) | (1<<URSEL);

Wäre dass dann so quasi korrekt? :)

Danke für die Hilfe!

von Thomas E. (thomase)


Lesenswert?

Freddy schrieb:
>
1
> UCSRC = (1<<UCSZ1) | (1<<UCSZ0) | (0<<UMSEL) | (0<<UMSEL) | (1<<URSEL);
2
>
>
> Wäre dass dann so quasi korrekt? :)
Ja. Aber da die UCSZ-Werte ohnehin 1 sind, kannst du dir das Ganze auch 
sparen.

mfg.

: Bearbeitet durch User
von Paul B. (paul_baumann)


Lesenswert?

Die Ursel und das Umsel,
die hatten einen Streit:
Wer wohl am Besten sendet,
wer wohl am Besten sendet,
zur schönen Maien-zei-heit-heit
zur schönen Maien-Zeit....

;-)
MfG Paul

(ich bin ein großer Fan von schönen Variablen -und Registernamen)

: Bearbeitet durch User
von Freddy (Gast)


Lesenswert?

Thomas Eckmann schrieb:
> Ja. Aber da die UCSZ-Werte ohnehin 1 sind, kannst du dir das Ganze auch
> sparen.

Okay, aber dann wär ja auch die Angabe der UMSEL und URSEL Werte 
überflüssig.. Die sind standardmäßig ja auch entsprechend gesetzt.

MfG

von Thomas E. (thomase)


Lesenswert?

Freddy schrieb:
> Thomas Eckmann schrieb:
>> Ja. Aber da die UCSZ-Werte ohnehin 1 sind, kannst du dir das Ganze auch
>> sparen.
>
> Okay, aber dann wär ja auch die Angabe der UMSEL und URSEL Werte
> überflüssig.. Die sind standardmäßig ja auch entsprechend gesetzt.

Darum geht es nicht. Vergiss das UMSEL. Das schaltet eine Funktion im 
UART und steht per Default auf Asynchron. Das ist das, was du brauchst.

Das URSEL-Bit schaltet aber keine Funktion im UART, sondern steuert den 
Zugriff auf UBRRH und UCSRC. Diese Register haben dieselbe(!) Adresse.
Wenn URSEL 1 ist, geht der Wert ins UCSRC, wenn es 0 ist, ins UBRRH. Per 
Default ist dieses Bit eins. Wenn man zuerst das UCSRC setzt, braucht 
man sich nicht darum kümmern. Man darf nur nicht das ganze Byte 
zuweisen.
> UCSRC = (1<<UCSZ1) | (1<<UCSZ0) | (0<<UMSEL) = 0x06;
Damit ist URSEL nämlich 0!

Es dürfen nur die Bits geändert werden:
1
UCSRC |= (1<<UCSZ1) | (1<<UCSZ0;

oder
1
UCSRC = (1 << URSEL) | (1<<UCSZ1) | (1<<UCSZ0;

Sonst landet das Byte im UBRRH und setzt es in diesem Fall auf 6. Welche 
Baudrate du dann hast, kannst du selber ausrechnen. Die, die du haben 
haben willst auf jeden Fall nicht.

Nach einem Zugriff auf UBRRH, für das der Maximalwert 15 ist und kein 
normaler Mensch einzelne Bits setzt, wird das URSEL automatisch auf 0 
gesetzt.
1
UBRRH = 7;

Damit ist das Bit7, also URSEL, 0 und der Wert geht ins UBRRH.

Deswegen ist es grundsätzlich keine gute Idee, das URSEL beim Schreiben 
nicht explizit zu setzen.

mfg.

: Bearbeitet durch User
von Freddy (Gast)


Lesenswert?

Ahh! Ich verstehe! Sehr eingängige und klare Erklärung! :)
Danke!

Das URSEL bit ist quasi eine Art Steuerbit das sozusagen eine Art 
Switch-Funktion hat zwischen den Registern!
Und da ich das "|=" nich hatte hat es logischerweise das URSEL immer 0 
gesetzt und dadurch den Wert 6 ins BAUD-Bestimmende Register UBRR 
geschrieben...

Macht echt total sinn!

Vielen Dank! :)
Ich probier das mal!

von Freddy (Gast)


Lesenswert?

EDIT:!

Grandios! Läuft. Danke! :)

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.