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:10_spi_schnittstelle [2021/10/25 08:55]
tfischer
microcontrollertechnik:10_spi_schnittstelle [2024/01/22 13:47] (aktuell)
mexleadmin
Zeile 1: Zeile 1:
-====== 11. SPI-Schnittstelle  ======+====== 10 SPI Schnittstelle  ======
 <WRAP group>  <WRAP group> 
 <WRAP half column> <WRAP half column>
Zeile 27: Zeile 27:
 <imgcaption BildNr09 | Zusammenspiel der SPI-Register> <imgcaption BildNr09 | Zusammenspiel der SPI-Register>
 </imgcaption> </imgcaption>
-{{drawio>SPIRegister}}+{{drawio>SPIRegister.svg}}
 </WRAP> </WRAP>
  
Zeile 59: Zeile 59:
  
 <-- <--
---> III. Eingabe in Atmel Studio #+--> III. Eingabe in Microchip Studio #
 <WRAP group><WRAP column 40%> <WRAP group><WRAP column 40%>
 <sxh c; first-line: 1> <sxh c; first-line: 1>
 /* ============================================================================ /* ============================================================================
- +  
-Experiment 7:  MEXLE-Uhr mit hh:mm:ss-Anzeige und SPI-Master +Experiment 7:   MEXLE-Uhr mit hh:mm:ss-Anzeige und SPI-Master 
-============= ========================================================= +=============   ========================================================= 
- +  
-Dateiname: MEXLEuhr_Master.c +Dateiname:      MEXLEuhr_Master.c 
- +  
-Autoren: Prof. T. Fischer (Hochschule Heilbronn) +Autoren:        Prof. T. Fischer (Hochschule Heilbronn) 
- Prof. G. Gruhler (Hochschule Heilbronn) +                Prof. G. Gruhler (Hochschule Heilbronn) 
- D. Chilachava  (Georgische Technische Universitaet) +                D. Chilachava    (Georgische Technische Universitaet) 
- +  
-Version: 0.2 vom 23.05.2020 +Version:        0.2 vom 23.05.2020 
- +  
-Hardware: Simulide  +Hardware:       Simulide  
- +  
-Software: Atmel Studio Ver. 7.xx   +Software:       Microchip Studio Ver. 7.xx               
- +  
-Funktion: Digitaluhr mit Anzeige von Stunden, Minuten und Sekunden. Eine +Funktion:       Digitaluhr mit Anzeige von Stunden, Minuten und Sekunden. Eine 
- einfache Stellfunktion ist mit den Tasten S2 und S3 realisiert. +                einfache Stellfunktion ist mit den Tasten S2 und S3 realisiert. 
- Mit S1 und S4 kann die SPI-Kommunikation mit einem Slave-Display +                Mit S1 und S4 kann die SPI-Kommunikation mit einem Slave-Display 
- gestartet werden +                gestartet werden 
- +  
-Displayanzeige: Start (fuer 2s): Betrieb: +Displayanzeige: Start (fuer 2s):        Betrieb: 
- +----------------+ +----------------+ +                +----------------+      +----------------+ 
- | MEXLEuhr - SPI | |=== 00:00:00 ===| +                | MEXLEuhr - SPI |      |=== 00:00:00 ===| 
- |     Master     | |10tl Std Min Lin| +                |     Master          |10tl Std Min Lin| 
- +----------------+ +----------------+ +                +----------------+      +----------------+ 
- +  
-Tastenfunktion: S1: uebertraegt die Zehntelsekunde vom Master zum Slave +Tastenfunktion: S1: uebertraegt die Zehntelsekunde vom Master zum Slave 
- S2: Std (zaehlt Stunden bei Flanke aufwaerts. Ueberlauf bei 24) +                S2: Std (zaehlt Stunden bei Flanke aufwaerts. Ueberlauf bei 24) 
- S3: Min (zaehlt Minuten bei Flanke aufwaerts. Ueberlauf 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) 
- S4: uebertraegt die Info zum Darstellen einer Linie zum Master +                S4: uebertraegt die Info zum Darstellen einer Linie zum Master 
- +  
-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.2) 
- +  
-Libraries: pcd8544.c (Library fuer die Ansteuerung des Displays) +Libraries:      pcd8544.c       (Library        fuer die Ansteuerung des Displays) 
- pcd8544.h (Header-Datei fuer die Ansteuerung des Displays) +                pcd8544.h       (Header-Datei   fuer die Ansteuerung des Displays) 
- +  
-Module: 1) Taktgenerator +Module:         1) Taktgenerator 
- 2) Zaehler fuer Uhr (Takt: 1 s) +                2) Zaehler fuer Uhr (Takt: 1 s) 
- 3) Anzeigetreiber  (Takt: 100 ms) +                3) Anzeigetreiber   (Takt: 100 ms) 
- 4) Stellfunktion   (Takt: 10 ms) +                4) Stellfunktion    (Takt: 10 ms) 
- 5) SPI-Funktionen +                5) SPI-Funktionen 
-  +                  
- +  
- Die Kopplung der Module wird ueber global definierte Variable realisiert: +    Die Kopplung der Module wird ueber global definierte Variable realisiert: 
- +  
-  1-Bit-Variable: takt10ms: Taktgenerator => Stellfunktion +    1-Bit-Variable:     takt10ms:   Taktgenerator => Stellfunktion 
- takt100ms: Taktgenerator => Anzeigetreiber +                        takt100ms:  Taktgenerator => Anzeigetreiber 
- takt1s: Taktgenerator => Zaehler fuer Uhr +                        takt1s:     Taktgenerator => Zaehler fuer Uhr 
- +  
- 8-Bit-Variable: sekunden Stellfunktion => Zaehler => Anzeige +    8-Bit-Variable:     sekunden    Stellfunktion => Zaehler => Anzeige 
- minuten +                        minuten 
- stunden +                        stunden 
 + 
 =============================================================================*/ =============================================================================*/
