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/24 15:40] tfischer |
microcontrollertechnik:7_uhr_und_zeitraster [2024/01/22 13:46] (aktuell) mexleadmin |
||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
- | ====== 7. Uhr und Zeitraster ====== | + | ====== 7 Uhr und Zeitraster ====== |
- | + | ||
- | <panel type=" | + | |
- | {{fa> | + | |
- | </ | + | |
==== Ziele ==== | ==== Ziele ==== | ||
Zeile 9: | Zeile 5: | ||
Nach dieser Lektion sollten Sie: | Nach dieser Lektion sollten Sie: | ||
- | - wissen, wie man eine einfache Menüführung | + | - wissen, wie man aus den auf Interupt-basierten Zeitrastern langsamere Raster umsetzt. |
==== Übung ==== | ==== Übung ==== | ||
Zeile 15: | Zeile 11: | ||
--> I. Vorarbeiten # | --> I. Vorarbeiten # | ||
- Laden Sie folgende Datei herunter: | - Laden Sie folgende Datei herunter: | ||
- | - {{microcontrollertechnik: | + | - {{microcontrollertechnik: |
- | - {{microcontrollertechnik: | + | - {{microcontrollertechnik: |
- | - {{microcontrollertechnik: | + | - {{microcontrollertechnik: |
<-- | <-- | ||
--> 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: |
- | - Die Schalter sind an den Pins C0...C3 angeschlossen, | + | - Laden Sie '' |
- | * Bei PB2 steht auch $\overline{SS}$ für "Slave Select" | + | |
- | * Bei PB3 steht auch $MOSI$ für " | + | |
- | * Bei PB4 steht auch $MISO$ für " | + | |
- | * zusätzlich steht bei PB5 steht auch $SCK$ für " | + | |
- | - Diese Anschlüsse sind an einem weiteren Display " | + | |
- | - PB3 ($MOSI$) ist zusätzlich an einem Oszilloskop angeschlossen. Die Eingänge zum PCD8544 sind jeweils an eine Probe angeschlossen. Die Probes sind mit einem Plotterkanal verbunden. | + | |
- | - 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 eine Uhr mit dem Format HH:MM:SS Menu zu sehen | - Als nächstes ist im Display eine Uhr mit dem Format HH:MM:SS Menu zu sehen | ||
- | - Die Tasten | + | - Die Tasten |
- | - Bleibt | + | |
- | - Beim Druck auf die Taste $S4$ wird eine Linie zwischen zwei zufälligen Punkten gezeichnet | + | |
- | - Das Programm zu diesem Hexfile soll nun erstellt und erklärt werden | + | |
<-- | <-- | ||
- | --> III. Eingabe in Atmel Studio # | + | |
+ | --> III. Eingabe in Microchip | ||
<WRAP group>< | <WRAP group>< | ||
+ | |||
/* ============================================================================ | /* ============================================================================ | ||
- | + | ||
- | Experiment 7: MiniMEXLE-Uhr | + | Experiment 7: 7_mexleclock |
- | ============= ========================================================= | + | ============= |
- | + | ||
- | Dateiname: MEXLEuhr_Master.c | + | Dateiname: |
- | + | ||
- | Autoren: Prof. T. Fischer (Hochschule Heilbronn) | + | Autoren: |
- | Prof. G. Gruhler (Hochschule Heilbronn) | + | Prof. G. Gruhler (Hochschule Heilbronn) |
- | D. Chilachava (Georgische Technische Universitaet) | + | D. Chilachava |
- | + | ||
- | Version: 0.2 vom 23.05.2020 | + | Version: |
- | + | ||
- | Hardware: Simulide | + | Hardware: |
- | + | AVR-USB-PROGI Ver. 2.0 | |
- | Software: Atmel Studio Ver. 7.xx | + | |
- | + | Software: | |
- | Funktion: Digitaluhr mit Anzeige von Stunden, Minuten und Sekunden. Eine | + | C-Compiler: AVR/GNU C Compiler 5.4.0 |
- | einfache Stellfunktion ist mit den Tasten S2 und S3 realisiert. | + | |
- | Mit S1 und S4 kann die SPI-Kommunikation mit einem Slave-Display | + | Funktion: |
- | gestartet werden | + | einfache Stellfunktion ist mit den Tasten S2 und S3 realisiert. |
- | + | ||
- | Displayanzeige: | + | Displayanzeige: |
- | +----------------+ +----------------+ | + | +----------------+ |
- | | MEXLEuhr | + | |- Experiment 7 -| |=== 00:00:00 ===| |
- | | Master | + | | Digital Clock |
- | +----------------+ +----------------+ | + | +----------------+ |
- | + | ||
- | Tastenfunktion: | + | Tastenfunktion: |
- | S2: | + | S3: Min (zaehlt Minuten bei Flanke aufwaerts. |
- | S3: Min (zaehlt Minuten bei Flanke aufwaerts. | + | (setzt Sekunden beim Druecken zurueck auf 00) |
- | (setzt Sekunden beim Druecken zurueck auf 00) | + | |
- | S4: uebertraegt die Info zum Darstellen einer Linie zum Master | + | Jumperstellung: keine Auswirkung |
- | + | ||
- | Fuses im uC: CKDIV8: Aus (keine generelle Vorteilung des Takts) | + | Fuses im uC: CKDIV8: Aus (keine generelle Vorteilung des Takts) |
- | + | ||
- | Header-Files: | + | Header-Files: |
- | + | ||
- | Libraries: | + | Module: |
- | pcd8544.h (Header-Datei fuer die Ansteuerung des Displays) | + | 2) Zaehler fuer Uhr (Takt: 1 s) |
- | + | 3) Anzeigetreiber | |
- | Module: 1) Taktgenerator | + | 4) Stellfunktion |
- | 2) Zaehler fuer Uhr (Takt: 1 s) | + | |
- | 3) Anzeigetreiber | + | Modul 1: Das Modul " |
- | 4) Stellfunktion | + | Zusaetzliche Takte: 10 ms fuer Stellfunktion |
- | 5) SPI-Funktionen | + | 100 ms fuer Anzeige. |
- | + | ||
- | + | Verwendung von Hardware-Timer 0 und T0 Overflow-Interrupt. | |
- | Die Kopplung der Module wird ueber global definierte Variable realisiert: | + | Frequenzen: Quarzfrequenz |
- | + | Timer-Vorteiler | |
- | 1-Bit-Variable: | + | Hardware-Timer |
- | takt100ms: | + | Software-Vorteiler |
- | takt1s: Taktgenerator => Zaehler fuer Uhr | + | Hundertstel-Zaehler / 10 => 10 Hz / 100 ms |
- | + | Zehntel-Zaehler | |
- | 8-Bit-Variable: | + | |
- | minuten | + | Modul 2: Das Modul " |
- | stunden | + | 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 ============================================================== | // Deklarationen ============================================================== | ||
+ | |||
// Festlegung der Quarzfrequenz | // Festlegung der Quarzfrequenz | ||
- | + | #ifndef F_CPU | |
- | #ifndef F_CPU // optional definieren | + | #define F_CPU 18432000UL |
- | #define F_CPU 6144000UL // MiniMEXLE | + | # |
- | #endif | + | |
- | + | ||
// Include von Header-Dateien | // Include von Header-Dateien | ||
- | + | #include < | |
- | #include < | + | #include < |
- | #include < | + | #include < |
- | #include < | + | #include " |
- | #include < | + | |
- | #include < | + | |
- | #include " | + | |
- | #include " | + | |
// Makros | // Makros | ||
- | + | #define SET_BIT(BYTE, BIT) ((BYTE) |= (1 << (BIT))) // Bit Zustand in Byte setzen | |
- | # | + | #define CLR_BIT(BYTE, BIT) ((BYTE) &= ~(1 << (BIT))) // Bit Zustand in Byte loeschen |
- | #define CLR_BIT(PORT, BIT) ((PORT) &= ~(1 << (BIT))) // Port-Bit Loeschen | + | #define TGL_BIT(BYTE, BIT) ((BYTE) ^= (1 << (BIT))) // Bit Zustand in Byte wechseln (toggle) |
- | #define TGL_BIT(PORT, BIT) ((PORT) ^= (1 << (BIT))) // Port-Bit Toggeln | + | |
// Konstanten | // Konstanten | ||
- | + | # | |
- | # | + | # |
- | # | + | # |
- | # | + | |
- | + | #define SPEAK_PORT | |
- | #define SPEAK_PORT PORTD // Port-Adresse fuer Lautsprecher | + | #define SPEAK_BIT |
- | #define SPEAK_BIT 5 // Port-Bit fuer Lautsprecher | + | |
- | #define LED_PORT PORTB // | + | #define ASC_NULL |
- | #define LED_BIT 0 // | + | #define ASC_COLON |
- | + | #define INPUT_PIN_MASK 0b00001111 | |
- | #define ASC_NULL 0x30 // Das Zeichen ' | + | |
- | #define ASC_COLON 0x3A // Das Zeichen ':' | + | |
// Variable | // 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 | ||
- | unsigned char vorteiler = VORTEILER_WERT; // Zaehlvariable Vorteiler | + | uint8_t buttonState |
- | unsigned char hundertstel | + | |
- | unsigned char zehntel = ZEHNTEL_WERT; | + | |
- | + | ||
- | unsigned char zehntelSekunden = 0; // Variable Sekunden | + | |
- | unsigned char sekunden = 56; // Variable Sekunden | + | |
- | unsigned char minuten = 34; // Variable Minuten | + | |
- | unsigned char stunden = 12; // Variable Stunden | + | |
- | + | ||
- | unsigned char zeile = 0; // x-Koordinate | + | |
- | unsigned char pos = 0; // y-Koordinate | + | |
- | unsigned char zeichen =' | + | |
- | + | ||
- | bool timertick; | + | |
- | bool takt10ms; | + | |
- | bool takt100ms; | + | |
- | bool takt1s; | + | |
- | + | ||
- | 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 PcdSendMessage = 0; // Flag fuer sendebereite SPI-Nachricht | + | |
// Funktionsprototypen | // Funktionsprototypen | ||
- | + | void initDisplay(void); // Init Anzeige | |
- | void timerInt0(void); // Init Zeitbasis mit Timer 0 | + | void setTime(void); |
- | void uhrStellen(void); | + | void showTime(void); // Anzeigefunktion |
- | void uhrAnzeigen(void); // Anzeigefunktion | + | void refreshTime(void); // Uhrfunktion |
- | void uhrZaehlen(void); // Uhrfunktion | + | |
- | void initDisplay(void); | + | |
- | void zehntelSekundenAufPcdAnzeigen(void);// | + | |
// Hauptprogramm ============================================================== | // Hauptprogramm ============================================================== | ||
- | |||
int main() | int main() | ||
{ | { | ||
- | // Initialisierung | + | |
- | + | initDisplay(); | |
- | initDisplay(); | + | |
- | pcd_init(); | + | TCCR0A = 0; |
- | + | SET_BIT(TCCR0B, | |
- | TCCR0A = 0; // Timer 0 auf " | + | SET_BIT(TIMSK0, |
- | SET_BIT(TCCR0B, | + | |
- | SET_BIT(TIMSK0, | + | SET_BIT(DDRD, |
- | + | ||
- | SET_BIT(DDRD, | + | sei(); |
- | PORTC |= 0b00001111; | + | |
- | SET_BIT(DDRB, | + | // Hauptprogrammschleife |
- | + | ||
- | sei(); // generell Interrupts einschalten | + | while(1) |
- | + | // Funktionen abhaengig von Taktbotschaften | |
- | // Hauptprogrammschleife | + | { |
- | + | if (cycle10msActive) | |
- | while(1) // unendliche Warteschleife mit Aufruf der | + | { |
- | // Funktionen abhaengig von Taktbotschaften | + | |
- | { | + | |
- | if (takt10ms) // alle 10ms: | + | } |
- | { | + | if (cycle100msActive) // alle 100ms: |
- | takt10ms | + | { |
- | uhrStellen(); // Tasten abfragen, | + | |
- | } | + | |
- | + | } | |
- | if (takt100ms) // alle 100ms: | + | if (cycle1sActive) |
- | { | + | { |
- | takt100ms | + | |
- | if (PcdSendMessage) // wenn SPI-Nachricht gesendet werden soll: | + | |
- | { | + | } |
- | PcdSendMessage = 0; // Botschaft loeschen | + | } |
- | TGL_BIT(LED_PORT, | + | return 0; |
- | zehntelSekundenAufPcdAnzeigen();// | + | |
- | } | + | |
- | uhrAnzeigen(); | + | |
- | uhrZaehlen(); | + | |
- | } | + | |
- | + | ||
- | if (takt1s) // alle Sekunden: | + | |
- | { | + | |
- | takt1s | + | |
- | TGL_BIT(LED_PORT, LED_BIT); // LED Zustand wechseln | + | |
- | pcd_init(); | + | |
- | } | + | |
- | } | + | |
- | return 0; | + | |
} | } | ||
- | + | ||
// Interrupt-Routine ========================================================== | // Interrupt-Routine ========================================================== | ||
ISR (TIMER0_OVF_vect) | ISR (TIMER0_OVF_vect) | ||
- | + | /* In der Interrupt-Routine sind die Softwareteiler realisiert, die die Takt- | |
- | /* In der Interrupt-Routine sind die Softwareteiler realisiert, die die Takt- | + | botschaften (10ms, 100ms, 1s) fuer die gesamte Uhr erzeugen. Die Interrupts |
- | botschaften (10ms, 100ms, 1s) fuer die gesamte Uhr erzeugen. Die Interrupts | + | werden von Timer 0 ausgeloest (Interrupt Nr. 1) |
- | werden von Timer 0 ausgeloest (Interrupt Nr. 1) | + | |
- | + | ||
- | Veraenderte Variable: vorteiler | + | |
- | | + | |
- | | + | |
- | + | ||
- | Ausgangsvariable: | + | |
- | | + | |
- | | + | |
*/ | */ | ||
- | |||
{ | { | ||
- | timertick = 1; // Botschaft 0,111ms senden | + | |
- | --vorteiler; // Vorteiler dekrementieren | + | --softwarePrescaler; // Vorteiler dekrementieren |
- | if (vorteiler==0) // wenn 0 erreicht: 10ms abgelaufen | + | if (softwarePrescaler==0) |
- | { | + | { |
- | vorteiler | + | |
- | takt10ms | + | |
- | --hundertstel; // Hunderstelzaehler dekrementieren | + | --cycle10msCount; // Hunderstelzaehler dekrementieren |
- | + | ||
- | if (hundertstel==0) // wenn 0 erreicht: 100ms abgelaufen | + | if (cycle10msCount==0) |
- | { | + | { |
- | hundertstel | + | |
- | takt100ms | + | |
- | --zehntel; // Zehntelzaehler dekrementieren | + | --cycle100msCount; // Zehntelzaehler dekrementieren |
- | + | ||
- | if (zehntel==0) // wenn 0 erreicht: 1s abgelaufen | + | if (cycle100msCount==0) |
- | { | + | { |
- | zehntel | + | |
- | takt1s | + | |
- | } | + | } |
- | } | + | } |
- | } | + | } |
} | } | ||
+ | | ||
// Stellfunktion ============================================================== | // Stellfunktion ============================================================== | ||
- | + | void setTime(void) | |
- | void uhrStellen(void) | + | /* Die Stellfunktion der Uhr wird alle 10ms aufgerufen. Dadurch wir eine |
- | + | Entprellung der Tastensignale realisiert. Das Stellen wir bei einer | |
- | /* Die Stellfunktion der Uhr wird alle 10ms aufgerufen. Dadurch wir eine | + | fallenden Flanke des jeweiligen Tastensignals durchgefuehrt. Darum |
- | Entprellung der Tastensignale realisiert. Das Stellen wir bei einer | + | muss fuer einen weiteren Stellschritt die Taste erneut betaetigt werden. |
- | 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. |
- | Ebenso wird die SPI-Funktion hier aufgerufen. | + | |
- | + | Mit der Taste S2 werden die Stunden aufwaerts gestellt. | |
- | Eine Flanke wird durch (alter Wert == 1) UND (aktueller Wert == 0) erkannt. | + | Mit der Taste S3 werden die Minuten aufwaerts gestellt (kein Uebertrag) |
- | + | Solange Taste S3 gedrueckt ist werden die Sekunden auf 00 gehalten | |
- | Mit der Taste S1 wird die Uebergabe der Zeit Master > Slave gestartet | + | |
- | Mit der Taste S2 werden die Stunden aufwaerts gestellt. | + | Veraenderte Variable: stunden |
- | Mit der Taste S3 werden die Minuten aufwaerts gestellt (kein Uebertrag) | + | minuten |
- | Solange Taste S3 gedrueckt ist werden die Sekunden auf 00 gehalten | + | sekunden |
- | Mit der Taste S4 wird die Uebergabe der Zeit Master < Slave gestartet | + | |
- | + | Speicher fuer Bits: | |
- | Veraenderte Variable: stunden | + | sw3Alt |
- | | + | |
- | | + | |
- | + | ||
- | Speicher fuer Bits: | + | |
- | | + | |
- | | + | |
- | | + | |
*/ | */ | ||
+ | { | ||
+ | DDRC = DDRC & | ||
+ | PORTC |= INPUT_PIN_MASK; | ||
+ | _delay_us(1); | ||
+ | buttonState | ||
+ | DDRC |= INPUT_PIN_MASK; | ||
- | { | + | |
- | sw1_neu = (PINC & (1 << PC0)); // Tasten von Port einlesen | + | |
- | sw2_neu | + | |
- | sw3_neu | + | |
- | sw4_neu = (PINC & (1 << PC3)); | + | |
- | + | if ((button2_new==0)&(button2_old==1)) // wenn Taste 2 eben gedrueckt wurde: | |
- | if ((sw1_neu==0)) // | + | { |
- | { | + | hours++; // Stunden hochzaehlen, |
- | PcdSendMessage = 1; | + | if (hours==24) |
- | } | + | |
- | + | } | |
- | if ((sw2_neu==0)&(sw2_alt==1)) // wenn Taste 2 eben gedrueckt wurde: | + | if ((button3_new==0)&(button3_old==1)) // wenn Taste 3 eben gedrueckt wurde: |
- | { | + | { |
- | stunden++; // Stunden hochzaehlen, | + | |
- | if (stunden==24) | + | if (minutes==60) |
- | stunden | + | |
- | } | + | } |
- | if ((sw3_neu==0)&(sw3_alt==1)) // wenn Taste 3 eben gedrueckt wurde: | + | if (button3_new==0) |
- | { | + | |
- | minuten++; // Minuten hochzaehlen, | + | |
- | if (minuten==60) | + | |
- | minuten | + | |
- | } | + | |
- | if (sw3_neu==0) // solange Taste 3 gedrueckt: | + | |
- | sekunden | + | |
- | + | ||
- | if ((sw4_neu==0)& | + | |
- | { | + | |
- | pcd_putLine(rand()%83, | + | |
- | pcd_updateDisplay(); | + | |
- | } | + | |
- | + | ||
- | sw1_alt = sw1_neu; | + | |
- | sw2_alt | + | |
- | sw3_alt = sw3_neu; | + | |
- | sw4_alt = sw4_neu; | + | |
} | } | ||
+ | |||
// Anzeigefunktion Uhr ======================================================== | // Anzeigefunktion Uhr ======================================================== | ||
- | + | void showTime(void) | |
- | void uhrAnzeigen(void) | + | /* Die Umrechnung der binaeren Zaehlwerte auf BCD ist folgendermaßen geloest: |
- | + | Zehner: einfache Integer-Teilung (/10) | |
- | /* Die Umrechnung der binaeren Zaehlwerte auf BCD ist folgendermaßen geloest: | + | Einer: |
- | Zehner: einfache Integer-Teilung (/10) | + | |
- | Einer: | + | |
*/ | */ | ||
- | |||
{ | { | ||
- | lcd_gotoxy(0, | + | |
- | + | | |
- | lcd_putc(ASC_NULL + stunden/10); // Stunden Zehner als ASCII ausgeben | + | lcd_putc(ASC_NULL + hours/10); // Stunden Zehner als ASCII ausgeben |
- | lcd_putc(ASC_NULL + stunden%10); // Stunden Einer als ASCII ausgeben | + | lcd_putc(ASC_NULL + hours%10); // Stunden Einer als ASCII ausgeben |
- | lcd_putc(ASC_COLON); | + | lcd_putc(ASC_COLON); |
- | + | | |
- | lcd_putc(ASC_NULL + minuten/10); // Minuten als ASCII ausgeben | + | lcd_putc(ASC_NULL + minutes/10); // Minuten als ASCII ausgeben |
- | lcd_putc(ASC_NULL + minuten%10); // | + | lcd_putc(ASC_NULL + minutes%10); // |
- | lcd_putc(ASC_COLON); | + | lcd_putc(ASC_COLON); |
- | + | | |
- | lcd_putc(ASC_NULL + sekunden/10); // Sekunden als ASCII ausgeben | + | lcd_putc(ASC_NULL + seconds/10); |
- | lcd_putc(ASC_NULL + sekunden%10); // | + | lcd_putc(ASC_NULL + seconds%10); |
} | } | ||
- | + | ||
- | // Anzeigefunktion fuer PCD Display ======================================================== | + | |
- | + | ||
- | void zehntelSekundenAufPcdAnzeigen(void) | + | |
- | + | ||
- | /* Anzeigen der Zenhtelsekunden auf dem Display PCD8544 | + | |
- | */ | + | |
- | + | ||
- | { | + | |
- | pcd_gotoxy(zeile, | + | |
- | pcd_putc(zehntelSekunden+0x30); | + | |
- | pcd_updateDisplay(); | + | |
- | if (++pos > 13) // naechste Position, und wenn diese ausserhalb der Anzeige | + | |
- | { | + | |
- | pos = 0; // zurueck auf erste Position | + | |
- | if (++zeile > 5) // naechste Zeile, und wenn diese ausserhalb der Anzeige | + | |
- | { | + | |
- | zeile = 0; // zurueck auf erste Zeile | + | |
- | pcd_clearDisplay(); | + | |
- | }; | + | |
- | } | + | |
- | } | + | |
// Initialisierung Display-Anzeige ============================================ | // Initialisierung Display-Anzeige ============================================ | ||
- | + | void initDisplay() | |
- | void initDisplay() // Start der Funktion | + | |
{ | { | ||
- | lcd_init(); | + | |
- | + | | |
- | lcd_gotoxy(0, | + | lcd_gotoxy(0, |
- | lcd_putstr(" | + | lcd_putstr(" |
- | + | ||
- | lcd_gotoxy(1, | + | lcd_gotoxy(1, |
- | lcd_putstr(" | + | lcd_putstr(" |
- | + | ||
- | _delay_ms(1000); // Wartezeit nach Initialisierung | + | _delay_ms(2000); // Wartezeit nach Initialisierung |
- | + | ||
- | lcd_gotoxy(0, | + | lcd_gotoxy(0, |
- | lcd_putstr(" | + | lcd_putstr(" |
- | + | ||
- | lcd_gotoxy(1, | + | lcd_gotoxy(1, |
- | lcd_putstr(" | + | lcd_putstr(" |
- | + | } | |
- | } // Ende der Funktion | + | |
- | + | ||
// Zaehlfunktion Uhr ========================================================== | // Zaehlfunktion Uhr ========================================================== | ||
- | + | void refreshTime | |
- | void uhrZaehlen | + | /* Die Uhr wird im Sekundentakt gezaehlt. Bei jedem Aufruf wird auch ein |
- | + | " | |
- | /* Die Uhr wird im Sekundentakt gezaehlt. Bei jedem Aufruf wird auch ein | + | die Minuten, die Ueberlaeufe der Minuten die Stunden hoch. |
- | " | + | |
- | die Minuten, die Ueberlaeufe der Minuten die Stunden hoch. | + | Veraenderte Variable: |
- | + | minuten | |
- | Veraenderte Variable: | + | stunden |
- | minuten | + | |
- | stunden | + | |
*/ | */ | ||
- | |||
{ | { | ||
- | TGL_BIT (SPEAK_PORT, | + | |
- | // durch Invertierung des Portbits | + | // durch Invertierung des Portbits |
- | zehntelSekunden++; | + | |
- | if (zehntelSekunden==10) // | + | |
- | { | + | if (seconds==60) |
- | zehntelSekunden=0; | + | { |
- | sekunden++; // Sekunden hochzaehlen | + | |
- | if (sekunden==60) // bei Ueberlauf: | + | |
- | { | + | if (minutes==60) // bei Ueberlauf: |
- | sekunden | + | { |
- | minuten++; // | + | |
- | if (minuten==60) // bei Ueberlauf: | + | hours++; // Stunden hochzaehlen |
- | { | + | if (hours==24) // bei Ueberlauf: |
- | minuten | + | |
- | stunden++; // Stunden hochzaehlen | + | } |
- | if (stunden==24) // bei Ueberlauf: | + | } |
- | stunden | + | |
- | } | + | |
- | } | + | |
- | } | + | |
} | } | ||
- | |||
</ | </ | ||
</ | </ | ||
Zeile 452: | Zeile 366: | ||
''/ | ''/ | ||
- | Ändern Sie auch hier wieder die Beschreibung am Anfang des C-Files, je nachdem was Sie entwickeln | + | Ä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. | + | - Hier wird wieder geprüft ob die Frequenz des Quarz bereits eingestellt wurde und - falls nicht - dessen Frequenz eingestellt. \\ \\ |
- | - Zusätzlich zu den bisherigen | + | - Die Header-Dateien |
- | - ''< | + | - Auch die Makros entsprechen denen der letzten Programme. \\ \\ \\ \\ |
- | - ''" | + | - Die Konstanten entsprechen denen der letzten Programme. \\ Zusätzlich wird der Ausdruck |
- | - Die Makros entsprechen denen der letzten Programme. \\ \\ \\ \\ | + | - Bei den Variablen entsprechen einige denen der letzten Programme. |
- | - Die Konstanten entsprechen | + | - Für die Uhr werden Stunden, Minuten, Sekunden und Zehntelsekunden mit Anfangswerten deklariert. \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ |
- | - Für die Zeichen | + | - Bei den Funktionsprototypen sind einige bekannte Unterprogramme vorhanden. Details werden weiter unten erklärt. \\ \\ \\ \\ \\ |
- | - Bei den Variablen entsprechen einige denen der letzten Programme. | + | |
- | - Für die Uhr werden Stunden, Minuten, Sekunden und Zehntelsekunden mit Anfangswerten deklariert. \\ \\ \\ | + | |
- | - Für das neue Display werden Variablen für die Textposition und für das auszugebenden Zeichen deklariert. | + | |
- | - Das Flag PcdSendMessage zeigt an, ob Zeichen regelmäßig zu übertragen sind. | + | |
- | - 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 wieder " | ||
- | - Die " | ||
- | - Auch die Konfiguration der Anschlüsse für die Schalter wurde bereits erklärt. Die an Port C angeschlossenen Taster erhalten dadurch einen Pull-up Widerstand. \\ \\ | ||
- | - Mit dem Befehl '' | ||
- | - In der Endlosschleife sind verschiedene Zeitzyklen vorgesehen (wie beim [[4._up_down_counter|Up/ | ||
- | - im $10ms$ Raster (auch $10ms$ Zyklus genannt) wird die Unterfunktion '' | ||
- | - im $100ms$ Raster werden die Unterfunktionen '' | ||
- | - im $1s$ Raster blinkt die LED und das Unterprogramm '' | ||
+ | - 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 '' | ||
'' | '' | ||
- | - Mit dem Befehl '' | + | - Auch die Interrupt Routine ist dem Programm |
- | - Die Ermittlung von '' | + | |
- | - Eine Erweiterung auf '' | + | |
- | '' | + | |
- | \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ | + | |
- | - In dieser Funktion werden zunächst die Stellungen aller Taster eingelesen (vgl. '' | + | |
- | - Die Flankenerkennung in den if-Bedingungen wurde auch bereits beim [[4._up_down_counter|Up/ | + | |
- | - Wenn die Taste '' | + | |
- | - Die Tasten '' | + | |
- | - Die Taste '' | + | |
- | '' | + | '' |
- | + | \\ \\ | |
- | \\ \\ \\ \\ \\ \\ | + | - In dieser Funktion werden |
- | + | - 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 | |
- | - Auf dem LCD wird zunächst die Position | + | |
- | - Vom Wert '' | + | |
- | - Danach | + | |
- | | + | |
- | + | ||
- | \\ \\ \\ \\ | + | |
- | + | ||
- | '' | + | |
- | \\ \\ \\ \\ | + | |
- | - Auch für die Anzeige auf dem PCD 8544 wird zunächst die Position auf dem Display mittels '' | + | |
- | - Der Wert der Zehntelsekunde wird über '' | + | |
- | - Danach wird die Displayanzeige aktualisiert | + | |
- | - Die Position auf dem PCD Display wird anschließend erhöht. Da nur 13 Zeichen in eine Zeile passen, wird - falls diese Grenze erreicht wurde - die Position zurückgesetzt. | + | |
- | - Falls das Ende einer Zeile erreicht wurde, wird die Zeilenposition erhöht. Wenn die Maximalzahl von 5 Zeilen erreicht wurde, so wird wieder auf die erste Position der ersten Zeile zurückgesprungen und das Display gelöscht. | + | |
- | + | ||
- | \\ \\ | + | |
- | '' | + | '' |
+ | - 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 | ||
+ | \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ | ||
- | | + | '' |
+ | | ||
+ | - Danach wird der erste Text auf den Bildschirm geschrieben und damit der Programmname dargestellt. | ||
+ | - Nach zwei Sekunden wird der Auswahlbildschirm angezeigt. | ||
- | \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ | + | \\ \\ \\ \\ \\ \\ \\ \\ \\ |
- | '' | + | |
- | \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ | + | |
- | - Hier wird zunächst ein Flankenwechsel für den Lautsprecher ausgegeben. Damit knackt der Lautsprecher etwa im $10ms$ Takt. | + | |
- | - In den verschachtelten if-Anweisungen werden jeweils die einzelnen Werte (z.B. '' | + | |
+ | '' | ||
+ | - 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 | ||
</ | </ | ||
Zeile 531: | Zeile 419: | ||
<-- | <-- | ||
+ | |||
\\ | \\ | ||
Bitte arbeiten Sie folgende Aufgaben durch: | Bitte arbeiten Sie folgende Aufgaben durch: | ||
- | --> | + | --> |
- | - Analyse der Zufallsfunktion '' | + | |
- | - Wenn Sie die Taste '' | + | - Bauen Sie einen " |
- | - Prüfen Sie nach, ob die Anfangs- | + | - Es sollen nicht nur Stunde, Minute, Sekunde dargestellt werden |
- | - Analyse der seriellen Kommunikation | + | - Achten |
- | - Wenn Daten vom Mikrocontroller zum PCD8544 übertragen werden, so ist auf dem Oszilloskop | + | - Erweitern |
- | - Dazu starten | + | - Überlegen Sie sich, wie man Ihre Programme testen |
- | - Auf dem Oszilloskop ist ein detailliertes Signal auf dem PCD8544-Eingang '' | + | - BONUS: Wie kann der Wochentag bestimmt |
- | - Ändern | + | |
- | - Der Abstand zwischen den Signale scheinen nun größer geworden zu sein. Falls keine Änderung der Signale im Potter zu sehen ist, kann durch das Drücken der Taste '' | + | |
- | - Öffnen Sie zunächst wieder den Schalter '' | + | |
- | - Schließen Sie nun wieder den Schalter '' | + | |
- | - Nun sollten die Signale gut aufgelöst sichtbar sein: | + | |
- | - Das 1. Signal '' | + | |
- | - Das 2. Signal '' | + | |
<-- | <-- | ||
+ | |||