Forum: Mikrocontroller und Digitale Elektronik Zeiger auf Array


von Siegfried S. (dieleena)


Lesenswert?

Hallo,

Habe folgendes Array angelegt.

unsigned int *Zeiger;

union
{
  struct
  {
    unsigned Bit7:1;    //  Bit  7
    unsigned Bit6:1;    //  Bit  6
    unsigned Bit5:1;    //  Bit  5
    unsigned Bit4:1;    //  Bit  4
    unsigned Bit3:1;    //  Bit  3
    unsigned Bit2:1;    //  Bit  2
    unsigned Bit1:1;    //  Bit  1
    unsigned Bit0:1;    //  Bit  0
  };
   unsigned char Byte;
} BusTransfer volatile BusSpiOutput[MaxBusSpiInOut];

nun möchte ich mit einem Zeiger auf das Array zugreifen.

Zeiger = BusSpiOutput;
oder
Zeiger = BusSpiOutput[];
oder
Zeiger = BusSpiOutput[0];

leider funktioniert dieses nicht.

Gruß Siegfried

von Pete K. (pete77)


Lesenswert?

Bustransfer *Zeiger;

von Siegfried S. (dieleena)


Lesenswert?

Hallo,
funktioniert leider nicht.
Gruß Siegfried

von Simon K. (simon) Benutzerseite


Lesenswert?

Siegfried Saueressig wrote:
> Hallo,
> funktioniert leider nicht.
> Gruß Siegfried

Tolle Fehlerbeschreibung. Fast so gut wie die Beschreibung des Problems.

von Siegfried S. (dieleena)


Lesenswert?

Hallo,
Zeiger = BusSpiOutput; -> Error [1131] type mismatch in assignment

Zeiger = BusSpiOutput[]; -> Error: syntax error

Zeiger = BusSpiOutput[8]; -> Error [1131] type mismatch in assignment

Gruß Siegfried

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Versuch mal das hier:

1
union BUS
2
{
3
  struct
4
  {
5
    unsigned Bit7:1;    //  Bit  7
6
    unsigned Bit6:1;    //  Bit  6
7
    unsigned Bit5:1;    //  Bit  5
8
    unsigned Bit4:1;    //  Bit  4
9
    unsigned Bit3:1;    //  Bit  3
10
    unsigned Bit2:1;    //  Bit  2
11
    unsigned Bit1:1;    //  Bit  1
12
    unsigned Bit0:1;    //  Bit  0
13
  };
14
  unsigned char Byte;
15
};
16
17
18
volatile union BUS BusSpiOutput[MaxBusSpiInOut];
19
20
union BUS *Zeiger;
21
22
Zeiger = BusSpiOutput;

Du solltest versuchen, nicht zu viele Deklarationen und Definitionen in 
einem Rutsch zu erledigen.

Obiges deklariert zunächst mal den Typen union BUS, dann ein Array aus 
Elementen dieses Typs (als volatile deklariert, weil Du's anscheinend 
brauchst) und dann einen Pointer auf diesen Typ.

Und dann wird dem Pointer die Anfangsadresse des Arrays zugewiesen.

Was genau bezweckst Du hiermit:
1
union
2
{
3
//...
4
} BusTransfer volatile BusSpiOutput[MaxBusSpiInOut];

Ist "BusTransfer" eine compilerspezifische Erweiterung? Oder wolltest Du 
den Union-Typ so nennen?
(analog zum von mir eingeführten Typ union BUS )

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Machs doch so, das geht immer   ;-)
1
Zeiger = (unsigned int*)(void*)&BusSpiOutput[0];

Oder gib dem Zeiger den richtigen Typ:
1
union BusTransfer
2
{
3
  struct
4
  {
5
    unsigned Bit7:1;    //  Bit  7
6
    unsigned Bit6:1;    //  Bit  6
7
    unsigned Bit5:1;    //  Bit  5
8
    unsigned Bit4:1;    //  Bit  4
9
    unsigned Bit3:1;    //  Bit  3
10
    unsigned Bit2:1;    //  Bit  2
11
    unsigned Bit1:1;    //  Bit  1
12
    unsigned Bit0:1;    //  Bit  0
13
  };
14
  unsigned char Byte;
15
} ;
16
17
BusTransfer BusSpiOutput[4];
18
BusTransfer *Zeiger;
19
20
Zeiger = BusSpiOutput;
21
// oder
22
Zeiger = &BusSpiOutput[0];



EDIT: schade, Zweiter...

von G. O. (aminox86)


Lesenswert?

