Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

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:
-====== 7Uhr und Zeitraster ====== +====== 7 Uhr und Zeitraster ======
- +
-<panel type="warning" title="ACHTUNG"> +
-{{fa>spinner?3x&pulse}} (nbsp)(nbsp)(nbsp)(nbsp)Diese Seite ist gerade in Bearbeitung ... +
-</panel>+
  
 ==== Ziele ==== ==== Ziele ====
Zeile 9: Zeile 5:
 Nach dieser Lektion sollten Sie: Nach dieser Lektion sollten Sie:
  
-  - wissen, wie man eine einfache Menüführung auf einem Display implementiert.+  - 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:mexleuhr_spi.simu}} +    - {{microcontrollertechnik:7._uhr_und_zeitraster.sim1}} 
-    - {{microcontrollertechnik:mexleuhr_master.hex}} +    - {{microcontrollertechnik:7._uhr_und_zeitraster.hex}} 
-    - {{microcontrollertechnik:mexleuhr_master.zip}}+    - {{microcontrollertechnik:lcd_lib_de.h}}
  
 <-- <--
 --> 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:simulide_open.jpg?25}} die Datei ''mexleuhr_spi.simu''. In der Simulation sind einige Änderungen zu finden: +    - Öffnen Sie SimulIDE und öffnen Sie dort mittels {{microcontrollertechnik:simulide_open.jpg?25}} die Datei ''7._uhr_und_zeitraster.sim1''  
