#define ASC0_TBUF (*((uword volatile *) 0xFEB0)) kann mir bitte jemand erklären, was dieser Befehl genau bedeutet? danke schön
Eine Anweisung an den Präprozessor, jedes Vorkommen des Bezeichners ASC0_TBUF durch *((uword volatile *) 0xFEB0)) zu ersetzen. Was das dann genau tut, hängt vom Kontext ab, in dem es benutzt wird. Sieht aber sehr nach einem IO-Register aus, das sich über die Speicheradresse 0xfeb0 ansprechen lässt.
Das ist kein Befehl sondern eine Definition, deswegen auch #define *((uword volatile *) ist ein Type-Cast. Du weißt ASC0_TBUF Adresse 0xFEB0 zu.
Das ist kein Befehl, sondern ein Makro des Präprozessors. Der ersetzt auf Textebene jedes Vorkommen von "ASC0_TBUF" durch den dahinterstehenden Text. Und der erzeugt mit einem Typecast aus der Int-Konstante 0xFEB0 einen volatile uword-Pointer und dereferenziert diesen, so daß das einen syntaktisch korrekten lvalue, dem Werte zugewiesen werden können bzw. der auch Werte liefern kann. Damit kannst Du im Programm also schreiben ASC0_TBUF = 1; oder a = ASC0_TBUF; In ersterem Falle wird in die Speicheradresse 0xFEB0 der Wert 1 geschrieben, im anderen Falle wird der Wert, der in der Speicheradresse 0xFEB0 liegt, der Variablen a zugewieden. Es findet in beiden Fällen ein 16-Bit-Zugriff statt. Solche Konstrukte werden verwendet, um "memory-mapped-I/O"-Zugriffe ausführen zu können, bei vielen Controllern kann so mit der eingebauten Peripherie kommuniziert werden.
Progi wrote: > #define ASC0_TBUF (*((uword volatile *) 0xFEB0)) > > kann mir bitte jemand erklären, was dieser Befehl genau bedeutet? > danke schön Wenn das erste Zeichen in einer Zeile in # ist, dann handelt es sich um ein Präprozessor-Makro. In dem Fall also um ein #define #define definiert eine Textersetzung. Überall wo im eigentlichen Quelltext der Text "ASC0_TBUF" vorkommt, wird dieser Text durch den Text "(*((uword volatile *) 0xFEB0))" ersetzt. zb. hier ASCO_TBUF = 5; die Textersetzung liefert (*((uword volatile *) 0xFEB0)) = 5 Worum handelt es sich? Da ist zunächst mal die Zahl 0xFEB0 diese Zahl wird umgecastet zu einem uword volatile Pointer (uword volatile *) 0xFEB0 Damit hat man also einen Zeiger, der auf ein uword zeigt, und dessen Zeigerwert die Adresse 0xFEB0 darstellt. Ugangssprachlich: Ein Zeiger auf die Speicheradresse 0xFEB0, wobei angenommen wird, dass sich an dieser Stelle im Speicher ein uword befindet. Von dieser Speicherstelle wird gelesen/geschrieben indem der Pointer dereferenziert wird. Ein Pointer wird dereferenziert indem man ihm ein * voranstellt: *((uword volatile *) 0xFEB0) Alles zusammen ergibt also: (*((uword volatile *) 0xFEB0)) = 5 und bedeudet: Schreibe an die Speicherstelle 0xFEB0 (und folgende) den Wert 5, wobei beim Schreiben der Wert 5 zu einem uword (also höchstwahrscheinlich ein unsigned word, also 2 Bytes) aufgeblasen wird und demenstprechend 2 Bytes geschrieben werden. Ach ja: Das volatile sorgt noch dafür, dass diese Operation nicht wegoptimiert werden kann, sondern der Zugriff auf jeden Fall gemacht werden muss. Ansonsten könnte der Optimizer bei sowas: ASCO_TBUF = 5; ASCO_TBUF = 7; die erste Zuweisung weg optimieren, da deren Effekt scheinbar durch die zweite Zuweisung sowieso zunichte gemacht wird.
ich habe da eine Funktion für die Ausgabe und zwar:
1 | void ASC0_vSendData(uword uwData) |
2 | {
|
3 | ASC0_TBUF = uwData; // load transmit buffer register |
4 | |
5 | }
|
bei:
1 | ASC0_vSendData ('H'); |
hab ich auch eine Ausgabe beim Hyperterminal. Wenn ich z.B. eine Variable ausgeben mag, z.B, int a = 3000; und ich es so programmier: ASC=_vSendData (a), dann passiert nix und ich hab keine Ausgabe. Ich dachte, dass es vllt. an der Diffinition von ASCO_TBUF liegt...also keine Ahnung
Und was passiert bei ASC0_vSendData (0xa55a); ? Wenn du nur 3000 probiert hast, dann kann es sein, dass nur das untere Byte verarbeitet wird bzw. nicht verarbeitet wird da 0. Konfiguration der Hardware prüfen, etc.
also ich weiß, was mein Fehler war (ganz toll..) hatte beim Hyperterm, die ganze Zeit Pause eingestellt gehabt und wunder mich, warum ich nichts zu sehen bekommen habe...naja Hätt da noch ne Frage und zwar werden bei mir nur die unteren 2 Bytes verarbeitet, also hab ich beim int a = 3000; ASC0_vSendData(a); nur B8 statt BB8 auf dem Bildschirm, weiß vllt. jemand, wie ich das auf 4 Bytes erweiter, denn ASC0_TBUF ist ja nur 16Bit breit..
Ich vermute mal, dass das ASC0_TBUF-Register an sich nur 8 Bit breit ist. Es wird allerdings von der 16-Bit-CPU wie ein 16-Bit-Register angesprochen, wobei die oberen 8 Bits einfach ins Leere laufen.
yalu wrote: > Es wird allerdings von der 16-Bit-CPU wie ein 16-Bit-Register > angesprochen, wobei die oberen 8 Bits einfach ins Leere laufen. ...oder nette Seiteneffekte verursacht. Welchen Prozessor verwendest du?
1 | #include <stdint.h> |
2 | |
3 | #define ASC0_TBUF (*((uint8_t volatile *) 0xFEB0))
|
4 | |
5 | void ASC0_vSendData(uword uwData) |
6 | {
|
7 | ASC0_TBUF = uwData % 0x100; // load transmit buffer (lower byte) |
8 | |
9 | // Hier noch Warteanweisungen einfügen (wenn nötig).
|
10 | |
11 | ASC0_TBUF = uwData / 0x100; // load transmit buffer (upper byte) |
12 | }
|
Du solltest mal nachschauen wie breit (8Bit oder 16Bit) dein ASC0-Register ist. Wenn es tatsächlich 16Bit breit ist, dann ist mein Vorschlag von oben suboptimal weil es in diesem Fall eine Möglichkeit geben muss 16Bit-Worte in einem Rutsch zu schreiben (und die Hardware sich dann um den Rest kümmert).
1 | #define ASC0_TBUF (*((uint8_t volatile *) (0xFEB0 + 1)))
|
2 | // ^^^
|
Edit: Evtl musst du - je nach Endianess - die Adresse modifizieren.
Auszug aus dem User Manual des C16x, um den (oder einen Ableger) es sich hier zu drehen scheint: "Only the number of data bits which is determined by the selected operating mode will actually be transmitted, i.e. bits written to positions 9 through 15 of register S0TBUF are always insignificant." Da über den UART bis zu 9 Bits/Datenwort übertragen werden können, muss auch das ASC0_TBUF-Register mindestens so breit sein. Deswegen wird ein 16-Bit-Register genommen, bei dem die obersten 7 ignoriert werden.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.