Forum: Mikrocontroller und Digitale Elektronik Funktionen mit Zugriff auf AVR-Register [C]


von Philipp H. (philipp_h)


Lesenswert?

Hallo Gemeinde,

ich habe folgendes Problem:
Ich möchte die Register des AT-Mega 644PU variabel mit einer Funktion 
beschreiben können. Der Hintergrund ist der, dass durch aufrufen der 
Funktion "gleichzeitig" ein anderes Register geupdatet werden soll.

Beispiel:
1
uint8_t MeinArray[255];
2
#define maPINA MeinArray[0x13]
3
//#define maSome MeinArray[0-FF] ; Gibt halt mehrere defines
4
5
void update_reg(uint8_t AVRREG, uint8_t update)
6
{
7
AVRREG = update;
8
maSome = update;
9
}
10
11
//Späterer Aufruf
12
update_reg(PINA,0xFF);
13
14
//Dann soll in MeinArray[0x13] bzw. maPINA 0xFF stehen

Meine Idee war zunächst das über Zeiger zu realisieren aber so richtig 
weiß ich nicht wie ... Die wohl etwas unschönere Variante wäre mit 
Switch-case und das Register als String zu übergeben.

Hat jemand sowas schon mal gemacht und kann mir helfen?

Mit freundlichem Gruß
Philipp Heise

von Karl H. (kbuchegg)


Lesenswert?

Philipp H. schrieb:

> Meine Idee war zunächst das über Zeiger zu realisieren aber so richtig
> weiß ich nicht wie ...

Pointer ist schon richtig. In der Beziehung ist ein Register für dich 
auch nichts anderes als eine Variable, die in einer Funktion einen neuen 
Wert kriegen soll. Details dazu hat jedes grindige C-Buch.

Der Datentyp der Register ist
1
volatile uint8_t

Also
1
void update_reg(volatile uint8_t* Register, uint8_t Wert)
2
{
3
  *Register = Wert;
4
  maSome = Wert;
5
}

und der Aufruf dann
1
  update_reg( &PINA, 0xFF );


Das unterscheidet sich aus C Sicht in nichts davon, wie eine Funktion 
arbeitet, die eine Variable des Aufrufers ändern soll
1
void foo( uint8_t* mod )
2
{
3
  *mod = 5;
4
}
5
6
int main()
7
{
8
  uint8_t i;
9
  uint8_t j;
10
11
  foo( &i );    // i soll von foo einen Wert kriegen
12
  foo( &j );    // j soll von foo einen Wert kriegen
13
}

von Stefan F. (Gast)


Lesenswert?

Die unschöne Variante ist jedoch die schnellere, wenn du das mit Makros 
oder inline Funktionen realisierst. Denn der Zugriff auf Register über 
Pointer erfordert andere Befehle die mehr Taktzyklen benötigen.

Damit die beiden register "gleichzeitig" beschrieben werden, solltest du 
voher Interrupts sperren und danach wieder freigeben.

von Moki (Gast)


Lesenswert?

Mein erster Gedanke:
1
#define REGISTER1 0xefef
2
#define REGISTER2 0xfefe
3
.
4
.
5
.

REGISTER1,2 usw sind deine Registernamen laut Datenblatt.
0xefef sind ist die Adresse. Dann sollte der Aufruf ohne switch-case 
funktionieren.

In etwa so:
1
foo(uint16_t address, uint8_t val) {
2
   *adress = val;
3
   maSome = val;
4
}

Und der Aufruf:
1
foo(REGISTER1, 0x23);
2
foo(REGISTER2, 0x24);

Aber schaus dir erst im Simulator an, der Code ist ungetestet!

von Karlo (Gast)


Lesenswert?

Nein.

von Philipp H. (philipp_h)


Lesenswert?

Danke für die Tipps ich werde wohl die Variante von Karl Heinz 
verwenden.

PS: Kann geschlossen 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
Noch kein Account? Hier anmelden.