www.mikrocontroller.net

Forum: Compiler & IDEs Folgenden Code vereinfachen


Autor: Christian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bin grad dabei einen Code zu schreiben.

Wie könnte man das vereinfachen...?

if (a==0) write_0();
  if (a==1) write_1();
  if (a==2) write_2();
  if (a==3) write_3();
  if (a==4) write_4();
  if (a==5) write_5();
  if (a==6) write_6();
  if (a==7) write_7();
  if (a==8) write_8();
  if (a==9) write_9();

danke für eure antworten

Autor: Björn Zacher (whocares)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
switch ?!? Nur so n vorschlag

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Christian!

Was macht denn jeweils write_n();?

Grüße

Chris

Autor: Christian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
write_n

n die zahl die am 7 seg ausgegeben wird
also irgendwelche werte auf einem port.

mfg

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Christian!

Häng doch mal den Quelltext (bzw. einen Ausschnitt) davon an.
Sagt mehr als ewiges herumgestocher in der Luft ;)

Grüße

Chris

Autor: Stefan M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mach ein array, das du schon zur design-zeit mit konstanten werten
füllst (für die jeweiligen ziffern der 7seg. anzeige)

dann musst du nurnoch die entsprechende zahl auswählen aus diesem
array

pseudocode ungefähr so:

array ziffern[11000, 00101, 10111]  (die versch. kodierungen der
ziffern)

darauf kannst du dann mit einem index zugreifen, z.b. willst du die
zahl "1" auf der 7seg. ausgeben, machst du:

port = ziffern[1]

ziffern[1] hätte in diesem beispiel den wert 00101, dies wär dann das
was auf dem port ausgegeben wird.

--> spart code, rechenzeit und nerven

Autor: Christian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hab mal einen bekannten gefragt der hat gemeint das geht mit einer
sprungtabelle am besten geht wenn es durchgängige werte sind.

wie heißt das im c im fachjargon? -> zu sprungtabelle hab ich im google
fast nichts gefunden.

mfg

Autor: The Daz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sprungtabellen sind arrays von Funktions-Pointern. Also z.B.

void(*)(void) sprungTabelle[10] = {
   write_1,
   write_2, ...
};

in main dann :

   sprungTabelle[a]();

Ist aber in deinem Fall ueberfluessig, Stefans Vorschlag erscheint mir
auch am sinnvollsten.

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schreibe nur eine write-Funktion für alle Ziffern, z.B.:
#include<io.h>

typedef unsigned char  u8;
typedef   signed char  s8;
typedef unsigned short u16;
typedef   signed short s16;
typedef unsigned long  u32;
typedef   signed long  s32;


#define _A      0x02                            //segment order
#define _B      0x04
#define _C      0x40
#define _D      0x10
#define _E      0x08
#define _F      0x01
#define _G      0x20
#define _DP     0x80                            //decimal point

#define _0      (u8)~( _A+_B+_C+_D+_E+_F     )  //number pattern, low
active
#define _1      (u8)~(    _B+_C             )
#define _2      (u8)~( _A+_B+   _D+_E+   _G )
#define _3      (u8)~( _A+_B+_C+_D+      _G )
#define _4      (u8)~(    _B+_C+      _F+_G )
#define _5      (u8)~( _A+   _C+_D+   _F+_G )
#define _6      (u8)~( _A+   _C+_D+_E+_F+_G )
#define _7      (u8)~( _A+_B+_C             )
#define _8      (u8)~( _A+_B+_C+_D+_E+_F+_G )
#define _9      (u8)~( _A+_B+_C+_D   +_F+_G )

u8 numbers[] = { _0, _1, _2, _3, _4, _5, _6, _7, _8, _9 };



// und hier kommt die super Funktion !!!

void write_0_9( u8 val )
{
  PORTA = numbers[val];
}


Peter

Autor: Ingo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Einfachster Code ( wie in Teilen bereits oben vorgeschlagen):

uint8_t digits =
{
  0b0000000, // Eine 1 z.B. für das Segment, das leuchten soll
  0b0000011,
  ... // usw. jeweils die bitmuster die Du brauchst
}

void write( uint8_t i )
{
  PORT = digits[i]
}

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Ingo,

