Forum: Compiler & IDEs Zweidimensionales 'array' für 'switch' Anweisung


von Firebird (Gast)


Lesenswert?

Hallo zusammen

In meinem Code mit 'switch' Anweisung habe ich Tabellen bestehend aus 16 
channels mit je ein zugewiesener Wert. Um das Ganze zu vereinfachen 
möchte ich die Tabellen durch ein zweidimensionales Array ersetzen.

Ich könnte mir sowas vorstellen:
1
unsigned int pwm_setting[channel][value]={{0,1,...14,15},{5,25,2,15....10}}

Hier sind Code-Ausschnitte um den Fall zu verdeutlichen:
1
// Makro zur einfacheren Handhabung
2
#define pwm_setting(channel, value) pwm_value[channel] = PWM_MAX - value
1
int main(void)
2
{.....
3
4
  pwm_setting(0,0);
5
  // bis ....
6
  pwm_setting(15,0);    
7
  
8
    while(1)
9
    {
10
    input = PINC;    // Schalterkombination an "input" übergeben
11
   
12
    switch (input)
13
    {
14
      case 0xc1:
15
        pwm_setting(0,5);
16
        //bis....
17
        pwm_setting(15,17);
18
      break;
19
20
      case 0xd1:
21
        pwm_setting(0,25);
22
        // bis.... 
23
        pwm_setting(15,5);
24
        break;
25
26
      default:           
27
        pwm_setting(0,14);
28
        // bis....
29
        pwm_setting(15,28);
30
    }  
31
}
Ist es überhaupt möglich 'pwm_setting(channel, value)' als Array zu 
bestimmen? Wie setze ich das am Besten um?

Danke und Gruss
Firebird

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Verstehe ich das richtig, Du hast einen 8-Bit-Eingang (Port C), und in 
Abhängigkeit vom anliegenden Wert möchtest Du eine Funktion mit zwei 
anderen Werten aufrufen?

Dafür braucht es kein zweidimensionales Array, und auch kein 
switch-Statement, sondern zwei eindimensionale Arrays mit je 256 
Elementen.

Und dann wird das ganze recht einfach:
1
uint8_t channels[256] = { ... };
2
uint8_t values[256] = { ... };
3
4
// etc. pp.
5
6
while (1)
7
{
8
  input = PINC;
9
10
  pwm_settings(channels[input], values[input]);
11
}

Du musst nur noch auseinanderklabüsern, welcher Bit-Kombination an Port 
C welche Werte für "Kanal" und "Wert" zuzuordnen sind.

Oder habe ich Dich komplett missverstanden?

von Firebird (Gast)


Angehängte Dateien:

Lesenswert?

In Abhängigkeit vom Port C Eingang möchte ich diverse LEDs mit 
unterschiedlicher Helligkeit schalten. Unter 'channel' sind die Port B 
und Port D Ausgänge gemeint, unter 'value' die vordefinierten 
Helligkeitswerte.

Im Anhang ist der komplete und funktionierende Code den ich anpassen 
möchte.

MfG
Firebird

von Klaus W. (mfgkw)


Lesenswert?

Ich habe jetzt den Anhang nicht gelesen, aber vermutlich suchst du
so wetwas in der Art:
1
#define N_CHANNELS            16
2
#define N_VALUES_PER_CHANNEL 256
3
4
  unsigned int PWM_Value_tab[N_CHANNELS][N_VALUES_PER_CHANNEL] =
5
    {
6
      [0] = { 0, 1, 14, 15, 0 /* TODO: hier die restlichen 251 Einfügen... */ },
7
      [1] = { 0, 1, 14, 15, 0 /* TODO: hier die restlichen 251 Einfügen... */ },
8
      [2] = { 0, 1, 14, 15, 0 /* TODO: hier die restlichen 251 Einfügen... */ },
9
      /* TODO: hier weitere 12 Kanäle einfügen... */
10
      [15] = { 0, 1, 14, 15, 0 /* TODO: hier die restlichen 251 Einfügen... */ },
11
    };
12
13
   // ...
14
15
  while( "42" )
16
  {
17
    uint8_t   input = PORTC;
18
    size_t iChannel;
19
    for( iChannel=0; iChannel<N_CHANNELS; ++iChannel )
20
    {
21
      /* irgendwas_zu_setzen_fuer_PORTB_ODER_D = */ PWM_Value_tab[iChannel][input];
22
    }
23
  }

Wenn sich die Werte nicht ändern, sollte die Tabelle const sein
und vermutlich auch global (außerhalb aller Funktionen) oder
zumindest static.
Ggf. explizit im Flash.

von Firebird (Gast)


Lesenswert?

Danke für die Vorschläge. Leider habe ich (als Anfänger) immernoch 
Verständnisprobleme und komme nicht weiter.

Der erste Case-Fall ist unten abgebildet. 'channel' ist für die Zuordung 
der PINs und 'value' den Wert für die Helligkeitsberechnung der LEDs. Im 
Prinzip eine einfache Tabelle mit PIN-Zuweisung und Wert.
1
  case 0xc1:               // Wenn PORTC = 11000001
2
    pwm_setting(0,0);      // (channel,value)  d.h. PB0 mit Wert 0
3
    pwm_setting(1,5);      // (channel,value)  d.h. PB1 mit Wert 5
4
    pwm_setting(2,5);      // (channel,value)  d.h. PB2 mit Wert 5
5
    pwm_setting(3,5);      // (channel,value)  d.h. PB3 mit Wert 5
6
    pwm_setting(4,0);      // (channel,value)  d.h. PB4 mit Wert 0
7
    pwm_setting(5,0);      // (channel,value)  d.h. PB5 mit Wert 0
8
    pwm_setting(7,0);      // (channel,value)  d.h. PB6 mit Wert 0
9
    pwm_setting(8,0);      // (channel,value)  d.h. PB6 mit Wert 0
10
    pwm_setting(9,0);      // (channel,value)  d.h. PB6 mit Wert 0
11
    pwm_setting(10,0);     // (channel,value)  d.h. PB6 mit Wert 0
12
    pwm_setting(11,0);     // (channel,value)  d.h. PB6 mit Wert 0
13
    pwm_setting(12,0);     // (channel,value)  d.h. PB6 mit Wert 0
14
    pwm_setting(13,5);     // (channel,value)  d.h. PB6 mit Wert 5
15
    pwm_setting(14,0);     // (channel,value)  d.h. PB6 mit Wert 0
16
    pwm_setting(15,0);     // (channel,value)  d.h. PB6 mit Wert 0
17
  break;
Weil es später ein Vielfaches an Case-Fälle geben soll suche ich eine 
kürzere Schreibform oder wenn möglich eine intelligentere Lösung.

Im Tutorial unter http://www.mikrocontroller.net/articles/Soft-PWM ist 
z.B.
1
const uint8_t t1[8]={27, 40, 3, 17, 150, 99, 5, 9};
2
memcpy(pwm_setting, t1, 8);
Ich weiss nicht wie ich sowas ähnliches in meinem Code anwenden, bzw. 
umsetzen kann.

MfG
Firebird

von Karl H. (kbuchegg)


Lesenswert?

Du suchst sowas
1
#define NR_CASES   5
2
#define NR_VALUES  16
3
4
unsigned char Values[ NR_CASES ][ NR_VALUES ] =
5
  { { 0,       5, 5,       5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0 },
6
    { 0, PWM_MAX, 5, PWM_MAX, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0 },
7
    { 0,       5, 5,       5, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0 },
8
    { 0, PWM_MAX, 5, PWM_MAX, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0 },
9
    { 0,       0, 0,       0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5 },
10
  };
11
12
...
13
14
    input = PINC;    // Schalterkombination an "input" übergeben
15
   
16
    switch (input)
17
    {
18
      case 0xc1:
19
        for( i = 0; i < NR_VALUES; ++i )
20
          pwm_setting( i, Values[0][i] );
21
        break;
22
23
      case 0xd1:
24
        for( i = 0; i < NR_VALUES; ++i )
25
          pwm_setting( i, Values[1][i] );
26
        break;
27
28
      ...
29
30
      default:           
31
        for( i = 0; i < NR_VALUES; ++i )
32
          pwm_setting( i, Values[4][i] );
33
    }

von Karl H. (kbuchegg)


Lesenswert?

> Weil es später ein Vielfaches an Case-Fälle geben soll suche
> ich eine kürzere Schreibform oder wenn möglich eine
> intelligentere Lösung.

Wieviele Cases hast du und wie zeitkritisch ist das Ganze?

Intelligenter wär zb sowas:
1
#define NR_CASES   5
2
#define NR_VALUES  16
3
4
struct Led
5
{
6
  unsigned char InputValue;           // welcher Wert muss am PINC vorliegen ...
7
  unsigned char Values[ NR_VALUES ];  // ... damit diese Werte auf die Led ausgegeben werden
8
};
9
10
struct Led Cases[ NR_CASES ] =
11
  {
12
    { 0xC1,  { 0,       5, 5,       5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0 } },
13
    { 0xD1,  { 0, PWM_MAX, 5, PWM_MAX, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0 } },
14
    { 0xC5,  { 0,       5, 5,       5, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0 } },
15
    { 0xD5,  { 0, PWM_MAX, 5, PWM_MAX, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0 } },
16
    { 0x00,  { 0,       0, 0,       0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5 } },
17
  };
18
19
...
20
21
    input = PINC;    // Schalterkombination an "input" übergeben
22
23
    // den richtigen caseNr suchen
24
    // wird keiner gefunden, dann ist NR_CASES - 1 (also der letzte) der Default
25
    caseNr = NR_CASES - 1;
26
    for( i = 0; i < NR_CASES - 1; ++i )
27
    {
28
      if( Cases[i].InputValue == input )
29
      {
30
        caseNr = i;
31
        break;
32
      }
33
    }
34
35
    // die Werte für diesen Fall ausgeben
36
    for( i = 0; i < NR_VALUES; ++i )
37
      pwm_setting( i, Cases[caseNr].Values[i] );
38
    }