- +  
 + 
 // Deklarationen ============================================================== // Deklarationen ==============================================================
 + 
 // Festlegung der Quarzfrequenz // Festlegung der Quarzfrequenz
 + 
 #ifndef F_CPU // optional definieren #ifndef F_CPU // optional definieren
-#define F_CPU 6144000UL // MiniMEXLE mit 6,144 MHz Quarz  +#define F_CPU 12288000UL                // MiniMEXLE mit 12,288 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 <stdbool.h>  // Bibliothek fuer Bit-Variable +#include <stdbool.h> // Bibliothek fuer Bit-Variable 
-#include <stdlib.h> // Bibliothek fuer Bit-Variable +#include <stdlib.h> // Bibliothek fuer Bit-Variable 
-#include <avr/interrupt.h> // Definition von Interrupts +#include <avr/interrupt.h>              // Definition von Interrupts 
-#include <util/delay.h> // Definition von Delays (Wartezeiten) +#include <util/delay.h>                 // Definition von Delays (Wartezeiten) 
-#include "lcd_lib_de.h" // Header-Datei fuer LCD-Anzeige +#include "lcd_lib_de.h"                 // Header-Datei fuer LCD-Anzeige 
-#include "pcd8544.h" // Header Datei des Displays +#include "pcd8544.h"                    // Header Datei des Displays 
 + 
 // 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, BIT)  ((BYTE) &   (1 << (BIT))) // Bit Zustand in Byte einlesen 
 + 
 // Konstanten // Konstanten
 + 
 +#define PRESCALER_VAL 30          // Faktor Vorteiler = 90
 +#define CYCLE10MS_MAX 10 // Faktor Hundertstel = 10
 +#define CYCLE100MS_MAX      10          // Faktor Zehntel = 10
 + 
 +#define SPEAK_PORT          PORTD       // Port-Adresse fuer Lautsprecher
 +#define SPEAK_BIT                     // Port-Bit fuer Lautsprecher
 +#define LED_PORT            PORTB       // Port-Adresse fuer LED
 +#define LED_BIT                       // Port-Bit fuer gelbe LED an PB2
 + 
 +#define ASC_NULL            0x30        // Das Zeichen '0' in ASCII
 +#define ASC_COLON           0x3A        // Das Zeichen ':' in ASCII
 + 
 +#define NO 0 // Deactive Wert
 +#define YES 1 // Active Wert
 +#define PRESSED 0 // Button gedrückt
 +#define UNPRESSED 1 // Button nicht gedrückt
  
-#define VORTEILER_WERT  30 // Faktor Vorteiler = 90 +#define HOURS_MAX 24 // max Wert der Stunden 
-#define HUNDERTSTEL_WERT 10 // Faktor Hundertstel = 10 +#define MINUTES_MAX 60 // max Wert der Minuten 
-#define ZEHNTEL_WERT 10 // Faktor Zehntel = 10+#define SECONDS_MAX 60 // max Wert der Sekunden 
 +#define TENTH_MAX 10 // max Wert der Zentelsekunden
  
-#define SPEAK_PORT PORTD // Port-Adresse fuer Lautsprecher +#define POS_MAX 13 // max Wert der (x)-Position 
-#define SPEAK_BIT 5 // Port-Bit fuer Lautsprecher +#define LINE_MAX 5 // max Wert der Zeile
-#define LED_PORT PORTB // Port-Adresse fuer LED +
-#define LED_BIT 0 // Port-Bit fuer gelbe LED an PB2 +
- +
-#define ASC_NULL 0x30 // Das Zeichen '0' in ASCII +
-#define ASC_COLON 0x3A // Das Zeichen ':' in ASCII+
  
 // Variable // Variable
- +  
-unsigned char vorteiler VORTEILER_WERT; // Zaehlvariable Vorteiler +unsigned char softwarePrescaler PRESCALER_VAL   // Zaehlvariable fuer den Software-Vorteiler 
-unsigned char hundertstel HUNDERTSTEL_WERT; // Zaehlvariable Hundertstel +unsigned char cycle10msCount CYCLE10MS_MAX; // Zaehlvariable Hundertstel 
-unsigned char zehntel ZEHNTEL_WERT; // Zaehlvariable Zehntel +unsigned char cycle100msCount   CYCLE100MS_MAX  // Zaehlvariable Zehntel 
- +  
-unsigned char zehntelSekunden = 0; // Variable Sekunden +unsigned char tenthOfASecond = 0; // Variable Sekunden 
-unsigned char sekunden  = 56; // Variable Sekunden +unsigned char seconds = 56; // Variable Sekunden 
-unsigned char minuten  = 34; // Variable Minuten +unsigned char minutes = 34; // Variable Minuten 
-unsigned char stunden = 12; // Variable Stunden +unsigned char hours = 12; // Variable Stunden 
- +  
-unsigned char zeile = 0; // x-Koordinate +unsigned char line = 0; // x-Koordinate 
-unsigned char pos = 0; // y-Koordinate +unsigned char pos = 0;    // y-Koordinate 
-unsigned char zeichen ='a'-1; // auszugebendes Zeichen +unsigned char character ='a'-1; // auszugebendes Zeichen 
- +  
-bool timertick; // Bit-Botschaft alle 0,111ms (bei Timer-Interrupt) +bool timertick;                         // Bit-Botschaft alle 0,111ms (bei Timer-Interrupt) 
-bool takt10ms; // Bit-Botschaft alle 10ms +bool cycle10msActive                  // Bit-Botschaft alle 10ms 
-bool takt100ms; // Bit-Botschaft alle 100ms +bool cycle100msActive                 // Bit-Botschaft alle 100ms 
-bool takt1s; // Bit-Botschaft alle 1s +bool cycle1sActive                    // Bit-Botschaft alle 1s 
- +  
-bool sw1_neu = 1; // Bitspeicher fuer Taste 1 +bool button1_new = 1;                   // Bitspeicher fuer Taste 1 
-bool sw2_neu = 1; // Bitspeicher fuer Taste 2 +bool button2_new = 1;                   // Bitspeicher fuer Taste 2 
-bool sw3_neu = 1; // Bitspeicher fuer Taste 3 +bool button3_new = 1;                   // Bitspeicher fuer Taste 3 
-bool sw4_neu = 1; // Bitspeicher fuer Taste 4 +bool button4_new = 1;                   // Bitspeicher fuer Taste 4 
-bool sw1_alt = 1; // alter Wert von Taste 1 +bool button1_old = 1;                   // alter Wert von Taste 1 
-bool sw2_alt = 1; // alter Wert von Taste 2 +bool button2_old = 1;                   // alter Wert von Taste 2 
-bool sw3_alt = 1; // alter Wert von Taste 3 +bool button3_old = 1;                   // alter Wert von Taste 3 
-bool sw4_alt = 1; // alter Wert von Taste 4 +bool button4_old = 1;                   // alter Wert von Taste 4 
- +  
-bool PcdSendMessage = 0; // Flag fuer sendebereite SPI-Nachricht +bool PcdSendMessage = 0;                // Flag fuer sendebereite SPI-Nachricht 
 + 
 // Funktionsprototypen // Funktionsprototypen