nicht in Teilen, sondern ganz genau so.


Peter

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

Bewertung
0 lesenswert
nicht lesenswert
Nicht ganz.
Ingo hat einen Fehler eingebaut :-)

uint8_t digits [] =

              ****

Und Peters Art die Konstanten zu bestimmen ist wesentlich
schöner und übersichtlicher als die Bitmuster selbst
zu bestimmen. Nach dem Motto: Lass den Compiler sich
um die Bitdetails kümmern, der Programmierer soll sich
nicht mit so einem Taschenrechnerkram rumärgern.

Autor: Werner B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sprungtabelle:

Statt der Werte die Ausgegeben werden sollen stehen in der Tabelle die
Adressen der jeweiligen Ausgabefunktion => Unnötiger Overhead im
Quadrat

==>  Sprungtabelle == Mit Kanonen auf Spatzen schießen!

Autor: Ingo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter & Karl-Heinz:

Ihr habt ja recht. Pfui über mich!

Dann aber vielleicht noch:
#define _A      (1<<PIN1)

statt magic number?

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

Bewertung
0 lesenswert
nicht lesenswert
> ==>  Sprungtabelle == Mit Kanonen auf Spatzen schießen!

Im gegenstaendlichen Fall: Ja, klar. Voellig unnoetig.

Aber um mal das Prinzip zu demonstrieren:
Ich hab vor Jahren mal eine Z80 Simulation am PC gemacht
(in C++).

Die wesentliche Hauptschleife sah so aus:

void CPU::Run()
{
  BYTE OpCode;

  while( 1 ) {
    OpCode = m_Ram[m_PC++];
    (this->*m_Fnktions[OpCode])();
  }
}

Dazu gibts dann einen Haufen Funktionen, die die Funktionalitaet
einzelner OP-Codes implementieren: zb

void CPU::CALL ()
{
  WORD Address = FetchAddress();
  PushStack( m_PC );
  m_PC = Address;
}

void CPU::RET ()
{
  m_PC = PopStack();
}

...

Dazu gibt es dann ein Array von Funktionszeigern ....

class CPU
{
  ....

  void( CPU::* m_Fnktions[256] )();
}

... welches die Verknüpfung von Op_Codes zu den einzelnen
Funktionen herstellt:

CPU::CPU()
{
  ...
  m_Fnktions[0xC9] = RET;
  ...
  m_Fnktions[0xCD] = CALL;
  ...

In der Run-Schleife wird ueber den Program-Counter m_PC der
nechste OP-Code aus dem (simulierten) RAM geholt

    OpCode = m_Ram[m_PC++];

dieser OpCode als Index in die Funktionszeiger-Tabelle genommen

  m_Fnktions[OpCode]

und die entsprechende Funktion aufgerufen:

  (this->*m_Fnktions[OpCode])();

(stoert euch jetzt nicht an der Syntax. Die ist in C++ so
notwendig, wenn man Funktionszeiger auf Memberfunktionen machen
moechte).

War also der OpCode gleich 0xCD dann wird die Funktion CALL
dafuer aufgerufen.

Autor: Ingo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sehr elegante Lösung!


Kannst Du mir bitte erklären warum man:

(this->*m_Fnktions[OpCode])();

schreiben muss und nicht

(this->m_Fnktions[OpCode])();

Im Array steht doch ein Zeiger auf eine Memberfunktion. Eigentlich ist
dann doch

(this->m_Fnktions[OpCode])

der Zeiger auf die Funktion, und

(this->m_Fnktions[OpCode])();

Dereferenzierung und Aufruf?

Fragt sich
Ingo

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

Bewertung
0 lesenswert
nicht lesenswert
(this->m_Fnktions[OpCode])();

koenntest Du benutzen, wenn in m_Fnktions lauter
Pointer auf freistehende Funktionen stünden. Das ist
aber hier nicht der Fall. m_Fnktions enthaelt Pointer
auf Memberfunktionen einer Klasse.
Memberfunktionen muessen aber anders aufgerufen werden
(der this Pointer innerhalb der Funktion muss ja besetzt
werden). Daher ist eine neue Syntax notwendig:  ->*

Autor: Ingo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Super, danke.

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.