Hier muss man den Programmtext überhaupt nicht mehr ändern, wenn ein 
neuer Fall dazukommt. Die neuen Einstellungen werden zusammen mit dem 
auslösenden Wert am PINC einfach in die Tabelle eingetragen und der 
Programmcode sucht und findet die Led-Einstellungen wenn am PINC der 
richtige Wert vorliegt.

von Firebird (Gast)


Angehängte Dateien:

Lesenswert?

Danke, sowas suchte ich. Nach einer kleinen Anpassung sieht der 
Code-Ausschnitt so aus:
1
unsigned char Values[ NR_CASES ][ PWM_CHANNELS ] =
2
  { { 0,       5, 5,       5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0 },
3
    { 0, PWM_MAX, 5, PWM_MAX, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0 },
4
    { 0,       5, 5,       5, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0 },
5
    { 0, PWM_MAX, 5, PWM_MAX, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0 },
6
    { 0,       0, 0,       0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5 },
7
    };
8
9
  sei();        // Interruptfreigabe
10
    
11
  while(1)
12
  
13
  input = ~PINC;    // Schalterkombination an "input" übergeben
14
   
15
    switch (input)
16
    {
17
      case 0xc1:
18
        for( i = 0;i < PWM_CHANNELS; i++ )
19
        pwm_setting( i, Values[0][i] );
20
      break;
21
22
      case 0xd1:
23
        for( i = 0; i < PWM_CHANNELS; ++i )
24
        pwm_setting( i, Values[1][i] );
25
      break;
26
27
      case 0xc5:
28
        for( i = 0; i < PWM_CHANNELS; ++i )
29
        pwm_setting( i, Values[2][i] );
30
      break;
31
32
      case 0xd5:
33
        for( i = 0; i < PWM_CHANNELS; ++i )
34
        pwm_setting( i, Values[3][i] );
35
      break;
36
37
      default:           
38
        for( i = 0; i < PWM_CHANNELS; ++i )
39
        pwm_setting( i, Values[4][i] );
40
    }  
