Forum: Mikrocontroller und Digitale Elektronik Array von Konstanten nicht im RAM ablegen (in C)


von Dussel (Gast)


Lesenswert?

Moin,

in meiner Schaltung habe ich einige LED, die über Multiplexing 
angesteuert werden. Jetzt würde ich natürlich gerne im Quelltext 
übersichtlich die Zuordnung LED<->(Pins,Speicherplatz) haben.
Der für mich schönste Ansatz wäre sowas wie
1
#define ZEILE 0
2
#define SPALTE 1
3
4
const uint8_t LED_Start[3]={0,0,0};
5
const uint8_t LED_Stop[3]={1,0,1};
6
const uint8_t LED_Bereit[3]={2,0,2};
7
const uint8_t LED_Aus[3]={0,1,4};
8
// ...
9
10
void LED_schalten(uint8_t Zeile, uint8_t Spalte);
11
12
int main(void)
13
{
14
    LED_schalten(LED_Start[ZEILE],LED_Start[SPALTE]);
15
}
Die Arrays werden aber dabei natürlich im RAM abgelegt und da möchte ich 
sie ungerne haben, weil es ein paar mehr LED sind und RAM knapp ist.

Die andere Möglichkeit wäre, alles mit #define zu machen
1
#define LED_Start_Zeile 0
2
#define LED_Start_Spalte 0
3
#define LED_Start_Position 0
4
#define LED_Stop_Zeile 1
5
#define LED_Stop_Spalte 0
6
#define LED_Stop_Position 1
7
#define LED_Bereit_Zeile 2
8
// ...
Das hat sehr viel Redundanz und ist dadurch unübersichtlicher.

Die Konstanten werden auch wirklich nur konstant, also zur Compilezeit 
vorhersagbar benutzt, auch die Arrayindizes. Es wird also nicht sowas 
wie
for(int i=0;i<3;i++) x=LED_Start[i];
oder sowas geben.

Gibt es eine saubere Möglichkeit, die const-Konstanten im Code zu 
speichern oder über #define mit Arrays zu arbeiten?

von Dussel (Gast)


Lesenswert?

Im ersten Codestück fehlt noch ein #define POSITION 2. Das macht in dem 
Fall keinen Unterschied, aber damit ist es konsistent zum zweiten Code.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Dussel schrieb:
> Die Arrays werden aber dabei natürlich im RAM abgelegt und da möchte ich
> sie ungerne haben, weil es ein paar mehr LED sind und RAM knapp ist.

Welcher µC? Für die AVRs gibt es dafür PROGMEM bzw. beim avr-gcc neueren 
Datums __flash.

von Dussel (Gast)


Lesenswert?

Frank M. schrieb:
> Dussel schrieb:
>> Die Arrays werden aber dabei natürlich im RAM abgelegt und da möchte ich
>> sie ungerne haben, weil es ein paar mehr LED sind und RAM knapp ist.
>
> Welcher µC? Für die AVRs gibt es dafür PROGMEM bzw. beim avr-gcc neueren
> Datums __flash.
Es ist ein AVR (ein ATmega8).
Stimmt, die Anweisungen gibt es und ich kenne sie auch. Dafür muss ich 
dann aber die speziellen Zugriffsfunktionen für Flash oder EEPROM 
verwenden. Das wollte ich eigentlich nicht.
Mir geht es einfach nur darum, dass wie bei #define alle Vorkommen im 
Code durch die entsprechenden Konstanten ersetzt werden.

von Cyberpunk (Gast)


Lesenswert?

Dussel schrieb:
> Stimmt, die Anweisungen gibt es und ich kenne sie auch. Dafür muss ich
> dann aber die speziellen Zugriffsfunktionen für Flash oder EEPROM
> verwenden. Das wollte ich eigentlich nicht.

Geht auf Harvard-Architekturen nicht anders.

Dussel schrieb:
> Mir geht es einfach nur darum, dass wie bei #define alle Vorkommen im
> Code durch die entsprechenden Konstanten ersetzt werden.

Sowas kann C nicht, was du suchst bietet C++ mit constexpr.

von Ingo Less (Gast)


Lesenswert?

Wenn du _Flash nutzt, kannst du die Variable wie eine „normale“ 
ansprechen.

von asdfasd (Gast)


Lesenswert?

Mach die Arrays mal "static const" ...

von Rolf M. (rmagnus)


Lesenswert?

Das geht übrigens auch mit Makros.
Man kann z.B. schreiben:
1
#define LED_START (int[]){0, 0, 0}
2
3
LED_schalten(LED_START[ZEILE],LED_START[SPALTE]);

von M. K. (sylaina)


Lesenswert?