- +  
-void timerInt0(void); // Init Zeitbasis mit Timer 0 +void timerInt0(void);                   // Init Zeitbasis mit Timer 0 
-void uhrStellen(void); // Stellfunktion +void setTime(void); // Stellfunktion 
-void uhrAnzeigen(void); // Anzeigefunktion +void showTime(void); // Anzeigefunktion 
-void uhrZaehlen(void); // Uhrfunktion +void refreshTime(void);                 // Uhrfunktion 
-void initDisplay(void); // Init Anzeige +void initDisplay(void);                 // Init Anzeige 
-void zehntelSekundenAufPcdAnzeigen(void);//  +void showTenthOfASecond(void); // Anzeige der Zehntelsenkunde auf separatem Display 
 + 
 // Hauptprogramm ============================================================== // Hauptprogramm ==============================================================
 + 
 int main() int main()
 { {
- // Initialisierung +    // Initialisierung 
-  +      
- initDisplay(); // Initialisierung LCD-Anzeige +    initDisplay();                      // Initialisierung LCD-Anzeige 
- pcd_init(); +    pcd_init(); 
- +  
- TCCR0A = 0; // Timer 0 auf "Normal Mode" schalten +    TCCR0A = 0;                         // Timer 0 auf "Normal Mode" schalten 
- SET_BIT(TCCR0B, CS01); // mit Prescaler /8 betreiben +    SET_BIT(TCCR0B, CS01);              // mit Prescaler /8 betreiben 
- SET_BIT(TIMSK0, TOIE0); // Overflow-Interrupt aktivieren +    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 
- PORTC |= 0b00001111; // Taster Anschluesse auf Pullup R +    PORTC |= 0b00001111;                // Taster Anschluesse auf Pullup R 
- SET_BIT(DDRB, LED_BIT); // LED-Bit auf Ausgabe +    SET_BIT(DDRB, LED_BIT);             // LED-Bit auf Ausgabe 
- +  
- sei(); // generell Interrupts einschalten +    sei();                              // generell Interrupts einschalten 
-  +      
- // Hauptprogrammschleife +    // Hauptprogrammschleife 
- +  
- while(1) // unendliche Warteschleife mit Aufruf der +    while(1)                            // unendliche Warteschleife mit Aufruf der 
- // Funktionen abhaengig von Taktbotschaften +                                        // Funktionen abhaengig von Taktbotschaften 
-+    
- if (takt10ms) // alle 10ms: +        if (cycle10msActive           // alle 10ms: 
- +        
- takt10ms 0; // Botschaft "10ms" loeschen +            cycle10msActive NO; //      Botschaft "10ms" loeschen 
- uhrStellen(); // Tasten abfragen, Stellen, SPI-Komm. +            setTime(); //      Tasten abfragen, Stellen, SPI-Komm. 
- +        
- +  
- if (takt100ms) // alle 100ms: +        if (cycle100msActive          // alle 100ms: 
- +        
- takt100ms 0; // Botschaft "100ms" loeschen +            cycle100msActive NO     //      Botschaft "100ms" loeschen 
- if (PcdSendMessage) // wenn SPI-Nachricht gesendet werden soll: +            if (PcdSendMessage)         // wenn SPI-Nachricht gesendet werden soll: 
- {  +                           
- PcdSendMessage = 0; // Botschaft loeschen +                PcdSendMessage = NO    // Botschaft loeschen 
- TGL_BIT(LED_PORT, LED_BIT); // LED Zustand wechseln +                TGL_BIT(LED_PORT, LED_BIT);     // LED Zustand wechseln 
- zehntelSekundenAufPcdAnzeigen();// Anzeige auf PCD Display +                showTenthOfASecond(); // Anzeige auf PCD Display 
- +            
- uhrAnzeigen(); // Uhrzeit auf Anzeige ausgeben +            showTime(); //      Uhrzeit auf Anzeige ausgeben 
- uhrZaehlen(); // Uhr weiterzaehlen +            refreshTime();              //      Uhr weiterzaehlen 
- +        
- +  
- if (takt1s) // alle Sekunden: +        if (cycle1sActive             // alle Sekunden: 
- +        
- takt1s 0; // Botschaft "1s" loeschen +            cycle1sActive NO        //      Botschaft "1s" loeschen 
- TGL_BIT(LED_PORT, LED_BIT); // LED Zustand wechseln +            TGL_BIT(LED_PORT, LED_BIT); // LED Zustand wechseln 
- pcd_init(); +            pcd_init(); 
- }  +               
-+    
- return 0;+    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 +    Veraenderte Variable: softwarePrescaler 
-   hunderstel +                          cycle10msCount 
-   zehntel +                          cycle100msCount 
- +  
- Ausgangsvariable:   takt10ms +    Ausgangsvariable:     cycle10msActive 
-   takt100ms +                          cycle100msActive 
-   takt1s+                          cycle1sActive
 */ */
 + 
 { {
- timertick = 1; // Botschaft 0,111ms senden +    timertick = 1; // Botschaft 0,111ms 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   YES; //    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 YES; //    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   YES; //    Botschaft 1s senden 
- +            
- +        
- }+    }
 } }
 + 
 // Stellfunktion ============================================================== // Stellfunktion ==============================================================