41
  }
Irgendwo habe ich etwas übersehen, die LEDs leuchten alle hell auf 
unabhängig vom Zustand an PORTC. Ich vermute dass die 'Values' nicht 
übergeben werden.

MfG
Firebird

von Firebird (Gast)


Lesenswert?

Der zweite Vorschlag scheint mir besser zu passen für meinen 
Anwendungsfall. Aber, auch hier leuchten die LEDs einfach hell. Wie kann 
man die Werte von
1
pwm_setting( i, Cases[caseNr].Values[i] );
an die Definition
1
// Makro zur einfacheren Handhabung
2
#define pwm_setting(channel, value) pwm_value[channel] = PWM_MAX - value
übergeben, bzw. anpassen?

Voraussichtlich sollen 24 Case-Fälle geschaltet werden. Zeitkritisch ist 
das Ganze nicht.

Danke und Gruss
Firebird

von Karl H. (kbuchegg)


Lesenswert?

Firebird schrieb:
> Der zweite Vorschlag scheint mir besser zu passen für meinen
> Anwendungsfall. Aber, auch hier leuchten die LEDs einfach hell. Wie kann
> man die Werte von
>
1
pwm_setting( i, Cases[caseNr].Values[i] );
> an die Definition
>
1
> // Makro zur einfacheren Handhabung
2
> #define pwm_setting(channel, value) pwm_value[channel] = PWM_MAX - value
3
>
> übergeben, bzw. anpassen?