asdfasd schrieb:
> Mach die Arrays mal "static const" ...

Ändert nichts daran, dass sie dennoch im RAM landen.

Dussel schrieb:
> Gibt es eine saubere Möglichkeit, die const-Konstanten im Code zu
> speichern oder über #define mit Arrays zu arbeiten?

Bei deinem Atmega 8 mit PROGMEM arbeiten
1
#include <avr/pgmspace.h> // fuer PROGMEM und entsprechenden Funktionen zum Zugriff auf die Variablen im Flash
2
...
3
#define ZEILE 0
4
#define SPALTE 1
5
6
const uint8_t LED_Start[3] PROGMEM ={0,0,0};
7
const uint8_t LED_Stop[3] PROGMEM ={1,0,1};
8
const uint8_t LED_Bereit[3] PROGMEM ={2,0,2};
9
const uint8_t LED_Aus[3] PROGMEM ={0,1,4};
10
// ...
11
12
void LED_schalten(uint8_t Zeile, uint8_t Spalte);
13
14
int main(void)
15
{
16
    LED_schalten(pgm_read_byte(&LED_Start[ZEILE]),pgm_read_byte(&LED_Start[SPALTE]));
17
}

von asdfasd (Gast)


Lesenswert?

>> Mach die Arrays mal "static const" ...
>
> Ändert nichts daran, dass sie dennoch im RAM landen.

Doch! Der Optimizer verwirft sie. Ohne const darf er nicht.

von asdfasd (Gast)


Lesenswert?

Ehem, sollte natürlich ohne "static" heißen :-/

von CR Zebra (Gast)


Lesenswert?

An Deiner Stelle würde ich versuchen das Programm mit avr-g++ zu 
compilieren und schauen obs einen Unterschied macht. Wurde ja schon 
gesagt, dass hier die kleinen Unterschiede zwischen C und dem C Teil von 
C++ liegen.

von Dussel (Gast)


Lesenswert?

Static habe ich jetzt mal ausprobiert und das scheint das Problem zu 
lösen. Ich habe auch mal ausprobiert, ob es einen Unterschied gibt, wenn 
ich die Konstante benutze oder nicht. Da hat sich nichts geändert. Die 
Ersparnis liegt also nicht darin, dass er die Konstanten wegoptimiert.

Die anderen Hinweise werde ich ausprobieren, wenn es doch noch Problem 
gibt.

Vielen Dank.

von Carl D. (jcw2)


Lesenswert?

Dussel schrieb:
> Static habe ich jetzt mal ausprobiert und das scheint das Problem zu
> lösen. Ich habe auch mal ausprobiert, ob es einen Unterschied gibt, wenn
> ich die Konstante benutze oder nicht. Da hat sich nichts geändert. Die
> Ersparnis liegt also nicht darin, dass er die Konstanten wegoptimiert.
>
> Die anderen Hinweise werde ich ausprobieren, wenn es doch noch Problem
> gibt.
>
> Vielen Dank.

Bezogen auf den Code im ersten Post:
Darin wird ein konstanter Wert, zugegeben komplex notiert, an eine 
Funktion übergeben. Da die ganzen const Arrays aber nicht static 
deklariert sind, sind sie von anderen "Compilation-Units", sprich 
anderen c-Files des gleichen Projekts aus sichtbar. Ob das so ist, weis 
der Compiler nicht, also kann er sie nicht wegwerfen. Mit static kennt 
er jede Verwendung, kann nur in diesem c-File sein, und weiß, daß damit 
nur kompliziert 8 Bit "errechnet" werden. Das kann er auch zur 
Compile-Time und damit sind die Arrays nicht mehr notwendig. Ob sie dann 
const sind, ist egal, denn jegliche Verwendung ist bekannt.

von Dussel (Gast)


Lesenswert?

Carl D. schrieb:
> Mit static kennt
> er jede Verwendung, kann nur in diesem c-File sein, und weiß, daß damit
> nur kompliziert 8 Bit "errechnet" werden. Das kann er auch zur
> Compile-Time und damit sind die Arrays nicht mehr notwendig. Ob sie dann
> const sind, ist egal, denn jegliche Verwendung ist bekannt.
Das war ja der Plan. Ich hatte nur Bedenken, dass der niedrigere 
Speicherverbrauch dadurch zustande kommt, dass der Compiler merkt, dass 
die meisten Konstanten nie verwendet werden (das Projekt steht ja noch 
ganz am Anfange) und sie deshalb komplett wegoptimiert.

Gewundert hat mich zuerst, dass auch der Programmspeicherverbrauch 
zurückgeht. Aber es werden durch die Codierung ja auch alle 
Speicherladebefehle gespart.

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.