mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Versteh die Anweisung nicht..


Autor: Progi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#define ASC0_TBUF              (*((uword volatile *) 0xFEB0))

kann mir bitte jemand erklären, was dieser Befehl genau bedeutet?
danke schön

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Rooney Bob (rooney)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist kein Befehl sondern eine Definition, deswegen auch #define

*((uword volatile *) ist ein Type-Cast.

Du weißt ASC0_TBUF Adresse 0xFEB0 zu.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Progi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich habe da eine Funktion für die Ausgabe und zwar:
void ASC0_vSendData(uword uwData)
{
  ASC0_TBUF    = uwData; //  load transmit buffer register

}

bei:
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

Autor: die ??? (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Progi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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..

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: die ??? (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?
#include <stdint.h>

#define ASC0_TBUF (*((uint8_t volatile *) 0xFEB0))

void ASC0_vSendData(uword uwData)
{
  ASC0_TBUF    = uwData % 0x100; //  load transmit buffer (lower byte)

  // Hier noch Warteanweisungen einfügen (wenn nötig).

  ASC0_TBUF    = uwData / 0x100; //  load transmit buffer (upper byte)
}

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).

Autor: die ??? (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
  #define ASC0_TBUF (*((uint8_t volatile *) (0xFEB0 + 1)))
  //                                                ^^^

Edit: Evtl musst du - je nach Endianess - die Adresse modifizieren.

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.