Siegfried Saueressig wrote:
> Hallo,
>
> Habe folgendes Array angelegt.
>
> unsigned int *Zeiger;
>
> union
> {
>   struct
>   {
>     unsigned Bit7:1;    //  Bit  7
>     unsigned Bit6:1;    //  Bit  6
>     unsigned Bit5:1;    //  Bit  5
>     unsigned Bit4:1;    //  Bit  4
>     unsigned Bit3:1;    //  Bit  3
>     unsigned Bit2:1;    //  Bit  2
>     unsigned Bit1:1;    //  Bit  1
>     unsigned Bit0:1;    //  Bit  0
>   };
--------------- Komponentenname fehlt ------
>    unsigned char Byte;
> } BusTransfer volatile BusSpiOutput[MaxBusSpiInOut];
>
> nun möchte ich mit einem Zeiger auf das Array zugreifen.
>
> Zeiger = BusSpiOutput;
> oder
> Zeiger = BusSpiOutput[];
> oder
> Zeiger = BusSpiOutput[0];
>
> leider funktioniert dieses nicht.
>
> Gruß Siegfried

1)In der union BusTransfer ist nur eine Komponente benannt.
2)Ein Zeiger auf das Array BusSpiOutput muss vom Typ BusTransfer sein, 
zB BusSpiOutput *BusTransferzgr.
3) Die Zuweisung von BusSpiOutput an Zeiger funktioniert nicht, da 
*Zeiger den Typ int hat, s.o.

mfg

von Siegfried S. (dieleena)


Lesenswert?

Hallo, guten morgen,
mußte gestern kurzfristig abbrechen.

Vorab vielen Dank für alle Informationen.

->"BusTransfer" eine compilerspezifische Erweiterung<- ist eine von mir 
frei gewählte Bezeichnung. Dieses ergibt sich aus

#ifndef BusTransfer
#define BusTransfer extern
#endif

->volatile<- habe ich genutzt, da in einem anderem Beitrag dieses mir 
geraten wurde.

Möchte mal kurz mein Programm beschreiben.

BusSpiOutput[..] ist der Buffer(Master) für die über SPI verbunde Slave 
Board
Jedes Slave Board hat eine Kapazität von 4 Byte / 32 Bits.

Um im Proramm die Übersicht zu behalten habe ich in einer *.h diesen 
Code angelegt.
union
{
  struct
  {
    unsigned Bit7:1;    //  Bit  7
.......
    unsigned Bit0:1;    //  Bit  0
  };
   unsigned char Byte;
} BusTransfer volatile BusSpiOutput[MaxBusSpiInOut];

in einer weiteren *.h habe ich diesen Code angelegt
#define Lampe_7 BusSpiOutput[0].Bit7
#define Lampe_0 BusSpiOutput[0].Bit0

In der *.c ist dann folgendes.
Lampe_7 = 1;
Lampe_1 = 1;
Nach meiner Sicht habe ich somit mehr Kontrolle im Programm, denn ich 
brauche nicht immer zu überlegen, an welchem Bit und Byte Lampe_1 
"angeschlossen ist.

Soweit funktioniert es prima.

Nachträglich habe ich folgendes eingefügt, um an die Adresse zu 
gelangen, unter der die Variable "BusSpiOutput[..]" steht. Leider waren 
meine Anläufe erfolglos.

Den Zeiger benötige ich, um meine Befehle in ein separaten Speicher 
"Stabel" abzulegen.
Möchte damit erreichen, das Lampe_1 30 sek. eingeschaltet ist, danach 
ausschaltet und erst dann Lampe_7 für 20 sek. eingeschaltet wird.
Mit einer delay schleife kann ich das nicht machen (hoffe das ich es 
richtig darstelle) der PIC in der Schleife sich drehen würde, bis die 
Zeit abgelaufen ist, und somit andere Programmteile nicht bearbeitet 
würden.

Es fehlt mir noch einen Gedanken, wie ich genau definiere, das "Lampe_7" 
an "BusSpiOutput[0].Bit7" ist.
Der Zeiger Liefert mir nur die erste Adresse des Array (BusSpiOutput) 
zurück.

Werde jetzt mal die Beispiele einsetzen, und sehen wie weit ich komme.
Für weitere Info's bin ich sehr aufgeschlossen.

Gruß Siegfried

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> Es fehlt mir noch einen Gedanken, wie ich genau definiere, das "Lampe_7"
> an "BusSpiOutput[0].Bit7" ist.
> Der Zeiger Liefert mir nur die erste Adresse des Array (BusSpiOutput)
> zurück.

Es gibt keine Möglichkeit, Elemente eines Bitfeldes über Pointer 
anzusprechen. Es gibt nur Pointer auf das gesamte Bitfeld, aber nicht 
welche auf Elemente des Bitfeldes.

Wenn man sich aber mal 'ne halbe Stunde Zeit nimmt, und sich mit 
logischen Operationen und Bitmasken beschäftigt, stellt man fest, daß 
man für die einfache Abbildung einzelner Bits auch gar kein Bitfeld 
benötigt. Wenn Du Dir eh' nur ein Element des Bitfeldes merken möchtest, 
reicht es auch, dessen Nummer aufzuheben.

Die kann dann mit dem bei AVR-C-Programmieren ubiquitären 
Shift-Operatoren verwendet werden.

