mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Array of Register


Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich möchte gerne in einem Array verschiedene DDRs hinterlegen, weiß aber 
nicht genau, wie ich das ganze hinbekommen kann. Ich stelle mir die 
Struktur wie folgt vor:
const XXXX    ddr_array[]  = {DDRB, DDRB, DDRC, DDRD, DDRB};
const XXXX    port_array[] = {DDRB, DDRB, DDRC, DDRD, DDRB};
const uint8_t bit_array[]  = { 1,   2,    2,    2,     5};

Kann mir sagen, welchen Typ ich statt XXXX eintragen muss und ob das 
überhaupt möglich ist?

Ziel ist, in einer schleife verschiedene Bits an oder aus zu schalten, 
z.B.

port_array[i] |= (1 << bitarray[i]);

in der iom8.h bin ich über diese Zeile gestolpert, die mich aber auch 
nicht weitergebracht haben:
/* Port D */
#define PIND  _SFR_IO8(0x10)
#define DDRD  _SFR_IO8(0x11)
#define PORTD  _SFR_IO8(0x12)

/* Port C */
#define PINC  _SFR_IO8(0x13)
#define DDRC  _SFR_IO8(0x14)
#define PORTC  _SFR_IO8(0x15)

/* Port B */
#define PINB  _SFR_IO8(0x16)
#define DDRB  _SFR_IO8(0x17)
#define PORTB  _SFR_IO8(0x18)

Vielen Dank und viele Grüße,
Martin

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In C kann man keine Variablen an feste Adressen legen, wie du es
vorhast (in C++ sehr wohl).

Du kannst aber statt eines Feldes mit den Registern ein Feld
mit Zeigern auf die Register anlegen, und dann über diese
Zeiger zugreifen:
const uint8_t  *  p_ddr_array[]  = {&DDRB, &DDRB, &DDRC, &DDRD, &DDRB};
const uint8_t  *  p_port_array[] = {&PORTB, &PORTB, &PORTC, &PORTD, &PORTB};
const uint8_t bit_array[]  = { 1,   2,    2,    2,     5};
...
*p_port_array[i] |= ...

Oder C++ nehmen. :-)

Autor: Florian Löffler (Firma: Studi) (muut) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PINx, DDRx und PORTx sind reine Adressen, die im I/O-Bereich des AVR 
liegen.

Also brauchst du als Datentyp theroretisch einen Zeiger auf nen 
8bit-Wert, also uint8_t*
Bin mir aber grad nicht sicher, alle Versuche auf eigene Gefahr :-)

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die Antwort!

ICh denke, ich werde mich mit dem Adressen Array zufrieden geben, das 
scheint mir für meine Anwendung die beste Lösung zu sein.

C++ habe ich zwar auch mal zu Unizeiten ein wenig gelernt, aber da sind 
die Grundlagen noch weiter weg, als in C :-)

Schönen Abend noch,
Martin

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Martin schrieb:
> Kann mir sagen, welchen Typ ich statt XXXX eintragen muss und ob das
> überhaupt möglich ist?

schau doch einfach nach wie DDRA definiert ist und übernimm den typ.
da steht _SFR_IO8
jetzt such das Makro, und so weiter. Irgend wann steht da auch mal ein 
Datentyp dran

auf jeden Fall darf das volatile nicht vergessen werden.

Abgesehen davon: wozu soll das gut sein?

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

Bewertung
0 lesenswert
nicht lesenswert
Martin schrieb:

> ICh denke, ich werde mich mit dem Adressen Array zufrieden geben, das
> scheint mir für meine Anwendung die beste Lösung zu sein.

Wenn du schon so etwas machst, dann solltest du in deinem C-Buch über 
Strukuren nachlesen
struct portBit {
   volatile uint8_t * ddr_register;
   volatile uint8_t * port_register;
   uint8_t            pin;
};

und dir dann daraus die Arrays (oder Variablen) bauen
struct portBit leds[] =
    { { &DDRB, &PORTB, 1<<PB0 },
      { &DDRB, &PORTB, 1<<PB1 },
      { &DDRC, &PORTC, 1<<PC5 },
      { &DDRD, &PORTD, 1<<PD4 },
    };

#define ARRAY_SIZE(x)   ( sizeof(x) / sizeof(*x) )

void blink_once( struct portBit * led )
{
  *(led->port_register) |= led->pin;
  _delay_ms( 100 );
  *(led->port_register) &= ~led->pin;
  _delay_ms( 100 );
}

int main()
{
  uint8_t i;

  // configure all led pins as output
  for( i = 0; i < ARRAY_SIZE( leds ); ++i )
    *(leds[i].ddr_register) |= leds[i].pin;

  // turn on all leds
  for( i = 0; i < ARRAY_SIZE( leds ); ++i )
    *(leds[i].port_register) |= leds[i].pin;

  _delay_ms( 1000 );

  // now turn off all leds in the given order
  for( i = 0; i < ARRAY_SIZE( leds ); ++i ) {
    *(leds[i].port_register) &= ~leds[i].pin;
    _delay_ms( 500 );
  }

  while( 1 ) {
    for( i = 0; i < ARRAY_SIZE( leds ); ++i )
      blink_once( &leds[i] );
  }
}

Autor: Andreas Ferber (aferber)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:
>
> const uint8_t  *  p_ddr_array[]  = {&DDRB, &DDRB, &DDRC, &DDRD, &DDRB};
> 

Bitte
volatile uint8_t * const p_ddr_array[] = { ... }

Sonst ist erstens das Pointerziel anstatt des Pointers "const", und 
zweitens kann einem ohne das "volatile" der Optimizer da böse Streiche 
spielen.

Andreas

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für eure weiteren Antworten.

Besonders der Kommentar von Karl Heinz hat mich noch mal weitergebracht. 
Im Hinterkopf gab es wohl noch so etwas wie strukturen, warum ich in 
diesem Zusammenhang nicht drauf gekommen bin, ist mir noch schleierhaft.

Dann füge ich noch mal einen DimValue hinzu und habe alles, was ich für 
eine LED benötige zusammen :-)

Schönen Abend,
Martin

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.