Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
microcontrollertechnik:5_menuefuehrung [2020/05/14 01:15] tfischer |
microcontrollertechnik:5_menuefuehrung [2024/03/29 20:24] (aktuell) mexleadmin |
||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
- | ====== | + | ====== |
- | <panel type=" | + | ==== Ziele ==== |
- | {{fa> | + | |
- | </ | + | |
+ | Nach dieser Lektion sollten Sie: | ||
+ | |||
+ | - wissen, wie man eine einfache Menüführung auf einem Display implementiert. | ||
+ | |||
+ | ==== Übung ==== | ||
+ | |||
+ | --> I. Vorarbeiten # | ||
+ | - Laden Sie folgende Datei herunter: | ||
+ | - {{microcontrollertechnik: | ||
+ | - {{microcontrollertechnik: | ||
+ | - {{microcontrollertechnik: | ||
+ | |||
+ | <-- | ||
+ | --> II. Analyse des fertigen Programms # | ||
+ | - Initialisieren des Programms | ||
+ | - Öffnen Sie SimulIDE und öffnen Sie dort mittels {{microcontrollertechnik: | ||
+ | - Laden Sie '' | ||
+ | - Zunächst wird eine Startanzeige mit dem Namen des Programms dargestellt. | ||
+ | - Als nächstes ist im Display ein Menu zu sehen, in dem verschiedene Programme P1 ... P4 durch Tastendruck auswählbar ist. Dadurch sind die bisherigen Programme auswählbar. Im Unterprogramm ermöglicht der Schalter S1 das Zurückspringen ins Menu. | ||
+ | - Das Programm zu diesem Hexfile soll nun erstellt werden | ||
+ | |||
+ | <-- | ||
+ | --> III. Eingabe in Microchip Studio # | ||
+ | <WRAP group>< | ||
+ | / | ||
+ | | ||
+ | Experiment 5: | ||
+ | ============= | ||
+ | |||
+ | Dateiname: | ||
+ | | ||
+ | Autoren: | ||
+ | Prof. G. Gruhler (Hochschule Heilbronn) | ||
+ | D. Chilachava (Georgische Technische Universitaet) | ||
+ | | ||
+ | Version: | ||
+ | | ||
+ | Hardware: | ||
+ | AVR-USB-PROGI Ver. 2.0 | ||
+ | | ||
+ | Software: | ||
+ | C-Compiler: | ||
+ | | ||
+ | Funktion: | ||
+ | programme verwaltet. Dies sind: | ||
+ | P1: Blinking LED | ||
+ | P2: Creating Sound | ||
+ | P3: Logic Functions | ||
+ | P4: Up/ | ||
+ | Der Start der Teilprogramme erfolgt den zugeordneten Funktions- | ||
+ | tasten. Nach dem Abbruch eines Teilprogramms (immer mit S1) | ||
+ | wird wieder die Programmauswahl gestartet. | ||
+ | | ||
+ | Displayanzeige: | ||
+ | +----------------+ | ||
+ | |- Experiment 5 -| | Main Level | | ||
+ | | Program Menu | | P1 P2 P3 P4 | | ||
+ | +----------------+ | ||
+ | | ||
+ | Anzeige fuer Teilprogramme siehe bei einzelnen Programmen | ||
+ | | ||
+ | Tastenfunktion: | ||
+ | Im Teilprogramm ist die Funktion unterschiedlich (siehe dort) | ||
+ | | ||
+ | Jumperstellung: | ||
+ | Schalter muss fuer des Buzzer zwischen geschlossen sein | ||
+ | | ||
+ | Fuses im uC: CKDIV8: Aus (keine generelle Vorteilung des Takts) | ||
+ | | ||
+ | Header-Files: | ||
+ | | ||
+ | =============================================================================*/ | ||
+ | | ||
+ | | ||
+ | // Deklarationen ============================================================== | ||
+ | | ||
+ | // Festlegung der Quarzfrequenz | ||
+ | #ifndef F_CPU | ||
+ | #define F_CPU 18432000UL // | ||
+ | # | ||
+ | | ||
+ | | ||
+ | // Include von Header-Dateien | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include " | ||
+ | | ||
+ | | ||
+ | // Makros | ||
+ | #define SET_BIT(BYTE, | ||
+ | #define CLR_BIT(BYTE, | ||
+ | #define TGL_BIT(BYTE, | ||
+ | #define GET_BIT(BYTE, | ||
+ | | ||
+ | // Konstanten | ||
+ | #define VORTEILER_WERT 90 | ||
+ | #define HUNDERTSTEL_WERT 10 | ||
+ | #define ZEHNTEL_WERT 10 | ||
+ | | ||
+ | #define ON_TIME 100 // | ||
+ | #define OFF_TIME 100 // | ||
+ | | ||
+ | #define MIN_PER 143 // | ||
+ | #define MAX_PER 239 // | ||
+ | #define WAIT_SND 2000// | ||
+ | #define WAIT_LED 1000// | ||
+ | |||
+ | #define ASC_ZERO 0x30// | ||
+ | #define ASC_ONE 0x31// | ||
+ | | ||
+ | | ||
+ | // Variable | ||
+ | unsigned char vorteiler | ||
+ | unsigned char hundertstel = HUNDERTSTEL_WERT; | ||
+ | unsigned char modus | ||
+ | | ||
+ | int counter = 0000; // Variable fuer Zaehler | ||
+ | | ||
+ | bool timertick; | ||
+ | bool takt10ms; | ||
+ | bool takt100ms; | ||
+ | | ||
+ | bool sw1_neu = 1; // Bitspeicher fuer Taste 1 | ||
+ | bool sw2_neu = 1; // Bitspeicher fuer Taste 2 | ||
+ | bool sw3_neu = 1; // Bitspeicher fuer Taste 3 | ||
+ | bool sw4_neu = 1; // Bitspeicher fuer Taste 4 | ||
+ | | ||
+ | bool sw1_alt = 1; // alter Wert von Taste 1 | ||
+ | bool sw2_alt = 1; // alter Wert von Taste 2 | ||
+ | bool sw3_alt = 1; // alter Wert von Taste 3 | ||
+ | bool sw4_alt = 1; // alter Wert von Taste 4 | ||
+ | | ||
+ | bool sw1_slope = 0; // Flankenspeicher fuer Taste 1 | ||
+ | bool sw2_slope = 0; // Flankenspeicher fuer Taste 2 | ||
+ | bool sw3_slope = 0; // Flankenspeicher fuer Taste 3 | ||
+ | bool sw4_slope = 0; // Flankenspeicher fuer Taste 4 | ||
+ | | ||
+ | | ||
+ | // Funktionsprototypen | ||
+ | void initTimer0(void); | ||
+ | void initDisplay(void); | ||
+ | |||
+ | void readButton(void); | ||
+ | void getChoiceInMainMenu(void); | ||
+ | void showMainDisplay(void); | ||
+ | | ||
+ | void doBlinkingLed(void); | ||
+ | void showBlinkingLedDisplay(void); | ||
+ | | ||
+ | void doSound(void); | ||
+ | void showSoundDisplay(void); | ||
+ | | ||
+ | void doLogicFunctions(void); | ||
+ | void showLogicDisplay(void); | ||
+ | | ||
+ | void doCounterProg(void); | ||
+ | void showCounterDisplay(void); | ||
+ | | ||
+ | // Hauptprogramm ============================================================== | ||
+ | | ||
+ | int main() | ||
+ | { | ||
+ | initDisplay(); | ||
+ | | ||
+ | TCCR2A = 0; // Timer 2 auf " | ||
+ | TCCR2B |= (1<< | ||
+ | TIMSK2 |= (1<< | ||
+ | | ||
+ | sei(); | ||
+ | | ||
+ | while(1) // | ||
+ | { | ||
+ | switch(modus) // | ||
+ | { | ||
+ | case 0: // Modus 0: Hauptmenu | ||
+ | showMainDisplay(); | ||
+ | getChoiceInMainMenu(); | ||
+ | break; | ||
+ | | ||
+ | case 1: // Modus 1: Blinkende LED | ||
+ | doBlinkingLed(); | ||
+ | modus = 0; // danach auf Hauptmenu zurueckschalten | ||
+ | break; | ||
+ | | ||
+ | case 2: // Modus 2: Soundgenerierung | ||
+ | doSound(); | ||
+ | modus = 0; // danach auf Hauptmenu zurueckschalten | ||
+ | break; | ||
+ | | ||
+ | case 3: // Modus 3: Logische Funktionen | ||
+ | doLogicFunctions(); | ||
+ | modus = 0; // danach auf Hauptmenu zurueckschalten | ||
+ | break; | ||
+ | | ||
+ | case 4: // Modus 4: Up-Down-Counter | ||
+ | doCounterProg(); | ||
+ | modus = 0; // danach auf Hauptmenu zurueckschalten | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | return 0; | ||
+ | } | ||
+ | | ||
+ | | ||
+ | // Interrupt-Routine ========================================================== | ||
+ | ISR(TIMER2_OVF_vect) | ||
+ | | ||
+ | // In der Interrupt-Routine sind die Softwareteiler realisiert, durch die Takt- | ||
+ | // botschaften (10ms, 100ms) erzeugt werden. Die Interrupts werden von Timer 2 | ||
+ | // ausgeloest. | ||
+ | | ||
+ | { | ||
+ | timertick = 1; // Botschaft 0,166ms senden | ||
+ | --vorteiler; | ||
+ | if (vorteiler==0) // | ||
+ | { | ||
+ | vorteiler = VORTEILER_WERT; | ||
+ | takt10ms = 1; | ||
+ | readButton(); | ||
+ | --hundertstel; | ||
+ | | ||
+ | if (hundertstel==0) // | ||
+ | { | ||
+ | hundertstel = HUNDERTSTEL_WERT; | ||
+ | takt100ms = 1; | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | | ||
+ | // Funktion Tasten einlesen =================================================== | ||
+ | void readButton(void) | ||
+ | { | ||
+ | // | ||
+ | // | ||
+ | DDRC = DDRC & | ||
+ | PORTC = 0b00001111; | ||
+ | _delay_us(1); | ||
+ | |||
+ | // Einlesen der 4 Tastensignale | ||
+ | sw1_neu = (PINC & (1 << PC0)); | ||
+ | sw2_neu = (PINC & (1 << PC1)); | ||
+ | sw3_neu = (PINC & (1 << PC2)); | ||
+ | sw4_neu = (PINC & (1 << PC3)); | ||
+ | | ||
+ | DDRC = DDRC | 0b00001111; | ||
+ | |||
+ | // Auswerten der Flanken beim Druecken | ||
+ | | ||
+ | if ((sw1_neu==0)& | ||
+ | sw1_slope = 1; | ||
+ | | ||
+ | if ((sw2_neu==0)& | ||
+ | sw2_slope = 1; | ||
+ | | ||
+ | if ((sw3_neu==0)& | ||
+ | sw3_slope = 1; | ||
+ | | ||
+ | if ((sw4_neu==0)& | ||
+ | sw4_slope = 1; | ||
+ | | ||
+ | // Zwischenspeichern aktuelle Tastenwerte | ||
+ | sw1_alt = sw1_neu; | ||
+ | sw2_alt = sw2_neu; | ||
+ | sw3_alt = sw3_neu; | ||
+ | sw4_alt = sw4_neu; | ||
+ | } | ||
+ | |||
+ | | ||
+ | // Initialisierung Display-Anzeige ============================================ | ||
+ | void initDisplay() | ||
+ | { | ||
+ | lcd_init(); | ||
+ | | ||
+ | lcd_gotoxy(0, | ||
+ | lcd_putstr(" | ||
+ | | ||
+ | lcd_gotoxy(1, | ||
+ | lcd_putstr(" | ||
+ | | ||
+ | _delay_ms(2000); | ||
+ | | ||
+ | showMainDisplay(); | ||
+ | } | ||
+ | | ||
+ | | ||
+ | // Anzeige Hauptmenu ========================================================== | ||
+ | void showMainDisplay() | ||
+ | { | ||
+ | lcd_gotoxy(0, | ||
+ | lcd_putstr(" | ||
+ | | ||
+ | lcd_gotoxy(1, | ||
+ | lcd_putstr(" | ||
+ | | ||
+ | } | ||
+ | |||
+ | | ||
+ | /* Teilprogramm 1: Blinkende LED ============================================== | ||
+ | | ||
+ | Funktion: | ||
+ | Periodendauer von 2 Sekunden (1 s ein, 1 s aus). Auf dem LCD- | ||
+ | Display wird rechts unten der Wert der LED (" | ||
+ | Zahl dargestellt. Abbruch mit Taste S1 nach voller Periode. | ||
+ | | ||
+ | Displayanzeige: | ||
+ | |P1: Blinking LED| | ||
+ | |Home | ||
+ | +----------------+ | ||
+ | | ||
+ | Tastenfunktion: | ||
+ | | ||
+ | ============================================================================ */ | ||
+ | void doBlinkingLed() | ||
+ | { | ||
+ | | ||
+ | showBlinkingLedDisplay(); | ||
+ | SET_BIT(DDRB, | ||
+ | | ||
+ | while(!sw1_slope) | ||
+ | { | ||
+ | SET_BIT(PORTB, | ||
+ | lcd_gotoxy(1, | ||
+ | lcd_putc(ASC_ONE); | ||
+ | | ||
+ | _delay_ms(WAIT_LED); | ||
+ | | ||
+ | CLR_BIT(PORTB, | ||
+ | lcd_gotoxy(1, | ||
+ | lcd_putc(ASC_ZERO); | ||
+ | | ||
+ | _delay_ms(WAIT_LED); | ||
+ | | ||
+ | } | ||
+ | | ||
+ | sw1_slope = 0; // Alle Flankenbits loeschen | ||
+ | sw2_slope = 0; | ||
+ | sw3_slope = 0; | ||
+ | sw4_slope = 0; | ||
+ | } | ||
+ | | ||
+ | | ||
+ | // Anzeige zu Teilprogramm 1 | ||
+ | void showBlinkingLedDisplay() | ||
+ | { | ||
+ | lcd_gotoxy(0, | ||
+ | lcd_putstr(" | ||
+ | | ||
+ | lcd_gotoxy(1, | ||
+ | lcd_putstr(" | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | /* Teilprogramm 2: Soundgenerierung =========================================== | ||
+ | | ||
+ | Funktion: | ||
+ | wird ein sirenenartiger Sound ausgegeben. Zwischen den auf- | ||
+ | und absteigenden Tönen bleibt die Frequenz kurz stabil. | ||
+ | Die Frequenz wird mit dem Timer 0 (im CTC-Mode) erzeugt und | ||
+ | direkt über den Output-Compare-Pin im Toggle-Mode ausgegeben. | ||
+ | Die jeweilige Periodendauer wird dreistellig in Timerticks | ||
+ | auf der Anzeige rechts unten dargestellt. | ||
+ | | ||
+ | Displayanzeige: | ||
+ | |P2: Create Sound| | ||
+ | |Home 123| | ||
+ | +----------------+ | ||
+ | | ||
+ | Tastenfunktion: | ||
+ | gesamten Sound-Zyklus | ||
+ | | ||
+ | ============================================================================ */ | ||
+ | void doSound() | ||
+ | { | ||
+ | unsigned char temp = 0; // lokale Variable | ||
+ | | ||
+ | showSoundDisplay(); | ||
+ | | ||
+ | // Ports initialisieren | ||
+ | | ||
+ | DDRB |= (1<< | ||
+ | DDRD |= (1<< | ||
+ | | ||
+ | initTimer0(); | ||
+ | | ||
+ | while(!sw1_slope) | ||
+ | { | ||
+ | for (OCR0A=MAX_PER; | ||
+ | { | ||
+ | temp = OCR0A; | ||
+ | lcd_gotoxy(1, | ||
+ | lcd_putc(temp/ | ||
+ | temp = temp%100; | ||
+ | lcd_putc(temp/ | ||
+ | lcd_putc(temp%10 + ASC_ZERO); | ||
+ | | ||
+ | _delay_ms(100); | ||
+ | | ||
+ | if(sw1_slope) | ||
+ | { | ||
+ | TCCR0A = 0; // Timer 0 stoppen: Sound ausschalten | ||
+ | | ||
+ | sw1_slope = 0; // alle Flankenbits loeschen | ||
+ | sw2_slope = 0; | ||
+ | sw3_slope = 0; | ||
+ | sw4_slope = 0; | ||
+ | | ||
+ | return; | ||
+ | } | ||
+ | } | ||
+ | _delay_ms(WAIT_SND); | ||
+ | | ||
+ | for (OCR0A=MIN_PER; | ||
+ | { | ||
+ | temp = OCR0A; | ||
+ | lcd_gotoxy(1, | ||
+ | lcd_putc(temp/ | ||
+ | temp = temp%100; | ||
+ | lcd_putc(temp/ | ||
+ | lcd_putc(temp%10 + ASC_ZERO); | ||
+ | | ||
+ | _delay_ms(100); | ||
+ | | ||
+ | if(sw1_slope) | ||
+ | { | ||
+ | TCCR0A = 0; // Timer 0 stoppen: Sound ausschalten | ||
+ | | ||
+ | sw1_slope = 0; // alle Flankenbits loeschen | ||
+ | sw2_slope = 0; | ||
+ | sw3_slope = 0; | ||
+ | sw4_slope = 0; | ||
+ | | ||
+ | return; | ||
+ | } | ||
+ | } | ||
+ | _delay_ms(WAIT_SND); | ||
+ | | ||
+ | } | ||
+ | | ||
+ | // Nach Erkennen der Flanke von SW1 | ||
+ | | ||
+ | TCCR0A = 0; // Timer 0 stoppen: Sound ausschalten | ||
+ | | ||
+ | sw1_slope = 0; // alle Flankenbits loeschen | ||
+ | sw2_slope = 0; | ||
+ | sw3_slope = 0; | ||
+ | sw4_slope = 0; | ||
+ | } | ||
+ | | ||
+ | // Intialisierung des Timers 0 fuer Sounderzeugung | ||
+ | void initTimer0() | ||
+ | { | ||
+ | TCCR0A = (1<< | ||
+ | TCCR0B = (1<< | ||
+ | | ||
+ | OCR0A = MAX_PER; | ||
+ | } | ||
+ | | ||
+ | // Anzeige zu Teilprogramm 2 | ||
+ | void showSoundDisplay() // | ||
+ | { | ||
+ | lcd_gotoxy(0, | ||
+ | lcd_putstr(" | ||
+ | | ||
+ | lcd_gotoxy(1, | ||
+ | lcd_putstr(" | ||
+ | | ||
+ | } | ||
+ | | ||
+ | /* Teilprogramm 3: Logische Funktionen ======================================== | ||
+ | | ||
+ | Funktion: | ||
+ | logischen Verknuepfungen (UND, ODER, NOT, XOR) dargestellt. | ||
+ | Die logischen Eingangssignale werden von den Tasten S3 und S4 | ||
+ | eingelesen. | ||
+ | | ||
+ | Displayanzeige: | ||
+ | +----------------+ | ||
+ | |P3: Logic Funct.| | ||
+ | |Home | | ||
+ | +----------------+ | ||
+ | | ||
+ | Tastenfunktion: | ||
+ | S3: Logischer Eingang (ohne Entprellung) | ||
+ | S4: Logischer Eingang (ohne Entprellung) | ||
+ | | ||
+ | ============================================================================ */ | ||
+ | void doLogicFunctions() | ||
+ | { | ||
+ | unsigned char temp = 0; // lokale Variable | ||
+ | | ||
+ | showLogicDisplay(); | ||
+ | | ||
+ | while(!sw1_slope) | ||
+ | { | ||
+ | if ((!sw3_alt)&& | ||
+ | else temp=ASC_ZERO; | ||
+ | lcd_gotoxy(0, | ||
+ | lcd_putc(temp); | ||
+ | | ||
+ | if ((!sw3_alt)||(!sw4_alt)) temp=ASC_ONE; | ||
+ | else temp=ASC_ZERO; | ||
+ | lcd_gotoxy(0, | ||
+ | lcd_putc(temp); | ||
+ | | ||
+ | if (sw3_alt) temp=ASC_ONE; | ||
+ | else temp=ASC_ZERO; | ||
+ | lcd_gotoxy(1, | ||
+ | lcd_putc(temp); | ||
+ | | ||
+ | if ((!sw3_alt)^(!sw4_alt)) temp=ASC_ONE; | ||
+ | else temp=ASC_ZERO; | ||
+ | lcd_gotoxy(1, | ||
+ | lcd_putc(temp); | ||
+ | | ||
+ | _delay_ms(100); | ||
+ | } | ||
+ | | ||
+ | sw1_slope = 0; // alle Flankenbits loeschen | ||
+ | sw2_slope = 0; | ||
+ | sw3_slope = 0; | ||
+ | sw4_slope = 0; | ||
+ | } | ||
+ | | ||
+ | | ||
+ | // Anzeige zu Teilprogramm 3 | ||
+ | void showLogicDisplay() | ||
+ | { | ||
+ | lcd_gotoxy(0, | ||
+ | lcd_putstr(" | ||
+ | | ||
+ | lcd_gotoxy(1, | ||
+ | lcd_putstr(" | ||
+ | | ||
+ | _delay_ms(2000); | ||
+ | | ||
+ | lcd_gotoxy(0, | ||
+ | lcd_putstr(" | ||
+ | | ||
+ | lcd_gotoxy(1, | ||
+ | lcd_putstr("/ | ||
+ | } | ||
+ | | ||
+ | | ||
+ | /* Teilprogramm 4: Up-Down-Counter ============================================ | ||
+ | | ||
+ | Funktion: | ||
+ | Anzeige und Ueber-/ Unterlauf realisiert. Das Aufwaerts- und | ||
+ | Abwaertszaehlen wird mit zwei Tasten (S3: +) (S4: -) gesteuert. | ||
+ | Es werden die Flanken beim Druecken der Tasten ausgewertet. | ||
+ | Die Taste S2 dient zum Ruecksetzen des Zaehlers auf 0000. | ||
+ | | ||
+ | Displayanzeige: | ||
+ | |P4: Counter 0000| | ||
+ | |Home RES + - | | ||
+ | +----------------+ | ||
+ | | ||
+ | Tastenfunktion: | ||
+ | S2 Reset Counter (ohne Entprellung) | ||
+ | S3 Flanke: Counter++ (mit Entprellung) | ||
+ | S4 Flanke: Counter-- (mit Entprellung) | ||
+ | | ||
+ | ============================================================================ */ | ||
+ | void doCounterProg() | ||
+ | { | ||
+ | int temp; | ||
+ | | ||
+ | showCounterDisplay(); | ||
+ | | ||
+ | // Auswertung der Tasten | ||
+ | | ||
+ | while(!sw1_slope) | ||
+ | { | ||
+ | if (sw2_alt==0) // solange Taste 1 gedrueckt: | ||
+ | counter = 0000; // Counter auf 0000 setzen | ||
+ | | ||
+ | if (sw3_slope) | ||
+ | { | ||
+ | sw3_slope = 0; // | ||
+ | | ||
+ | counter++; | ||
+ | if (counter==10000) | ||
+ | counter = 0000; // auf 0000 setzen | ||
+ | } | ||
+ | | ||
+ | if (sw4_slope) | ||
+ | { | ||
+ | sw4_slope = 0; // | ||
+ | | ||
+ | counter--; | ||
+ | if (counter< | ||
+ | counter = 9999; // auf 9999 setzen | ||
+ | } | ||
+ | | ||
+ | _delay_ms(100); | ||
+ | | ||
+ | // Anzeige der Werte | ||
+ | | ||
+ | lcd_gotoxy(0, | ||
+ | | ||
+ | temp = counter; | ||
+ | lcd_putc(temp/ | ||
+ | | ||
+ | temp = temp%1000; | ||
+ | lcd_putc(temp/ | ||
+ | | ||
+ | temp = temp%100; | ||
+ | lcd_putc(temp/ | ||
+ | lcd_putc(temp%10+ASC_ZERO); | ||
+ | } | ||
+ | | ||
+ | sw1_slope = 0; // alle Flankenbits loeschen | ||
+ | sw2_slope = 0; | ||
+ | sw3_slope = 0; | ||
+ | sw4_slope = 0; | ||
+ | } | ||
+ | | ||
+ | | ||
+ | // Anzeige zu Teilprogramm 4 | ||
+ | void showCounterDisplay() | ||
+ | { | ||
+ | lcd_gotoxy(0, | ||
+ | lcd_putstr(" | ||
+ | | ||
+ | lcd_gotoxy(1, | ||
+ | lcd_putstr(" | ||
+ | } | ||
+ | | ||
+ | // Auswahl im Hauptmenu ermitteln ======================================================= | ||
+ | void getChoiceInMainMenu() | ||
+ | { | ||
+ | if (sw1_slope) | ||
+ | { | ||
+ | sw1_slope=0; | ||
+ | modus=1; | ||
+ | } | ||
+ | | ||
+ | if (sw2_slope) | ||
+ | { | ||
+ | sw2_slope=0; | ||
+ | modus=2; | ||
+ | } | ||
+ | | ||
+ | if (sw3_slope) | ||
+ | { | ||
+ | sw3_slope=0; | ||
+ | modus=3; | ||
+ | } | ||
+ | | ||
+ | if (sw4_slope) | ||
+ | { | ||
+ | sw4_slope=0; | ||
+ | modus=4; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | ''/ | ||
+ | |||
+ | Ändern Sie auch hier wieder die Beschreibung am Anfang des C-Files, je nachdem was Sie entwickeln | ||
+ | '' | ||
+ | \\ \\ | ||
+ | - Hier wird wieder geprüft ob die Frequenz des Quarz bereits eingestellt wurde und - falls nicht - dessen Frequenz eingestellt. \\ \\ \\ \\ | ||
+ | - Die Header-Dateien entsprechen denen der letzten Programme. \\ \\ \\ \\ \\ | ||
+ | - Auch die Makros entsprechen denen der letzten Programme. \\ \\ \\ \\ \\ | ||
+ | - Die Konstanten entsprechen denen der letzten Programme. \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ | ||
+ | - Auch die anfänglichen Variablen entsprechen denen der letzten Programme. Hierbei sind alle vier Schalter berücksichtigt.\\ \\ \\ \\ \\ \\ \\ | ||
+ | - Wird die Taste S1 gedrückt, so wird '' | ||
+ | - Wird eine ansteigende Flanke der Taste S1 gedrückt, so wird '' | ||
+ | - Bei den Funktionsprototypen sind einige bekannte Unterprogramme vorhanden. Details werden weiter unten erklärt. \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ | ||
+ | |||
+ | '' | ||
+ | |||
+ | - Zunächst werden zwei Initialisierungsroutinen aufgerufen (siehe weiter unten) | ||
+ | - Dann werden die " | ||
+ | - Auch hier gibt es eine " | ||
+ | - Mit dem Befehl '' | ||
+ | - in der Endlosschleife ist nur eine switch-case Anweisung zu finden. Diese stellt den Auswahlteil einer Zustandsmaschine dar: \\ {{drawio> | ||
+ | - Beim '' | ||
+ | |||
+ | '' | ||
+ | - Mit dem Befehl '' | ||
+ | - Der Überlauf-Interrupt durch den Timer2 wird erst bei Überlauf des 8-Bit Wert ausgeführt. Auch hier ergibt sich durch den Prescaler und Modus ('' | ||
+ | - Die Ermittlung von '' | ||
+ | - Eine große Änderung ist, dass bereits im Interrupt alle 10ms die Unterfunktion '' | ||
+ | '' | ||
+ | \\ \\ \\ | ||
+ | - In dieser Funktion werden zunächst die Stellungen aller Taster eingelesen (vgl. '' | ||
+ | - Neu hier ist, dass über '' | ||
+ | |||
+ | '' | ||
+ | - Die Funktion '' | ||
+ | - Danach wird der erste Text auf den Bildschirm geschrieben und damit der Programmname dargestellt. | ||
+ | - Nach zwei Sekunden wird der Auswahlbildschirm angezeigt. | ||
+ | |||
+ | \\ \\ \\ \\ \\ \\ | ||
+ | |||
+ | '' | ||
+ | - Da der Auswahlbildschirm mit dem Hauptmenu nicht nur beim Start, sondern auch nach jeder Rückkehr aus Unterprogrammen dargestellt werden muss, wird der Auswahlbildschirm in einem neuen Unterprogramm angezeigt. | ||
+ | |||
+ | \\ \\ \\ \\ \\ | ||
+ | |||
+ | ''/ | ||
+ | |||
+ | Hier ist das Programm der [[1_hello_blinking_world|Blinking LED]] etwas angepasst eingefügt. | ||
+ | \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ | ||
+ | - Zunächst wird ein Unterprogramm zur Anzeige das Displays aufgerufen | ||
+ | - '' | ||
+ | - Die Schleife wird solange ausgeführt, | ||
+ | - Beim Aktivieren der LED wird auch auf dem Display eine '' | ||
+ | - Nach einer Sekunde wird die LED ausgeschalten und auf dem Display eine '' | ||
+ | - Nach Beendigung der Schleife werden alle Flanken gelöscht. Damit wird verhindert, dass beim Aufruf des Hauptmenus sofort ein Sprung in ein Unterprogramm ausgeführt wird. | ||
+ | |||
+ | \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ | ||
+ | ''/ | ||
+ | |||
+ | Hier ist das Programm [[2_sound_und_timer|Sound und Timer]] etwas angepasst eingefügt. | ||
+ | \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ | ||
+ | |||
+ | - Die Port Initialisierung, | ||
+ | - Hier wird Timer 0 genutzt, um das gepulste Signal an den Lautsprecher zu verändern. | ||
+ | - Die while-Schleife wird wieder abgebrochen, | ||
+ | - Neben dem Herunterzählen der Periodenlänge (über '' | ||
+ | - Da die for-Schleife zum Herunterzählen der Periodenlänge sehr lange dauert (etwa 2 Sekunden) wird auch darin der Tastendruck der Taste 1 abgefragt werden. \\ \\ \\ \\ \\ | ||
+ | - Falls die Taste 1 gedrückt wurde, wird sowohl __in der for__-Schleife, | ||
+ | - Das Heraufzählen der Frequenz gleich dem Herunterzählen, | ||
+ | |||
+ | \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ | ||
+ | ''/ | ||
+ | |||
+ | Hier ist das Programm [[3_logische_funktionen|Logische Funktionen]] etwas angepasst eingefügt. | ||
+ | \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ | ||
+ | |||
+ | - Durch den Anschluss des Tasters zwischen Port und Masse erzeugt ein geschlossener ein LOW Signal (logisch 0). Hier sollen aber nun der Tastendruck dem Wert HIGH (logisch 1) entsprechen. Aus diesem Grund sind die Tasterwerte in den Bedingungen negiert, z.B. '' | ||
+ | |||
+ | \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ | ||
+ | ''/ | ||
+ | |||
+ | Hier ist das Programm [[4_up_down_counter|Up/ | ||
+ | \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ | ||
+ | |||
+ | - Im wesentlichen gleicht das Programm dem bereits bekanntem. Es kann aber auf die bereits berechnete Flanken '' | ||
+ | |||
+ | \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ | ||
+ | '' | ||
+ | |||
+ | - Je nach gedrückter Taste wird hier die Variable '' | ||
+ | |||
+ | </ | ||
+ | |||
+ | <-- | ||
+ | --> IV. Ausführung in Simulide # | ||
+ | - Geben Sie die oben dargestellten Codezeilen ein und kompilieren Sie den Code. | ||
+ | - Öffnen Sie Ihre hex-Datei in SimulIDE und testen Sie, ob diese die gleiche Ausgabe erzeugt | ||
+ | |||
+ | <-- | ||
+ | \\ | ||
+ | |||
+ | Bitte arbeiten Sie folgende Aufgaben durch: | ||
+ | |||
+ | --> Aufgaben# | ||
+ | |||
+ | Vielleicht haben Sie es schon bemerkt: gelegentlich scheint das Display für einen kurzen Augenblick einzelne falsche Zeichen anzuzeigen. | ||
+ | Der Grund dafür ist, dass das Auslesen der Taster und die Datenübertragung an das Display über die gleichen Pins stattfindet und nicht synchronisiert ist. | ||
+ | Um dies zu beheben ist eine Verbesserung des Programms notwendig. | ||
+ | |||
+ | Speicherauslastung und Programmoptimierung: | ||
+ | - Merken Sie sich die Speicherauslastung des bisherigen Programms. Diese finden Sie z.B. über den Solution Explorer: '' | ||
+ | - Der oben gezeigte Code wurde in zwei Schritten optimiert: Erster Schritt war {{microcontrollertechnik: | ||
+ | - Wie funktioniert die optimierte Funktionen '' | ||
+ | - Für was wird der Array '' | ||
+ | - Für zweite Version wurde gänzlich auf Delays im Millisekundenbereich verzichtet: {{microcontrollertechnik: | ||
+ | - Analysieren Sie die '' | ||
+ | - Alle Unterfunktionen wurden in separate Dateien ausgelagert. '' | ||
+ | |||
+ | <-- | ||