- +  
-void uhrStellen(void) +void setTime(void) 
- +  
-/*  Die Stellfunktion der Uhr wird alle 10ms aufgerufen. Dadurch wir eine +/*  Die Stellfunktion der Uhr wird alle 10ms aufgerufen. Dadurch wir eine 
-  Entprellung der Tastensignale realisiert. Das Stellen wir bei einer  +    Entprellung der Tastensignale realisiert. Das Stellen wir bei einer  
-  fallenden Flanke des jeweiligen Tastensignals durchgefuehrt. Darum  +    fallenden Flanke des jeweiligen Tastensignals durchgefuehrt. Darum  
-  muss fuer einen weiteren Stellschritt die Taste erneut betaetigt werden. +    muss fuer einen weiteren Stellschritt die Taste erneut betaetigt werden. 
- Ebenso wird die SPI-Funktion hier aufgerufen. +    Ebenso wird die SPI-Funktion hier aufgerufen. 
- +  
-  Eine Flanke wird durch (alter Wert == 1) UND (aktueller Wert == 0) erkannt. +    Eine Flanke wird durch (alter Wert == 1) UND (aktueller Wert == 0) erkannt. 
- +  
-  Mit der Taste S1 wird die Uebergabe der Zeit Master > Slave gestartet +    Mit der Taste S1 wird die Uebergabe der Zeit Master > Slave gestartet 
- Mit der Taste S2 werden die Stunden aufwaerts gestellt. +    Mit der Taste S2 werden die Stunden aufwaerts gestellt. 
-  Mit der Taste S3 werden die Minuten aufwaerts gestellt (kein Uebertrag) +    Mit der Taste S3 werden die Minuten aufwaerts gestellt (kein Uebertrag) 
-  Solange Taste S3 gedrueckt ist werden die Sekunden auf 00 gehalten +    Solange Taste S3 gedrueckt ist werden die Sekunden auf 00 gehalten 
- Mit der Taste S4 wird die Uebergabe der Zeit Master < Slave gestartet +    Mit der Taste S4 wird die Uebergabe der Zeit Master < Slave gestartet 
- +  
-  Veraenderte Variable: stunden +    Veraenderte Variable: hours 
-   minuten +                          minutes 
-   sekunden +                          seconds 
- +                            
-  Speicher fuer Bits:   sw1Alt +    Speicher fuer Bits:   button1_old 
-   sw2Alt +                          button2_old 
-   sw3Alt +                          button3_old 
-   sw4Alt+                          button4_old
 */ */
