mikrocontroller.net

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


Autor: Firebird (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
unsigned int pwm_setting[channel][value]={{0,1,...14,15},{5,25,2,15....10}}

Hier sind Code-Ausschnitte um den Fall zu verdeutlichen:
// Makro zur einfacheren Handhabung
#define pwm_setting(channel, value) pwm_value[channel] = PWM_MAX - value

int main(void)
{.....

  pwm_setting(0,0);
  // bis ....
  pwm_setting(15,0);    
  
    while(1)
    {
    input = PINC;    // Schalterkombination an "input" übergeben
   
    switch (input)
    {
      case 0xc1:
        pwm_setting(0,5);
        //bis....
        pwm_setting(15,17);
      break;

      case 0xd1:
        pwm_setting(0,25);
        // bis.... 
        pwm_setting(15,5);
        break;

      default:           
        pwm_setting(0,14);
        // bis....
        pwm_setting(15,28);
    }  
}
Ist es überhaupt möglich 'pwm_setting(channel, value)' als Array zu 
bestimmen? Wie setze ich das am Besten um?

Danke und Gruss
Firebird

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
uint8_t channels[256] = { ... };
uint8_t values[256] = { ... };

// etc. pp.

while (1)
{
  input = PINC;

  pwm_settings(channels[input], values[input]);
}

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?

Autor: Firebird (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe jetzt den Anhang nicht gelesen, aber vermutlich suchst du
so wetwas in der Art:
#define N_CHANNELS            16
#define N_VALUES_PER_CHANNEL 256

  unsigned int PWM_Value_tab[N_CHANNELS][N_VALUES_PER_CHANNEL] =
    {
      [0] = { 0, 1, 14, 15, 0 /* TODO: hier die restlichen 251 Einfügen... */ },
      [1] = { 0, 1, 14, 15, 0 /* TODO: hier die restlichen 251 Einfügen... */ },
      [2] = { 0, 1, 14, 15, 0 /* TODO: hier die restlichen 251 Einfügen... */ },
      /* TODO: hier weitere 12 Kanäle einfügen... */
      [15] = { 0, 1, 14, 15, 0 /* TODO: hier die restlichen 251 Einfügen... */ },
    };

   // ...

  while( "42" )
  {
    uint8_t   input = PORTC;
    size_t iChannel;
    for( iChannel=0; iChannel<N_CHANNELS; ++iChannel )
    {
      /* irgendwas_zu_setzen_fuer_PORTB_ODER_D = */ PWM_Value_tab[iChannel][input];
    }
  }

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.

Autor: Firebird (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.
  case 0xc1:               // Wenn PORTC = 11000001
    pwm_setting(0,0);      // (channel,value)  d.h. PB0 mit Wert 0
    pwm_setting(1,5);      // (channel,value)  d.h. PB1 mit Wert 5
    pwm_setting(2,5);      // (channel,value)  d.h. PB2 mit Wert 5
    pwm_setting(3,5);      // (channel,value)  d.h. PB3 mit Wert 5
    pwm_setting(4,0);      // (channel,value)  d.h. PB4 mit Wert 0
    pwm_setting(5,0);      // (channel,value)  d.h. PB5 mit Wert 0
    pwm_setting(7,0);      // (channel,value)  d.h. PB6 mit Wert 0
    pwm_setting(8,0);      // (channel,value)  d.h. PB6 mit Wert 0
    pwm_setting(9,0);      // (channel,value)  d.h. PB6 mit Wert 0
    pwm_setting(10,0);     // (channel,value)  d.h. PB6 mit Wert 0
    pwm_setting(11,0);     // (channel,value)  d.h. PB6 mit Wert 0
    pwm_setting(12,0);     // (channel,value)  d.h. PB6 mit Wert 0
    pwm_setting(13,5);     // (channel,value)  d.h. PB6 mit Wert 5
    pwm_setting(14,0);     // (channel,value)  d.h. PB6 mit Wert 0
    pwm_setting(15,0);     // (channel,value)  d.h. PB6 mit Wert 0
  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.
const uint8_t t1[8]={27, 40, 3, 17, 150, 99, 5, 9};
memcpy(pwm_setting, t1, 8);
Ich weiss nicht wie ich sowas ähnliches in meinem Code anwenden, bzw. 
umsetzen kann.

MfG
Firebird

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du suchst sowas
#define NR_CASES   5
#define NR_VALUES  16

unsigned char Values[ NR_CASES ][ NR_VALUES ] =
  { { 0,       5, 5,       5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0 },
    { 0, PWM_MAX, 5, PWM_MAX, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0 },
    { 0,       5, 5,       5, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0 },
    { 0, PWM_MAX, 5, PWM_MAX, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0 },
    { 0,       0, 0,       0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5 },
  };

...

    input = PINC;    // Schalterkombination an "input" übergeben
   
    switch (input)
    {
      case 0xc1:
        for( i = 0; i < NR_VALUES; ++i )
          pwm_setting( i, Values[0][i] );
        break;

      case 0xd1:
        for( i = 0; i < NR_VALUES; ++i )
          pwm_setting( i, Values[1][i] );
        break;

      ...

      default:           
        for( i = 0; i < NR_VALUES; ++i )
          pwm_setting( i, Values[4][i] );
    }  

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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:

#define NR_CASES   5
#define NR_VALUES  16

struct Led
{
  unsigned char InputValue;           // welcher Wert muss am PINC vorliegen ...
  unsigned char Values[ NR_VALUES ];  // ... damit diese Werte auf die Led ausgegeben werden
};

struct Led Cases[ NR_CASES ] =
  {
    { 0xC1,  { 0,       5, 5,       5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0 } },
    { 0xD1,  { 0, PWM_MAX, 5, PWM_MAX, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0 } },
    { 0xC5,  { 0,       5, 5,       5, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0 } },
    { 0xD5,  { 0, PWM_MAX, 5, PWM_MAX, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0 } },
    { 0x00,  { 0,       0, 0,       0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5 } },
  };

...

    input = PINC;    // Schalterkombination an "input" übergeben

    // den richtigen caseNr suchen
    // wird keiner gefunden, dann ist NR_CASES - 1 (also der letzte) der Default
    caseNr = NR_CASES - 1;
    for( i = 0; i < NR_CASES - 1; ++i )
    {
      if( Cases[i].InputValue == input )
      {
        caseNr = i;
        break;
      }
    }

    // die Werte für diesen Fall ausgeben
    for( i = 0; i < NR_VALUES; ++i )
      pwm_setting( i, Cases[caseNr].Values[i] );
    }

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.

Autor: Firebird (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Danke, sowas suchte ich. Nach einer kleinen Anpassung sieht der 
Code-Ausschnitt so aus:
unsigned char Values[ NR_CASES ][ PWM_CHANNELS ] =
  { { 0,       5, 5,       5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0 },
    { 0, PWM_MAX, 5, PWM_MAX, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0 },
    { 0,       5, 5,       5, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0 },
    { 0, PWM_MAX, 5, PWM_MAX, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0 },
    { 0,       0, 0,       0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5 },
    };

  sei();        // Interruptfreigabe
    
  while(1)
  
  input = ~PINC;    // Schalterkombination an "input" übergeben
   
    switch (input)
    {
      case 0xc1:
        for( i = 0;i < PWM_CHANNELS; i++ )
        pwm_setting( i, Values[0][i] );
      break;

      case 0xd1:
        for( i = 0; i < PWM_CHANNELS; ++i )
        pwm_setting( i, Values[1][i] );
      break;

      case 0xc5:
        for( i = 0; i < PWM_CHANNELS; ++i )
        pwm_setting( i, Values[2][i] );
      break;

      case 0xd5:
        for( i = 0; i < PWM_CHANNELS; ++i )
        pwm_setting( i, Values[3][i] );
      break;

      default:           
        for( i = 0; i < PWM_CHANNELS; ++i )
        pwm_setting( i, Values[4][i] );
    }  
  }
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

Autor: Firebird (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
pwm_setting( i, Cases[caseNr].Values[i] );
an die Definition
// Makro zur einfacheren Handhabung
#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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
>
pwm_setting( i, Cases[caseNr].Values[i] );
> an die Definition
>
> // Makro zur einfacheren Handhabung
> #define pwm_setting(channel, value) pwm_value[channel] = PWM_MAX - value
> 
> übergeben, bzw. anpassen?

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

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

Autor: Firebird (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Frank Link (franklink)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, Du hast das #define pwm_setting nicht einkommentiert.
#define NR_CASES 5      // Anzahl Cases
#define NR_VALUES  16    // Entspricht PWM_CHANNELS 16

// Makro zur einfacheren Handhabung
//#define pwm_setting(channel, value) pwm_value[channel] = PWM_MAX - values


muss so lauten:
#define NR_CASES 5      // Anzahl Cases
#define NR_VALUES  16    // Entspricht PWM_CHANNELS 16

// Makro zur einfacheren Handhabung
#define pwm_setting(channel, value) pwm_value[channel] = PWM_MAX - values


Gruß
Frank

Autor: Firebird (Gast)
Datum:

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

Gruss
Firebird

Autor: Frank Link (franklink)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

steht etwas weiter oben, geschrieben von  Karl heinz Buchegger.

Bist Du sicher, dass Du weisst was Du tust?

Gruß
Frank

Autor: Firebird (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Frank

Karl heinz Buchegger schrieb:

>Vergiss das Makro. Du brauchst es nicht.
>Schreib
>
>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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Firebird schrieb:
> @ Frank
>
> Karl heinz Buchegger schrieb:
>
>>Vergiss das Makro. Du brauchst es nicht.
>>Schreib
>>
>
>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
    for( i = 0; i < NR_VALUES; ++i )
      pwm_setting( i, Cases[caseNr].Values[i] );

das hier
    for( i = 0; i < NR_VALUES; ++i )
      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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
  while(1)
  
  input = ~PINC;    // Schalterkombination an "input" ?ben

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

Autor: Firebird (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.