Forum: Mikrocontroller und Digitale Elektronik Array of Register


von Martin (Gast)


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:
1
const XXXX    ddr_array[]  = {DDRB, DDRB, DDRC, DDRD, DDRB};
2
const XXXX    port_array[] = {DDRB, DDRB, DDRC, DDRD, DDRB};
3
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:
1
/* Port D */
2
#define PIND  _SFR_IO8(0x10)
3
#define DDRD  _SFR_IO8(0x11)
4
#define PORTD  _SFR_IO8(0x12)
5
6
/* Port C */
7
#define PINC  _SFR_IO8(0x13)
8
#define DDRC  _SFR_IO8(0x14)
9
#define PORTC  _SFR_IO8(0x15)
10
11
/* Port B */
12
#define PINB  _SFR_IO8(0x16)
13
#define DDRB  _SFR_IO8(0x17)
14
#define PORTB  _SFR_IO8(0x18)

Vielen Dank und viele Grüße,
Martin

von Klaus W. (mfgkw)


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:
1
const uint8_t  *  p_ddr_array[]  = {&DDRB, &DDRB, &DDRC, &DDRD, &DDRB};
2
const uint8_t  *  p_port_array[] = {&PORTB, &PORTB, &PORTC, &PORTD, &PORTB};
3
const uint8_t bit_array[]  = { 1,   2,    2,    2,     5};
4
...
5
*p_port_array[i] |= ...

Oder C++ nehmen. :-)

von Florian L. (muut) Benutzerseite


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

von Martin (Gast)


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

von Vlad T. (vlad_tepesch)


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?

von Karl H. (kbuchegg)


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
1
struct portBit {
2
   volatile uint8_t * ddr_register;
3
   volatile uint8_t * port_register;
4
   uint8_t            pin;
5
};

und dir dann daraus die Arrays (oder Variablen) bauen
1
struct portBit leds[] =
2
    { { &DDRB, &PORTB, 1<<PB0 },
3
      { &DDRB, &PORTB, 1<<PB1 },
4
      { &DDRC, &PORTC, 1<<PC5 },
5
      { &DDRD, &PORTD, 1<<PD4 },
6
    };
7
8
#define ARRAY_SIZE(x)   ( sizeof(x) / sizeof(*x) )
9
10
void blink_once( struct portBit * led )
11
{
12
  *(led->port_register) |= led->pin;
13
  _delay_ms( 100 );
14
  *(led->port_register) &= ~led->pin;
15
  _delay_ms( 100 );
16
}
17
18
int main()
19
{
20
  uint8_t i;
21
22
  // configure all led pins as output
23
  for( i = 0; i < ARRAY_SIZE( leds ); ++i )
24
    *(leds[i].ddr_register) |= leds[i].pin;
25
26
  // turn on all leds
27
  for( i = 0; i < ARRAY_SIZE( leds ); ++i )
28
    *(leds[i].port_register) |= leds[i].pin;
29
30
  _delay_ms( 1000 );
31
32
  // now turn off all leds in the given order
33
  for( i = 0; i < ARRAY_SIZE( leds ); ++i ) {
34
    *(leds[i].port_register) &= ~leds[i].pin;
35
    _delay_ms( 500 );
36
  }
37
38
  while( 1 ) {
39
    for( i = 0; i < ARRAY_SIZE( leds ); ++i )
40
      blink_once( &leds[i] );
41
  }
42
}

von Andreas F. (aferber)


Lesenswert?

Klaus Wachtler schrieb:
>
1
> const uint8_t  *  p_ddr_array[]  = {&DDRB, &DDRB, &DDRC, &DDRD, &DDRB};
2
>

Bitte
1
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

von Martin (Gast)


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

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.