2-Dimensionales Array. Fehler. Läuft aber trotzdem ?

Gast #4033087
Lesenswert?

Hallo zusammen,
ich habe ein 2-Dimensionaled Feld erstellt, in dem ich den Zustand von 
74 Relais auf 5 Steckkarten festhalten wollte.
Dabei ist mir der Fehler pssiert, dass ich das Feld für die Kartennummer 
um 1 zu klein gewählt habe.
(Ich weiss, normalerwise fängt man bei 0 an, und nicht bei 1. Bitte dies 
nicht diskutuieren)

unsigned char Relais[5][75]; //Karte 1-5   Relais 1-74

Seltsamerweise funktioniert das Programm aber trotzdem, wenn ich Schreib 
/ Lesezugriff auf z.B Relais[5][74]  = 1;  mache.
Ist das jetzt nur Glück, dass meine MCU nicht abstürzt weil der 
beschriebene Speicherbereich zufällig frei war ?

LG Dirk
#4033092
Lesenswert?

@ Dirk F (Gast)

>ich habe ein 2-Dimensionaled Feld erstellt, in dem ich den Zustand von
>74 Relais auf 5 Steckkarten festhalten wollte.

Hmm.

>Dabei ist mir der Fehler pssiert, dass ich das Feld für die Kartennummer
>um 1 zu klein gewählt habe.
>(Ich weiss, normalerwise fängt man bei 0 an, und nicht bei 1. Bitte dies
>nicht diskutuieren)

>unsigned char Relais[5][75]; //Karte 1-5   Relais 1-74

Für 74 Relais braucht man bei der Kenntnis von Bitmanipulation 
gerade mal 12 Bytes.

>Seltsamerweise funktioniert das Programm aber trotzdem, wenn ich Schreib
>/ Lesezugriff auf z.B Relais[5][74]  = 1;  mache.
>Ist das jetzt nur Glück, dass meine MCU nicht abstürzt weil der
>beschriebene Speicherbereich zufällig frei war ?

Ja.
Gast #4033099
Lesenswert?

Hallo Falk,
ja Du hast Recht, aber die Funktion ist jetzt schon für mich so komplex, 
dass ich lieber ein paar Bytes opfere, als den Überblick zu verlieren.
Hier ist der Lesezugriff auf das Array, um 5 x 2 LEDs anzusteuern:
1
    //------------------control----------------------------------------------------
2
void HL_LED_control (void)
3
    {
4
    static bit b_P12,b_P34;
5
    static unsigned char i,Port;
6
    static unsigned char LED_H[6],LED_H_alt[6],LED_L[6],LED_L_alt[6];
7

8
    Port ++;              // Port = 1-5
9
    if (Port==6) Port = 1;
10

11
    b_P34 = 0;
12
    b_P12 = 0;
13
    LED_H[Port]= 0;
14
    LED_L[Port]= 0;
15

16
    for (i=2;i<=64;i=i+2)                           // wenn ein even Relais = 1
17
       if (Relais [Port][i] == 1)  b_P34 = 1 ;      // setze bit
18

19
   for (i=1;i<=64;i=i+2)                            // wenn ein odd Relais  = 1
20
       if (Relais [Port][i] == 1)  b_P12 = 1 ;      //  setze bit
21

22
        LED_H[Port] =  (((bit) b_P34 && ((bit) Relais [Port][68] || (bit) Relais [Port][71]))    ||  ( b_P12 && ((bit)Relais [Port][65] || (bit) Relais [Port][66] )) ) ;  // ein even = 1 und (Relais 68 = 1 oder K71 = 1)
23
        LED_L[Port] =  (((bit) b_P34 && ((bit) Relais [Port][69] || (bit) Relais [Port][70]))    ||  ( b_P12 && ((bit)Relais [Port][67] || (bit) Relais [Port][72] )) ) ;  // ein even = 1 und (Relais 68 = 1 oder K71 = 1)
24

25
    if (LED_H[Port]  != LED_H_alt[Port])                // Hat sich der Zustand geändert ?
26
                writeSlave24 (Port, 1<<6 | Chip[73-1 ]<<3 | (bit)LED_H[Port],  2<<6 | Pin[73-1]-1  );  //  dann High-LED ein/aus schalten
27

28
    if (LED_L[Port]  != LED_L_alt[Port])                // Hat sich der Zustand geändert ?
29
                 writeSlave24 (Port, 1<<6 | Chip[74-1 ]<<3 | (bit)LED_L[Port],  2<<6 | Pin[74-1]-1  );  //  dann Low-LED ein/aus schalten
30

31
        LED_H_alt[Port] = LED_H[Port];                      // Zustand merken
32
        LED_L_alt[Port] = LED_L[Port];
33
    }

Anm. d. Mods: Hab etwas Farbe in den Quellcode gekippt :)
(Firma: Vescomp) #4033104
Lesenswert?

Dirk F schrieb:
> Ist das jetzt nur Glück, dass meine MCU nicht abstürzt weil der
> beschriebene Speicherbereich zufällig frei war ?

 Natürlich.
 Mach noch ein Array hinterher, z.B. TestArray, mit Nullen auffüllen,
 zugriff auf Relais[5][74]  = 1;
 und sende TestArray zum PC.

 Ich glaube, TestArray[0][73] sollte nun gesetzt sein.
#4033120
Lesenswert?

@ Dirk F (Gast)

