diff --git a/main_kommentiert.c b/main_kommentiert.c index 0681faa..f38455d 100644 --- a/main_kommentiert.c +++ b/main_kommentiert.c @@ -439,7 +439,7 @@ void uart2_init(void) /** - * @brief Sendet ein einzelnes Zeichen über USART2 (Polling-basiert) + * @brief Sendet ein einzelnes Zeichen über USART2 * * @param zeichen ASCII-Zeichen, das übertragen werden soll * @@ -452,25 +452,6 @@ void uart2_init(void) * 1. Prüfen, ob Datenregister leer ist (TXE = 1) * 2. Schreiben des Zeichens in das DR-Register * 3. Hardware übernimmt serielle Ausgabe automatisch - * - * Technischer Hintergrund: - * - SR Bit 7 = TXE - * - DR = Data Register - * - Schreiben in DR startet die Übertragung - * - * TXE bedeutet: - * Das Datenregister ist leer und bereit für neue Daten. - * - * Wichtig: - * TXE ? TC - * TXE = Datenregister leer - * TC = Übertragung vollständig abgeschlossen (inkl. Stopbit) - * - * Diese Funktion wartet nur auf TXE, nicht auf TC. - * - * @note - * Blockierend – CPU wartet aktiv (Busy Waiting). - * Für hohe Datenraten oder Multitasking ungeeignet. */ void uart2_putChar(char zeichen) { @@ -478,7 +459,7 @@ void uart2_putChar(char zeichen) * Warten bis TXE (Bit 7 im Statusregister) gesetzt ist. * * USART2->SR & 0x80: - * 0x80 = 1000 0000b ? Bit 7 + * 0x80 = 1000 0000b ... Bit 7 auf 1 * * Solange TXE = 0 bleibt, * befindet sich noch ein Zeichen im Datenregister. @@ -488,52 +469,27 @@ void uart2_putChar(char zeichen) /** * Schreiben des Zeichens in das Datenregister. * - * DR ist 9 Bit breit (bei 9-Bit Modus), - * hier jedoch 8 Bit aktiv (8N1). - * * Das Schreiben startet sofort: * - Startbit wird generiert * - 8 Datenbits werden seriell ausgegeben * - Stopbit folgt - * - * Bitzeit bei 9600 Baud: - * 1 / 9600 ˜ 104 µs pro Bit - * - * Gesamtdauer pro Zeichen: - * 10 Bit ? ~1.04 ms */ USART2->DR = zeichen; } - /** - * @brief Sendet eine nullterminierte Zeichenkette über USART2 + * @brief Sendet eine Zeichenkette über USART2 * - * @param string Zeiger auf ein C-String-Array (char*) + * @param string Zeiger auf ein char-Array (char*) * * @details * Diese Funktion überträgt eine ASCII-Zeichenkette, - * die im klassischen C-Format vorliegt: * - * Stringstruktur: - * -------------------------------- - * 'H' 'a' 'l' 'l' 'o' '\0' - * -------------------------------- - * - * Das Stringende wird durch das Nullbyte ('\0') - * signalisiert. Dieses wird nicht mitgesendet. + * char-Array ist mit (\n) nullterminiert! + * Dieses wird nicht mitgesendet. * * Die Funktion arbeitet blockierend und ruft * für jedes Zeichen uart2_putChar() auf. - * - * Laufzeitverhalten: - * Bei 9600 Baud dauert ein Zeichen ˜ 1.04 ms. - * Ein 20-Zeichen-String benötigt also ˜ 20 ms. - * - * @note - * Keine Längenprüfung. - * Kein Timeout. - * Kein Schutz gegen NULL-Pointer. */ void uart2_putString(char* string) { @@ -543,9 +499,6 @@ void uart2_putString(char* string) * * Das Dereferenzieren (*string) liest * das aktuelle Zeichen im Speicher. - * - * ASCII-Wert 0 entspricht '\0' - * ? Ende der Zeichenkette. */ while(*string) { @@ -556,76 +509,11 @@ void uart2_putString(char* string) * *string liest das Zeichen. * string++ erhöht den Pointer * auf das nächste Zeichen. - * - * Post-Increment: - * Erst lesen, dann erhöhen. */ uart2_putChar(*string++); } } - -/** - * @brief Liest ein einzelnes Zeichen von USART2 (Polling-basiert) - * - * @return Empfangenes ASCII-Zeichen (8 Bit) - * - * @details - * Diese Funktion wartet solange, bis das RXNE-Bit - * (Receive Data Register Not Empty) im Statusregister (SR) - * gesetzt ist. - * - * Sobald RXNE = 1: - * - Ein vollständiges Zeichen wurde empfangen - * - Das Datenregister (DR) enthält gültige Daten - * - * Danach wird DR gelesen und als char zurückgegeben. - * - * Hardware-Ablauf: - * ----------------------------------------- - * UART Leitung ? Shift Register ? DR - * ----------------------------------------- - * - * RXNE wird gesetzt, sobald: - * - Startbit erkannt - * - 8 Datenbits korrekt empfangen - * - Stopbit validiert - * - * @note - * Blockierend – CPU wartet aktiv. - * Keine Fehlerprüfung (Framing, Overrun etc.). - */ -char uart2_getChar(void) -{ - /** - * Warten bis RXNE gesetzt ist. - * - * USART2->SR & 0x20: - * 0x20 = 0010 0000b ? Bit 5 - * - * RXNE = 1 bedeutet: - * Datenregister enthält neue Empfangsdaten. - * - * Solange RXNE = 0 bleibt, - * ist noch kein vollständiges Zeichen eingetroffen. - */ - while(!(USART2->SR & 0x20)); - - /** - * Lesen des Datenregisters. - * - * DR ist 9 Bit breit, - * hier aber im 8-Bit-Modus (M=0). - * - * & 0xFF maskiert auf 8 Bit. - * - * Wichtiger Nebeneffekt: - * Das Lesen von DR löscht das RXNE-Flag automatisch. - */ - return ((char) (USART2->DR & 0xFF)); -} - - /** * @brief Initialisiert ein Nextion-Event-Objekt * @@ -638,25 +526,6 @@ char uart2_getChar(void) * Diese Funktion setzt die Grundparameter eines * Nextion-Objekts und versetzt es in einen definierten * Startzustand. - * - * Strukturtyp (vereinfacht angenommen): - * - * typedef struct { - * uint8_t pid; // Page-ID - * uint8_t cid; // Component-ID - * const char *name; // Objektname im HMI - * void (*pophandler)(void); // Handler bei Loslassen - * void (*pushhandler)(void); // Handler bei Drücken - * } NexEventObj; - * - * Zweck: - * - Kapselung der UI-Komponenten - * - Einheitliche Initialisierung - * - Vermeidung undefinierter Pointer - * - * @note - * static ? nur innerhalb dieser Datei sichtbar. - * Keine globale Symbol-Exposition. */ static void NexEventObj_Init(NexEventObj *obj, uint8_t pid, uint8_t cid, const char *name) { @@ -665,7 +534,7 @@ static void NexEventObj_Init(NexEventObj *obj, uint8_t pid, uint8_t cid, const c * * pid referenziert die Seite im Nextion-HMI-Editor. * Beispiel: - * page0 ? pid = 0 + * page0 ... pid = 0 */ obj->pid = pid; @@ -679,13 +548,6 @@ static void NexEventObj_Init(NexEventObj *obj, uint8_t pid, uint8_t cid, const c /** * Speichert den Namen des UI-Elements. - * - * Wichtig für textbasierte Befehle wie: - * "fuellstand.val=50" - * - * const char* bedeutet: - * - Zeiger auf statischen String - * - Inhalt wird nicht verändert */ obj->name = name; @@ -694,10 +556,6 @@ static void NexEventObj_Init(NexEventObj *obj, uint8_t pid, uint8_t cid, const c * * pophandler wird ausgelöst, * wenn ein Button losgelassen wird. - * - * NULL verhindert: - * - Zufällige Funktionsaufrufe - * - HardFault durch ungültige Funktionspointer */ obj->pophandler = NULL; @@ -707,12 +565,11 @@ static void NexEventObj_Init(NexEventObj *obj, uint8_t pid, uint8_t cid, const c * pushhandler wird ausgelöst, * wenn ein Button gedrückt wird. * - * Initial NULL ? sicherer Zustand. + * Initial NULL ... sicherer Zustand. */ obj->pushhandler = NULL; } - /** * @brief Initialisiert alle verwendeten Nextion-UI-Objekte * @@ -720,37 +577,13 @@ static void NexEventObj_Init(NexEventObj *obj, uint8_t pid, uint8_t cid, const c * Diese Funktion ruft für jedes globale NexEventObj * die Initialisierungsroutine NexEventObj_Init() auf. * - * Ziel: - * - Verknüpfung der Firmware-Objekte - * mit den UI-Elementen im Nextion-Display - * - Setzen von Page-ID (pid) - * - Setzen von Component-ID (cid) - * - Hinterlegen des Objekt-Namens - * - * Architekturprinzip: - * Firmware kennt das UI nur über: - * - pid (Seite) - * - cid (Komponente) - * - name (String im HMI) - * - * Dadurch entsteht eine klare Trennung zwischen: - * Embedded-Logik ? HMI-Darstellung - * * @note * Alle Objekte liegen auf derselben Page (NEX_PID_MAIN) - * und vermutlich im selben Komponenten-Kontext. */ void configNexObjects(void) { /** * Füllstandsanzeige (ProgressBar) - * - * "fuellstand" muss exakt so - * im Nextion-Editor heißen. - * - * Wird später über: - * NexProgressBar_setValue() - * angesteuert. */ NexEventObj_Init(&fuellstandInd, NEX_PID_MAIN, @@ -799,11 +632,6 @@ void configNexObjects(void) /** * Textfeld für numerische Füllstandsausgabe - * - * Wahrscheinlich ein NexText-Objekt. - * - * Achtung: - * Name im HMI muss exakt "fuellstandn" heißen. */ NexEventObj_Init(&fuellstandText, NEX_PID_MAIN, @@ -811,12 +639,11 @@ void configNexObjects(void) "fuellstandn"); } - /** * @brief Setzt oder löscht den globalen Fehlerzustand * - * @param state true ? Fehler aktiv - * false ? Fehler behoben + * @param state true ... Fehler aktiv + * false ... Fehler behoben * * @details * Diese Funktion realisiert eine zustandsabhängige @@ -829,25 +656,17 @@ void configNexObjects(void) * • Hardware-Ausgang (Bit-Banding GPIO) * • UART-Debugausgabe * - * Implementiert als einfache endliche Zustandsmaschine (FSM): - * * Zustände: - * 0 ? Kein Fehler - * 1 ? Fehler aktiv - * - * Übergänge erfolgen nur bei Zustandsänderung. - * - * @note - * Verwendet statische Variablen zur Zustandsspeicherung. + * 0 ... Kein Fehler + * 1 ... Fehler aktiv */ void fehler(bool state) { /** * Speichert den letzten gesetzten Zustand. - * static ? bleibt über Funktionsaufrufe erhalten. + * static ... bleibt über Funktionsaufrufe erhalten. * * Initialwert = true - * (wird beim ersten Aufruf ignoriert) */ static bool lastStateF = true; @@ -879,8 +698,7 @@ void fehler(bool state) } /** - * Falls sich der Zustand nicht geändert hat: - * ? Keine Aktion notwendig. + * Falls sich der Zustand nicht geändert hat ... Keine Aktion notwendig. * * Verhindert: * - unnötige UART-Ausgaben @@ -910,23 +728,12 @@ void fehler(bool state) /** * Hardware-Ausgang setzen. * - * FEHLER ist ein Bit-Banding-Makro: - * ? Direkter atomarer Zugriff auf ein einzelnes ODR-Bit. - * - * Elektrisch: - * GPIO-Pin wird High. - * Mögliche Nutzung: - * - Fehler-LED - * - Summer - * - Sicherheitsabschaltung + * FEHLER ist ein Bit-Banding-Makro ... Direkter atomarer Zugriff auf ein einzelnes ODR-Bit. */ FEHLER = 1; /** * UART-Debugmeldung. - * - * \r\n = CR + LF - * Windows-kompatible Zeilenumbrüche. */ uart2_putString("Fehler aufgetreten!\r\n"); } @@ -951,12 +758,11 @@ void fehler(bool state) return; } - /** * @brief Steuert das Leerblasventil (Ein/Aus) mit Zustandsüberwachung * - * @param state true ? Ventil öffnen - * false ? Ventil schließen + * @param state true ... Ventil öffnen + * false ... Ventil schließen * * @details * Diese Funktion implementiert eine zustandsbasierte @@ -970,22 +776,14 @@ void fehler(bool state) * • GPIO-Ausgang (Bit-Banding) * • UART-Debugmeldung * - * Systemtechnisch handelt es sich um eine - * einfache 2-Zustands-FSM: - * - * Zustand 0 ? Ventil geschlossen - * Zustand 1 ? Ventil geöffnet - * - * @note - * Keine Entprellung notwendig, da rein softwareseitiger Aufruf. + * Zustand 0 ... Ventil geschlossen + * Zustand 1 ... Ventil geöffnet */ void leerBlasen(bool state) { /** * Speichert den zuletzt gesetzten Zustand. - * static ? bleibt über Funktionsaufrufe erhalten. - * - * Kein Initialwert gesetzt ? implizit 0. + * static ... bleibt über Funktionsaufrufe erhalten. */ static bool lastStateB; @@ -1016,8 +814,7 @@ void leerBlasen(bool state) } /** - * Wenn Zustand unverändert: - * ? keine Aktion. + * Wenn Zustand unverändert ... keine Aktion. * * Verhindert: * - unnötige UART-Ausgaben @@ -1048,18 +845,11 @@ void leerBlasen(bool state) * GPIO setzen via Bit-Banding. * * Atomarer Zugriff auf einzelnes ODR-Bit. - * - * Elektrische Wirkung: - * - Ausgang High - * - Transistor / Treiber aktiviert - * - Magnetventil bekommt Versorgung */ LEERBLASEN = 1; /** * Debugmeldung über UART. - * - * Blockierend (~30 ms bei 9600 Baud). */ uart2_putString("Leerblasventil geoeffnet!\r\n"); } @@ -1072,10 +862,6 @@ void leerBlasen(bool state) /** * GPIO löschen. - * - * Magnetfeld des Ventils bricht zusammen. - * Achtung: - * Freilaufdiode notwendig! */ LEERBLASEN = 0; @@ -1088,17 +874,14 @@ void leerBlasen(bool state) return; } - /** * @brief Steuert das Fein-Dosierventil (Ein/Aus) mit Zustandsüberwachung * - * @param state true ? Feinventil öffnen - * false ? Feinventil schließen + * @param state true ... Feinventil öffnen + * false ... Feinventil schließen * * @details - * Diese Funktion implementiert eine einfache - * zustandsabhängige Aktorsteuerung (Finite State Machine) - * für das Feinventil der Dosieranlage. + * Diese Funktion implementiert eine einfache Aktorsteuerung für das Feinventil der Dosieranlage. * * Aufgaben: * - Initialisierung beim ersten Funktionsaufruf @@ -1109,20 +892,14 @@ void leerBlasen(bool state) * • UART-Debugausgabe * * Zustände: - * 0 ? Ventil geschlossen - * 1 ? Ventil geöffnet - * - * @note - * Die Funktion ist deterministisch und besitzt - * keine dynamische Speicherallokation. + * 0 ... Ventil geschlossen + * 1 ... Ventil geöffnet */ void fein(bool state) { /** * Speichert den letzten Ventilzustand. - * static ? persistiert über Funktionsaufrufe. - * - * Implizit initialisiert mit 0 (false). + * static ... persistiert über Funktionsaufrufe. */ static bool lastStateFein; @@ -1154,9 +931,7 @@ void fein(bool state) /** * Falls sich der gewünschte Zustand - * nicht geändert hat: - * - * ? Keine Aktion durchführen. + * nicht geändert hat ... Keine Aktion durchführen. * * Verhindert: * - unnötiges Toggeln der Ventilspule @@ -1187,18 +962,11 @@ void fein(bool state) * GPIO-Bit setzen (Bit-Banding). * * Atomarer Zugriff auf einzelnes ODR-Bit. - * - * Elektrisch: - * - Ausgang HIGH - * - Treibertransistor aktiviert - * - Magnetspule des Feinventils wird bestromt */ FEIN = 1; /** * UART-Debugmeldung. - * - * Blockierend (~25–30 ms bei 9600 Baud). */ uart2_putString("Feinventil geoeffnet!\r\n"); } @@ -1210,10 +978,7 @@ void fein(bool state) NexProgressBar_setValue(&feinInd, 0); /** - * Ventil abschalten. - * - * Strom durch Spule wird unterbrochen. - * Magnetfeld bricht zusammen. + * Feinventil abschalten. */ FEIN = 0; @@ -1226,17 +991,14 @@ void fein(bool state) return; } - /** * @brief Steuert das Grobventil (Ein/Aus) mit Zustandsüberwachung * - * @param state true ? Grobventil öffnen - * false ? Grobventil schließen + * @param state true ... Grobventil öffnen + * false ... Grobventil schließen * * @details - * Diese Funktion implementiert eine einfache, - * zustandsabhängige Aktorsteuerung (Finite State Machine) - * für das Grobventil der Dosieranlage. + * Diese Funktion implementiert eine einfache Aktorsteuerung für das Grobventil der Dosieranlage. * * Eigenschaften: * - Initialisierung beim ersten Aufruf @@ -1245,19 +1007,12 @@ void fein(bool state) * • Nextion-HMI-Anzeige * • GPIO-Ausgang (Bit-Banding) * • UART-Debugausgabe - * - * Funktionale Rolle im System: - * Das Grobventil liefert hohen Volumenstrom - * und wird typischerweise bei großem Abstand - * zum Sollwert aktiviert. */ void grob(bool state) { /** * Speichert den zuletzt gesetzten Zustand. - * static ? Wert bleibt zwischen Funktionsaufrufen erhalten. - * - * Implizite Initialisierung = false. + * static ... Wert bleibt zwischen Funktionsaufrufen erhalten. */ static bool lastStateGrob; @@ -1289,14 +1044,7 @@ void grob(bool state) /** * Falls gewünschter Zustand identisch - * mit dem letzten Zustand ist: - * - * ? Keine Aktion durchführen. - * - * Verhindert: - * - unnötige Magnetspulen-Schaltzyklen - * - unnötige UART-Last - * - unnötige HMI-Kommunikation + * mit dem letzten Zustand ist ... Keine Aktion durchführen. */ else if (state == lastStateGrob) { @@ -1322,17 +1070,11 @@ void grob(bool state) * GPIO setzen via Bit-Banding. * * Atomarer Zugriff auf ein einzelnes ODR-Bit. - * - * Elektrisch: - * - Ausgang HIGH - * - Treibertransistor aktiviert - * - Magnetspule des Grobventils wird bestromt */ GROB = 1; /** * Debugmeldung. - * Blockierend bei 9600 Baud. */ uart2_putString("Grobventil geoeffnet!\r\n"); } @@ -1345,9 +1087,6 @@ void grob(bool state) /** * Ventil deaktivieren. - * - * Spulenstrom wird unterbrochen. - * Magnetfeld kollabiert. */ GROB = 0; @@ -1360,17 +1099,14 @@ void grob(bool state) return; } - /** * @brief Steuert die Förderpumpe der Dosieranlage (Ein/Aus) * - * @param state true ? Pumpe einschalten - * false ? Pumpe ausschalten + * @param state true ... Pumpe einschalten + * false ... Pumpe ausschalten * * @details - * Diese Funktion implementiert eine einfache - * zustandsbasierte Steuerlogik (Finite State Machine) - * für die Hauptpumpe. + * Diese Funktion implementiert eine einfache Steuerlogik (Finite State Machine) für die Hauptpumpe. * * Eigenschaften: * - Initialisierung beim ersten Aufruf @@ -1379,21 +1115,12 @@ void grob(bool state) * • Nextion-HMI-Anzeige (ProgressBar) * • GPIO-Ausgang (Bit-Banding) * • UART-Debugausgabe - * - * Systemtechnische Rolle: - * Die Pumpe stellt den Systemdruck und Volumenstrom bereit. - * Ventile regeln anschließend die Feindosierung. - * - * @note - * Blockierende UART-Ausgabe bei Zustandswechsel. */ void pumpe(bool state) { /** * Speichert den zuletzt gesetzten Pumpenzustand. - * static ? persistiert über Funktionsaufrufe. - * - * Initialwert implizit = false. + * static ... persistiert über Funktionsaufrufe. */ static bool lastState; @@ -1415,8 +1142,7 @@ void pumpe(bool state) firstCall = false; /** - * ProgressBar auf 0% - * ? Pumpe aus anzeigen. + * ProgressBar auf 0% ... Pumpe aus anzeigen. */ NexProgressBar_setValue(&pumpeInd, 0); @@ -1425,14 +1151,7 @@ void pumpe(bool state) /** * Falls der gewünschte Zustand - * identisch mit dem letzten Zustand ist: - * - * ? Keine Aktion. - * - * Verhindert: - * - unnötiges Schalten von Relais/MOSFET - * - unnötige UART-Ausgaben - * - unnötige HMI-Kommunikation + * identisch mit dem letzten Zustand ist ... Keine Aktion. */ else if (state == lastState) { @@ -1456,20 +1175,11 @@ void pumpe(bool state) /** * GPIO-Bit setzen (Bit-Banding). - * - * Elektrisch: - * - Ausgang HIGH - * - Treibertransistor aktiviert - * - Motor erhält Versorgung - * - * Bei DC-Motor: - * ? Einschaltstrom (Inrush) beachten */ PUMPE = 1; /** * Debugmeldung. - * Blockiert CPU für ~20–30 ms bei 9600 Baud. */ uart2_putString("Pumpe eingeschaltet!\r\n"); } @@ -1482,9 +1192,6 @@ void pumpe(bool state) /** * GPIO löschen. - * - * Motor wird stromlos. - * Induktive Last ? Freilaufdiode erforderlich. */ PUMPE = 0; @@ -1497,7 +1204,6 @@ void pumpe(bool state) return; } - /** * @brief Aktualisiert die Füllstandsanzeige (0–100 %) * @@ -1514,8 +1220,8 @@ void pumpe(bool state) * - Debug-Ausgabe bei Änderung * * Wertebereich: - * 0 ? leer - * 100 ? voll + * 0 ... leer + * 100 ... voll * * @note * Datentyp int8_t erlaubt Werte von -128 bis +127. @@ -1557,13 +1263,7 @@ void fuellstand(int8_t value) } /** - * Falls sich der Wert nicht geändert hat: - * - * ? Keine Aktualisierung durchführen. - * - * Verhindert: - * - unnötige UART-Ausgaben - * - unnötige HMI-Kommandos + * Falls sich der Wert nicht geändert hat ... Keine Aktualisierung durchführen. */ else if (value == lastValue) { @@ -1592,17 +1292,13 @@ void fuellstand(int8_t value) /** * Debugmeldung. - * Blockierend (~20 ms bei 9600 Baud). */ uart2_putString("Fuellstand geaendert!\r\n"); } else { /** - * Ungültiger Wert ? Anzeige zurücksetzen. - * - * Sicherheitsmaßnahme gegen - * fehlerhafte Berechnungen. + * Ungültiger Wert ... Anzeige zurücksetzen. */ NexProgressBar_setValue(&fuellstandInd, 0); @@ -1613,11 +1309,10 @@ void fuellstand(int8_t value) } } - /** * @brief Skaliert einen Messwert auf Prozent (0–100 %) * - * @param value Eingangsgröße (z.B. ADC-Wert, Schalterwert) + * @param value Eingangsgröße * @param max Maximalwert der Eingangsgröße * * @return Prozentwert (0–100) @@ -1637,25 +1332,17 @@ void fuellstand(int8_t value) * Dadurch wird mathematisch korrekt gerundet * (statt immer abzurunden). * - * Eigenschaften: - * - Integer-Arithmetik (keine Float-Berechnung) - * - Deterministisch - * - Sehr schnell - * - Geeignet für Cortex-M3 ohne FPU - * * @note * max darf nicht 0 sein (Division durch 0!). */ uint8_t toPercent(uint8_t value, uint8_t max) { /** - * Clipping: * Falls value größer als max ist, * wird value auf max begrenzt. * * Verhindert: * - Prozentwerte > 100 - * - Überlauf bei Berechnung */ if (value > max) value = max; @@ -1664,23 +1351,20 @@ uint8_t toPercent(uint8_t value, uint8_t max) * Prozentberechnung mit Rundung. * * Schritt 1: - * value * 100 - * ? Skalierung auf Prozentbasis + * value * 100 ... Skalierung auf Prozentbasis * * Schritt 2: - * + max/2 - * ? Rundung auf nächstes Ganzzahl-Ergebnis + * + max/2 ... Rundung auf nächstes Ganzzahl-Ergebnis * * Schritt 3: * Division durch max * * Ganzzahl-Division rundet normalerweise ab. - * Durch +max/2 wird korrekt gerundet. + * Durch + max/2 wird korrekt gerundet. */ return (value * 100 + max / 2) / max; } - /** * @brief Setzt den numerischen Füllstandstext und aktualisiert die Prozentanzeige * @@ -1689,18 +1373,9 @@ uint8_t toPercent(uint8_t value, uint8_t max) * @details * Diese Funktion übernimmt zwei Aufgaben: * - * 1. Formatierung des absoluten Füllwerts als Text - * ? Anzeige in Litern auf dem Nextion-Display + * 1. Formatierung des absoluten Füllwerts als Text ... Anzeige in Litern auf dem Nextion-Display * - * 2. Umrechnung des Wertes in Prozent - * ? Aktualisierung der ProgressBar - * - * Systemarchitektur: - * Absolutwert (0–255) ? Textanzeige "xxx l" - * Absolutwert (0–255) ? Skalierung ? Prozentanzeige - * - * @note - * Verwendet sprintf(), daher relativ hoher Stack- und Laufzeitbedarf. + * 2. Umrechnung des Wertes in Prozent ... Aktualisierung der ProgressBar */ void setFuellstand(uint8_t value) { @@ -1708,39 +1383,24 @@ void setFuellstand(uint8_t value) * Lokaler Zeichenpuffer. * * Größe: 20 Byte - * - * Maximaler Inhalt: - * "255 l" + '\0' - * - * 20 Byte sind mehr als ausreichend. */ char buf[20]; /** * Formatierung des Wertes als String. * - * "%u l" - * - * %u ? unsigned Integer - * " l" ? Einheit Liter - * - * Beispiel: - * value = 123 - * buf = "123 l" + * "%u l": + * - %u ... unsigned Integer + * - " l" ... Einheit Liter * * sprintf: * - erzeugt Null-terminierten String - * - blockierend - * - relativ rechenintensiv */ sprintf(buf, "%u l", value); /** * Übergibt den formatierten Text * an das Nextion-Textobjekt. - * - * Intern wird ein UART-Befehl erzeugt: - * "fuellstandn.txt=\"123 l\"" */ NexText_setText(&fuellstandText, buf); @@ -1749,27 +1409,24 @@ void setFuellstand(uint8_t value) * * value (0–255) wird linear auf * 0–100 % skaliert. - * - * 255 entspricht 100 % */ fuellstand(toPercent(value, 255)); } - /** - * @brief Wandelt den Zustand der DIP-Schalter in einen Integerwert um + * @brief Wandelt den Zustand der DIP-Schalter in einen Integerwert um. * * @return Ganzzahlige Bitkodierung der Schalterzustände * * @details * Diese Funktion liest die digitalen Eingänge aus dem - * globalen Pointer-Array `Switch[]` ein und erzeugt daraus + * globalen Pointer-Array "Switch[]" ein und erzeugt daraus * eine Bitmaske. * * Logik: * - Jeder Schalter repräsentiert ein Bit. - * - Schalter gedrückt (Low-Pegel) ? Bit wird gesetzt. - * - Schalter offen (High-Pegel) ? Bit bleibt 0. + * - Schalter gedrückt (Low-Pegel) ... Bit wird gesetzt. + * - Schalter offen (High-Pegel) ... Bit bleibt 0. * * Daraus ergibt sich: * result = Summe( 2^i ) für alle aktiven Schalter. @@ -1778,12 +1435,7 @@ void setFuellstand(uint8_t value) * Switch0 = aktiv * Switch1 = inaktiv * Switch2 = aktiv - * - * ? result = 0000 0101b = 5 - * - * @note - * Die Eingänge sind offenbar mit Pull-Ups beschaltet - * (Low-Active-Logik). + * - result = 0000 0101b = 5 */ int SwitchesToInt(void) { @@ -1796,7 +1448,7 @@ int SwitchesToInt(void) int result = 0; /** - * Schleifenindex (0–6). + * Zählvariable (0–6). */ uint8_t i = 0; @@ -1805,18 +1457,17 @@ int SwitchesToInt(void) * * Hinweis: * Switch[7] wird hier NICHT berücksichtigt. - * (Vermutlich separater Start-/Stop-Schalter) */ for (i = 0; i < 7; i++) { /** * Dereferenzieren des Zeigers: * - * Switch[i] ? Zeiger auf ein Bit-Banding-Register - * *Switch[i] ? aktueller GPIO-Pegel (0 oder 1) + * Switch[i] ... Zeiger auf ein Bit-Banding-Register + * *Switch[i] ... aktueller GPIO-Pegel (0 oder 1) * - * Low-Active-Logik: - * 0 ? Schalter gedrückt + * Active-Low-Logik: + * 0 ... Schalter gedrückt */ if (!*Switch[i]) { @@ -1826,13 +1477,12 @@ int SwitchesToInt(void) * (1 << i) * erzeugt eine Maske: * - * i = 0 ? 0000 0001 - * i = 1 ? 0000 0010 - * i = 2 ? 0000 0100 + * i = 0 ... 0000 0001 + * i = 1 ... 0000 0010 + * i = 2 ... 0000 0100 * ... * - * result |= Maske - * ? Bit wird gesetzt, andere bleiben erhalten. + * result |= Maske ... Bit wird gesetzt, andere bleiben erhalten. */ result |= (1 << i); } @@ -1845,9 +1495,8 @@ int SwitchesToInt(void) } - /** - * @brief Hauptprogramm der Dosieranlage + * @brief Hauptprogramm der Dosieranlage. * * @details * Implementiert: @@ -1858,12 +1507,10 @@ int SwitchesToInt(void) * - Leitungsleerblasen nach Dosierende * * Regelprinzip: - * - Grobventil ? hoher Durchfluss (Vorregelung) - * - Feinventil ? präzise Enddosierung - * - Pumpe ? Systemdruck - * - Nachlaufmodell ? Kompensation von Restvolumen - * - * System arbeitet rein polling-basiert. + * - Grobventil ... hoher Durchfluss (Vorregelung) + * - Feinventil ... präzise Enddosierung + * - Pumpe ... Systemdruck + * - Nachlaufmodell ... Kompensation von Restvolumen */ int main(void) { @@ -1876,7 +1523,7 @@ int main(void) /** * Nextion-Eventliste. - * Hier leer ? keine Touch-Events registriert. + * Hier leer ... keine Touch-Events registriert. */ NexEventObj *nextlisten_list[] = {NULL}; @@ -1910,7 +1557,7 @@ int main(void) while(1) { /** - * Nextion Event-Handling (falls später erweitert) + * Nextion Event-Handling */ Nex_Event_Loop(nextlisten_list); @@ -1923,13 +1570,12 @@ int main(void) uint8_t istWert = SwitchesToInt(); /** - * Effektiver Wert inkl. Nachlaufkompensation + * Effektiver Wert inklusive Nachlaufkompensation */ uint16_t effektiverWert = istWert + nachlaufOffset; /** - * Start-Schalter (Switch[7]) Low-Active? - * ? Dosierung aktiv + * Start-Schalter (Switch[7]) Low-Active? ... Dosierung aktiv */ if(*Switch[7] == 0) { @@ -1995,8 +1641,8 @@ int main(void) * 3 Sekunden Nachlaufkompensation * Aufgeteilt in NACHLAUF Schritte */ - int time = 3000 / NACHLAUF; - int rest = 3000 % NACHLAUF; + int time = 3000 / NACHLAUF; /**< 3 Sekunden in passende Teile dividieren */ + int rest = 3000 % NACHLAUF; /**< Rest berechnen */ uint8_t i = 0; for(i = 0; i < NACHLAUF; i++) @@ -2013,8 +1659,7 @@ int main(void) } /** - * Offset erhöhen - * ? simuliert Restvolumen + * Offset erhöhen ... simuliert Restvolumen */ nachlaufOffset += 1; @@ -2031,7 +1676,4 @@ int main(void) } } } - - return 0; /**< wird nie erreicht */ } -