Sehr geehrte Community,
mein Name ist Christian und ich bin 16 Jahre alt.
Seit ca. 2 Wochen beschäftige ich mich mit dem ATmega8515 und der
Programmierung des AVR's in C (benutze das AtmelStudio).
Beim Lernen und bei Problemen mit der Programmiersprache C hat mir
dieses Forum und generell das Internet schon oft weitergeholfen.
Nun möchte ich versuchen ein DMX-Signal mit meinem AVR zu empfangen.
Das Protokoll von DMX ist mir bekannt.
Jedoch bin ich auf eine Initialisierung der USART gestoßen, die ich
leider nicht durchschauen kann. Und bitte darum, um eine einfache
Erklärung des Programmtextes (ich habe auch selbst schon im Internet
gesucht, die Funktion des Programmblocks jedoch trotzdem nicht
verstanden).
Vielen Dank im Voraus,
Christian.
Hier der Programmtext:
void init_USART()
{
UBRRL = 1;
UBRRH = 0;
UCSRC = (1<<URSEL)|(3<<UCSZ0);
UDR = 0;
UCSRA = 0;
UCSRB = (1<<RXCIE)|(1<<RXEN);
}
Hallo Christian,
Die Informationen die dir fehlen findest du im Datenblatt bzw. der Doku
des µCs.
Diese Funktion setzt Bits in den UART-Registern über die der UART
konfiguriert wird, welche Bedeutung diese Bits haben steht, wie gesagt,
in der Doku. (Mit dem Lesen der Doku muss man sich ganz einfach
anfreunden wenn man µCs programmieren will).
Vom Syntax er ist dir aber grundsätzlich klar was hier passiert
(Bitshift, bitweises Oder und so), oder?
Hi
>Jedoch bin ich auf eine Initialisierung der USART gestoßen, die ich>leider nicht durchschauen kann. Und bitte darum, um eine einfache>Erklärung des Programmtextes (ich habe auch selbst schon im Internet>gesucht, die Funktion des Programmblocks jedoch trotzdem nicht>verstanden).
Dir ist aber bekannt, das im Datenblatt vom ATMega8515 Codebeispiele zur
Initialisierung und auch zum Senden und Empfangen sind?
MfG Spess
Vielen Dank für die schnellen Antworten.
Mir ist bewusst das ich die UART mittels dem Setzen eines Bits an einer
bestimmten Stelle Konfigurieren kann.
Ich weis dass, das UBRR-Register aus 12-Bits besteht,
unterteilt in:
UBRRL (enthält die 8 unteren Bits)
UBRRH (enthält die 4 oberen Bits)
Zusatz:
(DMX-Baudrate=250000Bd)
(CPU Frequenz=8MHz mit externem Quarz)-> Fusebits sind richtig
eingestellt.
Die Zahl die in dieses Register übertragen werden muss berechnet sich
dann nach folgender Formel (CPU-Frequenz/(Baudrate*16-1))
in diesem Fall wäre das Ergebnis "2".
Im Quellcode steht nun:
UBRRL = 1; -> Bedeutet das bei UBRR1 ein Bit gesetzt wird ?
UBRRH = 0; -> Bedeutet dass, das gesamte Register 0 ist?
Somit würde das Register im Binärsystem so aussehen : 000000000010 =
2(in Dezimal)
Habe ich das Alles richtig verstanden ?
Oder mache ich einen Denkfehler?
Christian Karle schrieb:> Vielen Dank für die schnellen Antworten.>> Mir ist bewusst das ich die UART mittels dem Setzen eines Bits an einer> bestimmten Stelle Konfigurieren kann.
Gut
>> Ich weis das das UBRR-Register aus 12-Bits besteht,> unterteilt in:> UBRRL (enthält die 8 unteren Bits)> UBRRH (enthält die 4 oberen Bits)
Ja, Diese Unterteilung ist aber ein technisches Detail.
Wichtig ist: es ist ein 12 Bit Wert.
Die eigentliche Frage ist: Was besagt der Wert, was macht er? wie wird
er berechnet?
> Die Zahl die in dieses Register übertragen werden muss berechnet sich> dann nach folgender Formel (CPU-Frequenz/(Baudrate*16-1))
SChau dir nochmal genau deine Vorlage an, von der du die Formel her
hast. Wo genau stehen die -1?
Ist das
1
CPU_Frequenz
2
--------------------
3
Baudrate * 16 - 1
oder steht dort
1
CPU_Frequenz
2
-------------------- - 1
3
Baudrate * 16
Beides ist nicht dasselbe!
> UBRRL = 1; -> Bedeutet das bei UBRR1 ein Bit gesetzt wird> UBRRH = 0;
Nö, das bedeutet, dass da nicht 2, sondern 1 als Ergebnis der Berechnung
in das UBRR Register geladen wird (sieh die beiden Einzelregister als
notwendiges Übel an. Das UBRR Register ist die logische Zusammenfassung
der beiden, so dass wir von einem 16 Bit Wert reden können, der in ein
Register geladen wird. UBRR ist ein uint16_t, den du aber aus
technischen Gründen in 2 Stück 8-Bit Happen beschreiben musst.)
Hi
>Die Zahl die in dieses Register übertragen werden muss berechnet sich>dann nach folgender Formel (CPU-Frequenz/(Baudrate*16-1))>in diesem Fall wäre das Ergebnis "2".
Deine Formel ist falsch. Richtig: CPU-Frequenz/(Baudrate*16)-1.
Und das ergibt für UBRR 1.
>UBRRL = 1; -> Bedeutet das bei UBRR1 ein Bit gesetzt wird
Ja, Bit0.
>Somit würde das Register im Binärsystem so aussehen : 000000000010 =>2(in Dezimal)
Nein. wenn das Register 1 enthalten soll darf nur Bit0 gesetzt sein ->
0b000000000001.
MfG Spess
Also ich habe noch einmal nachgeschaut die Formel ist:
CPU_Frequenz
-------------------- - 1
Baudrate * 16
Somit wäre das Ergebnis "1" Binär= 000000000001 = 1(in Dezimal)
Ok, den Teil mit dem UBRR-Register verstehe ich jetz.
Muss UBRRH unbedingt mit UBRRH=0; angegeben werden, oder darf dieser
Teil auch einfach weggelassen werden und die Bits sind Automatisch "0"?
An nächster Stelle steht dann:
UCSRC = (1<<URSEL)|(3<<UCSZ0);
Bedeutet das ein Bit bei URSEL gesetzt wird und die Zahl
3(Dezimalsystem)= 11 im Binärsystem um 0 Stellen (also um UCSZ0(da
erstes Bit)) verschoben wird. Somit ergibt sich eine Framerate von
8-Bits(steht in der Tabelle im Datenblatt). Beide Werte werden danach
per "oder" verknüpft und in das UCSRC-Register geschrieben.
Die Funktion von (1<<URSEL) verstehe ich jedoch nicht...
Im Datenblatt steht dazu:
Bit 7 – URSEL: Register Select
Diese Bit wählt zwischen einem Zugriff auf das UCSRC oder dass UBRRH
Register aus. Es wird als 1 gelesen, wenn das UCSRC Register gelesen
wird. Das URSEL Bit muss 1 sein, wenn in das UCSRC Register geschrieben
wird.
Hier im Forum gibt es wirklich tolle Leute :)
Vielen, vielen Dank das Ihr mich so toll unterstützt :)
Christian Karle schrieb:> Ok, den Teil mit dem UBRR-Register verstehe ich jetz.> Muss UBRRH unbedingt mit UBRRH=0; angegeben werden, oder darf dieser> Teil auch einfach weggelassen werden und die Bits sind Automatisch "0"?
Du ahnst es schon :-)
Die Antwort lautet: Was steht dazu im Datenblatt?
> An nächster Stelle steht dann:>> UCSRC = (1<<URSEL)|(3<<UCSZ0);>> Bedeutet das ein Bit bei URSEL gesetzt wird und die Zahl> 3(Dezimalsystem)= 11 im Binärsystem um 0 Stellen (also um UCSZ0(da> erstes Bit)) verschoben wird. Somit ergibt sich eine Framerate von> 8-Bits(steht in der Tabelle im Datenblatt). Beide Werte werden danach> per "oder" verknüpft und in das UCSRC-Register geschrieben.>> Die Funktion von (1<<URSEL) verstehe ich jedoch nicht...
Atmel hat Register-Adressen gespart.
UBRRH und UCSRC sind vom Programm aus an der selben Stelle im Speicher.
WEnn das Programm also an diese Stelle in den Speicher schreibt, muss es
eine Möglichkeit geben, wie man angeben kann "Ich meine jetzt das UBRRH
Register" bzw. "Ich meine jetzt das UCSRC Register".
Genau das macht das URSEL Bit.
Christian Karle schrieb:> Ich weis dass, das UBRR-Register aus 12-Bits besteht,> unterteilt in:> UBRRL (enthält die 8 unteren Bits)> UBRRH (enthält die 4 oberen Bits)
Grundsätzlich sind alle Register dieses µCs 8 Bit breit.
Wenn man mal mehr als 8 Bit braucht, dann werden diese aus mehreren
Registern zusammengesetzt.
Das 12 Bit breite UBRR-Register gibt es also "in Hardware" nicht, dieses
wird aus 2 Registern, eben UBRRL und UBRRH zusammengesetzt.
Grundsätzlich simmt das mit den oberen und untern Bits aber.
In c kann man (teilweise) auch direkt 12 (16) Bits auf UBRR setzen, da
kümmert sich dann der Kompiler um die Aufteilung auf UBRRL und UBRRH
(nur falls dir das mal irgendwo unterkommt).
> Im Quellcode steht nun:>> UBRRL = 1; -> Bedeutet das bei UBRR1 ein Bit gesetzt wird ?> UBRRH = 0; -> Bedeutet dass, das gesamte Register 0 ist?>> Somit würde das Register im Binärsystem so aussehen : 000000000010 => 2(in Dezimal)> Oder mache ich einen Denkfehler?
Einen kleinen. Die 1 ist Dezimal, also 0000 0001 binär.
In UBBRH + UBRRL steht somit 0000 0000 0000 0001.
Ok, wenn ich das richtig verstanden habe heißt das so viel wie:
(1<<URSEL)
Wenn dieses Bit gesetzt ist kann ich in das UCSRC-Register schreiben.
Dies ist ja von mir erwünscht, da ich ja die Framerate einstellen
möchte.
Wenn dieses Bit nicht gesetzt ist kann ich in das UBRR-Register
schreiben?
Da ich ja schon das UBBR-Register beschrieben habe(da vorher das Bit
nicht gesetzt war) und nun die Framerate einstellen möchte setzte ich
zum weiter Programmieren(also zum Einstellen der Framerate) das Bit für
URSEL.
Entschuldigung, das ich jetzt vielleicht "dumm" frage aber für Anfänger
ist das Datenblatt doch eher schwer verständlich...
Christian Karle schrieb:> Ok, wenn ich das richtig verstanden habe heißt das so viel wie:> (1<<URSEL)> Wenn dieses Bit gesetzt ist kann ich in das UCSRC-Register schreiben.> Dies ist ja von mir erwünscht, da ich ja die Framerate einstellen> möchte.> Wenn dieses Bit nicht gesetzt ist kann ich in das UBRR-Register> schreiben?
Genau.
UBRRH und UCSRC sind aus Sicht des Programms dasselbe.
Du könntest genausogut schreiben
1
UBRRH=(1<<URSEL)|(3<<UCSZ0);
und würdest trotzdem ins UCSRC schreiben.
UBRRH und UCSRC sind im Speicher an derselben Stelle angeordnet. Quasi 2
Variablen, die zwar verschieden heißen, aber eigentlich dasselbe sind,
weil sie im Speicher an derselben Stelle liegen.
Nur durch die Angabe des Registernamens kann man die beiden (auf diesem
µC-Typ) nicht unterscheiden.
In der nächsten Zeile wird nun UDR=0; gesetzt.
Im Datenblatt gibt es jedoch keine Tabelle oder Funktion für diesen
Zustand...
Wird also durch den Befehl UDR=0; Binär einfach nur 00000000 in das
Register geschrieben?
Und wenn ja, welche genaue Funktion besitzt dieses Register. Habe schon
im Datenblatt nachgelesen, aber werde daraus nicht schlau...ich glaub
mir fehlt an dieser Stelle Vorwissen...
Danach wird gleich noch UCSRA = 0; gesetzt.
Im Datenblatt steht das beide Befehle, soweit ich das verstanden habe
voneinander abhängig sind.
Ich verstehe aber nicht was hier genau passiert, bzw. zu was das gut
ist.
Hi
>In der nächsten Zeile wird nun UDR=0; gesetzt.>Im Datenblatt gibt es jedoch keine Tabelle oder Funktion für diesen>Zustand...
Ist ja auch Unsinn. UDR ist das Register in das du Daten schreibst die
du Senden willst und aus dem du Daten liest die empfangen wurden. Das
hat in der Initialisierung nichts verloren.
>Danach wird gleich noch UCSRA = 0; gesetzt.
Genau solcher Blödsinn. Nach einem Reset (auch nach dem Einschalten)
brauchst du das Register für dein Vorhaben nicht anfassen.
MfG Spess
Christian Karle schrieb:> In der nächsten Zeile wird nun UDR=0; gesetzt.> Im Datenblatt gibt es jedoch keine Tabelle oder Funktion für diesen> Zustand...>>> Wird also durch den Befehl UDR=0; Binär einfach nur 00000000 in das> Register geschrieben?
Zuweisung ist Zuweisung.
Wird an UDR 0 zugewiesen, wird binär 0b00000000 ins Register
geschrieben.
> Und wenn ja, welche genaue Funktion besitzt dieses Register.
Das ist in dem Fall (weil es eine Zuweisung ist) das Senderegister.
Alles was du diesem Register zuweißt, wird rausgesendet. In diesem Fall
eben ein Byte mit dem Wert 0
> Danach wird gleich noch UCSRA = 0; gesetzt.
Was soviel bedeutet wie: alle gesetzten Bits in UCSRA werden gelöscht.
Welche Bits sind in UCSRA? Alles was durch ein 1 Bit in UCSRA aktiviert
worden wäre, wird damit wieder deaktiviert.
> Im Datenblatt steht das beide Befehle, soweit ich das verstanden habe> voneinander abhängig sind.
Kann man so nicht sagen.
Ja und nein.
Beim Versenden könnten theoretisch Fehler auftreten, die durch
entsprechende Bits in UCSRA angezeigt werden würden.
> Ich verstehe aber nicht was hier genau passiert, bzw. zu was das gut> ist.
Er schickt ein 0-Byte raus und setzt dann die UART wieder zurück.
Karl Heinz schrieb:> Er schickt ein 0-Byte raus und setzt dann die UART wieder zurück.
Nö.
Moment mal.
Er schickt kein 0 Byte raus.
Denn der Transmitter ist zu diesem Zeitpunkt nicht eingeschaltet.
Daher: Panikzuweisung um auf Nummer sicher zu gehen, dass das Register
auch wirklich 0 ist. Reichlich sinnlos.
Ok, also das kann ich dann weglassen :) Hab mich auch schon gewundert
warum das gelöscht werden soll... wahrscheinlich eh nur zur Sicherheit
oder so...
Dann noch zu letzten Zeile:
UCSRB = (1<<RXCIE)|(1<<RXEN);
Bedeutet das Interrupts erlaubt werden falls ein Bit am USART ankommt
indem das Bit RXCIE gesetzt wird. Das aktuelle Programm wird dann
unterbrochen und der Controller springt in den Programmteil ISR. sei()
muss global erlaubt sein und die Header-Datei <avr/interrupt.h> muss
eingebunden sein. Zum Schluss wird der USART dann noch als Empfänger
eingestellt indem das Bit RXEN gesetzt wird. Beide werden per "oder"
verknüpft und in das Register geschrieben.
Ist das Alles so richtig ?