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 03:21] tfischer |
microcontrollertechnik:5_menuefuehrung [2024/03/29 20:24] (aktuell) mexleadmin |
||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
- | ====== 5. Menüführung ====== | + | ====== 5 Menüführung ====== |
- | + | ||
- | <panel type=" | + | |
- | {{fa> | + | |
- | </ | + | |
==== Ziele ==== | ==== Ziele ==== | ||
Zeile 15: | Zeile 11: | ||
--> I. Vorarbeiten # | --> I. Vorarbeiten # | ||
- Laden Sie folgende Datei herunter: | - Laden Sie folgende Datei herunter: | ||
- | - {{microcontrollertechnik: | + | - {{microcontrollertechnik: |
- | - {{microcontrollertechnik: | + | - {{microcontrollertechnik: |
- {{microcontrollertechnik: | - {{microcontrollertechnik: | ||
Zeile 22: | Zeile 18: | ||
--> II. Analyse des fertigen Programms # | --> II. Analyse des fertigen Programms # | ||
- Initialisieren des Programms | - Initialisieren des Programms | ||
- | - Öffnen Sie SimulIDE und öffnen Sie dort mittels {{microcontrollertechnik: | + | - Öffnen Sie SimulIDE und öffnen Sie dort mittels {{microcontrollertechnik: |
- | - Laden Sie '' | + | - Laden Sie '' |
- Zunächst wird eine Startanzeige mit dem Namen des Programms dargestellt. | - 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. | - 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. | ||
Zeile 29: | Zeile 25: | ||
<-- | <-- | ||
- | --> III. Eingabe in Atmel Studio # | + | --> III. Eingabe in Microchip |
<WRAP group>< | <WRAP group>< | ||
/ | / | ||
- | + | | |
Experiment 5: | Experiment 5: | ||
============= | ============= | ||
- | + | ||
- | Dateiname: | + | Dateiname: |
- | + | ||
- | Autoren: | + | Autoren: Peter Blinzinger |
- | Prof. G. Gruhler (Hochschule Heilbronn) | + | Prof. G. Gruhler (Hochschule Heilbronn) |
- | D. Chilachava | + | D. Chilachava (Georgische Technische Universitaet) |
- | + | ||
- | Version: | + | Version: 1.2 vom 29.04.2020 |
- | + | ||
- | Hardware: | + | Hardware: MEXLE2020 Ver. 1.0 oder höher |
- | AVR-USB-PROGI Ver. 2.0 | + | AVR-USB-PROGI Ver. 2.0 |
- | + | ||
- | Software: | + | Software: Entwicklungsumgebung: |
- | C-Compiler: AVR/GNU C Compiler 5.4.0 | + | C-Compiler: AVR/GNU C Compiler 5.4.0 |
- | + | ||
- | Funktion: | + | Funktion: Unter einer gemeinsamen Programmoberflaeche werden vier Teil- |
- | programme verwaltet. Dies sind: | + | programme verwaltet. Dies sind: |
- | P1: Blinking LED | + | P1: Blinking LED |
- | P2: Creating Sound | + | P2: Creating Sound |
- | P3: Logic Functions | + | P3: Logic Functions |
- | P4: Up/ | + | P4: Up/ |
- | Der Start der Teilprogramme erfolgt den zugeordneten Funktions- | + | Der Start der Teilprogramme erfolgt den zugeordneten Funktions- |
- | tasten. Nach dem Abbruch eines Teilprogramms (immer mit S1) | + | tasten. Nach dem Abbruch eines Teilprogramms (immer mit S1) |
- | wird wieder die Programmauswahl gestartet. | + | wird wieder die Programmauswahl gestartet. |
- | + | ||
- | Displayanzeige: | + | Displayanzeige: |
- | +----------------+ | + | +----------------+ |
- | |- Experiment 5 -| | Main Level | | + | |- Experiment 5 -| |
- | | Program Menu | | P1 P2 P3 P4 | | + | | Program Menu | |
- | +----------------+ | + | +----------------+ |
- | + | ||
- | Anzeige fuer Teilprogramme siehe bei einzelnen Programmen | + | Anzeige fuer Teilprogramme siehe bei einzelnen Programmen |
- | + | ||
Tastenfunktion: | Tastenfunktion: | ||
- | | + | Im Teilprogramm ist die Funktion unterschiedlich (siehe dort) |
- | + | ||
Jumperstellung: | Jumperstellung: | ||
- | | + | Schalter muss fuer des Buzzer zwischen geschlossen sein |
- | + | ||
- | Fuses im uC: CKDIV8: Aus (keine generelle Vorteilung des Takts) | + | Fuses im uC: CKDIV8: Aus (keine generelle Vorteilung des Takts) |
- | + | ||
- | Header-Files: | + | Header-Files: |
- | + | ||
=============================================================================*/ | =============================================================================*/ | ||
- | + | | |
- | + | ||
// Deklarationen ============================================================== | // Deklarationen ============================================================== | ||
- | + | | |
// Festlegung der Quarzfrequenz | // Festlegung der Quarzfrequenz | ||
- | #ifndef F_CPU | + | #ifndef F_CPU // optional definieren |
- | #define F_CPU 12288000UL | + | #define F_CPU 18432000UL // ATmega 88 mit 18,432 MHz Quarz |
- | # | + | #endif |
- | + | ||
- | + | ||
// Include von Header-Dateien | // Include von Header-Dateien | ||
- | #include < | + | #include < |
- | #include < | + | #include < |
- | #include < | + | #include < |
- | #include < | + | #include < |
- | #include " | + | #include " |
- | + | ||
- | + | ||
// Makros | // Makros | ||
- | #define SET_BIT(PORT, BIT) ((PORT) |= (1 << (BIT))) // Port-Bit Setzen | + | #define SET_BIT(BYTE, BIT) ((BYTE) |= (1 << (BIT))) // Bit Zustand in Byte setzen |
- | #define CLR_BIT(PORT, BIT) ((PORT) &= ~(1 << (BIT))) // Port-Bit Loeschen | + | #define CLR_BIT(BYTE, BIT) ((BYTE) &= ~(1 << (BIT))) // Bit Zustand in Byte loeschen |
- | #define TGL_BIT(PORT, BIT) ((PORT) ^= (1 << (BIT))) // Port-Bit Toggeln | + | #define TGL_BIT(BYTE, BIT) ((BYTE) ^= (1 << (BIT))) // Bit Zustand in Byte wechseln (toggle) |
- | + | #define GET_BIT(BYTE, | |
- | + | ||
// Konstanten | // Konstanten | ||
- | #define VORTEILER_WERT | + | #define VORTEILER_WERT 90 // Faktor Vorteiler = 60 |
- | #define HUNDERTSTEL_WERT | + | #define HUNDERTSTEL_WERT 10 |
- | #define ZEHNTEL_WERT | + | #define ZEHNTEL_WERT 10 // Faktor Zehntel = 10 |
- | + | ||
- | #define ON_TIME | + | #define ON_TIME 100 // " |
- | #define OFF_TIME | + | #define OFF_TIME 100 // " |
- | + | ||
- | #define MIN_PER | + | #define MIN_PER 143 // minimale Periodendauer in " |
- | #define MAX_PER | + | #define MAX_PER 239 // maximale Periodendauer in " |
- | # | + | # |
- | + | # | |
- | # | + | |
- | #define EINS 0x31 // ASCII-Zeichen ' | + | |
- | + | ||
+ | #define ASC_ZERO 0x30// | ||
+ | #define ASC_ONE 0x31// | ||
+ | | ||
+ | | ||
// Variable | // Variable | ||
- | unsigned char vorteiler | + | unsigned char vorteiler |
- | unsigned char hundertstel | + | unsigned char hundertstel = HUNDERTSTEL_WERT; |
- | unsigned char modus | + | unsigned char modus |
- | + | ||
- | int counter = 0000; | + | int counter = 0000; // Variable fuer Zaehler |
- | + | ||
- | bool timertick; | + | bool timertick; // Bit-Botschaft alle 0,111ms (Timer-Interrupt) |
- | bool takt10ms; | + | bool takt10ms; |
- | bool takt100ms; | + | bool takt100ms; // Bit-Botschaft alle 100ms |
- | + | ||
- | bool sw1_neu = 1; | + | bool sw1_neu = 1; // Bitspeicher fuer Taste 1 |
- | bool sw2_neu = 1; | + | bool sw2_neu = 1; // Bitspeicher fuer Taste 2 |
- | bool sw3_neu = 1; | + | bool sw3_neu = 1; // Bitspeicher fuer Taste 3 |
- | bool sw4_neu = 1; | + | bool sw4_neu = 1; // Bitspeicher fuer Taste 4 |
- | + | ||
- | bool sw1_alt = 1; | + | bool sw1_alt = 1; // alter Wert von Taste 1 |
- | bool sw2_alt = 1; | + | bool sw2_alt = 1; // alter Wert von Taste 2 |
- | bool sw3_alt = 1; | + | bool sw3_alt = 1; // alter Wert von Taste 3 |
- | bool sw4_alt = 1; | + | bool sw4_alt = 1; // alter Wert von Taste 4 |
- | + | ||
- | bool sw1_slope = 0; | + | bool sw1_slope = 0; // Flankenspeicher fuer Taste 1 |
- | bool sw2_slope = 0; | + | bool sw2_slope = 0; // Flankenspeicher fuer Taste 2 |
- | bool sw3_slope = 0; | + | bool sw3_slope = 0; // Flankenspeicher fuer Taste 3 |
- | bool sw4_slope = 0; | + | bool sw4_slope = 0; // Flankenspeicher fuer Taste 4 |
- | + | ||
- | + | ||
// Funktionsprototypen | // Funktionsprototypen | ||
- | void initTaster(void); | + | void initTimer0(void); |
- | void initTimer0(void); | + | void initDisplay(void); |
- | void initDisplay(void); | + | |
- | + | ||
- | void readButton(void); | + | |
- | void getChoiceInMainMenu(void); | + | |
- | void showMainDisplay(void); | + | |
- | void doBlinkingLed(void); | + | void readButton(void); |
+ | void getChoiceInMainMenu(void); | ||
+ | void showMainDisplay(void); | ||
+ | |||
+ | void doBlinkingLed(void); | ||
void showBlinkingLedDisplay(void); | void showBlinkingLedDisplay(void); | ||
- | + | | |
- | void doSound(void); | + | void doSound(void); |
void showSoundDisplay(void); | void showSoundDisplay(void); | ||
- | + | | |
void doLogicFunctions(void); | void doLogicFunctions(void); | ||
void showLogicDisplay(void); | void showLogicDisplay(void); | ||
- | + | | |
- | void doCounterProg(void); | + | void doCounterProg(void); |
- | void showCounterDisplay(void); | + | void showCounterDisplay(void); |
- | + | ||
// Hauptprogramm ============================================================== | // Hauptprogramm ============================================================== | ||
- | + | | |
int main() | int main() | ||
- | { | + | { |
- | | + | initDisplay(); |
- | | + | |
- | | + | TCCR2A = 0; // Timer 2 auf " |
- | TCCR2A = 0; | + | TCCR2B |= (1<< |
- | TCCR2B |= (1<< | + | TIMSK2 |= (1<< |
- | TIMSK2 |= (1<< | + | |
- | + | sei(); // generell Interrupts einschalten | |
- | sei(); | + | |
- | + | while(1) // unendliche Schleife | |
- | while(1) | + | { |
- | { | + | switch(modus) // Programmverteiler: |
- | switch(modus) | + | { |
- | { | + | case 0: // Modus 0: Hauptmenu |
- | case 0: | + | showMainDisplay(); |
- | showMainDisplay(); | + | getChoiceInMainMenu(); |
- | getChoiceInMainMenu(); | + | break; |
- | break; | + | |
- | + | case 1: // Modus 1: Blinkende LED | |
- | case 1: | + | doBlinkingLed(); |
- | doBlinkingLed(); | + | modus = 0; // danach auf Hauptmenu zurueckschalten |
- | modus = 0; // danach auf Hauptmenu zurueckschalten | + | break; |
- | break; | + | |
- | + | case 2: // Modus 2: Soundgenerierung | |
- | case 2: | + | doSound(); // Programm laeuft bis zum Abbruch |
- | doSound(); | + | modus = 0; // danach auf Hauptmenu zurueckschalten |
- | modus = 0; // danach auf Hauptmenu zurueckschalten | + | break; |
- | break; | + | |
- | + | case 3: // Modus 3: Logische Funktionen | |
- | case 3: | + | doLogicFunctions(); |
- | doLogicFunctions(); | + | modus = 0; // danach auf Hauptmenu zurueckschalten |
- | modus = 0; // danach auf Hauptmenu zurueckschalten | + | break; |
- | break; | + | |
- | | + | case 4: // Modus 4: Up-Down-Counter |
- | case 4: | + | doCounterProg(); |
- | doCounterProg(); | + | modus = 0; // danach auf Hauptmenu zurueckschalten |
- | modus = 0; // danach auf Hauptmenu zurueckschalten | + | break; |
- | break; | + | } |
- | } | + | } |
- | } | + | return 0; |
- | return 0; | + | |
} | } | ||
- | + | | |
- | + | ||
// Interrupt-Routine ========================================================== | // Interrupt-Routine ========================================================== | ||
ISR(TIMER2_OVF_vect) | ISR(TIMER2_OVF_vect) | ||
- | + | | |
// In der Interrupt-Routine sind die Softwareteiler realisiert, durch die Takt- | // In der Interrupt-Routine sind die Softwareteiler realisiert, durch die Takt- | ||
// botschaften (10ms, 100ms) erzeugt werden. Die Interrupts werden von Timer 2 | // botschaften (10ms, 100ms) erzeugt werden. Die Interrupts werden von Timer 2 | ||
// ausgeloest. | // ausgeloest. | ||
- | + | | |
{ | { | ||
- | | + | timertick = 1; // Botschaft 0,166ms senden |
- | --vorteiler; | + | --vorteiler; |
- | if (vorteiler==0) | + | if (vorteiler==0) // wenn 0 erreicht: 10ms abgelaufen |
- | { | + | { |
- | vorteiler = VORTEILER_WERT; | + | vorteiler = VORTEILER_WERT; |
- | takt10ms = 1; | + | takt10ms = 1; // |
- | readButton(); | + | readButton(); |
- | --hundertstel; | + | --hundertstel; |
- | | + | |
- | if (hundertstel==0) | + | if (hundertstel==0) // wenn 0 erreicht: 100ms abgelaufen |
- | { | + | { |
- | hundertstel = HUNDERTSTEL_WERT; | + | hundertstel = HUNDERTSTEL_WERT; |
- | takt100ms = 1; // Botschaft 100ms senden | + | takt100ms = 1; // |
- | | + | |
- | } | + | } |
- | } | + | } |
} | } | ||
- | + | ||
- | // Taster initialisieren ======================================================= | + | |
- | void initTaster(void) | + | |
- | { | + | |
- | DDRB = DDRB & 0xE1; // Port B auf Eingabe schalten | + | |
- | PORTB |= 0x1E; // Pullup-Rs eingeschaltet | + | |
- | _delay_us(10); | + | |
- | } | + | |
- | + | ||
// Funktion Tasten einlesen =================================================== | // Funktion Tasten einlesen =================================================== | ||
void readButton(void) | void readButton(void) | ||
{ | { | ||
- | | + | // |
- | sw1_neu = (PINB & (1 << | + | // |
- | sw2_neu = (PINB & (1 << | + | DDRC = DDRC & |
- | sw3_neu = (PINB & (1 << | + | PORTC = 0b00001111; |
- | sw4_neu = (PINB & (1 << | + | _delay_us(1); |
- | + | ||
- | // Auswerten der Flanken beim Druecken | + | // Einlesen der 4 Tastensignale |
- | + | sw1_neu = (PINC & (1 << | |
- | if ((sw1_neu==0)& | + | sw2_neu = (PINC & (1 << |
- | sw1_slope = 1; // Flankenbit Taste 1 setzen | + | sw3_neu = (PINC & (1 << |
- | + | sw4_neu = (PINC & (1 << | |
- | if ((sw2_neu==0)& | + | |
- | sw2_slope = 1; // Flankenbit Taste 2 setzen | + | DDRC = DDRC | 0b00001111; |
- | | + | |
- | if ((sw3_neu==0)& | + | // Auswerten der Flanken beim Druecken |
- | sw3_slope = 1; // Flankenbit Taste 3 setzen | + | |
- | | + | if ((sw1_neu==0)& |
- | if ((sw4_neu==0)& | + | sw1_slope = 1; // |
- | sw4_slope = 1; // Flankenbit Taste 4 setzen | + | |
- | + | if ((sw2_neu==0)& | |
- | // Zwischenspeichern aktuelle Tastenwerte | + | sw2_slope = 1; // |
- | + | | |
- | | + | if ((sw3_neu==0)& |
- | sw2_alt = sw2_neu; | + | sw3_slope = 1; // |
- | sw3_alt = sw3_neu; | + | |
- | sw4_alt = sw4_neu; | + | if ((sw4_neu==0)& |
+ | sw4_slope = 1; // | ||
+ | |||
+ | // Zwischenspeichern aktuelle Tastenwerte | ||
+ | sw1_alt = sw1_neu; // aktuelle Tastenwerte speichern | ||
+ | sw2_alt = sw2_neu; // in Variable fuer alte Werte | ||
+ | sw3_alt = sw3_neu; | ||
+ | sw4_alt = sw4_neu; | ||
} | } | ||
- | + | ||
- | + | ||
- | + | ||
// Initialisierung Display-Anzeige ============================================ | // Initialisierung Display-Anzeige ============================================ | ||
- | void initDisplay() | + | void initDisplay() |
{ | { | ||
- | | + | lcd_init(); |
- | | + | |
- | lcd_gotoxy(0, | + | lcd_gotoxy(0, |
- | lcd_putstr(" | + | lcd_putstr(" |
- | + | ||
- | lcd_gotoxy(1, | + | lcd_gotoxy(1, |
- | lcd_putstr(" | + | lcd_putstr(" |
- | + | ||
- | _delay_ms(2000); | + | _delay_ms(2000); |
- | + | ||
- | showMainDisplay(); | + | showMainDisplay(); |
} | } | ||
- | + | | |
- | + | ||
// Anzeige Hauptmenu ========================================================== | // Anzeige Hauptmenu ========================================================== | ||
void showMainDisplay() | void showMainDisplay() | ||
{ | { | ||
- | | + | lcd_gotoxy(0, |
- | lcd_putstr(" | + | lcd_putstr(" |
- | + | ||
- | lcd_gotoxy(1, | + | lcd_gotoxy(1, |
- | lcd_putstr(" | + | lcd_putstr(" |
- | + | ||
- | } | + | } |
- | + | ||
- | + | ||
+ | | ||
/* Teilprogramm 1: Blinkende LED ============================================== | /* Teilprogramm 1: Blinkende LED ============================================== | ||
- | + | | |
- | Funktion: | + | Funktion: Die gelbe LED (LED 3) in der Schaltung |
- | Periodendauer von 2 Sekunden (1 s ein, 1 s aus). Auf dem LCD- | + | Periodendauer von 2 Sekunden (1 s ein, 1 s aus). Auf dem LCD- |
- | Display wird rechts unten der Wert der LED (" | + | Display wird rechts unten der Wert der LED (" |
- | Zahl dargestellt. Abbruch mit Taste S1 nach voller Periode. | + | Zahl dargestellt. Abbruch mit Taste S1 nach voller Periode. |
- | + | ||
Displayanzeige: | Displayanzeige: | ||
- | | + | |P1: Blinking LED| |
- | |Home | + | |Home 1| |
- | +----------------+ | + | +----------------+ |
- | + | ||
Tastenfunktion: | Tastenfunktion: | ||
- | + | | |
============================================================================ */ | ============================================================================ */ | ||
void doBlinkingLed() | void doBlinkingLed() | ||
{ | { | ||
- | + | | |
- | showBlinkingLedDisplay(); | + | showBlinkingLedDisplay(); |
- | SET_BIT(DDRB, | + | SET_BIT(DDRB, |
- | | + | |
- | while(!sw1_slope) | + | while(!sw1_slope) // unendliche Schleife |
- | { | + | { |
- | SET_BIT(PORTB, | + | SET_BIT(PORTB, |
- | lcd_gotoxy(1, | + | lcd_gotoxy(1, |
- | lcd_putc(EINS); | + | lcd_putc(ASC_ONE); // Anzeige LED-Wert " |
- | + | ||
- | _delay_ms(1000); | + | _delay_ms(WAIT_LED); |
- | + | ||
- | CLR_BIT(PORTB, | + | CLR_BIT(PORTB, |
- | lcd_gotoxy(1, | + | lcd_gotoxy(1, |
- | lcd_putc(NULL); | + | lcd_putc(ASC_ZERO); // Anzeige LED-Wert " |
- | + | ||
- | _delay_ms(1000); | + | _delay_ms(WAIT_LED); |
- | + | ||
- | } | + | } // Ende der Warteschleife |
- | + | ||
- | sw1_slope = 0; // Alle Flankenbits loeschen | + | sw1_slope = 0; |
- | sw2_slope = 0; | + | sw2_slope = 0; |
- | sw3_slope = 0; | + | sw3_slope = 0; |
- | sw4_slope = 0; | + | sw4_slope = 0; |
- | } | + | } |
- | + | ||
- | + | ||
// Anzeige zu Teilprogramm 1 | // Anzeige zu Teilprogramm 1 | ||
- | void showBlinkingLedDisplay() | + | void showBlinkingLedDisplay() |
{ | { | ||
- | | + | lcd_gotoxy(0, |
- | lcd_putstr(" | + | lcd_putstr(" |
- | + | ||
- | lcd_gotoxy(1, | + | lcd_gotoxy(1, |
- | lcd_putstr(" | + | lcd_putstr(" |
- | + | ||
- | } | + | } |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
/* Teilprogramm 2: Soundgenerierung =========================================== | /* Teilprogramm 2: Soundgenerierung =========================================== | ||
- | + | | |
- | Funktion: | + | Funktion: Auf dem kleinen Lautsprecher (Buzzer) |
- | wird ein sirenenartiger Sound ausgegeben. Zwischen den auf- | + | wird ein sirenenartiger Sound ausgegeben. Zwischen den auf- |
- | und absteigenden Tönen bleibt die Frequenz kurz stabil. | + | und absteigenden Tönen bleibt die Frequenz kurz stabil. |
- | Die Frequenz wird mit dem Timer 0 (im CTC-Mode) erzeugt und | + | Die Frequenz wird mit dem Timer 0 (im CTC-Mode) erzeugt und |
- | direkt über den Output-Compare-Pin im Toggle-Mode ausgegeben. | + | direkt über den Output-Compare-Pin im Toggle-Mode ausgegeben. |
- | Die jeweilige Periodendauer wird dreistellig in Timerticks | + | Die jeweilige Periodendauer wird dreistellig in Timerticks |
- | auf der Anzeige rechts unten dargestellt. | + | auf der Anzeige rechts unten dargestellt. |
- | + | ||
Displayanzeige: | Displayanzeige: | ||
- | | + | |P2: Create Sound| |
- | |Home | + | |Home 123| |
- | +----------------+ | + | +----------------+ |
- | + | ||
Tastenfunktion: | Tastenfunktion: | ||
- | | + | gesamten Sound-Zyklus |
- | + | ||
============================================================================ */ | ============================================================================ */ | ||
void doSound() | void doSound() | ||
{ | { | ||
- | | + | unsigned char temp = 0; // lokale Variable |
- | + | ||
- | showSoundDisplay(); | + | showSoundDisplay(); |
- | + | ||
- | // Ports initialisieren | + | // Ports initialisieren |
- | + | ||
- | DDRB |= (1<<DDB0); // Port B, Pin 0 (zur LED) auf Ausgang | + | DDRB |= (1<<DDB2); // Port B, Pin 0 (zur LED) auf Ausgang |
- | DDRD |= (1<< | + | DDRD |= (1<< |
- | | + | |
- | initTimer0(); | + | initTimer0(); |
- | + | ||
- | while(!sw1_slope) | + | while(!sw1_slope) // Solange keine Flanke auf SW1: Warteschleife |
- | { | + | { |
- | for (OCR0A=MAX_PER; | + | for (OCR0A=MAX_PER; |
- | { | + | { |
- | temp = OCR0A; | + | temp = OCR0A; // Anzeige des aktuellen Periodenzaehlers |
- | lcd_gotoxy(1, | + | lcd_gotoxy(1, |
- | lcd_putc(temp/ | + | lcd_putc(temp/ |
- | temp = temp%100; | + | temp = temp%100; // Rest = Zehner, Einer |
- | lcd_putc(temp/ | + | lcd_putc(temp/ |
- | lcd_putc(temp%10 + NULL); // Einer als ASCII ausgeben | + | lcd_putc(temp%10 + ASC_ZERO); // Einer als ASCII ausgeben |
- | + | ||
- | _delay_ms(100); | + | _delay_ms(100); |
- | | + | |
- | if(sw1_slope) | + | if(sw1_slope) // Schleifenabbruch, |
- | { | + | { |
- | TCCR0A = 0; | + | TCCR0A = 0; // Timer 0 stoppen: Sound ausschalten |
- | | + | |
- | sw1_slope = 0; // alle Flankenbits loeschen | + | sw1_slope = 0; |
- | sw2_slope = 0; | + | sw2_slope = 0; |
- | sw3_slope = 0; | + | sw3_slope = 0; |
- | sw4_slope = 0; | + | sw4_slope = 0; |
- | | + | |
- | return; | + | return; |
- | } | + | } |
- | } | + | } |
- | _delay_ms(WAIT_TIME); // Wartezeit hohe Frequenz | + | _delay_ms(WAIT_SND); // Wartezeit hohe Frequenz |
- | + | ||
- | for (OCR0A=MIN_PER; | + | for (OCR0A=MIN_PER; |
- | { | + | { |
- | temp = OCR0A; | + | temp = OCR0A; // Anzeige des aktuellen Periodenzaehlers |
- | lcd_gotoxy(1, | + | lcd_gotoxy(1, |
- | lcd_putc(temp/ | + | lcd_putc(temp/ |
- | temp = temp%100; | + | temp = temp%100; // Rest = Zehner, Einer |
- | lcd_putc(temp/ | + | lcd_putc(temp/ |
- | lcd_putc(temp%10 + NULL); // Einer als ASCII ausgeben | + | lcd_putc(temp%10 + ASC_ZERO); // Einer als ASCII ausgeben |
- | + | ||
- | _delay_ms(100); | + | _delay_ms(100); |
- | | + | |
- | if(sw1_slope) | + | if(sw1_slope) // Schleifenabbruch, |
- | { | + | { |
- | TCCR0A = 0; | + | TCCR0A = 0; // Timer 0 stoppen: Sound ausschalten |
- | | + | |
- | sw1_slope = 0; // alle Flankenbits loeschen | + | sw1_slope = 0; |
- | sw2_slope = 0; | + | sw2_slope = 0; |
- | sw3_slope = 0; | + | sw3_slope = 0; |
- | sw4_slope = 0; | + | sw4_slope = 0; |
- | | + | |
- | return; | + | return; |
- | } | + | } |
- | } | + | } |
- | _delay_ms(WAIT_TIME); // Wartezeit niedrige Frequenz | + | _delay_ms(WAIT_SND); // Wartezeit niedrige Frequenz |
- | + | ||
- | } | + | } // Ende der unendlichen Schleife |
- | | + | |
- | // Nach Erkennen der Flanke von SW1 | + | // Nach Erkennen der Flanke von SW1 |
- | | + | |
- | TCCR0A = 0; | + | TCCR0A = 0; // Timer 0 stoppen: Sound ausschalten |
- | + | ||
- | sw1_slope = 0; // alle Flankenbits loeschen | + | sw1_slope = 0; |
- | sw2_slope = 0; | + | sw2_slope = 0; |
- | sw3_slope = 0; | + | sw3_slope = 0; |
- | sw4_slope = 0; | + | sw4_slope = 0; |
- | } | + | } |
- | + | ||
// Intialisierung des Timers 0 fuer Sounderzeugung | // Intialisierung des Timers 0 fuer Sounderzeugung | ||
void initTimer0() | void initTimer0() | ||
{ | { | ||
- | | + | TCCR0A = (1<< |
- | TCCR0B = (1<< | + | TCCR0B = (1<< |
- | + | ||
- | OCR0A = MAX_PER; | + | OCR0A = MAX_PER; // Start mit tiefstem Ton |
} | } | ||
- | + | | |
// Anzeige zu Teilprogramm 2 | // Anzeige zu Teilprogramm 2 | ||
- | void showSoundDisplay() | + | void showSoundDisplay() // Start der Funktion |
{ | { | ||
- | | + | lcd_gotoxy(0, |
- | lcd_putstr(" | + | lcd_putstr(" |
- | + | ||
- | lcd_gotoxy(1, | + | lcd_gotoxy(1, |
- | lcd_putstr(" | + | lcd_putstr(" |
- | + | ||
- | } | + | } |
- | + | ||
/* Teilprogramm 3: Logische Funktionen ======================================== | /* Teilprogramm 3: Logische Funktionen ======================================== | ||
- | + | | |
- | Funktion: | + | Funktion: Auf dem Display werden Ergebnisse von |
- | logischen Verknuepfungen (UND, ODER, NOT, XOR) dargestellt. | + | logischen Verknuepfungen (UND, ODER, NOT, XOR) dargestellt. |
- | Die logischen Eingangssignale werden von den Tasten S3 und S4 | + | Die logischen Eingangssignale werden von den Tasten S3 und S4 |
- | eingelesen. | + | eingelesen. |
- | + | ||
- | Displayanzeige: | + | Displayanzeige: |
- | +----------------+ | + | +----------------+ |
- | |P3: Logic Funct.| | + | |P3: Logic Funct.| |
- | |Home | |/ | + | |Home | |
- | +----------------+ | + | +----------------+ |
- | + | ||
Tastenfunktion: | Tastenfunktion: | ||
- | | + | S3: Logischer Eingang (ohne Entprellung) |
- | S4: Logischer Eingang (ohne Entprellung) | + | S4: Logischer Eingang (ohne Entprellung) |
- | + | ||
============================================================================ */ | ============================================================================ */ | ||
void doLogicFunctions() | void doLogicFunctions() | ||
{ | { | ||
- | | + | unsigned char temp = 0; // lokale Variable |
- | + | ||
- | showLogicDisplay(); | + | showLogicDisplay(); |
- | + | ||
- | while(!sw1_slope) | + | while(!sw1_slope) // Solange keine Flanke auf SW1: Warteschleife |
- | { | + | { |
- | if ((!sw3_alt)&& | + | if ((!sw3_alt)&& |
- | else temp=NULL; | + | else temp=ASC_ZERO; |
- | lcd_gotoxy(0, | + | lcd_gotoxy(0, |
- | lcd_putc(temp); | + | lcd_putc(temp); |
- | + | ||
- | if ((!sw3_alt)||(!sw4_alt)) temp=EINS; // Ergebnis der ODER-Verknuepfung | + | if ((!sw3_alt)||(!sw4_alt)) temp=ASC_ONE; // Ergebnis der ODER-Verknuepfung |
- | else temp=NULL; | + | else temp=ASC_ZERO; |
- | lcd_gotoxy(0, | + | lcd_gotoxy(0, |
- | lcd_putc(temp); | + | lcd_putc(temp); |
- | + | ||
- | if (sw3_alt) temp=EINS; // Ergebnis der Negation | + | if (sw3_alt) temp=ASC_ONE; // Ergebnis der Negation |
- | else temp=NULL; | + | else temp=ASC_ZERO; |
- | lcd_gotoxy(1, | + | lcd_gotoxy(1, |
- | lcd_putc(temp); | + | lcd_putc(temp); |
- | + | ||
- | if ((!sw3_alt)^(!sw4_alt)) temp=EINS; // Ergebnis der XOR-Verknuepfung | + | if ((!sw3_alt)^(!sw4_alt)) temp=ASC_ONE; // Ergebnis der XOR-Verknuepfung |
- | else temp=NULL; | + | else temp=ASC_ZERO; |
- | lcd_gotoxy(1, | + | lcd_gotoxy(1, |
- | lcd_putc(temp); | + | lcd_putc(temp); |
- | + | ||
- | _delay_ms(100); | + | _delay_ms(100); |
- | } | + | } |
- | + | ||
- | sw1_slope = 0; // alle Flankenbits loeschen | + | sw1_slope = 0; |
- | sw2_slope = 0; | + | sw2_slope = 0; |
- | sw3_slope = 0; | + | sw3_slope = 0; |
- | sw4_slope = 0; | + | sw4_slope = 0; |
- | } | + | } |
- | + | ||
- | + | ||
// Anzeige zu Teilprogramm 3 | // Anzeige zu Teilprogramm 3 | ||
void showLogicDisplay() | void showLogicDisplay() | ||
{ | { | ||
- | | + | lcd_gotoxy(0, |
- | lcd_putstr(" | + | lcd_putstr(" |
- | + | ||
- | lcd_gotoxy(1, | + | lcd_gotoxy(1, |
- | lcd_putstr(" | + | lcd_putstr(" |
- | + | ||
- | _delay_ms(2000); | + | _delay_ms(2000); |
- | + | ||
- | lcd_gotoxy(0, | + | lcd_gotoxy(0, |
- | lcd_putstr(" | + | lcd_putstr(" |
- | + | ||
- | lcd_gotoxy(1, | + | lcd_gotoxy(1, |
- | lcd_putstr("/ | + | lcd_putstr("/ |
} | } | ||
- | + | | |
- | + | ||
/* Teilprogramm 4: Up-Down-Counter ============================================ | /* Teilprogramm 4: Up-Down-Counter ============================================ | ||
- | + | | |
- | Funktion: | + | Funktion: Es wird ein 4-stelliger Dezimal-Zaehler (0000..9999) mit |
- | Anzeige und Ueber-/ Unterlauf realisiert. Das Aufwaerts- und | + | Anzeige und Ueber-/ Unterlauf realisiert. Das Aufwaerts- und |
- | Abwaertszaehlen wird mit zwei Tasten (S3: +) (S4: -) gesteuert. | + | Abwaertszaehlen wird mit zwei Tasten (S3: +) (S4: -) gesteuert. |
- | Es werden die Flanken beim Druecken der Tasten ausgewertet. | + | Es werden die Flanken beim Druecken der Tasten ausgewertet. |
- | Die Taste S2 dient zum Ruecksetzen des Zaehlers auf 0000. | + | Die Taste S2 dient zum Ruecksetzen des Zaehlers auf 0000. |
- | + | ||
Displayanzeige: | Displayanzeige: | ||
- | | + | |P4: Counter 0000| |
- | |Home RES + - | | + | |Home RES + - | |
- | +----------------+ | + | +----------------+ |
- | + | ||
Tastenfunktion: | Tastenfunktion: | ||
- | | + | S2 Reset Counter (ohne Entprellung) |
- | S3 Flanke: Counter++ (mit Entprellung) | + | S3 Flanke: Counter++ (mit Entprellung) |
- | S4 Flanke: Counter-- (mit Entprellung) | + | S4 Flanke: Counter-- (mit Entprellung) |
- | + | ||
============================================================================ */ | ============================================================================ */ | ||
void doCounterProg() | void doCounterProg() | ||
{ | { | ||
- | | + | int temp; // lokale Variable |
- | | + | |
- | showCounterDisplay(); | + | showCounterDisplay(); |
- | + | ||
- | // Auswertung der Tasten | + | // Auswertung der Tasten |
- | + | ||
- | while(!sw1_slope) | + | while(!sw1_slope) // Solange keine Flanke auf SW1: Warteschleife |
- | { | + | { |
- | if (sw2_alt==0) | + | if (sw2_alt==0) // solange Taste 1 gedrueckt: |
- | counter = 0000; | + | counter = 0000; // Counter auf 0000 setzen |
- | + | ||
- | if (sw3_slope) | + | if (sw3_slope) |
- | { | + | { |
- | sw3_slope = 0; // Flankenbit loeschen | + | sw3_slope = 0; |
- | + | ||
- | counter++; | + | counter++; |
- | if (counter==10000) | + | if (counter==10000) |
- | counter = 0000; // | + | counter = 0000; // auf 0000 setzen |
- | } | + | } |
- | | + | |
- | if (sw4_slope) | + | if (sw4_slope) |
- | { | + | { |
- | sw4_slope = 0; // Flankenbit loeschen | + | sw4_slope = 0; |
- | + | ||
- | counter--; | + | counter--; |
- | if (counter< | + | if (counter< |
- | counter = 9999; // | + | counter = 9999; // auf 9999 setzen |
- | } | + | } |
- | + | ||
- | _delay_ms(100); | + | _delay_ms(100); |
- | | + | |
- | // Anzeige der Werte | + | // Anzeige der Werte |
- | + | ||
- | lcd_gotoxy(0, | + | lcd_gotoxy(0, |
- | | + | |
- | temp = counter; | + | temp = counter; |
- | lcd_putc(temp/ | + | lcd_putc(temp/ |
- | + | ||
- | temp = temp%1000; | + | temp = temp%1000; // Rest = Hunderter, Zehner, Einer |
- | lcd_putc(temp/ | + | lcd_putc(temp/ |
- | + | ||
- | temp = temp%100; | + | temp = temp%100; // Rest = Zehner. Einer |
- | lcd_putc(temp/ | + | lcd_putc(temp/ |
- | lcd_putc(temp%10+NULL); // Einer ausgeben | + | lcd_putc(temp%10+ASC_ZERO); // Einer ausgeben |
- | } | + | } |
- | + | ||
- | sw1_slope = 0; // alle Flankenbits loeschen | + | sw1_slope = 0; |
- | sw2_slope = 0; | + | sw2_slope = 0; |
- | sw3_slope = 0; | + | sw3_slope = 0; |
- | sw4_slope = 0; | + | sw4_slope = 0; |
- | } | + | } |
- | + | ||
- | + | ||
// Anzeige zu Teilprogramm 4 | // Anzeige zu Teilprogramm 4 | ||
void showCounterDisplay() | void showCounterDisplay() | ||
{ | { | ||
- | | + | lcd_gotoxy(0, |
- | lcd_putstr(" | + | lcd_putstr(" |
- | + | ||
- | lcd_gotoxy(1, | + | lcd_gotoxy(1, |
- | lcd_putstr(" | + | lcd_putstr(" |
} | } | ||
- | + | | |
- | // Hauptmenu | + | // Auswahl im Hauptmenu |
void getChoiceInMainMenu() | void getChoiceInMainMenu() | ||
{ | { | ||
- | | + | if (sw1_slope) |
- | { | + | { |
- | sw1_slope=0; | + | sw1_slope=0; |
- | modus=1; | + | modus=1; // neuer Modus 1 |
- | } | + | } |
- | | + | |
- | if (sw2_slope) | + | if (sw2_slope) |
- | { | + | { |
- | sw2_slope=0; | + | sw2_slope=0; |
- | modus=2; | + | modus=2; // neuer Modus 2 |
- | } | + | } |
- | | + | |
- | if (sw3_slope) | + | if (sw3_slope) |
- | { | + | { |
- | sw3_slope=0; | + | sw3_slope=0; |
- | modus=3; | + | modus=3; // neuer Modus 3 |
- | } | + | } |
- | | + | |
- | if (sw4_slope) | + | if (sw4_slope) |
- | { | + | { |
- | sw4_slope=0; | + | sw4_slope=0; |
- | modus=4; | + | modus=4; // neuer Modus 4 |
- | } | + | } |
} | } | ||
</ | </ | ||
Zeile 691: | Zeile 682: | ||
- Zunächst werden zwei Initialisierungsroutinen aufgerufen (siehe weiter unten) | - Zunächst werden zwei Initialisierungsroutinen aufgerufen (siehe weiter unten) | ||
- | - Dann werden die " | + | - Dann werden die " |
- Auch hier gibt es eine " | - Auch hier gibt es eine " | ||
- Mit dem Befehl '' | - Mit dem Befehl '' | ||
- | - in der Endlosschleife ist nur eine switch-case Anweisung zu finden. Diese stellt den Auswahlteil einer Zustandsmaschine dar: \\ {{drawio> | + | - in der Endlosschleife ist nur eine switch-case Anweisung zu finden. Diese stellt den Auswahlteil einer Zustandsmaschine dar: \\ {{drawio> |
- Beim '' | - Beim '' | ||
'' | '' | ||
- Mit dem Befehl '' | - 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 ('' | + | - 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 '' | + | - Die Ermittlung von '' |
- | - Eine große Änderung ist, dass bereits im Interrupt alle 10ms die Unterfunktion '' | + | - Eine große Änderung ist, dass bereits im Interrupt alle 10ms die Unterfunktion '' |
- | '' | + | |
- | - Das Einstellen des Data Direction Registers und der Pullups wurde bereits in vorherigen Programmen erklärt. | + | |
'' | '' | ||
\\ \\ \\ | \\ \\ \\ | ||
- | - In dieser Funktion werden zunächst die Stellungen aller Taster eingelesen (vgl. '' | + | - In dieser Funktion werden zunächst die Stellungen aller Taster eingelesen (vgl. '' |
- Neu hier ist, dass über '' | - Neu hier ist, dass über '' | ||
Zeile 714: | Zeile 703: | ||
- Nach zwei Sekunden wird der Auswahlbildschirm angezeigt. | - Nach zwei Sekunden wird der Auswahlbildschirm angezeigt. | ||
- | \\ \\ \\ \\ \\ | + | \\ \\ \\ \\ \\ \\ |
'' | '' | ||
Zeile 723: | Zeile 712: | ||
''/ | ''/ | ||
- | Hier ist das Programm der [[1._hello_blinking_world|Blinking LED]]eingefügt. | + | Hier ist das Programm der [[1_hello_blinking_world|Blinking LED]] etwas angepasst |
+ | \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ | ||
- Zunächst wird ein Unterprogramm zur Anzeige das Displays aufgerufen | - Zunächst wird ein Unterprogramm zur Anzeige das Displays aufgerufen | ||
- '' | - '' | ||
- | - Die Endlosschleife | + | - Die Schleife |
+ | - 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 der Blinking LED direkt eingefügt | ||
- | \\ \\ \\ \\ \\ | + | 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 # | --> IV. Ausführung in Simulide # | ||
- | - Geben Sie die oben dargestellten Codezeilen | + | - 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 | - Öffnen Sie Ihre hex-Datei in SimulIDE und testen Sie, ob diese die gleiche Ausgabe erzeugt | ||
Zeile 746: | Zeile 769: | ||
--> Aufgaben# | --> Aufgaben# | ||
- | - Erweiterung der des Zählers: | ||
- | - Bauen Sie den Zähler so um, dass er jede Sekunde um 1 nach oben zählt. | ||
- | - Ändern Sie die Funktionsweise der Tasten S2 und S3 so, dass diese die Zählrichtung angeben. | ||
- | - Variation der Eingabe | ||
- | - Fügen Sie einen weiteren Schalter S4 hinzu. | ||
- | - Mit diesem Schalter | ||
- | - ++ Tipp 1| Ändern Sie das herauf-/ | ||
- | - ++ Tipp 2| Wie muss die neue Variable bei Tastendruck auf S4 geändert werden? Wann muss die neue Variable wieder zurückgesetzt werden? | ||
- | <-- | + | 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. '' | ||
+ | |||
+ | <-- | ||