Bei allen Varianten wird bei 0 angefangen zu zählen, die 8 Bits eines 
Bytes werden von 0 bis 7 und nicht von 1 bis 8 numeriert.

Bit setzen:

  Port |= 1 << Bitnummer;

Bit löschen:

  Port &= ~(1 << Bitnummer);

Bit abfragen:

  Port & (1 << Bitnummer)

Hier bool'sche Auswertung anwenden, also auf Null bzw. nicht Null 
testen.
Also:

  if (Port & (1 << Bitnummer))
  {
    // bit ist gesetzt
  }
  else
  {
    // bit ist nicht gesetzt
  }

oder

  if (Port & (1 << Bitnummer) == 0)
  {
    // bit ist nicht gesetzt
  }

oder

  if (!(Port & (1 << Bitnummer))
  {
    // bit ist nicht gesetzt
  }

Aber nicht

  if (Port & (1 << Bitnummer) == 1)
  {
    // bit ist gesetzt
  }

Das schlägt fehl, wenn Bitnummer nicht 0 ist.


Wenn man das verinnerlicht hat, braucht man keine Bitfelder mehr, um auf 
einzelne Bits zuzugreifen.

Und schon gar keine unions aus Bitfeldern und anderen Typen.

von Siegfried S. (dieleena)


Lesenswert?

Hallo,
@Rufus t. Firefly (rufus) (Moderator)
Danke für die schnelle Antwort.
Ein Schritt bin ich weiter. Habe deine Code eingesetzt. Soweit ist alles 
in Ordnung.
Habe bewust diesen Weg mit den Bit/Byte gewählt (wenn auch erfahrene 
Programmier dieses anderst lösen würden) um ein Bit unter einem Namen 
ansprechen können. Derzeitige Ausbaustufe ist 1 Master Board und 10 
Slave Board. Das wären bei allen Slave Boards 320 Bit's. Die Bit's 
werden einzeln abgearbeitet. Ich denke, das ich hier mit mehr überblick 
habe.
Es ist schon ein großer Vorteil für mich, das ich zumindest die Adresse 
des ersten Byte's bekomme.
Mit den Bit's Bezeichnungen muß ich noch überlegen, wie ich das 
bewältige.

Gruß Siegfried

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Nun, wenn Du mit Bitnummern arbeitest, kannst Du die natürlich auch 
unter einem Namen ansprechen, da gäbe es verschiedene Möglichkeiten. 
Einerseits könntest Du die Bitnummern als Präprozessor-#define mit Namen 
versehen

  #define LAMPE_GRUEN 1
  #define LAMPE_GELB 2
  #define LAMPE_ROT 3

und diese Namen anstelle der Nummern verwenden:

  Port |= 1 << LAMPE_GRUEN;

Du kannst natürlich auch den Bit_wert_ definieren

  #define LAMPE_GRUEN (1 << 0)
  #define LAMPE_GELB (1 << 1)
  #define LAMPE_ROT (1 << 2)

und den dann verwenden:

  Port |= LAMPE_GRUEN;

von Siegfried S. (dieleena)


Lesenswert?

Hallo,
@Rufus t. Firefly (rufus) (Moderator)
ein guter Ansatz für mich. Du hast mir viel Arbeit abgenommen.
eine bescheidene Frage. Besteht die Möglichkeit, auch die Byte Nummer 
einzubauen?
  #define LAMPE_GRUEN (1 << 0)
  #define LAMPE_GELB (1 << 1)
  #define LAMPE_ROT (1 << 2)
Gruß Siegfried

von Siegfried S. (dieleena)


Lesenswert?

Hallo,
@Rufus t. Firefly (rufus) (Moderator)
@Lothar Miller (lkmiller)
habe jetzt folgendes gemacht.

*.h
#ifndef List
#define List extern
#endif

List unsigned int *FifoZeiger;
List unsigned int FifoBit;

#define LAMPE_XY_01() { FifoZeiger = (unsigned 
int*)(void*)&BusSpiOutput[3]; FifoBit=1; }
#define LAMPE_XY_02() { FifoZeiger = (unsigned 
int*)(void*)&BusSpiOutput[3]; FifoBit=2; }
#define LAMPE_XY_03() { FifoZeiger = (unsigned 
int*)(void*)&BusSpiOutput[3]; FifoBit=3; }

*.c
LAMPE_XY_01();
FifoAdresse[FifoCount] = FifoZeiger;
FifoByte[FifoCount++] = FifoBit;
..
LAMPE_XY_03();
FifoAdresse[FifoCount] = FifoZeiger;
FifoByte[FifoCount++] = FifoBit;

hoffe, das ich das mein Ziel erreicht habe. Jetzt kann ich in der 
"define" festlegen, an welcher Adresse ich das Bit X bearbeiten will.
Ich möchte/muß die "Befehle" zwischenspeichern und diese über einen 
Timer-Interrupt schrittweise abarbeiten.

Gruß Siegfried

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.