Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
microcontrollertechnik:vorgaben_fuer_die_softwareentwicklung [2019/09/16 22:16] tfischer [Bewertung] |
microcontrollertechnik:vorgaben_fuer_die_softwareentwicklung [2024/06/20 00:25] mexleadmin [Bewertung] |
||
---|---|---|---|
Zeile 6: | Zeile 6: | ||
* Es empfiehlt sich für alle definierten und deklarierten Namen die Englische Sprache zu verwenden. Für Variablen, Funktionen und Kommentare darf die Deutsche Sprache genutzt werden. | * Es empfiehlt sich für alle definierten und deklarierten Namen die Englische Sprache zu verwenden. Für Variablen, Funktionen und Kommentare darf die Deutsche Sprache genutzt werden. | ||
- | * Eine detailliertere Liste ist im [[https:// | + | * Eine detailliertere Liste ist im [[https:// |
+ | * Neben der Struktur beim Programmieren zählt auch eine interessante und schöne Umsetzung für den Nutzer in die Bewertung. | ||
==== Kommentare ==== | ==== Kommentare ==== | ||
Zeile 18: | Zeile 19: | ||
++++Beschreibung| | ++++Beschreibung| | ||
- | <code c> | + | <sxh c; first-line: 1> |
/* ============================================================================ | /* ============================================================================ | ||
Zeile 24: | Zeile 25: | ||
============= | ============= | ||
- | Dateiname: | + | Dateiname: |
Autoren: | Autoren: | ||
Zeile 30: | Zeile 31: | ||
Version: | Version: | ||
- | Hardware: | + | Hardware: |
| | ||
- | Software: | + | Software: |
Funktion: | Funktion: | ||
Zeile 40: | Zeile 41: | ||
Displayanzeige: | Displayanzeige: | ||
| | ||
- | | Mein Programm | + | | Mein Programm |
- | | | + | |
| | ||
Zeile 53: | Zeile 54: | ||
Header-Files: | Header-Files: | ||
- | Module: | + | Module: |
- | 2) Werte ausgeben | + | 2) set_display_values: |
- | | + | 1) get_switch_state: ... |
- | | + | |
=============================================================================*/ | =============================================================================*/ | ||
- | </code> | + | </sxh> |
++++ | ++++ | ||
Zeile 67: | Zeile 68: | ||
++++Beispiel für Code-Kommentierung| | ++++Beispiel für Code-Kommentierung| | ||
- | |<fc # | + | |<fc # |
if(i==0) output=0; // wenn i = 1, output=0 | if(i==0) output=0; // wenn i = 1, output=0 | ||
- | </code> | + | </sxh> | |
- | |<fc # | + | |<fc # |
if(i==0) output=0; // nur für erstes Element wird der Output zurückgesetzt | if(i==0) output=0; // nur für erstes Element wird der Output zurückgesetzt | ||
- | </code> | + | </sxh> | |
++++ | ++++ | ||
Zeile 80: | Zeile 81: | ||
++++Beispiel für auskommentierten Code| | ++++Beispiel für auskommentierten Code| | ||
- | |<fc # | + | |<fc # |
... | ... | ||
if (i==1) output(" | if (i==1) output(" | ||
Zeile 89: | Zeile 90: | ||
... | ... | ||
- | </code> | + | </sxh> | |
- | |<fc # | + | |<fc # |
... | ... | ||
if (i==STARTWERT) LCDoutput(startAusgabe); | if (i==STARTWERT) LCDoutput(startAusgabe); | ||
Zeile 96: | Zeile 97: | ||
// Ausgabe, weil i <=1 | // Ausgabe, weil i <=1 | ||
... | ... | ||
- | </code> | + | </sxh> | |
++++ | ++++ | ||
Zeile 106: | Zeile 107: | ||
++++Beispiel für die vordefinierten Makros| | ++++Beispiel für die vordefinierten Makros| | ||
- | |<fc # | + | |<fc # |
# | # | ||
Zeile 120: | Zeile 121: | ||
... | ... | ||
} | } | ||
- | </code> | + | </sxh> | |
- | |<fc # | + | |<fc # |
// Makros | // Makros | ||
Zeile 136: | Zeile 137: | ||
... | ... | ||
} | } | ||
- | </code> | + | </sxh> | |
++++ | ++++ | ||
Zeile 142: | Zeile 143: | ||
==== Konstanten ==== | ==== Konstanten ==== | ||
- | * Konstanten per #define sollten z.B. für die feste Größe von Arrays verwendet werden. Sie können (bzw. werden) auch für hardwarenahe Werte, wie Portnummern, | + | * Konstanten per '' |
- | * Für andere | + | * Auch Werte in '' |
- | * Konstanten per # | + | * Bei Defines wird keine Typisierung überwacht. Ist dies notwendig |
+ | * Konstanten per '' | ||
* Falls Sie aus mehreren Wörtern zusammengefügt sind, sollten Sie **mit Unterstrich** | * Falls Sie aus mehreren Wörtern zusammengefügt sind, sollten Sie **mit Unterstrich** | ||
+ | <sxh c; first-line: 1> | ||
+ | enum tage {MONTAG, DIENSTAG, MITTWOCH, DONNERSTAG, FREITAG, SAMSTAG, SONNTAG}; | ||
+ | |||
+ | for (enum tage aktuellerTag = MONTAG; aktuellerTag <= SONNTAG; aktuellerTag++) | ||
+ | {...};</ | ||
++++Beispiel für Konstanten| | ++++Beispiel für Konstanten| | ||
- | |<fc # | + | {{tablelayout? |
+ | |<fc # | ||
// Konstanten | // Konstanten | ||
# | # | ||
# | # | ||
+ | # | ||
+ | # | ||
+ | # | ||
+ | # | ||
... | ... | ||
Zeile 161: | Zeile 173: | ||
... | ... | ||
- | </code> | + | </sxh> | |
- | |<fc # | + | |<fc # |
// Konstanten | // Konstanten | ||
Zeile 170: | Zeile 182: | ||
#define YMAX_LCD | #define YMAX_LCD | ||
+ | enum gameStates{ | ||
+ | GAMESTATE_INTRO, | ||
+ | GAMESTATE_STARTED, | ||
+ | GAMESTATE_PAUSED, | ||
+ | GAMESTATE_ENDED}; | ||
+ | |||
... | ... | ||
Zeile 176: | Zeile 194: | ||
... | ... | ||
- | </code> | + | </sxh> | |
++++ | ++++ | ||
Zeile 186: | Zeile 204: | ||
* Variablen beginnen mit Kleinbuchstaben. | * Variablen beginnen mit Kleinbuchstaben. | ||
* Falls Sie aus mehreren Wörtern zusammengefügt sind, so werden die folgenden Wörter **ohne Unterstrich** | * Falls Sie aus mehreren Wörtern zusammengefügt sind, so werden die folgenden Wörter **ohne Unterstrich** | ||
- | * Vermeiden Sie zu allgemeine Namen, wie anzahl, uebergabewert oder string. Sinnvoller sind Namen, wie anzahlBuchstaben, | + | * Vermeiden Sie zu allgemeine Namen, wie anzahl, uebergabewert oder string. Sinnvoller sind Namen, wie '' |
* Nutzen sie auch bei Zählvariablen aussagekräftige Namen. | * Nutzen sie auch bei Zählvariablen aussagekräftige Namen. | ||
- | * Auch kann eine zu allgemeine Deklaration kann zu Problemen führen. Schlecht ist z.B. "int a;". | + | * Auch kann eine zu allgemeine Deklaration kann zu Problemen führen. Schlecht ist z.B. '' |
- | * Es bietet sich an bei der Definition bereits zu initialisieren. Gut ist also "bool a=1;". | + | * Es bietet sich an bei der Definition bereits zu initialisieren. Gut ist also '' |
++++Beispiel für Variablen| | ++++Beispiel für Variablen| | ||
- | |<fc # | + | |<fc # |
// Variablen | // Variablen | ||
Zeile 203: | Zeile 221: | ||
char wasKopie2; | char wasKopie2; | ||
- | </code> | + | </sxh> | |
- | |<fc # | + | |<fc # |
// Variablen | // Variablen | ||
const int | const int | ||
uint8_t | uint8_t | ||
- | unsigned char | + | unsigned char |
bool zeichenAusgabe | bool zeichenAusgabe | ||
// ein Zeichen ausgegeben werden darf | // ein Zeichen ausgegeben werden darf | ||
- | </code> | + | </sxh> | |
++++ | ++++ | ||
Zeile 219: | Zeile 237: | ||
* Teilen Sie Ihr Projekt in sinnvolle Unterstrukturen. Diese sind meist Funktionen. Die Unterstrukturen sollten nicht zu groß werden, um die Übersichtlichkeit zu bewahren. | * Teilen Sie Ihr Projekt in sinnvolle Unterstrukturen. Diese sind meist Funktionen. Die Unterstrukturen sollten nicht zu groß werden, um die Übersichtlichkeit zu bewahren. | ||
- | * Bei größeren Programmen ist auch die Aufteilung in mehrere Dateien sinnvoll, also z.b. main.c, LED.c, motorDriver.c. Dabei sollte darauf geachtet werden, dass globalen Variablen und Konstanten jeweils nur im Kontext der einzelnen Dateien genutzt werden und, dass header-Dateien angelegt werden. Das ermöglicht ein separates Testen der unterschiedlichen Dateien (z.B. mit einer Datei testLED.c, welche LED.h inlcude't). | + | * Bei größeren Programmen ist auch die Aufteilung in mehrere Dateien sinnvoll, also z.b. '' |
- | * Nutzen Sie den Zeileneinschub den AtmelStudio | + | * Nutzen Sie den Zeileneinschub den Microchip Studio |
+ | * Für die Benennung von Funktionen bietet sich - wie bei Variablen - camelCase an. Zum leichteren Verständnis sollten die Funktionsnamen aus Objekt(e) und Verb zusammengesetzt werden (z.B. '' | ||
* Vermeiden Sie zu viele Leerzeilen. | * Vermeiden Sie zu viele Leerzeilen. | ||
- | * Für die Benennung von Funktionen bietet sich - wie bei Variablen - camelCase an. Zum leichteren Verständnis sollten die Funktionsnamen aus Objekt(e) und ggf. Verb zusammengesetzt werden (z.B. bool istGesendet() oder void I2CBotschaftSenden()). | ||
* Stellen Sie auch jeder Funktion eine kurze Beschreibung voran. Aus dieser sollte hervorgehen, | * Stellen Sie auch jeder Funktion eine kurze Beschreibung voran. Aus dieser sollte hervorgehen, | ||
++++Beispiel für Anweisungsblöcke| | ++++Beispiel für Anweisungsblöcke| | ||
- | |<fc # | + | |<fc # |
uint8_t unter2_neu(uint8_t Was) | uint8_t unter2_neu(uint8_t Was) | ||
{ | { | ||
Zeile 242: | Zeile 260: | ||
return 0; | return 0; | ||
} | } | ||
- | </code> | + | </sxh> | |
- | |<fc # | + | |<fc # |
uint8_t schluesselPositionFinden(uint8_t schluessel) | uint8_t schluesselPositionFinden(uint8_t schluessel) | ||
/* Das Array schluesselArray wird nach dem übergebenen Schlüssel durchsucht. | /* Das Array schluesselArray wird nach dem übergebenen Schlüssel durchsucht. | ||
Zeile 250: | Zeile 268: | ||
*/ | */ | ||
{ | { | ||
- | | + | for( int aktuelleSchluesselPosition=ERSTE_SCHLUESSEL_POSITION; a<=LETZTE_SCHLUESSEL_POSITION; aktuelleSchluesselPosition++) |
- | | + | |
{ // durchlaufe alle Schlüsselpositionen | { // durchlaufe alle Schlüsselpositionen | ||
- | if(schluesselArray[a]==schluessel) return | + | if(schluesselArray[aktuelleSchluesselPosition]==schluessel) return |
// falls Schlüssel gefunden, | // falls Schlüssel gefunden, | ||
}; // gib die erste Position zurück | }; // gib die erste Position zurück | ||
return 0; | return 0; | ||
} | } | ||
- | </code> | + | </sxh> In diesem Beispiel wäre der Funktionsname |
+ | |||
+ | ++++ | ||
+ | |||
+ | ==== Arrays, Schleifen und Abfragen ==== | ||
+ | * Es ist sinnvoll Deklaration und Definition der Schleifenvariable direkt in den if-Befehl zu packen. Also: '' | ||
+ | * Vermeiden Sie Zugriffe auf Bereiche von Arrays, welche nicht definiert wurden. So erhält man bei einem Array '' | ||
+ | |||
+ | ++++Beispiel für Arrays, Schleifen und Abfragen| | ||
+ | |||
+ | |<fc # | ||
+ | #define MAX 10 | ||
+ | |||
+ | uint8_t array[MAX]; | ||
+ | |||
+ | ... | ||
+ | for(unit8_t a = 0 ; a<=MAX ; a++) | ||
+ | { // durchlaufe alle Schlüsselpositionen | ||
+ | array[a*2] = array[a*2-1]; | ||
+ | }; | ||
+ | |||
+ | </ | ||
+ | |<fc # | ||
+ | #define MAX 10 | ||
+ | |||
+ | uint8_t array[MAX]; | ||
+ | |||
+ | ... | ||
+ | for(unit8_t a = 1 ; a<=MAX/2 ; a++) | ||
+ | { // durchlaufe alle notwendigen Schlüsselpositionen | ||
+ | array[a*2] = array[a*2-1]; | ||
+ | }; | ||
+ | |||
+ | </ | ||
++++ | ++++ | ||
Zeile 269: | Zeile 319: | ||
++++Beispiel für ähnliche Zeilen| | ++++Beispiel für ähnliche Zeilen| | ||
- | |<fc # | + | |<fc # |
... | ... | ||
temp = hunderter; | temp = hunderter; | ||
Zeile 284: | Zeile 334: | ||
... | ... | ||
- | </code> | + | </sxh> | |
- | |<fc # | + | |<fc # |
+ | #define ASCII_ZERO 0x30 | ||
+ | #define MOD_TEN 10 | ||
+ | |||
+ | #define DISP_LINE1 | ||
+ | |||
+ | #define DISP_POS0 | ||
+ | #define DISP_POS1 | ||
+ | #define DISP_POS2 | ||
... | ... | ||
void printDecimalDigit(int x, int y, int DigitToBePrint) | void printDecimalDigit(int x, int y, int DigitToBePrint) | ||
{ | { | ||
lcd_goto(x, | lcd_goto(x, | ||
- | lcd_putc(0x30 + DigitToBePrint%10); | + | lcd_putc(ASCII_ZERO |
}; | }; | ||
... | ... | ||
- | printDecimalDigit(1, 0, hunderter); | + | printDecimalDigit(DISP_LINE1, DISP_POS0, hunderter); |
- | printDecimalDigit(1, 1, zehner); | + | printDecimalDigit(DISP_LINE1, DISP_POS1, zehner); |
- | printDecimalDigit(1, 2, einer); | + | printDecimalDigit(DISP_LINE1, DISP_POS2, einer); |
... | ... | ||
- | </code> | + | </sxh> | |
++++ | ++++ | ||
* Prüfen Sie, ob aufeinanderfolgende, | * Prüfen Sie, ob aufeinanderfolgende, | ||
+ | * Auch Switch case kann auch durch verschiedene Vereinfachungen noch verbessert werden. | ||
+ | |||
++++Beispiel für Verzweigungen 1 - Umwandlung in Array | | ++++Beispiel für Verzweigungen 1 - Umwandlung in Array | | ||
- | |<fc # | + | |<fc # |
... | ... | ||
if (i==0) output(" | if (i==0) output(" | ||
Zeile 314: | Zeile 375: | ||
... | ... | ||
- | </code> | + | </sxh> | |
- | |<fc # | + | |<fc # |
+ | #define MAX_ANZ_AUSGABE 6 | ||
+ | #define MAX_ZEICHEN_AUSGABE 4 | ||
... | ... | ||
- | char AusgabeZahl[6][4] = { | + | char AusgabeZahl[MAX_ANZ_AUSGABE][MAX_ZEICHEN_AUSGABE] = { |
" | " | ||
" | " | ||
Zeile 328: | Zeile 392: | ||
outputToLCD(AusgabeZahl[i]); | outputToLCD(AusgabeZahl[i]); | ||
... | ... | ||
- | </code> | + | </sxh> | |
++++++++Beispiel für Verzweigungen 2 - Umwandlung in Switch-Case| | ++++++++Beispiel für Verzweigungen 2 - Umwandlung in Switch-Case| | ||
- | |<fc # | + | |<fc # |
... | ... | ||
if (i==0) doZero; | if (i==0) doZero; | ||
Zeile 342: | Zeile 406: | ||
... | ... | ||
- | </code> | + | </sxh> | |
- | |<fc # | + | |<fc # |
... | ... | ||
switch(i) { | switch(i) { | ||
Zeile 354: | Zeile 418: | ||
}; | }; | ||
... | ... | ||
- | </code> | + | </sxh> | |
- | ++++++++Beispiel für Verzweigungen 3 - Umwandlung in For-Next| | + | ++++++++Beispiel für Verzweigungen 3 - Optimierung von Switch-Case| |
- | |<fc # | + | |<fc # |
+ | ... | ||
+ | switch(i) { | ||
+ | case 1: doOne; | ||
+ | case 2: doOne; | ||
+ | case 3: doThree; | ||
+ | case 4: doFour; | ||
+ | case 5: doFive; | ||
+ | case 6: doOne; | ||
+ | case 7: doOne; | ||
+ | case 8: doOne; | ||
+ | case 9: doOne; | ||
+ | default: break; | ||
+ | }; | ||
+ | ... | ||
+ | |||
+ | </ | ||
+ | |<fc # | ||
+ | ... | ||
+ | switch(i) { | ||
+ | case 1: | ||
+ | case 2: // Einzelne Zahlen können mit case's untereinander ... | ||
+ | case 6 ... 9: doOne; | ||
+ | case 3: doThree; | ||
+ | case 4: doFour; | ||
+ | case 5: doFive; | ||
+ | default: | ||
+ | }; | ||
+ | ... | ||
+ | </ | ||
+ | |||
+ | ++++++++Beispiel für Verzweigungen 4 - Umwandlung in For-Next| | ||
+ | |||
+ | |<fc # | ||
... | ... | ||
if (( 0<i) && (i<= 7)) j=j+2; | if (( 0<i) && (i<= 7)) j=j+2; | ||
Zeile 368: | Zeile 465: | ||
... | ... | ||
- | </code> | + | </sxh> | |
- | |<fc # | + | |<fc # |
... | ... | ||
int maxSteps | int maxSteps | ||
Zeile 379: | Zeile 476: | ||
}; | }; | ||
... | ... | ||
- | </code> | + | </sxh> | |
++++ | ++++ | ||
Zeile 386: | Zeile 483: | ||
++++Beispiel für Verzweigungen 4 - Verwenden von Else if| | ++++Beispiel für Verzweigungen 4 - Verwenden von Else if| | ||
- | |<fc # | + | |<fc # |
... | ... | ||
if (( 0<i) && (i<= 7)) j=j+2; | if (( 0<i) && (i<= 7)) j=j+2; | ||
Zeile 396: | Zeile 493: | ||
... | ... | ||
- | </code> | + | </sxh> | |
- | |<fc # | + | |<fc # |
... | ... | ||
if (( 0<i) && (i<= 7)) { j = j + 2;} | if (( 0<i) && (i<= 7)) { j = j + 2;} | ||
Zeile 406: | Zeile 503: | ||
else if ((12<i) && (i<=20)) { j = j + 3;}; | else if ((12<i) && (i<=20)) { j = j + 3;}; | ||
... | ... | ||
- | </code> | + | </sxh> | |
++++++++Beispiel für Verzweigungen 5 - Reduzieren der Anweisungen| | ++++++++Beispiel für Verzweigungen 5 - Reduzieren der Anweisungen| | ||
- | |<fc # | + | |<fc # |
... | ... | ||
if (i<=7) { | if (i<=7) { | ||
Zeile 428: | Zeile 525: | ||
... | ... | ||
- | </code> | + | </sxh> | |
- | |<fc # | + | |<fc # |
- | <code c> | + | |
... | ... | ||
if (i<=7) { | if (i<=7) { | ||
Zeile 445: | Zeile 541: | ||
DoOne; | DoOne; | ||
... | ... | ||
- | </code> auch möglich, aber etwas schwerer leserlich: | + | </sxh> |
... | ... | ||
- | if (i< | + | if |
- | else | + | else{if |
- | | + | else if (12< |
- | else if (12< | + | |
DoZero; | DoZero; | ||
}; | }; | ||
DoOne; | DoOne; | ||
- | |||
... | ... | ||
- | </code> | + | </sxh> | |
++++ | ++++ | ||
Zeile 465: | Zeile 559: | ||
++++Beispiel für Schleifen 1 - main()| | ++++Beispiel für Schleifen 1 - main()| | ||
- | |<fc # | + | |<fc # |
void main() | void main() | ||
{ | { | ||
Zeile 477: | Zeile 571: | ||
} | } | ||
- | </code> | + | </sxh> | |
- | |<fc # | + | |<fc # |
void main() | void main() | ||
{ | { | ||
Zeile 494: | Zeile 588: | ||
} | } | ||
- | </code> | + | </sxh> | |
++++++++Beispiel für Schleifen 2 - Abbrechen von verschachtelten Schleifen| | ++++++++Beispiel für Schleifen 2 - Abbrechen von verschachtelten Schleifen| | ||
- | |<fc # | + | |<fc # |
for(int xpos=0; | for(int xpos=0; | ||
initYPos; | initYPos; | ||
Zeile 510: | Zeile 604: | ||
... | ... | ||
- | </code> | + | </sxh> | |
- | |<fc # | + | |<fc # |
int xposMax=10, yposMax=20; | int xposMax=10, yposMax=20; | ||
Zeile 526: | Zeile 620: | ||
... | ... | ||
- | </code> | + | </sxh> **Beachten Sie, dass in diesem Fall CancelButton eine Variable sein muss und sich zwischen den beiden if-Bedingungen nicht ändern darf (z.B. durch Interrupts).** |
++++ | ++++ | ||
- | * _delay_ms() und _delay_us() sind zu 99% nicht notwendig. Verwenden Sie stattdessen Interrupts, bzw. Timer. Es können z.B. durch Interrupts Takte angelegt werden: takt10ms, takt100ms, takt1s. Diese können dann im main() Verzweigungen in einer Zustandsmaschine | + | * _delay_ms() und _delay_us() sind zu 99% nicht notwendig. Verwenden Sie stattdessen Interrupts, bzw. Timer. |
+ | * Häufig bietet es sich an, in den Takten dann auch Verzweigungen in einer Zustandsmaschine | ||
* Wenn Sie Zahlen in Variablen speichern und diese auch mathematisch weiterverwenden, | * Wenn Sie Zahlen in Variablen speichern und diese auch mathematisch weiterverwenden, | ||
++++Beispiel für Variablen mit Ausgabe| | ++++Beispiel für Variablen mit Ausgabe| | ||
- | |<fc # | + | |<fc # |
... | ... | ||
Zahlenwert = (ADC_Wert/ | Zahlenwert = (ADC_Wert/ | ||
Zeile 542: | Zeile 637: | ||
... | ... | ||
- | </code> | + | </sxh> | |
- | |<fc # | + | |<fc # |
+ | |||
+ | #define ASCII_ZERO 0x30 | ||
+ | #define MOD_TEN 10 | ||
... | ... | ||
- | Laenge | + | Laenge |
Laengen[i] = Laenge; | Laengen[i] = Laenge; | ||
Flaeche | Flaeche | ||
- | LCD_putc(Laengen[i]+ | + | LCD_putc(Laengen[i]+ |
... | ... | ||
- | </code> \\ | + | </sxh> | |
++++ | ++++ | ||
Zeile 556: | Zeile 655: | ||
====== Bewertung ====== | ====== Bewertung ====== | ||
- | + | Zur Bewertung lege ich {{microcontrollertechnik:bewertung_ss24_prj99.xlsx|diese Checkliste (xls-File)}} als Maßstab an. | |
- | + | ||
- | Zur Bewertung lege ich {{:checkliste_290718.pdf|diese Checkliste}} | + | |