Vergiss das Makro. Du brauchst es nicht.
Schreib
1
     pwm_value[i] = PWM_MAX - Cases[caseNr].Values[i];

ist genausogut wie dein Makro und man sieht wenigstens was wirklich 
passiert.

von Firebird (Gast)


Angehängte Dateien:

Lesenswert?

Jetzt bekomme ich eine Fehlermeldung:
main.c:116: warning: implicit declaration of function 'pwm_setting'

Kannst Du mir bitte einen Hinweis geben was ich übersehen habe.

Danke und Gruss
Firebird

von Frank L. (franklink)


Lesenswert?

Hallo, Du hast das #define pwm_setting nicht einkommentiert.
1
#define NR_CASES 5      // Anzahl Cases
2
#define NR_VALUES  16    // Entspricht PWM_CHANNELS 16
3
4
// Makro zur einfacheren Handhabung
5
//#define pwm_setting(channel, value) pwm_value[channel] = PWM_MAX - values

muss so lauten:
1
#define NR_CASES 5      // Anzahl Cases
2
#define NR_VALUES  16    // Entspricht PWM_CHANNELS 16
3
4
// Makro zur einfacheren Handhabung
5
#define pwm_setting(channel, value) pwm_value[channel] = PWM_MAX - values

Gruß
Frank

von Firebird (Gast)


Lesenswert?

@ Frank
1
pwm_setting(channel, value)
wurde mit der ellenlangen 'switch' Anweisung rausgenommen. Für welchen 
Teil des Programms braucht es die Makro?

Gruss
Firebird

von Frank L. (franklink)


Lesenswert?

Hallo,

steht etwas weiter oben, geschrieben von  Karl heinz Buchegger.

Bist Du sicher, dass Du weisst was Du tust?

Gruß
Frank

von Firebird (Gast)


Lesenswert?

@ Frank

Karl heinz Buchegger schrieb:

>Vergiss das Makro. Du brauchst es nicht.
>Schreib
>
1
>pwm_value[i] = PWM_MAX - Cases[caseNr].Values[i];
>
>ist genausogut wie dein Makro und man sieht wenigstens was wirklich
>passiert.

Es ist bestimmt eine Kleinigkeit das ich übersehe.

Gruss
Firebird

von Karl H. (kbuchegg)


Lesenswert?

Firebird schrieb:
> @ Frank
>
> Karl heinz Buchegger schrieb:
>
>>Vergiss das Makro. Du brauchst es nicht.
>>Schreib
>>
>
1
>pwm_value[i] = PWM_MAX - Cases[caseNr].Values[i];
>>
>>ist genausogut wie dein Makro und man sieht wenigstens was wirklich
>>passiert.
>
> Es ist bestimmt eine Kleinigkeit das ich übersehe.
>

Nein. Keine Kleinigkeit.

Du sollst dort, wo du das Makro verwendest, anstelle des Makros den 
Inhalt des Makros einsetzen.

Anstatt
1
    for( i = 0; i < NR_VALUES; ++i )
2
      pwm_setting( i, Cases[caseNr].Values[i] );

das hier
1
    for( i = 0; i < NR_VALUES; ++i )
2
      pwm_value[i] = PWM_MAX - Cases[caseNr].Values[i];

Denn genau das macht der Präprozessor aus deinem Makro.
Ich dachte eigentlich, dass das sonnenklar sei. Aber man lernt nie aus.

von Karl H. (kbuchegg)


Lesenswert?

So.
Und jetzt rückst du mal dein Programm richtig ein und achtest auch 
darauf wo du { } hast, und wo nicht.

Im speziellen würde mich interessieren, wie du dir vorstellst, dass
1
  while(1)
2
  
3
  input = ~PINC;    // Schalterkombination an "input" ?ben

jemals den Teil nach dem input = ~PINC ausführen soll, wenn du keine { } 
um den Block hast.

von Firebird (Gast)


Lesenswert?

Das Fehlen der {} habe ich übersehen und der Hinweis mit dem Makro hatte 
ich falsch verstanden.

Jetzt funktioniert alles wie gewünscht.

Danke an allen fürs Mitwirken und Helfen.
MfG
Firebird

von Karl H. (kbuchegg)


Lesenswert?

Firebird schrieb:
> Das Fehlen der {} habe ich übersehen.

Genau darum gehts.
Wenn du dein Programm sauber einrückst, dann kannst du das nicht 
übersehen. Eine optisch saubere Programmstruktur ist nicht nur reiner 
Selbstzweck sondern auch ein Fehlerverhütungs bzw. 
Fehlersuchmechanismus.

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.