-      - Die Schalter sind an den Pins C0...C3 angeschlossen, statt an den Pins B1...B4. Viele der Pins haben - neben er Möglichkeit digitale Werte auszugeben - weitere Funktionen. Im [[http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf#page=3|Datenblatt]] ist diese Belegung beschrieben:  +    - Laden Sie ''7._uhr_und_zeitraster.hex'' als firmware auf den 88 Chip
-        * Bei PB2 steht auch $\overline{SS}$ für "Slave Select" +
-        * Bei PB3 steht auch $MOSI$ für "Master out, slave in" +
-        * Bei PB4 steht auch $MISO$ für "Master in, slave out" +
-        * zusätzlich steht bei PB5 steht auch $SCK$ für "serial clock" +
-      - Diese Anschlüsse sind an einem weiteren Display "Pcd8544" angeschlossen. Zusätzlich ist PB1 an "D/C" des Displays angeschlossen +
-      - 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 ''mexleuhr_master.hex'' als firmware auf den 328 Chip+
     - 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 $S2$ und $S3$ ermöglichen das Einstellen der Stunde und Minute.  +    - Die Tasten ''2'' und ''3'' ermöglichen das Einstellen der Stunde und Minute. Werden die Minuten hochgezählt, so werden die Sekunden auf 0 gesetzt.
-    - Bleibt die Taste $S1$ gedrückt, so werden die Zehntelsekunden auf dem Display Pcd8544 ausgegeben. +
-    - 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 Studio #
 <WRAP group><WRAP column 40%><sxh c; first-line: 1> <WRAP group><WRAP column 40%><sxh c; first-line: 1>
 +
 /* ============================================================================ /* ============================================================================
- +  
-Experiment 7:  MiniMEXLE-Uhr mit hh:mm:ss-Anzeige und SPI-Master +Experiment 7:   7_mexleclock mit Stunden-, Minuten- und Sekunden-Anzeige 
-============= ========================================================= +=============   ========================================================= 
- +  
-Dateiname: MEXLEuhr_Master.c +Dateiname:      7_MexleClock.c 
- +  
-Autoren: Prof. T. Fischer (Hochschule Heilbronn) +Autoren:        Peter Blinzinger 
- Prof. G. Gruhler (Hochschule Heilbronn) +                Prof. G. Gruhler (Hochschule Heilbronn) 
- D. Chilachava  (Georgische Technische Universitaet) +                D. Chilachava    (Georgische Technische Universitaet) 
- +  
-Version: 0.vom 23.05.2020 +Version:        1.vom 22.10.2022 
- +  
-Hardware: Simulide  +Hardware:       MEXLE2020 Ver. 1.0 oder höher 
- +                AVR-USB-PROGI Ver. 2.0 
-Software: Atmel Studio Ver. 7.xx  +  
- +Software:       Entwicklungsumgebung: AtmelStudio 7.
-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:       Digitaluhr mit Anzeige von Stunden, Minuten und Sekunden. Eine 
- gestartet werden +                einfache Stellfunktion ist mit den Tasten S2 und S3 realisiert. 
- +  
-Displayanzeige: Start (fuer 2s): Betrieb: +Displayanzeige: Start (fuer 2s):        Betrieb: 
- +----------------+ +----------------+ +                +----------------+      +----------------+ 
- MEXLEuhr SPI | |=== 00:00:00 ===| +                |- Experiment 7 -     |=== 00:00:00 ===| 
-     Master     | |10tl Std Min Lin+                Digital Clock         Std Min      
- +----------------+ +----------------+ +                +----------------+      +----------------+ 
- +  
-Tastenfunktion: S1: uebertraegt die Zehntelsekunde vom Master zum Slave +Tastenfunktion: S2: Std (zaehlt Stunden bei Flanke aufwaerts. Überlauf bei 24) 
- S2: Std (zaehlt Stunden bei Flanke aufwaerts. Ueberlauf bei 24) +                S3: Min (zaehlt Minuten bei Flanke aufwaerts. Überlauf bei 60) 
- S3: Min (zaehlt Minuten bei Flanke aufwaerts. Ueberlauf bei 60) +                        (setzt Sekunden beim Druecken zurueck auf 00) 
- (setzt Sekunden beim Druecken zurueck auf 00) +  
- S4uebertraegt die Info zum Darstellen einer Linie zum Master +Jumperstellungkeine Auswirkung 
- +  
-Fuses im uC: CKDIV8: Aus (keine generelle Vorteilung des Takts) +Fuses im uC:    CKDIV8: Aus (keine generelle Vorteilung des Takts) 
- +  
-Header-Files: lcd_lib_de.h (Library zur Ansteuerung LCD-Display Ver. 1.2) +Header-Files:   lcd_lib_de.h    (Library zur Ansteuerung LCD-Display Ver. 1.3
- +  
-Libraries: pcd8544.c (Library fuer die Ansteuerung des Displays) +Module:         1) Taktgenerator 
- pcd8544.h (Header-Datei fuer die Ansteuerung des Displays+                2) Zaehler fuer Uhr (Takt: 1 s) 
- +                3) Anzeigetreiber   (Takt: 100 ms) 
-Module: 1) Taktgenerator +                4) Stellfunktion    (Takt: 10 ms) 
- 2) Zaehler fuer Uhr (Takt: 1 s) +  
- 3) Anzeigetreiber  (Takt: 100 ms) +    Modul 1:    Das Modul "Taktgenerator" erzeugt den Takt von 1s fuer die Uhr. 
- 4) Stellfunktion   (Takt: 10 ms) +                Zusaetzliche Takte: 10 ms fuer Stellfunktion 
- 5SPI-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                   12,288 MHz. 
- +                            Timer-Vorteiler     /  8    =>   1,536 MHz 
-  1-Bit-Variable: takt10ms: Taktgenerator => Stellfunktion +                            Hardware-Timer      /256    =>   6 kHz / 166 µs 
- takt100ms: Taktgenerator => Anzeigetreiber +                            Software-Vorteiler  / 60    => 100 Hz  /  10 ms 
- takt1s: Taktgenerator => Zaehler fuer Uhr +                            Hundertstel-Zaehler / 10    =>  10 Hz  / 100 ms 
- +                            Zehntel-Zaehler     / 10    =>   1 Hz  /   1 s 
- 8-Bit-Variable: sekunden Stellfunktion => Zaehler => Anzeige +  
- minuten +    Modul 2:    Das Modul "Zaehler fuer Uhr" wird durch den Takt 1s aufgerufen. 
- stunden +                Sekunden, Minuten und Stunden werden als Binaerzahlen gezaehlt 
 +                Sekunden und Minuten zaehlen 00..59, die Stunden 00..23. 
 +                Ein "Tick" auf dem Lautsprecher wird jede Sekunde ausgegeben. 
 +  
 +    Modul 3:    Das Modul "Anzeigetreiber" startet alle 100 ms. Es gibt die 
 +                Hintergrundinformationen und die aktuelle Uhrzeit aus. 
 +                Darstellung auf der Anzeige (mittig in Zeile 1):  [23:59:59] 
 +      
 +    Modul 4:    Das Modul "Stellfunktion" ist an den 10 ms-Takt gekoppelt. 
 +                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:     takt10ms:   Taktgenerator => Stellfunktion 
 +                        takt100ms:  Taktgenerator => Anzeigetreiber 
 +                        takt1s:     Taktgenerator => Zaehler fuer Uhr 
 +  
 +    8-Bit-Variable:     sekunden    Stellfunktion => Zaehler => Anzeige 
 +                        minuten 
 +                        stunden 
 + 
 =============================================================================*/ =============================================================================*/
- + 
 // Deklarationen ============================================================== // Deklarationen ==============================================================
 + 
 // Festlegung der Quarzfrequenz // Festlegung der Quarzfrequenz
- +#ifndef F_CPU                   // optional definieren 
-#ifndef F_CPU // optional definieren +#define F_CPU 18432000UL        // ATmega 88 mit 18,432 MHz Quarz 
-#define F_CPU 6144000UL // MiniMEXLE mit 6,144 MHz Quarz  +#endif                               
-#endif  + 
- +
 // Include von Header-Dateien // Include von Header-Dateien
- +#include <avr/io.h>               // I/O-Konfiguration (intern weitere Dateien) 
-#include <avr/io.h> // I/O-Konfiguration (intern weitere Dateien) +#include <avr/interrupt.h>        // Definition von Interrupts 
-#include <stdbool.h> // Bibliothek fuer Bit-Variable +#include <util/delay.h>           // Definition von Delays (Wartezeiten) 
-#include <stdlib.h> // Bibliothek fuer Bit-Variable +#include "lcd_lib_de.h"         // Header-Datei fuer LCD-Anzeige 
-#include <avr/interrupt.h> // Definition von Interrupts + 
-#include <util/delay.h> // Definition von Delays (Wartezeiten) +
-#include "lcd_lib_de.h" // Header-Datei fuer LCD-Anzeige +
-#include "pcd8544.h" // Header Datei des Displays +
 // Makros // Makros
- +#define SET_BIT(BYTE, BIT)  ((BYTE) |=  (1 << (BIT))) // Bit Zustand in Byte setzen 
-#define SET_BIT(PORT, BIT) ((PORT) |=  (1 << (BIT))) // Port-Bit 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 PRESCALER_VAL 90      // Faktor Vorteiler = 90 
-#define VORTEILER_WERT 30 // Faktor Vorteiler = 90 +#define CYCLE10MS_MAX 10      // Faktor Hundertstel = 10 
-#define HUNDERTSTEL_WERT  10 // Faktor Hundertstel = 10 +#define CYCLE100MS_MAX      10      // Faktor Zehntel = 10 
-#define ZEHNTEL_WERT 10   // Faktor Zehntel = 10 +  
- +#define SPEAK_PORT          PORTD   // Port-Adresse fuer Lautsprecher 
-#define SPEAK_PORT PORTD // Port-Adresse fuer Lautsprecher +#define SPEAK_BIT                 // Port-Bit fuer Lautsprecher 
-#define SPEAK_BIT 5 // Port-Bit fuer Lautsprecher +  
-#define LED_PORT PORTB // Port-Adresse fuer LED +#define ASC_NULL            0x30        // Das Zeichen '0' in ASCII 
-#define LED_BIT 0 // Port-Bit fuer gelbe LED an PB2 +#define ASC_COLON           0x3A        // Das Zeichen ':' in ASCII 
- +#define INPUT_PIN_MASK 0b00001111 
-#define ASC_NULL 0x30 // Das Zeichen '0' in ASCII + 
-#define ASC_COLON 0x3A // Das Zeichen ':' in ASCII +
 // Variable // Variable
 +unsigned char softwarePrescaler = PRESCALER_VAL; // Zaehlvariable Vorteiler
 +unsigned char cycle10msCount = CYCLE10MS_MAX; // Zaehlvariable Hundertstel
 +unsigned char cycle100msCount   = CYCLE100MS_MAX;   // Zaehlvariable Zehntel
 +unsigned char seconds = 56; // Variable Sekunden
 +unsigned char minutes = 34; // Variable Minuten
 +unsigned char hours = 12; // Variable Stunden
 + 
 +bool timertick; // Bit-Botschaft alle 0,166ms (bei Timer-Interrupt)
 +bool cycle10msActive;               // Bit-Botschaft alle 10ms
 +bool cycle100msActive;              // Bit-Botschaft alle 100ms
 +bool cycle1sActive;                 // Bit-Botschaft alle 1s
 + 
 +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    0b00001111; // Bitspeicher fuer Tasten 
-unsigned char hundertstel  = HUNDERTSTEL_WERT; // Zaehlvariable Hundertstel + 
-unsigned char zehntel = ZEHNTEL_WERT; // Zaehlvariable Zehntel +
- +
-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 ='a'-1; // auszugebendes Zeichen +
- +
-bool timertick; // Bit-Botschaft alle 0,111ms (bei Timer-Interrupt) +
-bool takt10ms; // Bit-Botschaft alle 10ms +
-bool takt100ms; // Bit-Botschaft alle 100ms +
-bool takt1s; // Bit-Botschaft alle 1s +
- +
-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); // Stellfunktion 
-void uhrStellen(void); // Stellfunktion +void showTime(void); // Anzeigefunktion 
-void uhrAnzeigen(void); // Anzeigefunktion +void refreshTime(void); // Uhrfunktion 
-void uhrZaehlen(void); // Uhrfunktion + 
-void initDisplay(void); // Init Anzeige +
-void zehntelSekundenAufPcdAnzeigen(void);//  +
 // Hauptprogramm ============================================================== // Hauptprogramm ==============================================================
- 
 int main() int main()
 { {
- // Initialisierung +    // Initialisierung 
-  +    initDisplay();              // Initialisierung LCD-Anzeige 
- initDisplay(); // Initialisierung LCD-Anzeige +  
- pcd_init(); +    TCCR0A = 0;                 // Timer 0 auf "Normal Mode" schalten 
- +    SET_BIT(TCCR0B, CS01);      // mit Prescaler /8 betreiben 
- TCCR0A = 0; // Timer 0 auf "Normal Mode" schalten +    SET_BIT(TIMSK0, TOIE0);     // Overflow-Interrupt aktivieren 
- SET_BIT(TCCR0B, CS01); // mit Prescaler /8 betreiben +  
- SET_BIT(TIMSK0, TOIE0); // Overflow-Interrupt aktivieren +    SET_BIT(DDRD, SPEAK_BIT);   // Speaker-Bit auf Ausgabe 
- +  
- SET_BIT(DDRD, SPEAK_BIT); // Speaker-Bit auf Ausgabe +    sei();                      // generell Interrupts einschalten 
- PORTC |= 0b00001111; // Taster Anschluesse auf Pullup R +  
- SET_BIT(DDRB, LED_BIT); // LED-Bit auf Ausgabe +    // Hauptprogrammschleife 
- +  
- sei(); // generell Interrupts einschalten +    while(1)                    // unendliche Warteschleife mit Aufruf der 
-  +                                // Funktionen abhaengig von Taktbotschaften 
- // Hauptprogrammschleife +    
- +        if (cycle10msActive          // alle 10ms: 
- while(1) // unendliche Warteschleife mit Aufruf der +        
- // Funktionen abhaengig von Taktbotschaften +            cycle10msActive = 0;       //      Botschaft "10ms" loeschen 
-+            setTime();       //      Tasten abfragen, Uhr stellen 
- if (takt10ms) // alle 10ms: +        
- +        if (cycle100msActive         // alle 100ms:  
- takt10ms = 0; // Botschaft "10ms" loeschen +        
- uhrStellen(); // Tasten abfragen, Stellen, SPI-Komm. +            cycle100msActive = 0;      //      Botschaft "100ms" loeschen 
- +            showTime();      //      Uhrzeit auf Anzeige ausgeben 
- +        
- if (takt100ms) // alle 100ms: +        if (cycle1sActive            // alle Sekunden:  
- +        
- takt100ms = 0; // Botschaft "100ms" loeschen +            cycle1sActive = 0;         //      Botschaft "1s" loeschen 
- if (PcdSendMessage) // wenn SPI-Nachricht gesendet werden soll: +            refreshTime();       //      Uhr weiterzaehlen 
- {  +        
- PcdSendMessage = 0; // Botschaft loeschen +    
- TGL_BIT(LED_PORT, LED_BIT); // LED Zustand wechseln +    return 0;
- zehntelSekundenAufPcdAnzeigen();// Anzeige auf PCD Display +
-+
- uhrAnzeigen(); // Uhrzeit auf Anzeige ausgeben +
- uhrZaehlen(); // Uhr weiterzaehlen +
- +
- +
- if (takt1s) // alle Sekunden: +
- +
- takt1s = 0; // Botschaft "1s" loeschen +
- 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 +
-   hunderstel +
-   zehntel +
- +
- Ausgangsvariable:   takt10ms +
-   takt100ms +
-   takt1s+
 */ */
- 
 { {
- timertick = 1; // Botschaft 0,111ms senden +    timertick = 1;                  // Botschaft 0,166ms senden 
- --vorteiler; // Vorteiler dekrementieren +    --softwarePrescaler                   // Vorteiler dekrementieren 
- if (vorteiler==0) // wenn 0 erreicht: 10ms abgelaufen +    if (softwarePrescaler==0)               // wenn 0 erreicht: 10ms abgelaufen 
-+    
- vorteiler VORTEILER_WERT; //    Vorteiler auf Startwert +        softwarePrescaler PRESCALER_VAL; //    Vorteiler auf Startwert 
- takt10ms = 1; //    Botschaft 10ms senden +        cycle10msActive = 1;               //    Botschaft 10ms senden 
- --hundertstel; //    Hunderstelzaehler dekrementieren +        --cycle10msCount             //    Hunderstelzaehler dekrementieren 
- +  
- if (hundertstel==0) // wenn 0 erreicht: 100ms abgelaufen +        if (cycle10msCount==0)         // wenn 0 erreicht: 100ms abgelaufen 
- +        
- hundertstel HUNDERTSTEL_WERT; // Teiler auf Startwert +            cycle10msCount CYCLE10MS_MAX; // Teiler auf Startwert 
- takt100ms = 1; //    Botschaft 100ms senden +            cycle100msActive = 1;          //    Botschaft 100ms senden 
- --zehntel; //    Zehntelzaehler dekrementieren +            --cycle100msCount             //    Zehntelzaehler dekrementieren 
- +  
- if (zehntel==0) // wenn 0 erreicht: 1s abgelaufen +            if (cycle100msCount==0)         // wenn 0 erreicht: 1s abgelaufen 
- +            
- zehntel ZEHNTEL_WERT; //    Teiler auf Startwert +                cycle100msCount CYCLE100MS_MAX; //    Teiler auf Startwert 
- takt1s = 1; //    Botschaft 1s senden +                cycle1sActive = 1;             //    Botschaft 1s senden 
- +            
- +        
- }+    }
 } }
 +  
 // 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:   sw2Alt 
-  Veraenderte Variable: stunden +                          sw3Alt
-   minuten +
-   sekunden +
- +
-  Speicher fuer Bits:   sw1Alt +
-   sw2Alt +
-   sw3Alt +
-   sw4Alt+
 */ */
 +{
 + DDRC = DDRC &~INPUT_PIN_MASK; // Port B auf Eingabe schalten
 + PORTC |=   INPUT_PIN_MASK; // Pullup-Rs eingeschaltet
 + _delay_us(1); // Wartezeit Umstellung Hardware-Signal
 + buttonState    = (PINC & INPUT_PIN_MASK) ; // Hole den Schalterstatus von B1..B4, 0b1 ist hier offener SChalter
 + DDRC |= INPUT_PIN_MASK; // Port B auf Ausgabe schalten
  
-{  +    // Einlesen der Tastensignale    
- sw1_neu = (PINC & (1 << PC0)); // Tasten von Port einlesen +    button2_new = (buttonState & (1 << PC1)); 
- sw2_neu = (PINC & (1 << PC1)); +    button3_new = (buttonState & (1 << PC2)); 
- sw3_neu = (PINC & (1 << PC2)); +      
- sw4_neu = (PINC & (1 << PC3)); +  
- +    if ((button2_new==0)&(button2_old==1))  // wenn Taste 2 eben gedrueckt wurde: 
- if ((sw1_neu==0)) // wenn Taste 1 gedrueckt ist: +    
-+        hours++;                  //    Stunden hochzaehlen, Ueberlauf bei 23 
- PcdSendMessage = 1; //    Senden der SPI-Nachricht aktivieren +        if (hours==24) 
-+            hours = 00; 
-  +    
- 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, Ueberlauf bei 23 +        minutes++;                  //    Minuten hochzaehlen, Ueberlauf bei 59 
- if (stunden==24) +        if (minutes==60) 
- stunden = 00; +            minutes = 00; 
-+    
- if ((sw3_neu==0)&(sw3_alt==1)) // wenn Taste 3 eben gedrueckt wurde: +    if (button3_new==0)                 // solange Taste 3 gedrueckt:  
-+        seconds = 00;              //    Sekunden auf 00 setzen 
- minuten++; //    Minuten hochzaehlen, Ueberlauf bei 59 +  
- if (minuten==60) +    button2_old button2_new             // aktuelle Tastenwerte speichern 
- minuten = 00; +    button3_old button3_new             //    in Variable fuer alte Werte
-+
- if (sw3_neu==0) // solange Taste 3 gedrueckt: +
- sekunden = 00; //    Sekunden auf 00 setzen +
- +
- if ((sw4_neu==0)&(sw4_alt==1)) // wenn Taste 3 eben gedrueckt wurde: +
-+
- pcd_putLine(rand()%83,rand()%47,rand()%83,rand()%47); +
- pcd_updateDisplay(); +
-+
-  +
- sw1_alt = sw1_neu; // aktuelle Tastenwerte speichern +
- sw2_alt sw2_neu; //    in Variable fuer alte Werte +
- 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:  Modulo-Ermittlung (%10), d.h. Rest bei der Teilung durch 10
- Zehner: einfache Integer-Teilung (/10) +
- Einer:  Modulo-Ermittlung (%10), d.h. Rest bei der Teilung durch 10+
 */ */
- 
 { {
- lcd_gotoxy(0,4); // Cursor auf Start der Zeitausgabe setzen +    lcd_gotoxy(0,4);                    // Cursor auf Start der Zeitausgabe setzen 
- +      
- 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); // Doppelpunkt ausgeben +    lcd_putc(ASC_COLON);                // Doppelpunkt ausgeben 
- +      
- 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); // Doppelpunkt ausgeben +    lcd_putc(ASC_COLON);                // Doppelpunkt ausgeben 
- +      
- lcd_putc(ASC_NULL + sekunden/10); // Sekunden als ASCII ausgeben +    lcd_putc(ASC_NULL + seconds/10);   // Sekunden als ASCII ausgeben 
- 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, pos); // Setze Position am Display +
- pcd_putc(zehntelSekunden+0x30); // Schreibe Zehntelsekunden  +
- pcd_updateDisplay(); // Aktualisiere das Display des PCD8544 +
- 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(); // loesche Anzeige +
- }; +
-+
-+
 // Initialisierung Display-Anzeige ============================================ // Initialisierung Display-Anzeige ============================================
- +void initDisplay()              // Start der Funktion
-void initDisplay() // Start der Funktion+
 { {
- lcd_init(); // Initialisierungsroutine aus der lcd_lib +    lcd_init();                 // Initialisierungsroutine aus der lcd_lib 
-  +                      
- lcd_gotoxy(0,0); // Cursor auf 1. Zeile, 1. Zeichen +    lcd_gotoxy(0,0);                // Cursor auf 1. Zeile, 1. Zeichen 
- lcd_putstr("- Experiment 7a-"); // Ausgabe Festtext: 16 Zeichen +    lcd_putstr("- Experiment -"); // Ausgabe Festtext: 16 Zeichen 
- +  
- lcd_gotoxy(1,0); // Cursor auf 2. Zeile, 1. Zeichen +    lcd_gotoxy(1,0);                // Cursor auf 2. Zeile, 1. Zeichen 
- lcd_putstr("Uhr + SPI-Master"); // Ausgabe Festtext: 16 Zeichen +    lcd_putstr(" Digital Clock  "); // Ausgabe Festtext: 16 Zeichen 
- +  
- _delay_ms(1000); // Wartezeit nach Initialisierung +    _delay_ms(2000);            // Wartezeit nach Initialisierung 
- +  
- lcd_gotoxy(0,0);     // Cursor auf 1. Zeile, 1. Zeichen +    lcd_gotoxy(0,0);                // Cursor auf 1. Zeile, 1. Zeichen 
- lcd_putstr("=== 00:00:00 ==="); // Ausgabe Festtext: 16 Zeichen +    lcd_putstr("=== 00:00:00 ==="); // Ausgabe Festtext: 16 Zeichen 
- +  
- lcd_gotoxy(1,0);         // Cursor auf 2. Zeile, 1. Zeichen +    lcd_gotoxy(1,0);                // Cursor auf 2. Zeile, 1. Zeichen 
- lcd_putstr("10tl Std Min Lin."); // Ausgabe Festtext: 16 Zeichen +    lcd_putstr("   Std Min      "); // Ausgabe Festtext: 16 Zeichen 
- +                              // Ende der Funktion 
-} // Ende der Funktion + 
- +
 // Zaehlfunktion Uhr ========================================================== // Zaehlfunktion Uhr ==========================================================
- +void refreshTime (void)              // wird jede Sekunde gestartet 
-void uhrZaehlen (void) // wird jede Sekunde gestartet +/*  Die Uhr wird im Sekundentakt gezaehlt. Bei jedem Aufruf wird auch ein  
- +    "Tick" auf dem Lautsprecher ausgegeben. Ueberlaeufe der Sekunden zaehlen 
-/* Die Uhr wird im Sekundentakt gezaehlt. Bei jedem Aufruf wird auch ein  +    die Minuten, die Ueberlaeufe der Minuten die Stunden hoch. 
- "Tick" auf dem Lautsprecher ausgegeben. Ueberlaeufe der Sekunden zaehlen +  
- die Minuten, die Ueberlaeufe der Minuten die Stunden hoch. +    Veraenderte Variable:   sekunden 
- +                            minuten 
- Veraenderte Variable: sekunden +                            stunden
- minuten +
- stunden+
 */ */
- 
 { {
- TGL_BIT (SPEAK_PORT, SPEAK_BIT); // "Tick" auf Lautsprecher ausgeben +    TGL_BIT (SPEAK_PORT, SPEAK_BIT); // "Tick" auf Lautsprecher ausgeben 
- // durch Invertierung des Portbits +                                    // durch Invertierung des Portbits 
- zehntelSekunden++; +  
- if (zehntelSekunden==10) // bei Ueberlauf: +    seconds++;                     // Sekunden hochzaehlen 
-+    if (seconds==60)               // bei Überlauf
- zehntelSekunden=0; +    
- sekunden++; // Sekunden hochzaehlen +        seconds = 0;               //  Sekunden auf 00 setzen 
- if (sekunden==60) // bei Ueberlauf+        minutes++;                  //  Minuten hochzaehlen 
- +        if (minutes==60)            //  bei Ueberlauf: 
- sekunden = 0; //   Sekunden auf 00 setzen +        
- minuten++; //   Minuten hochzaehlen +            minutes = 0;            //  Minuten auf 00 setzen 
- if (minuten==60) // bei Ueberlauf: +            hours++;              //  Stunden hochzaehlen 
- +            if (hours==24)        //  bei Ueberlauf: 
- minuten = 0; //    Minuten auf 00 setzen +                hours = 0;        //  Stunden auf 00 setzen 
- stunden++; //    Stunden hochzaehlen +        
- if (stunden==24) //    bei Ueberlauf: +    }
- stunden = 0; //  Stunden auf 00 setzen +
- +
- +
- }+
 } }
- 
 </sxh> </sxh>
 </WRAP><WRAP column 55%> </WRAP><WRAP column 55%>
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  \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\
 ''Deklarationen ==================================='' ''Deklarationen ===================================''
 \\ \\ \\ \\
-  - Hier wird wieder geprüft ob die Frequenz des Quarz bereits eingestellt wurde und - falls nicht - dessen Frequenz eingestellt. Die Frequenz ist diesmal merklich niedriger, da die Ansteuerung des Display keine höheren Raten erlaubt\\ \\ \\  +  - Hier wird wieder geprüft ob die Frequenz des Quarz bereits eingestellt wurde und - falls nicht - dessen Frequenz eingestellt. \\ \\  
-  - Zusätzlich zu den bisherigen Header-Dateien sind nun folgende hinzugekommen: \\ \\ +  - Die Header-Dateien entsprechen denen der letzten Programme. \\ \\ \\ \\ \\  
-    - ''<stdlib.h>'' - Standard-Bibliothek für Typenumwandlung und mehr. Hiervon wird die Erstellung von Zufallswerten genutzt \\ \\ +  - Auch die Makros entsprechen denen der letzten Programme. \\ \\ \\ \\  
-    - ''"pcd8544.h"'' - Bibliothek für das einbinden des neuen Displays \\ \\ \\  +  - Die Konstanten entsprechen denen der letzten Programme. \\ Zusätzlich wird der Ausdruck ''ASC_NULL'' durch den Hexadezimalwert einer '0' in ASCII, also 0x30 und ''ASC_COLON'' durch den ASCI-Wert eines Doppelpunkts, also 0x3A, ersetzt \\ \\ \\ \\ \\  
-  - Die Makros entsprechen denen der letzten Programme. \\ \\ \\ \\  +  - Bei den Variablen entsprechen einige denen der letzten Programme. 
-  - Die Konstanten entsprechen im Wesentlichen denen der letzten Programme. Der Vorteiler Wert entspricht aber hier der Hälfte des bisherigen Wertes, da die Taktfrequenz ebenso halb so groß ist.  \\ \\ \\ \\ \\ \\   +  - Für die Uhr werden Stunden, Minuten, Sekunden und Zehntelsekunden mit Anfangswerten deklariert. \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ 
-  - Für die Zeichen ''0'und '':'' werden für die ASCII-Codes Makros definiert. Dadurch wird das Lesen des am Display ausgegebenen Textes im Code einfacher. \\ \\ +  - 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. \\ \\ \\ \\ \\ +
  
 ''Hauptprogramm ========================='' ''Hauptprogramm =========================''
-\\ \\ 
-  - Zunächst werden zwei Initialisierungsroutinen aufgerufen (siehe weiter unten) 
-  - Dann werden wieder "__T__imer/__C__ounter __C__ontrol __R__egister" und "__T__imer __I__nterrupt __M__a__SK__" konfiguriert. 
-  - Die "__D__ata __D__irection __R__egister" wurden auch bereits beschrieben. Diese werden hier so konfiguriert, dass zwei Anschlüsse für Lautsprecher und LED als Ausgang definiert sind. \\ \\ 
-  - 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 ''sei()'' wird die Bearbeitung von Interrupts aktiv. \\ \\ \\ 
-  - In der Endlosschleife sind verschiedene Zeitzyklen vorgesehen (wie beim [[4._up_down_counter|Up/Down Counter]]). \\ \\ 
-    - im $10ms$ Raster (auch $10ms$ Zyklus genannt) wird die Unterfunktion ''uhrStellen'' aufgerufen. \\ \\ \\ \\ 
-    - im $100ms$ Raster werden die Unterfunktionen ''uhrAnzeigen'' und ''UhrZaehlen'' aufgerufen. Davor wird, falls das Flag ''PcdSendMessage'' gesetzt ist, wird dieses zurückgesetzt, die LED blinkt und das Unterprogramm ''zehntelSekundenAufPcdAnzeigen'' wird aufgerufen. \\ \\ \\ \\ \\ \\ 
-    - im $1s$ Raster blinkt die LED und das Unterprogramm ''pcd_init'' zum initialisieren des PCD Displays wird aufgerufen. \\ \\ \\ \\ \\ \\ \\  
  
 +  - Das Hauptprogramm ähnelt sehr stark dem [[4_up_down_counter|Up/Down Counter]]. Entsprechend werden die Zeilen 143-157 hier nicht weiter erklärt. \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ 
 +  - In der Endlosschleife sind auf der ersten Ebene wieder nur If-Abfragen zu den Flags ''takt10ms'' und ''takt100ms'' zu finden. \\ \\
 +    - Alle $10~\rm ms$ (bzw. wenn das entsprechende Flag gesetzt wird) wird das Flag zurückgesetzt und das Unterprogramm ''uhrStellen()'' aufgerufen \\ \\ \\ 
 +    - Alle $100~\rm ms$ (bzw. wenn das entsprechende Flag gesetzt wird) wird das Flag zurückgesetzt und das Unterprogramm ''uhrAnzeigen()'' aufgerufen \\ \\ \\ 
 +    - Alle $1~\rm s$ (bzw. wenn das entsprechende Flag gesetzt wird) wird das Flag zurückgesetzt und das Unterprogramm ''uhrZaehlen()'' aufgerufen \\ \\ \\ \\ 
 ''Interrupt Routine ========================='' ''Interrupt Routine =========================''
-  - Mit dem Befehl ''ISR()'' wird wieder die Interrupt Service Routine für den  __OV__er__F__low Interrupt des __TIMER0__ angelegt. \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\  +  - Auch die Interrupt Routine ist dem Programm [[4_up_down_counter|Up/Down Counter]] entlehnt und wird hier nicht weiter erklärt. \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\
-  - Die Ermittlung von ''Timertick'', ''vorteiler'', ''takt10ms'', ''hundertstel'' und ''takt100ms'' ist hier wieder gleich dem im [[4._up_down_counter|Up/Down Counter]].  \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\  +
-  - Eine Erweiterung auf ''zehntel'' und ''takt1s'' wurde hier mit eingefügt. \\ \\ \\ \\ \\  +
-'' Funktion Tasten einlesen =============='' +
-\\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\  +
-  - In dieser Funktion werden zunächst die Stellungen aller Taster eingelesen (vgl. ''counterCounting(void)'' bei [[4._up_down_counter|Up/down Counter]]). \\ \\ +
-  - Die Flankenerkennung in den if-Bedingungen wurde auch bereits beim [[4._up_down_counter|Up/down Counter]] erklärt.  +
-  - Wenn die Taste ''S1'' gedrückt ist, so wird das Flag ''PcdSendMessage'' gesetzt, welches in ''main'' zum Aufrufen des Unterprogramm ''zehntelSekundenAufPcdAnzeigen'' in jedem $100ms$ Raster führt.  \\ \\ \\  +
-  - Die Tasten ''S2'' und ''S3'' führen zum einmaligem Hochzählen der Stunden bzw. Minuten. Wenn der jeweilige Wert über das Maximum hinausläuft, so beginnt dieser wieder beim Minimum.  \\ \\ \\ \\ \\ \\ \\ \\ +
-  -  Die Taste ''S4'' zeichnet eine Linie mittels ''pcd_putLine'' und aktualisiert das Displays des PCD8544 \\ \\ \\ \\ \\ \\ \\ \\+
  
-''Anzeigefunktion Uhr ========================='' +'' Stellfunktion =============='' 
- +\\ \\ 
-\\ \\ \\ \\ \\ \\ +  - In dieser Funktion werden zunächst die Stellungen aller Taster eingelesen (vgl. ''counterCounting(void)'' bei [[4_up_down_counter|Up/down Counter]]). \\ \\ \\ 
- +  - Neu hier ist, dass die Bedienung der Schalter die Variablen für Stunden, Minuten um eins hochsetzen, bzwbei Überlauf wider zurück auf 0 setzenZusätzlich wird bei eine Änderung des Minuten-Werts der Sekunden-Wert auf 0 gesetzt \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\
-  - Auf dem LCD wird zunächst die Position ''(0,4)'' als Ausgabeort vorgegeben +
-  - Vom Wert ''stunden'' wird zunächst die Zehnerstelle über Division ermittelt und ausgegebenDie Einerstelle ergibt sich über Modulo (''%''). +
-  - Danach wird ein Doppelpunkt ausgegeben +
-  Die Anzeige von Minuten und Sekunden erfolgt analog. +
- +
-\\ \\ \\ \\  +
- +
-''Anzeigefunktion fuer PCD Display ========================='' +
- \\ \\ \\ \\ +
-  - Auch für die Anzeige auf dem PCD 8544 wird zunächst die Position auf dem Display mittels ''pcd_gotoxy'' definiert.  +
-  - Der Wert der Zehntelsekunde wird über ''pcd_putc'' auf dem Display ausgegeben. +
-  - 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. +
- +
-\\ \\ +
  
-''Initialisierung Display-Anzeige =====''+'' Anzeigefunktion Uhr ========================='' 
 +  - 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 
 +\\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\
  
-  Hier werden der Anfangs-Screen ausgegeben, etwas gewartet und anschließend die Anzeige für die Uhr angelegt.+''Initialisierung Display-Anzeige ========================='' 
 +  Die Funktion ''initDisplay()'' wird zu Beginn des Programms aufgerufen und führt zunächst die Initialisierung des Displays aus. 
 +  - Danach wird der erste Text auf den Bildschirm geschrieben und damit der Programmname dargestellt. 
 +  - Nach zwei Sekunden wird der Auswahlbildschirm angezeigt.
  
-\\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ +\\ \\ \\ \\ \\ \\ \\ \\ \\
-''Zaehlfunktion Uhr ================='' +
- \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ +
-  - 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. ''zehntelsekunden'') hochgezählt. Sobald das Maximum erreicht wurde, so wird dieser Wert zurückgesetzt und der nächstgrößere Wert hochgezählt. Dies geschieht in der Art, dass auch mehrere Überläufe gleichzeitig stattfinden können: z.B. von 23:59:59:9 auf 0: 0: 0:0+
  
 +''Zaehlfunktion Uhr ===============================''
 +  - Die Zähl-Funktion ''uhrZaehlen()'' ist ganz ähnlich aufgebaut zur Interrupt-Service-Routine
 +  - 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
 </WRAP></WRAP> </WRAP></WRAP>
  
Zeile 531: Zeile 419:
  
 <-- <--
 +
 \\ \\
  
 Bitte arbeiten Sie folgende Aufgaben durch: Bitte arbeiten Sie folgende Aufgaben durch:
  
---> Aufgaben+--> Aufgabe# 
-  - Analyse der Zufallsfunktion ''rand()'' + 
-    - Wenn Sie die Taste ''S4'' drücken, erscheint eine Linie mit zufälligen Anfangs- und Endpunkten auf dem Display PCD8544. +  - Bauen Sie einen "ewigen Kalender" ein  
-    - Prüfen Sie nachob die Anfangs- und Endpunkte tatsächlich zufällig zu sein scheinen. \\ Wie sieht dies nach dem Neustart des Systems aus?  +    - Es sollen nicht nur StundeMinute, Sekunde dargestellt werden und veränderbar sein, sondern auch Tag, Monat und Jahr im Format dd:mm:yy 
-  - Analyse der seriellen Kommunikation +    - Achten Sie auf die Schaltjahrermittlung 
-    - Wenn Daten vom Mikrocontroller zum PCD8544 übertragen werdenso ist auf dem Oszilloskop und auf dem Plotter die Situation des Signals auf der "Data IN" Leitung zum Display zu sehen. Im folgenden soll dieses genauer betrachtet werden. +  Erweitern Sie den Kalender auf vierstellige Jahresangabe
-    - Dazu starten Sie zunächst die Simulation und zeichnen Sie durch mehrmaliges Drücken von ''S4'' viele Linien auf das Display und halten Sie ''S1'' geschlossen. +  Überlegen Sie sichwie man Ihre Programme testen kann. 
-    - Auf dem Oszilloskop ist ein detailliertes Signal auf dem PCD8544-Eingang ''DIN'' zu sehen. Das selbe Signal im Plotter (rot, 2. von oben) zeigt diese Details nicht. Weder das Oszilloskop, noch der Plotter ermöglicht dabei die Auswertung.  +  BONUS: Wie kann der Wochentag bestimmt werden? 
-    Ändern Sie die Taktfrequenz von ''6,144'' Mhz {{microcontrollertechnik:mexleuhr_spi.simu}}auf ''0,1'' Mhz. Der Controller läuft nun langsamer+
-    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 ''S4'' (Linie zeichnen) eine Kommunikation zum PCD8544 erzeugt werden. Das rote Signal im Plotter gleicht aber immer noch nicht dem des Oszilloskops+
-    Öffnen Sie zunächst wieder den Schalter ''S4''. Um das Signal besser aufzulösen kann die Simulationsgeschwindigkeit herabgesetzt werden. Dazu kann in die Freifläche der Simulation (beiger Hintergrund) geklickt und links der Reiter ''Properties'' ausgewählt werden. In der obersten Zeile ist nun die Eigenschaft ''Speed'' mit dem Wert ''1000000'' zu sehen. Ändern Sie diesen auf ''100000''. +
-    - Schließen Sie nun wieder den Schalter ''S4''. nach kurzer Zeit ist ein Signal auf der Schnittstelle zu sehen. Sobald dieses sichtbar ist, ändern Sie die Geschwindigkeit auf ''200''+
-    - Nun sollten die Signale gut aufgelöst sichtbar sein:{{microcontrollertechnik:simulide_beispiel_anzeige_plotter.jpg}} +
-      - Das 1. Signal ''CLK'' (gelb) taktet 8 mal und zeigt dann eine kurze Pause +
-      - Das 2. Signal ''DIN'' (rot) zeigt häufig nur LOW, bis auf einen kurzen HIGH Pegel am Ende der 8 Takte von ''CLK''.+
 <-- <--
 +