- +  
-{  +   
- sw1_neu = (PINC & (1 << PC0)); // Tasten von Port einlesen +    button1_new GET_BIT(PINCPC0);       // Tasten von Port einlesen 
- sw2_neu = (PINC & (1 << PC1)); +    button2_new GET_BIT(PINCPC1); 
- sw3_neu = (PINC & (1 << PC2)); +    button3_new GET_BIT(PINCPC2); 
- sw4_neu = (PINC & (1 << PC3)); +    button4_new GET_BIT(PINCPC3); 
- +  
- if ((sw1_neu==0)) // wenn Taste 1 gedrueckt ist: +    if (button1_new==PRESSED) // wenn Taste 1 gedrueckt ist: 
-+    
- PcdSendMessage = 1; //    Senden der SPI-Nachricht aktivieren +        PcdSendMessage = YES; //    Senden der SPI-Nachricht aktivieren 
-+    
-  +      
- if ((sw2_neu==0)&(sw2_alt==1)) // wenn Taste 2 eben gedrueckt wurde: +    if ( (button2_new==PRESSED) 
-+ &(button2_old==UNPRESSED)) // wenn Taste 2 eben gedrueckt wurde: 
- stunden++; //    Stunden hochzaehlen, Ueberlauf bei 23 +    
- if (stunden==24+        hours++; //    Stunden hochzaehlen, Ueberlauf bei 23 
- stunden = 00; +        if (hours== HOURS_MAX
-+            hours = 00; 
- if ((sw3_neu==0)&(sw3_alt==1)) // wenn Taste 3 eben gedrueckt wurde: +    
-+    if ( (button3_new==PRESSED) 
- minuten++; //    Minuten hochzaehlen, Ueberlauf bei 59 + &(button3_old==UNPRESSED)) // wenn Taste 3 eben gedrueckt wurde: 
- if (minuten==60+    
- minuten = 00; +        minutes++; //    Minuten hochzaehlen, Ueberlauf bei 59 
-+        if (minutes== MINUTES_MAX
- if (sw3_neu==0) // solange Taste 3 gedrueckt: +            minutes = 00; 
- sekunden = 00; //    Sekunden auf 00 setzen +    
- +    if (button3_new==PRESSED              // solange Taste 3 gedrueckt: 
- if ((sw4_neu==0)&(sw4_alt==1)) // wenn Taste 3 eben gedrueckt wurde: + seconds = 00; //    Sekunden auf 00 setzen 
-+  
- pcd_putLine(rand()%83,rand()%47,rand()%83,rand()%47); +    if ((button4_new==0)&(button4_old==1))  // wenn Taste 3 eben gedrueckt wurde: 
- pcd_updateDisplay(); +    
-+        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+    button1_old button1_new             // aktuelle Tastenwerte speichern 
- sw4_alt sw4_neu;+    button2_old button2_new             // in Variable fuer alte Werte 
 +    button3_old button3_new
 +    button4_old button4_new;
 } }
 + 
 // Anzeigefunktion Uhr ======================================================== // Anzeigefunktion Uhr ========================================================
- +  
-void uhrAnzeigen(void) +void showTime(void) 
- +  
-/* Die Umrechnung der binaeren Zaehlwerte auf BCD ist folgendermaßen geloest:  +/*  Die Umrechnung der binaeren Zaehlwerte auf BCD ist folgendermaßen geloest:  
- Zehner: einfache Integer-Teilung (/10) +    Zehner: einfache Integer-Teilung (/10) 
- Einer:  Modulo-Ermittlung (%10), d.h. Rest bei der Teilung durch 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 ======================================================== // Anzeigefunktion fuer PCD Display ========================================================
- +  
-void zehntelSekundenAufPcdAnzeigen(void) +void showTenthOfASecond(void) 
- +  
-/* Anzeigen der Zenhtelsekunden auf dem Display PCD8544+/*  Anzeigen der Zenhtelsekunden auf dem Display PCD8544
 */ */
 + 
 { {
- pcd_gotoxy(zeile, pos); // Setze Position am Display +    pcd_gotoxy(line, pos); // Setze Position am Display 
- pcd_putc(zehntelSekunden+0x30); // Schreibe Zehntelsekunden  +    pcd_putc(tenthOfASecond+0x30); // Schreibe Zehntelsekunden  
- pcd_updateDisplay(); // Aktualisiere das Display des PCD8544 +    pcd_updateDisplay(); // Aktualisiere das Display des PCD8544 
- if (++pos > 13) // naechste Position, und wenn diese ausserhalb der Anzeige +    if (++pos > POS_MAX) // naechste Position, und wenn diese ausserhalb der Anzeige 
-+    
- pos = 0; // zurueck auf erste Position +        pos = 0; // zurueck auf erste Position 
- if (++zeile 5) // naechste Zeile, und wenn diese ausserhalb der Anzeige +        if (++line LINE_MAX) // naechste Zeile, und wenn diese ausserhalb der Anzeige 
- +        
- zeile = 0; // zurueck auf erste Zeile +            line = 0; // zurueck auf erste Zeile 
- pcd_clearDisplay(); // loesche Anzeige +            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 7a-"); // 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("Uhr + SPI-Master"); // Ausgabe Festtext: 16 Zeichen 
- +  
- _delay_ms(1000); // Wartezeit nach Initialisierung +    _delay_ms(1000); // 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("10tl Std Min Lin.");        // Ausgabe Festtext: 16 Zeichen 
- +  
-} // Ende der Funktion +} // Ende der Funktion 
- +  
 + 
 // Zaehlfunktion Uhr ========================================================== // Zaehlfunktion Uhr ==========================================================
- +  
-void uhrZaehlen (void) // wird jede Sekunde gestartet +void refreshTime (void) // wird jede Sekunde gestartet 
- +  
-/* Die Uhr wird im Sekundentakt gezaehlt. Bei jedem Aufruf wird auch ein  +/*  Die Uhr wird im Sekundentakt gezaehlt. Bei jedem Aufruf wird auch ein  
- "Tick" auf dem Lautsprecher ausgegeben. Ueberlaeufe der Sekunden zaehlen +    "Tick" auf dem Lautsprecher ausgegeben. Ueberlaeufe der Sekunden zaehlen 
- die Minuten, die Ueberlaeufe der Minuten die Stunden hoch. +    die Minuten, die Ueberlaeufe der Minuten die Stunden hoch. 
- +  
- Veraenderte Variable: sekunden +    Veraenderte Variable:   seconds 
- minuten +                            minutes 
- stunden+                            hours
 */ */
 + 
 { {
- 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++; +    tenthOfASecond++; 
- if (zehntelSekunden==10) // bei Ueberlauf: +    if (tenthOfASecond== TENTH_MAX) // bei Ueberlauf: 
-+    
- zehntelSekunden=0; +        tenthOfASecond = 0; 
- sekunden++; // Sekunden hochzaehlen +        seconds++; // Sekunden hochzaehlen 
- if (sekunden==60) // bei Ueberlauf: +        if (seconds== SECONDS_MAX) // bei Ueberlauf: 
- +        
- sekunden = 0; //   Sekunden auf 00 setzen +            seconds = 0; //   Sekunden auf 00 setzen 
- minuten++; //   Minuten hochzaehlen +            minutes++; //   Minuten hochzaehlen 
- if (minuten==60) //  bei Ueberlauf: +            if (minutes== MINUTES_MAX) //   bei Ueberlauf: 
- +            
- minuten = 0; //    Minuten auf 00 setzen +                minutes = 0; //     Minuten auf 00 setzen 
- stunden++; //    Stunden hochzaehlen +                hours++; //     Stunden hochzaehlen 
- if (stunden==24) //    bei Ueberlauf: +                if (hours== HOURS_MAX) //     bei Ueberlauf: 
- stunden = 0; //  Stunden auf 00 setzen +                    hours = 0; //       Stunden auf 00 setzen 
- +            
- +        
- }+    }
 } }
- 
 </sxh> </sxh>
 </WRAP><WRAP column 55%> </WRAP><WRAP column 55%>
Zeile 481: Zeile 496:
     - ''"pcd8544.h"'' - Bibliothek für das einbinden des neuen Displays \\ \\ \\      - ''"pcd8544.h"'' - Bibliothek für das einbinden des neuen Displays \\ \\ \\ 
   - Die Makros entsprechen denen der letzten Programme. \\ \\ \\ \\    - Die Makros entsprechen 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.  \\ \\ \\ \\ \\ \\  +  - 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 Zeichen ''0'' und '':'' werden für die ASCII-Codes Makros definiert. Dadurch wird das Lesen des am Display ausgegebenen Textes im Code einfacher. \\ \\   - 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. \\ \\
 +  - Für die anschaulichere Beschreibung von Bitwerten wird "YES", "NO", sowie "PRESSED" und "UNPRESSED" definiert \\ \\ \\ \\
 +  - Die Grenzen der Zeitgrößen sind hier ebenso definiert. \\ \\ \\  
   - Bei den Variablen entsprechen einige denen der letzten Programme. \\ \\ \\ \\ \\     - Bei den Variablen entsprechen einige denen der letzten Programme. \\ \\ \\ \\ \\  
 +  - Bei den Variablen entsprechen einige denen der letzten Programme. \\ \\ \\ 
   - Für die Uhr werden Stunden, Minuten, Sekunden und Zehntelsekunden mit Anfangswerten deklariert. \\ \\ \\   - 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. \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\   - 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.  \\ \\ \\   - 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. \\ \\ \\ \\ \\ +  - 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)   - 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.   - Dann werden wieder "__T__imer/__C__ounter __C__ontrol __R__egister" und "__T__imer __I__nterrupt __M__a__SK__" konfiguriert.
Zeile 496: Zeile 514:
   - 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. \\ \\   - 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. \\ \\ \\   - 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]]). \\ \\ +  - 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 $10~\rm ms$ Raster (auch $10~\rm ms$ Zyklus genannt) wird die Unterfunktion ''setTime()'' zum (möglichen) Ändern der Uhrzeit 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 $100~\rm ms$ Raster werden die Unterfunktionen ''showTime()'' für die Anzeige und ''refreshTime()'' zum Weiterzählen aufgerufen. Davor wird, falls das Flag ''PcdSendMessage'' gesetzt ist, wird dieses zurückgesetzt, die LED blinkt und das Unterprogramm ''showTenthOfASecond()'' wird aufgerufen. \\ \\ \\ \\ \\ \\ \\ 