>ja Du hast Recht, aber die Funktion ist jetzt schon für mich so komplex,
>dass ich lieber ein paar Bytes opfere, als den Überblick zu verlieren.

FALSCH! Wenn man es richtig macht (tm), wird es eher einfacher als 
schwiegiger.

Jetzt schreibst du

Relais[4][74] = 1;

bzw. du liest

x = Relais[4][74];

Mit zwei Funktionen kann man die Bitmanipulation PROBLEMLOS 
"verstecken"

relais_set(uint8_t board, uint8_t relais, uint8_t value);
uint8_t relais_get(uint8_t board, uint8_t relais);

>Hier ist der Lesezugriff auf das Array, um 5 x 2 LEDs anzusteuern:

Waren es nicht erst Relais?

Ausserdem kann das durch die Zeilenumbrüche keiner lesen. Wenn man 
Quelltext einfügt, dann mit Markierung
1
[c]
2

3
Quelltext hier, wird ohne extra Umbruch angezeigt
4

5
[/c]
(Firma: Vescomp) #4033140
Lesenswert?

Falk Brunner schrieb:
> Für 74 Relais braucht man bei der Kenntnis von Bitmanipulation
> gerade mal 12 Bytes.

 Bei der Kenntnis von Bitmanipulation braucht man dafür genau 74 bits.

 Aber das Ganze bleibt viel übersichtlicher mit 2-Dimensionalem Array.
1
Oder man schreibt eine Funktion mit 3 Parametern (Karte, Relais, On/Off/Zustand)
2
 und lasst die Funktion die ganze bitschieberei machen.
#4033156
Lesenswert?

@ Dirk F (Gast)

>So, da wären wir wieer bei dem alten Thema, warum es in C kein
>Bit-Arrays  gibt....

Darüber kannst du jetzt lang und breit lammentieren, eine 
Selbsthilfegruppe gründen oder an den Papst schreiben. Oder einfach ein 
bisschen Pragmatismus an den Tag legen, die zwei läppischen Funktionen 
in 10 Minuten runtertippen und glücklich sein. Triff deine Wahl.
#4033159
Lesenswert?

Marc Vesely schrieb:
> Bei der Kenntnis von Bitmanipulation braucht man dafür genau 74 bits

Man macht sich damit aber das Leben u.U. ziemlich schwer.

Wenn man für jede Karte 10 Bytes (= 80Bits) nimmt, dann kann man den 
Index für die Karten normal als Array belassen. Damit reduziert sich die 
Bitschubserei darauf erstmal das richtige Byte zu suchen
1
 
2
ByteAddresse = RelaisNummer/8;

und anchließend das richtige Bit zu maskieren
1
toReturn = Array[Kartennummer][Byte_Adresse] & (1<<(RelaisNummer&0b111));
2
return toReturn;

Hier wird dann eine 0 geliefert wenn das Relais aus ist und etwas >0 
wenn es an ist (kann man über ein simples if verarbeiten).

PS: Wer will kann die Adressberechnung mit in die rechteckigen Klammern 
schreiben und das ganze via Funktionsmakro einbinden.
#4033164
Lesenswert?

@ Marc Vesely (Firma: Vescomp) (logarithmus)

>> Für 74 Relais braucht man bei der Kenntnis von Bitmanipulation
>> gerade mal 12 Bytes.

Ahhh, heute mal wieder in Kopfrechnen schwach. Es sind natürlich 10 
Bytes.

> Bei der Kenntnis von Bitmanipulation braucht man dafür genau 74 bits.

Was leider nicht ganz durch 8 teilbar ist.

> Aber das Ganze bleibt viel übersichtlicher mit 2-Dimensionalem Array.

Das ist doch gar nicht die Frage! Aber ein

char relais[5][10] braucht 50 Bytes
char relais[5][75] braucht 375 Bytes

Jaja, am bestern noch einen ARM dazu nehmen, sicher ist sicher ;-)
Gast #4033194
Lesenswert?

HI,
da kommt mir noch ein ganz anderer Gedanke:
Wenn auf den 5 Karten immer das gleiche gemacht wird, dann brauch ich 
doch die Logikberechnung nicht 5 mal einzel mit 1 Bit machen, sondern 
Byteweise die Und/Oder Verknüpfungen durchführen,erste Bit für die erste 
Karte, Bit4 für die 5.te Karte, und vom Ergebnisbyte dann die ersten 5 
Bits auswerten.

Dirk
#4033207
Lesenswert?

@ Dirk F (Gast)

>Wenn auf den 5 Karten immer das gleiche gemacht wird, dann brauch ich
>doch die Logikberechnung nicht 5 mal einzel mit 1 Bit machen, sondern
>Byteweise die Und/Oder Verknüpfungen durchführen,erste Bit für die erste
>Karte, Bit4 für die 5.te Karte, und vom Ergebnisbyte dann die ersten 5
>Bits auswerten.

Kann sein. Aber ich glaube nicht, dass du hier großartig Reichenleistung 
sparst. So eine Relaissteuerung ist sowieso um Faktor 1000++ langsamer 
als die langsamste CPU.

Kleiner Tip. Schreibe IMMER Klammern für den Körper bei for(), while(), 
if() etc. Sonst kannst du dir mal ganz schnell ins Knie schießen.

Siehe Strukturierte Programmierung auf Mikrocontrollern

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren