Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
microcontrollertechnik:7_uhr_und_zeitraster [2020/05/14 01:07] tfischer |
microcontrollertechnik:7_uhr_und_zeitraster [2024/01/22 13:46] mexleadmin |
||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
- | <code c> | + | ====== 7 Uhr und Zeitraster ====== |
+ | |||
+ | ==== Ziele ==== | ||
+ | |||
+ | Nach dieser Lektion sollten Sie: | ||
+ | |||
+ | - wissen, wie man aus den auf Interupt-basierten Zeitrastern langsamere Raster umsetzt. | ||
+ | |||
+ | ==== Ü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 eine Uhr mit dem Format HH:MM:SS Menu zu sehen | ||
+ | - Die Tasten '' | ||
+ | |||
+ | <-- | ||
+ | |||
+ | --> III. Eingabe in Microchip Studio # | ||
+ | <WRAP group>< | ||
+ | |||
+ | /* ============================================================================ | ||
+ | |||
+ | Experiment 7: | ||
+ | ============= | ||
+ | |||
+ | Dateiname: | ||
+ | |||
+ | Autoren: | ||
+ | Prof. G. Gruhler (Hochschule Heilbronn) | ||
+ | D. Chilachava | ||
+ | |||
+ | Version: | ||
+ | |||
+ | Hardware: | ||
+ | AVR-USB-PROGI Ver. 2.0 | ||
+ | |||
+ | Software: | ||
+ | C-Compiler: AVR/GNU C Compiler 5.4.0 | ||
+ | |||
+ | Funktion: | ||
+ | einfache Stellfunktion ist mit den Tasten S2 und S3 realisiert. | ||
+ | |||
+ | Displayanzeige: | ||
+ | +----------------+ | ||
+ | |- Experiment 7 -| |=== 00:00:00 ===| | ||
+ | | Digital Clock | | Std Min | | ||
+ | +----------------+ | ||
+ | |||
+ | Tastenfunktion: | ||
+ | S3: Min (zaehlt Minuten bei Flanke aufwaerts. Überlauf bei 60) | ||
+ | (setzt Sekunden beim Druecken zurueck auf 00) | ||
+ | |||
+ | Jumperstellung: | ||
+ | |||
+ | Fuses im uC: CKDIV8: Aus (keine generelle Vorteilung des Takts) | ||
+ | |||
+ | Header-Files: | ||
+ | |||
+ | Module: | ||
+ | 2) Zaehler fuer Uhr (Takt: 1 s) | ||
+ | 3) Anzeigetreiber | ||
+ | 4) Stellfunktion | ||
+ | |||
+ | Modul 1: Das Modul " | ||
+ | Zusaetzliche Takte: 10 ms fuer Stellfunktion | ||
+ | 100 ms fuer Anzeige. | ||
+ | |||
+ | Verwendung von Hardware-Timer 0 und T0 Overflow-Interrupt. | ||
+ | Frequenzen: Quarzfrequenz | ||
+ | Timer-Vorteiler | ||
+ | Hardware-Timer | ||
+ | Software-Vorteiler | ||
+ | Hundertstel-Zaehler / 10 => 10 Hz / 100 ms | ||
+ | Zehntel-Zaehler | ||
+ | |||
+ | Modul 2: Das Modul " | ||
+ | Sekunden, Minuten und Stunden werden als Binaerzahlen gezaehlt | ||
+ | Sekunden und Minuten zaehlen 00..59, die Stunden 00..23. | ||
+ | Ein " | ||
+ | |||
+ | Modul 3: Das Modul " | ||
+ | Hintergrundinformationen und die aktuelle Uhrzeit aus. | ||
+ | Darstellung auf der Anzeige (mittig in Zeile 1): [23: | ||
+ | |||
+ | Modul 4: Das Modul " | ||
+ | Es dient 1. zum Einlesen und Entprellen der Stelltasten | ||
+ | - Auswertung der fallenden Flanke 1=> 0 | ||
+ | 2. zum Ausfuehren der Stellfunktion: | ||
+ | - S2 zaehlt die Stunden aufwaerts | ||
+ | - S3 zaehlt die Minuten aufwaerts | ||
+ | - solange Taste S3 gedrueckt: Sekunden = 00 | ||
+ | (einfache Synchronisierung der Uhr!) | ||
+ | Beim Stellen kein Uebertrag von den Minuten auf die Stunden. | ||
+ | |||
+ | Die Kopplung der Module wird ueber global definierte Variable realisiert: | ||
+ | |||
+ | 1-Bit-Variable: | ||
+ | takt100ms: | ||
+ | takt1s: | ||
+ | |||
+ | 8-Bit-Variable: | ||
+ | minuten | ||
+ | stunden | ||
+ | |||
+ | =============================================================================*/ | ||
+ | |||
+ | // Deklarationen ============================================================== | ||
+ | |||
+ | // Festlegung der Quarzfrequenz | ||
+ | #ifndef F_CPU // optional definieren | ||
+ | #define F_CPU 18432000UL | ||
+ | # | ||
+ | |||
+ | // Include von Header-Dateien | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include " | ||
+ | |||
+ | // Makros | ||
+ | #define SET_BIT(BYTE, | ||
+ | #define CLR_BIT(BYTE, | ||
+ | #define TGL_BIT(BYTE, | ||
+ | |||
+ | // Konstanten | ||
+ | #define PRESCALER_VAL 90 | ||
+ | #define CYCLE10MS_MAX 10 | ||
+ | #define CYCLE100MS_MAX | ||
+ | |||
+ | #define SPEAK_PORT | ||
+ | #define SPEAK_BIT | ||
+ | |||
+ | #define ASC_NULL | ||
+ | #define ASC_COLON | ||
+ | #define INPUT_PIN_MASK 0b00001111 | ||
+ | |||
+ | // Variable | ||
+ | unsigned char softwarePrescaler = PRESCALER_VAL; | ||
+ | unsigned char cycle10msCount = CYCLE10MS_MAX; | ||
+ | unsigned char cycle100msCount | ||
+ | unsigned char seconds = 56; // Variable Sekunden | ||
+ | unsigned char minutes = 34; // Variable Minuten | ||
+ | unsigned char hours = 12; // Variable Stunden | ||
+ | |||
+ | bool timertick; | ||
+ | bool cycle10msActive; | ||
+ | bool cycle100msActive; | ||
+ | bool cycle1sActive; | ||
+ | |||
+ | bool button2_new = 1; // Bitspeicher fuer Taste 2 | ||
+ | bool button3_new = 1; // Bitspeicher fuer Taste 3 | ||
+ | bool button2_old = 1; // alter Wert von Taste 2 | ||
+ | bool button3_old = 1; // alter Wert von Taste 3 | ||
+ | |||
+ | uint8_t buttonState | ||
+ | |||
+ | // Funktionsprototypen | ||
+ | void initDisplay(void); | ||
+ | void setTime(void); | ||
+ | void showTime(void); | ||
+ | void refreshTime(void); | ||
+ | |||
+ | // Hauptprogramm ============================================================== | ||
+ | int main() | ||
+ | { | ||
+ | // Initialisierung | ||
+ | initDisplay(); | ||
+ | |||
+ | TCCR0A = 0; // Timer 0 auf " | ||
+ | SET_BIT(TCCR0B, | ||
+ | SET_BIT(TIMSK0, | ||
+ | |||
+ | SET_BIT(DDRD, | ||
+ | |||
+ | sei(); | ||
+ | |||
+ | // Hauptprogrammschleife | ||
+ | |||
+ | while(1) | ||
+ | // Funktionen abhaengig von Taktbotschaften | ||
+ | { | ||
+ | if (cycle10msActive) | ||
+ | { | ||
+ | cycle10msActive = 0; // | ||
+ | setTime(); | ||
+ | } | ||
+ | if (cycle100msActive) | ||
+ | { | ||
+ | cycle100msActive = 0; // Botschaft " | ||
+ | showTime(); | ||
+ | } | ||
+ | if (cycle1sActive) | ||
+ | { | ||
+ | cycle1sActive = 0; // | ||
+ | refreshTime(); | ||
+ | } | ||
+ | } | ||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | // Interrupt-Routine ========================================================== | ||
+ | |||
+ | ISR (TIMER0_OVF_vect) | ||
+ | /* In der Interrupt-Routine sind die Softwareteiler realisiert, die die Takt- | ||
+ | botschaften (10ms, 100ms, 1s) fuer die gesamte Uhr erzeugen. Die Interrupts | ||
+ | werden von Timer 0 ausgeloest (Interrupt Nr. 1) | ||
+ | |||
+ | */ | ||
+ | { | ||
+ | timertick = 1; // Botschaft 0,166ms senden | ||
+ | --softwarePrescaler; | ||
+ | if (softwarePrescaler==0) | ||
+ | { | ||
+ | softwarePrescaler = PRESCALER_VAL; | ||
+ | cycle10msActive = 1; // | ||
+ | --cycle10msCount; | ||
+ | |||
+ | if (cycle10msCount==0) | ||
+ | { | ||
+ | cycle10msCount = CYCLE10MS_MAX; | ||
+ | cycle100msActive = 1; // Botschaft 100ms senden | ||
+ | --cycle100msCount; | ||
+ | |||
+ | if (cycle100msCount==0) | ||
+ | { | ||
+ | cycle100msCount = CYCLE100MS_MAX; | ||
+ | cycle1sActive = 1; // | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // Stellfunktion ============================================================== | ||
+ | void setTime(void) | ||
+ | /* Die Stellfunktion der Uhr wird alle 10ms aufgerufen. Dadurch wir eine | ||
+ | Entprellung der Tastensignale realisiert. Das Stellen wir bei einer | ||
+ | fallenden Flanke des jeweiligen Tastensignals durchgefuehrt. Darum | ||
+ | muss fuer einen weiteren Stellschritt die Taste erneut betaetigt werden. | ||
+ | |||
+ | Eine Flanke wird durch (alter Wert == 1) UND (aktueller Wert == 0) erkannt. | ||
+ | |||
+ | Mit der Taste S2 werden die Stunden aufwaerts gestellt. | ||
+ | Mit der Taste S3 werden die Minuten aufwaerts gestellt (kein Uebertrag) | ||
+ | Solange Taste S3 gedrueckt ist werden die Sekunden auf 00 gehalten | ||
+ | |||
+ | Veraenderte Variable: stunden | ||
+ | minuten | ||
+ | sekunden | ||
+ | |||
+ | Speicher fuer Bits: | ||
+ | sw3Alt | ||
+ | */ | ||
+ | { | ||
+ | DDRC = DDRC & | ||
+ | PORTC |= INPUT_PIN_MASK; | ||
+ | _delay_us(1); | ||
+ | buttonState | ||
+ | DDRC |= INPUT_PIN_MASK; | ||
+ | |||
+ | // Einlesen der Tastensignale | ||
+ | button2_new = (buttonState & (1 << PC1)); | ||
+ | button3_new = (buttonState & (1 << PC2)); | ||
+ | |||
+ | |||
+ | if ((button2_new==0)& | ||
+ | { | ||
+ | hours++; | ||
+ | if (hours==24) | ||
+ | hours = 00; | ||
+ | } | ||
+ | if ((button3_new==0)& | ||
+ | { | ||
+ | minutes++; | ||
+ | if (minutes==60) | ||
+ | minutes = 00; | ||
+ | } | ||
+ | if (button3_new==0) | ||
+ | seconds = 00; // Sekunden auf 00 setzen | ||
+ | |||
+ | button2_old = button2_new; | ||
+ | button3_old = button3_new; | ||
+ | } | ||
+ | |||
+ | // Anzeigefunktion Uhr ======================================================== | ||
+ | void showTime(void) | ||
+ | /* Die Umrechnung der binaeren Zaehlwerte auf BCD ist folgendermaßen geloest: | ||
+ | Zehner: einfache Integer-Teilung (/10) | ||
+ | Einer: | ||
+ | */ | ||
+ | { | ||
+ | lcd_gotoxy(0, | ||
+ | |||
+ | lcd_putc(ASC_NULL + hours/ | ||
+ | lcd_putc(ASC_NULL + hours%10); | ||
+ | lcd_putc(ASC_COLON); | ||
+ | |||
+ | lcd_putc(ASC_NULL + minutes/ | ||
+ | lcd_putc(ASC_NULL + minutes%10); | ||
+ | lcd_putc(ASC_COLON); | ||
+ | |||
+ | lcd_putc(ASC_NULL + seconds/ | ||
+ | lcd_putc(ASC_NULL + seconds%10); | ||
+ | } | ||
+ | |||
+ | // Initialisierung Display-Anzeige ============================================ | ||
+ | void initDisplay() | ||
+ | { | ||
+ | lcd_init(); | ||
+ | |||
+ | lcd_gotoxy(0, | ||
+ | lcd_putstr(" | ||
+ | |||
+ | lcd_gotoxy(1, | ||
+ | lcd_putstr(" | ||
+ | |||
+ | _delay_ms(2000); | ||
+ | |||
+ | lcd_gotoxy(0, | ||
+ | lcd_putstr(" | ||
+ | |||
+ | lcd_gotoxy(1, | ||
+ | lcd_putstr(" | ||
+ | } // Ende der Funktion | ||
+ | |||
+ | // Zaehlfunktion Uhr ========================================================== | ||
+ | void refreshTime (void) | ||
+ | /* Die Uhr wird im Sekundentakt gezaehlt. Bei jedem Aufruf wird auch ein | ||
+ | " | ||
+ | die Minuten, die Ueberlaeufe der Minuten die Stunden hoch. | ||
+ | |||
+ | Veraenderte Variable: | ||
+ | minuten | ||
+ | stunden | ||
+ | */ | ||
+ | { | ||
+ | TGL_BIT (SPEAK_PORT, | ||
+ | // durch Invertierung des Portbits | ||
+ | |||
+ | seconds++; | ||
+ | if (seconds==60) | ||
+ | { | ||
+ | seconds = 0; // | ||
+ | minutes++; | ||
+ | if (minutes==60) | ||
+ | { | ||
+ | minutes = 0; // Minuten auf 00 setzen | ||
+ | hours++; | ||
+ | if (hours==24) | ||
+ | hours = 0; // Stunden auf 00 setzen | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | ''/ | ||
+ | |||
+ | Ä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. \\ Zusätzlich wird der Ausdruck '' | ||
+ | - Bei den Variablen entsprechen einige denen der letzten Programme. | ||
+ | - Für die Uhr werden Stunden, Minuten, Sekunden und Zehntelsekunden mit Anfangswerten deklariert. \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ | ||
+ | - Bei den Funktionsprototypen sind einige bekannte Unterprogramme vorhanden. Details werden weiter unten erklärt. \\ \\ \\ \\ \\ | ||
+ | |||
+ | '' | ||
+ | |||
+ | - Das Hauptprogramm ähnelt sehr stark dem [[4_up_down_counter|Up/ | ||
+ | - In der Endlosschleife sind auf der ersten Ebene wieder nur If-Abfragen zu den Flags '' | ||
+ | - Alle $10~\rm ms$ (bzw. wenn das entsprechende Flag gesetzt wird) wird das Flag zurückgesetzt und das Unterprogramm '' | ||
+ | - Alle $100~\rm ms$ (bzw. wenn das entsprechende Flag gesetzt wird) wird das Flag zurückgesetzt und das Unterprogramm '' | ||
+ | - Alle $1~\rm s$ (bzw. wenn das entsprechende Flag gesetzt wird) wird das Flag zurückgesetzt und das Unterprogramm '' | ||
+ | '' | ||
+ | - Auch die Interrupt Routine ist dem Programm [[4_up_down_counter|Up/ | ||
+ | |||
+ | '' | ||
+ | \\ \\ | ||
+ | - In dieser Funktion werden zunächst die Stellungen aller Taster eingelesen (vgl. '' | ||
+ | - Neu hier ist, dass die Bedienung der Schalter die Variablen für Stunden, Minuten um eins hochsetzen, bzw. bei Überlauf wider zurück auf 0 setzen. Zusätzlich wird bei eine Änderung des Minuten-Werts der Sekunden-Wert auf 0 gesetzt. | ||
+ | |||
+ | '' | ||
+ | - Hierüber wird die Uhrzeit in der ersten Zeile im Format hh:mm:ss ausgegeben. | ||
+ | - Ähnlich zum Counter werden die zweistelligen Werte mit Division durch 10 und dessen Rest in zwei einzelne Ziffern gewandelt | ||
+ | \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ | ||
+ | |||
+ | '' | ||
+ | - Die Funktion '' | ||
+ | - Danach wird der erste Text auf den Bildschirm geschrieben und damit der Programmname dargestellt. | ||
+ | - Nach zwei Sekunden wird der Auswahlbildschirm angezeigt. | ||
+ | |||
+ | \\ \\ \\ \\ \\ \\ \\ \\ \\ | ||
+ | |||
+ | '' | ||
+ | - Die Zähl-Funktion '' | ||
+ | - Zunächst wird ein Schaltwechsel am Ausgang mit dem Lautsprecher ausgegeben, um einen Knackton zu erzeugen | ||
+ | - Dann werden die Sekunden hochgezählt | ||
+ | - ist das Maximum erreicht, so wird der Sekunden-Wert zurückgesetzt und der Minuten-Wert um eins hochgezählt. | ||
+ | - ebenso wird beim Maximum des Minuten-Serts dieser zurückgesetzt und der Stundenwert hochgezählt. | ||
+ | - beim Maximum des Stunden-Werts wird dieser wieder auf Null gesetzt | ||
+ | </ | ||
+ | |||
+ | <-- | ||
+ | --> 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: | ||
+ | |||
+ | --> Aufgabe# | ||
+ | |||
+ | - Bauen Sie einen " | ||
+ | - Es sollen nicht nur Stunde, Minute, Sekunde dargestellt werden und veränderbar sein, sondern auch Tag, Monat und Jahr im Format dd:mm:yy | ||
+ | - Achten Sie auf die Schaltjahrermittlung | ||
+ | - Erweitern Sie den Kalender auf vierstellige Jahresangabe. | ||
+ | - Überlegen Sie sich, wie man Ihre Programme testen kann. | ||
+ | - BONUS: Wie kann der Wochentag bestimmt werden? | ||
+ | |||
+ | <-- | ||
- | bool sw1_slope = 0; // Flankenspeicher fuer Taste 1 | ||
- | </ |