-    - im $1s$ Raster blinkt die LED und das Unterprogramm ''pcd_init'' zum initialisieren des PCD Displays wird aufgerufen. \\ \\ \\ \\ \\ \\ \\ +    - im $1~\rm s$ Raster blinkt die LED und das Unterprogramm ''pcd_init'' zum initialisieren des PCD Displays wird 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. \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\    - Mit dem Befehl ''ISR()'' wird wieder die Interrupt Service Routine für den  __OV__er__F__low Interrupt des __TIMER0__ angelegt. \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ 
-  - Die Ermittlung von ''Timertick'', ''vorteiler'', ''takt10ms'', ''hundertstel'' und ''takt100ms'' ist hier wieder gleich dem im [[4._up_down_counter|Up/Down Counter]].  \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\  +  - Die Ermittlung von ''timertick'', ''softwarePrescaler'', ''cycle10msActive'', ''cycle10msCount'' und ''cycle100msActive'' ist hier wieder gleich dem im [[4_up_down_counter|Up/Down Counter]].  \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\  
-  - Eine Erweiterung auf ''zehntel'' und ''takt1s'' wurde hier mit eingefügt. \\ \\ \\ \\ \\ +  - Eine Erweiterung auf ''cycle100msCount'' und ''cycle1sActive'' wurde hier mit eingefügt. \\ \\ \\ \\ 
 '' Funktion Tasten einlesen =============='' '' 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]]). \\ \\ +  - 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.  +  - 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.  \\ \\ \\  +  - Wenn die Taste ''S1'' gedrückt ist, so wird das Flag ''PcdSendMessage'' gesetzt, welches in ''main'' zum Aufrufen des Unterprogramm ''showTenthOfASecond'' in jedem $100~\rm ms$ 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 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 \\ \\ \\ \\ \\ \\ \\ \\+  -  Die Taste ''S4'' zeichnet eine Linie mittels ''pcd_putLine'' und aktualisiert das Displays des PCD8544 \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\
  
 ''Anzeigefunktion Uhr ========================='' ''Anzeigefunktion Uhr =========================''
Zeile 518: Zeile 536:
  
   - Auf dem LCD wird zunächst die Position ''(0,4)'' als Ausgabeort vorgegeben   - 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 ausgegeben. Die Einerstelle ergibt sich über Modulo (''%'').+  - Vom Wert ''hours'' wird zunächst die Zehnerstelle über Division ermittelt und ausgegeben. Die Einerstelle ergibt sich über Modulo (''%'').
   - Danach wird ein Doppelpunkt ausgegeben   - Danach wird ein Doppelpunkt ausgegeben
   - Die Anzeige von Minuten und Sekunden erfolgt analog.   - Die Anzeige von Minuten und Sekunden erfolgt analog.
  
-\\ \\ \\ \\ +\\ \\ \\ \\ \\
  
 ''Anzeigefunktion fuer PCD Display ========================='' ''Anzeigefunktion fuer PCD Display =========================''
Zeile 541: Zeile 559:
 ''Zaehlfunktion Uhr ================='' ''Zaehlfunktion Uhr =================''
  \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\  \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\
-  - Hier wird zunächst ein Flankenwechsel für den Lautsprecher ausgegeben. Damit knackt der Lautsprecher etwa im $10ms$ Takt. +  - Hier wird zunächst ein Flankenwechsel für den Lautsprecher ausgegeben. Damit knackt der Lautsprecher etwa im $10~\rm ms$ 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+  - In den verschachtelten if-Anweisungen werden jeweils die einzelnen Werte (z.B. ''tenthOfASecond'') 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
  
 </WRAP></WRAP> </WRAP></WRAP>
Zeile 548: Zeile 566:
 <-- <--
 --> IV. Ausführung in Simulide # --> IV. Ausführung in Simulide #
-  - Legen Sie in Atmel Studio ein neues Projekt an. +  - Legen Sie in Microchip Studio ein neues Projekt an. 
-  - Fügen Sie in dieses die *.c und *.h Files aus dem File ''pcd8544.zip'' hinzu. \\ Dazu ist zunächst das zip-File zu entpacken und die Files dann als ''Existing Item'' hinzuzufügen - wie in [[2. Sound und Timer]] beschrieben.+  - Fügen Sie in dieses die *.c und *.h Files aus dem File ''pcd8544.zip'' hinzu. \\ Dazu ist zunächst das zip-File zu entpacken und die Files dann als ''Existing Item'' hinzuzufügen - wie in [[2_sound_und_timer]] beschrieben.
   - Geben Sie die oben dargestellten Codezeilen in ''main.c'' ein und kompilieren Sie den Code.   - Geben Sie die oben dargestellten Codezeilen in ''main.c'' 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 563: Zeile 581:
     - Prüfen Sie nach, ob die Anfangs- und Endpunkte tatsächlich zufällig zu sein scheinen. \\ Wie sieht dies nach dem Neustart des Systems aus? \\ \\     - Prüfen Sie nach, ob die Anfangs- und Endpunkte tatsächlich zufällig zu sein scheinen. \\ Wie sieht dies nach dem Neustart des Systems aus? \\ \\
   - Analyse der seriellen Kommunikation   - Analyse der seriellen Kommunikation
-    - Wenn Daten vom Mikrocontroller zum PCD8544 übertragen werden, so 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.+    - Wenn Daten vom Mikrocontroller zum PCD8544 übertragen werden, so ist auf dem Oszilloskop die Situation der Signale auf den Leitungen zum Display zu sehen. Im folgenden soll dieses genauer betrachtet werden.
     - 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.     - 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.
-    - 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.  +    - Nun sollten die Signale gut aufgelöst sichtbar sein: \\ {{microcontrollertechnik:simulide_beispiel_anzeige_osziklein.jpg}}
-    - Ä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'' (__CL__oc__K__, gelb) taktet 8 mal und zeigt dann eine kurze Pause       - Das 1. Signal ''CLK'' (__CL__oc__K__, gelb) taktet 8 mal und zeigt dann eine kurze Pause
-      - Das 2. Signal ''DIN'' (__D__ata _IN_, rot) zeigt das eigentliche Signal. Bei der SPI-Schnittstelle wird dieses Signal ''MOSI'' (__M__aster __O__ut, __S__lave __I__n) genannt. Dies kann bei Ihnen auch nur LOW, bis auf einen kurzen HIGH Pegel am Ende der 8 Takte von ''CLK'' zeigen. Das Signal entspricht jeweils einem 8-bit langen Teil einer Pixel-Zeile. Wenn nur wenig Pixel auf dem Display dunkel sein sollen, so ist dieses Signal häufig LOW. Im Bild oben ist ein etwas wechselhafteres Signal zu sehen.  +      - Das 2. Signal ''DIN'' (__D__ata _IN_, hellblau) zeigt das eigentliche Signal. Bei der SPI-Schnittstelle wird dieses Signal ''MOSI'' (__M__aster __O__ut, __S__lave __I__n) genannt. Dies kann bei Ihnen auch nur LOW, bis auf einen kurzen HIGH Pegel am Ende der 8 Takte von ''CLK'' zeigen. Das Signal entspricht jeweils einem 8-bit langen Teil einer Pixel-Zeile. Wenn nur wenig Pixel auf dem Display dunkel sein sollen, so ist dieses Signal häufig LOW. Im Bild oben ist ein etwas wechselhafteres Signal zu sehen.  
-      - Das 3. Signal ''D/C'' (__D__ata__/C__ommand, blau) ist fast immer HIGH. Dieses Signal zeit an, ob das Signal auf dem Kanal ''DIN'' als Kommando oder Daten interpretiert werden sollen. Wenn Daten auf dem Display ausgegeben werden sollen, so ist dieses Signal HIGH. Diese Signal ist kein Teil der offiziellen SPI Schnittstelle. +      - Das 3. Signal ''D/C'' (__D__ata__/C__ommand, orange) ist fast immer HIGH. Dieses Signal zeit an, ob das Signal auf dem Kanal ''DIN'' als Kommando oder Daten interpretiert werden sollen. Wenn Daten auf dem Display ausgegeben werden sollen, so ist dieses Signal HIGH. Diese Signal ist kein Teil der offiziellen SPI Schnittstelle. 
-      - Das 4. Signal ''CS'' (__C__hip __S__elect, grün) wird nur zwischen den takten von ''CLK'' HIGH. Das Signal zeigt an, dass der Slave auf das folgende Signal hören soll und wird gelegentlich auch ''SS'' (__S__lave __S__elect) genannt. +      - Das 4. Signal ''CS'' (__C__hip __S__elect, mintgrün) wird nur zwischen den takten von ''CLK'' HIGH. Das Signal zeigt an, dass der Slave auf das folgende Signal hören soll und wird gelegentlich auch ''SS'' (__S__lave __S__elect) genannt. 
-    - Das im Bild dargestellte Signal ist ''00110110'' also ''0x36'' oder dezimal 56\\ \\ <panel type="info" title="Info: Reale Hardware">Bei der realen Hardware kann zur Analyse der seriellen Schnittstelle ein Oszilloskop oder Logic Analyzer verwendet werden. Diese haben einen Triggereingang und bieten die Möglichkeit Zeitbasis der hoch aufgelösten Daten so zu verändern, dass einzelne Details besser sichtbar werden (ähnlich einem Zoom). Dies ist in der aktuellen Version von SimulIDE noch nicht möglich. \\ \\ Andererseits ist das Herabsetzten des Takts für die Analyse einer Hardware ohne Programmierinterface ein übliches Vorgehen. Beim "Reverse Engineering" kann so in einzelnen Schritten die Ausgabe (oder über diverse "Side Channels" auch die interne Abarbeitung)  analysiert werden. </panel> +    - Um den Signalverlauf besser zu sehen, kann mit einem Klick auf ''Expand'' das Oszilloskop separiert und größer dargestellt werden \\ {{microcontrollertechnik:simulide_beispiel_anzeige_oszigross.jpg}} 
-  - Analyse der Dateien in ''pcd8544.zip'' in Atmel Studio +    - Das im Bild dargestellte Signal ist ''00100111'' also ''0x27'' oder dezimal 39
 +  - Analyse der Dateien in ''pcd8544.zip'' in Microchip Studio 
     - In der Datei ''characterset5x8.c'' ist der Zeichensatz für das Display zu finden. Warum ist dieser um 90° gedreht?     - In der Datei ''characterset5x8.c'' ist der Zeichensatz für das Display zu finden. Warum ist dieser um 90° gedreht?
     - In der Datei ''pcd8544.c'' ist die eigentliche Bibliothek für die Kommunikation zum Display zu finden.     - In der Datei ''pcd8544.c'' ist die eigentliche Bibliothek für die Kommunikation zum Display zu finden.
Zeile 592: Zeile 606:
 <-- <--
  
 +===== weiterführendes =====
 +
 +  * Diese [[http://www.falstad.com/circuit/circuitjs.html?running=false&ctz=CQAgzCCMCmC0AcIAMA6SAmMkBsnsBZN8B2JfATmJAFYkaR8Jq5JIAoAGQaUXXjvw9wGEOiggAZgEMANgGdo9JJwaDR-VXSxixdafMXVkK2vnV1TwnckmyFSlSR0anV0eP32jyrtiR0+Oj8tETFIWwMHXzBnIJi3XQivYy5qbF4NNMRtd3DPQxSaMGxzIpKcsKSC5QBZbkQ0+qgSnRRqNjr8NUauuhx3dDaOmjIaEst+1vbO4jEe2eaBobrgsZBVydFl9fjG7HjNwemxhvH0xanh6mK165LDoYAlUUawch10MzfKsP8--y2RiONlQ7QA7uBRhgtKNBIhlBCwMQWv0wF1RP0EeB0ehUeiwDcsWivjdIEjyoS2BDsAQMfceLxMVTIWY4VA-k0sWTkXSoOTwJSIZAORhEMKAWyfOAeZBqGIwHKoIrKvkouz4GL4GZhbTIFr3Ho7NU2AAjEDwUi5LoQLq6NgAD3WxCMCBAxHwiFgRjMnxANSkcgALtAAE4O83wF2Icj4F3e0RmADKMikADdoOHkeQMXR4GAAmSGAm-QB5RMASUz2GzMUQea0WCLvpq5cTJarJUEudl3BtxcTAGEANJsWV9EXocdqaHiRLgkDkRWsMTEETLwqrsIidJi0I2VXeTOWnXmpC-bM+pOJ0cal7ld7qbIPm1hRhIfNk6g+9iO4iW+AruQJSRk2ZgAPpgWw5YLkua4iiIdCgjQzLCtOk7qmK6FElC6H8jOyhmpAzo2O6iC9MYKDmgAQgAloGiYABY0RIgaPNAADmNFBqGADqHAAPZSAAJgAIjRIY2IgKIgAOHBDkW4RiCJ5bPDW7gcCWACCIn0NYFYAHJuk2IBtgAqgAKtKRYQAAGloZhUOENnhPm6ziDZOjjO5EDoGI2ogDZ2rZO5RibE59LiE5VAlH0IAAJohEZdBxYp0U2HFOhMOlECQBe6XalQEDJaFinpcB4jJVQiR0CJABiMg0QADvV-GNQAojIAC2AA6ciQL16C9WAvX4N1IYCZxADGJYAK6Bo1c0dT1cjYGNE00dNc0LYGS0DWNNQzTIgZNTI0D2qGu1yMQvWrXI8A3b11C9eQvX9SGB1HSdZ0XV1e19Ugr39f9j3Pa9g3jfxU2zfNi2-Xda2Qxt0PbZdwpjXVDXNTIrWo4N8N9cNcijSGGNNS17Vw5Ao19UDsojQjUNbbDy04AzSNMztlNvR9x2Nad50hpd919bdRGvbdT1yC9fXEzzX0C6jtPC7lr3C5L0uTmzm0w5zLPXRDjM66j90k-VZPYxTy2a3111yLi9PvYdvP8z9esDXjmDuyDUsDcT63ayjlMvQb7NG3Dvno2bWM4+H1Mq3bkuy078uu69Gu3egtvoBLoN2yb-vI8zA3DSHAdF3bq2m5j5OXXwxcDdLSefXz32C+HhP5kNQOd3I6tDeDBcc7X+uD2Hy2d1X5sx+PHu2wSDtyy3Cvh3P1Or970sKlrhe61329D3DaKR9XFuXVvchYENt1N87rdn931N4znPsXyPiNl7vF-at1vUA3bP92zaHtAaQC+oALxv1P6g0QGS2gYAyWkC5B-0QX-OBRxgHwNeuArBUDwGgLQaAlBOD-7-xgRg9BYDf7EI9ng2BtDiHIOwaQzBzCKFEMoSQghdCyEcMYbgmBbB8DCmlMBMiHo+T3GonRRizFWIcS4sGEMfFBKiXElAR6ogYGaPgeou2uidBaI9m0XRfQNFGKBFooGYQBraOBOYkx+jbHGPsUDUKNj7EuI0VYpxFidGuMcR4yxv8AkCK4HhfUCowj6kSAeYwQjxy3lvKwPwEjxDwFovRJiLE2KcW4kogSwkxISSBgEQxQS9HeMCX44JJSfF1O8ZUsp1SkEhJ0Z4lpjS2nlNMXoqpwJamdLsd01pRxhgYHEY0cZYoWiAjGYENYoo+gzNGXUMk6JJnEguLM1ZOQNlrmWdsVg+pJl6m1Ac44GB+iTNxPcc5YzZRzHuA8rZKyoAzhOehB47QuBTNKL8io+4jRqkWX8+ZALDSREPD8zZ8y1lfD3HkIFUK+ShA0GSEQALEWQsKEcn0aLTkJA8EinFNzQWoj3BC5IUpWDKnxYqTFVRgUzlhTOBlsTqUMiVL8XUypAXYuUEAA|Falstad-Simulation]] skizziert die Funktionsweise der SPI Schnittstelle (Achtung: Die Simulation beinhaltet noch einige Bugs)
 +  * Ein einfaches Beispiel für eine Anfrage von Daten beim Slave ist unter [[weitere Codebeispiele]] eingefügt