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:2_sound_und_timer [2020/05/05 07:11]
tfischer
microcontrollertechnik:2_sound_und_timer [2024/03/10 23:53] (aktuell)
mexleadmin
Zeile 1: Zeile 1:
-====== 2Sound und Timer ====== +====== 2 Sound und Timer ======
  
 +Details dazu sind auch unter [[https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Die_Timer_und_Z%C3%A4hler_des_AVR|Die Timer und Zähler des AVR]] bei mikrocontroller.net zu finden.
  
 ===== schnelles Takten für Anfänger ===== ===== schnelles Takten für Anfänger =====
Zeile 12: Zeile 12:
 Nach dieser Lektion sollten Sie: Nach dieser Lektion sollten Sie:
  
-  - wissen, wie man im Atmel Studio eine Puls-Signal ausgibt+  - wissen, wie man im Microchip Studio eine Puls-Signal ausgibt
  
  
Zeile 18: Zeile 18:
 ==== Video ==== ==== Video ====
    
-{{youtube>6PWEpY6SlSc?size=700x400}}+{{youtube>_cRsC6pk_oc?size=700x400}}
  
 </WRAP> </WRAP> </WRAP> </WRAP>
  
 +<WRAP hide>
 +===== LCD Display ansteuern - wie kommt Test auf eine Anzeige? =====
 +<WRAP group> 
 +<WRAP column 30%>
 +
 +==== Ziele ====
 +
 +Nach dieser Lektion sollten Sie:
 +
 +  - wissen, wie Display angesprochen wird
 +
 +
 +</WRAP> <WRAP column 65%>
 +==== Video ====
 + 
 +{{youtube>p8r1EXRLQV0?size=700x400}}
 +
 +</WRAP> </WRAP>
 +</WRAP>
  
 ==== Übung ==== ==== Übung ====
-<WRAP group><WRAP column 60%> 
  
 --> I. Vorarbeiten # --> I. Vorarbeiten #
   - Laden Sie folgende Datei herunter:    - Laden Sie folgende Datei herunter: 
-    - {{microcontrollertechnik:2_sound.simu}} +    - {{microcontrollertechnik:2._sound_und_timer.sim1}} 
-    - {{microcontrollertechnik:2_sound.hex}}+    - {{microcontrollertechnik:2._sound_und_timer.hex}}
     - {{microcontrollertechnik:lcd_lib_de.h}}     - {{microcontrollertechnik:lcd_lib_de.h}}
  
Zeile 35: Zeile 53:
 --> 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?100}} die Datei ''2_sound.simu''  +    - Öffnen Sie SimulIDE und öffnen Sie dort mittels {{microcontrollertechnik:simulide_open.jpg?25}} die Datei ''2_sound_und_timer.sim1''  
-    - Laden Sie ''2_sound.hex'' als firmware auf den 328 Chip+    - Laden Sie ''2_sound_und_timer.hex'' als firmware auf den Atmega88 Chip
   - Betrachtung der neuen Komponenten   - Betrachtung der neuen Komponenten
     - In der Simulation sind nun neben der LED weitere Komponenten zu sehen, die im Folgenden erklärt werden sollen     - In der Simulation sind nun neben der LED weitere Komponenten zu sehen, die im Folgenden erklärt werden sollen
Zeile 45: Zeile 63:
     - Starten Sie die Simulation      - Starten Sie die Simulation 
       - Wenn Sie die Lautsprecher des PCs aktiv haben, werden Sie ein Knacken (und ggf. Brummen) vernehmen. Dies rührt von der unvollständigen Simulation her. Wenn Sie den den Schalter vor dem Lautsprecher schließen, so sollten Sie - zusätzlich zum Knacken - einen aufsteigenden und abfallenden Ton hören. Es ist möglich, dass dieser nach wenigen Sekunden aufhört, auch das ist eine Eigenschaft der unvollständigen Simulation.       - Wenn Sie die Lautsprecher des PCs aktiv haben, werden Sie ein Knacken (und ggf. Brummen) vernehmen. Dies rührt von der unvollständigen Simulation her. Wenn Sie den den Schalter vor dem Lautsprecher schließen, so sollten Sie - zusätzlich zum Knacken - einen aufsteigenden und abfallenden Ton hören. Es ist möglich, dass dieser nach wenigen Sekunden aufhört, auch das ist eine Eigenschaft der unvollständigen Simulation.
-      - Am Frequenzmesser ist dennoch zu sehen, dass ein Signal mit Frequenzen zwischen $375...1600Hz$ ausgegeben wird. +      - Am Frequenzmesser ist dennoch zu sehen, dass ein Signal mit Frequenzen zwischen $500...1000~\rm Hz$ ausgegeben wird. 
-      - Im Gegensatz dazu scheint das Oszilloskopbild still zu stehen und keine variierende Frequenz anzuzeigen. Um dies zu beheben, sollte am Oszilloskop der Haken bei Aut bzw. Auto entfernt werden. Nun ist eine Einstellung der xund y-Werte über die Drehregler möglich+      - Das Oszilloskopbild zeigt den Signal-Zeit-Verlauf, in welchem die länger und kürzer werdenden Wechsel von HIGH nach LOW sichtbar sind
-      - Die LED zeigt nun an, ob es sich um einen Aufsteigenden oder abfallenden Ton handelt+      - Die LED zeigt nun an, ob es sich um einen aufsteigenden oder abfallenden Ton handelt
       - Das Display zeigt zusätzlich an, welches Experiment geladen ist       - Das Display zeigt zusätzlich an, welches Experiment geladen ist
     - Das Programm zu diesem Hexfile soll nun erstellt werden     - Das Programm zu diesem Hexfile soll nun erstellt werden
  
 <-- <--
---> II. Eingabe in Atmel Studio # +--> III. Eingabe in Microchip Studio # 
-  - öffnen Sie Atmel Studio +  - öffnen Sie Microchip Studio 
-  - legen Sie ein neues "GCC C Executable Project" mit dem Namen ''2_sound'' für einen ATmega328 an +  - legen Sie ein neues "GCC C Executable Project" mit dem Namen ''2_sound_und_timer'' für einen ATmega88 an 
-  - +  - Bevor das eigentliche Coding beginnt sollte immer eine Beschreibung dem Code vorangestellt werden. Hierzu kann folgende Vorlage verwendet werden: <sxh c; first-line: 1> 
 +/*=============================================================================
  
-  Eingabe und Kompilieren des Code +Experiment 2: Sound-Generator 
-    - Ersetzen Sie den vorhandenen Code, durch den rechts stehenden Code  +============= ===============
-    - Kompilieren Sie den Code durch ''Build'' >> ''Build solution'' +
-    - Im unteren Teil des Fensters sollte nun die Ausgabe des Kompilers sichtbar werden. Diese sollte ''========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped =========='' lauten +
-  - Auswählen der hex-Datei +
-    - im Atmel Studio finden Sie rechts im Fenster den "Solution Explorer" +
-    - gehen Sie dort im Solution Explorer zu ''Solution'' >> ''Einfuehrung_v01'' >> ''Output Files''  +
-    - klicken Sie mit rechter Maustaste auf ''Einfuehrung_v01.hex'' und wählen Sie Pfad und Name aus+
  
-<-- +Dateiname: 2_sound_und_timer.c
---> IIIAusführung in Simulide # +
-  - Öffnen Sie SimulIDE (unter ...\bin\simulide.exe) +
-    - links in SimulIDE sollten Sie den Komponenten Browser finden. Wählen Sie dort ''Micro''>>''AVR''>>''atmega''>>''atmega328'' +
-    - Ziehen Sie den Eintrag ''atmega328'' per Drag and Drop in den Arbeitsbereich (rechter, beiger Teil des Fensters) +
-    - Es sollte nun ein Chip names ''atmega328-1'' dargestellt sein +
-  - Erstellen der Ausgangsschaltung +
-    - Im Programm wurde im auf PortD das 6bit angesprochen. Entsprechend soll auch hier am Port D der Ausgang 6 genutzt werden. Am Chip ist dieser mit D6 gekennzeichnet +
-    - Fügen Sie eine LED (im Komponenten Browser über Output LED) und ein Massepotential ein (Sources Ground) +
-    - Die Komponenten können mit dem Kontextmenu (Rechtsklick) gedreht und gespiegelt werden. Außerdem ist mit der Auswahl von ''Properties'' im Kontextmenu die Änderung von  +
-    - Verbinden Sie die LED mit Masse und mit Port D6. Achten Sie auf die richtige Richtung der LED. Die Verbindungen lassen sich dadurch erstellen, dass auf ein Komponenten-Pin geklickt wird und die Linie zu einem nächsten Komponenten-Pin gezogen wird. +
-  - Flashen der Software  +
-    - Klicken Sie rechts auf den Microcontroller und wählen Sie ''Load firmware'' +
-    - Fügen Sie hier den Pfad und Name des oben erstellten ''Einfuehrung_v01.hex'' ein und öffnen Sie dieses +
-  - Starten der Simulation +
-    - klicken Sie im Menu den Power-on Button {{fa>power-off}} +
-    - Die Simulation startet +
-  - Bugfixing +
-    - vermutlich ist bei Ihnen zu sehen, dass die Diode nicht gleichmäßig an und aus dargestellt wird. Dies ist kein Fehler des Simulationsprogramms. Es wurde noch eine wichtige Komponente vergessen, welche __immer__ bei der Verwendung von diskreten LEDs verwendet werden muss. Fügen Sie diese ein und Testen Sie die Schaltung nochmal+
  
-<--+Autoren : Peter Blinzinger 
 + Prof. G. Gruhler (Hochschule Heilbronn, Fakultät T1) 
 + D. Chilachava (Georgische Technische Universität) 
 + T. Fischer (Hochschule Heilbronn, Fakultät T1)
  
-\\ +Version: 1.3 vom 19.09.2022
-Sie sollten sich nach der Übung die ersten Kenntnisse mit dem Umgang der Umgebung angeeignet haben. Zum Festigen des der Fähigkeiten bieten sich folgende Aufgaben an:+
  
---> Aufgaben# +Hardware: MEXLE2020 Ver1.0 oder höher 
-  - Welche [[Vorgaben für die Softwareentwicklung]] wurden verletzt, trotzdem das Programm lauffähig ist? (Interrupts werden erst in späteren Übungen erklärt) + AVR-USB-PROGI Ver2.0
-  - Wie könnte ein Ampel-Licht-Abfolge oder Lauflicht aus 4 Dioden erstellt und programmiert werden? Welche Optimierungen könnten im Code vorgenommen werden? Welche Komponente in SimulIDE kann genutzt werden? Wie kann die Farbe der LEDs geändert werden? +
-  - Lesen Sie auf Mikrocontroller.net im Kapitel [[https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Warteschleifen_.28delay.h.29|Warteschleifen]] die "erste Seite", also bis: +
  
-<WRAP right 80%> +Software: Entwicklungsumgebung: AtmelStudio 7.0 
-> Abhängig von der Version der Bibliothek verhalten sich die Bibliotheksfunktionen etwas unterschiedlich+ C-Compiler: AVR/GNU C Compiler 5.4.0
-</WRAP>+
  
-<--+Funktion: Auf einem kleinen Lautsprecher (Buzzer) wird nur einem MEXLE-Board   
 + ein sirenenartiger Sound ausgegeben. Zwischen den auf- 
 + und absteigenden Tönen bleibt die Frequenz kurz stabil. 
 + Die Frequenz wird mit dem Timer 0 (im CTC-Mode) erzeugt und  
 + direkt über den Output-Compare-Pin im Toggle-Mode ausgegeben.
  
 +Displayanzeige: +----------------+
 + |- Experiment 2 -|
 + | Creating Sound |
 + +----------------+
  
-</WRAP><WRAP column 35%> +Tastenfunktion: keine
-<code C [enable_line_numbers=1, start_line_numbers_at=1] main.c> +
-/*=============================================================================+
  
-LCD_LIB_de Funktionen fuer die LCD-Anzeige des MiniMEXLE +Jumperstellung: Schalter muss fuer den Buzzer betätigt sein
-=========================================================+
  
-Dateinamelcd_lib_de.h +Fuses im uC: CKDIV8Aus (keine generelle Vorteilung des Takts)
- +
-Bibliothek fuer das LCD-Display des MiniMexle Boards bzw. optimiert für LCD-Display HD44780 +
- +
-Autor: Steffen Freihofer (2006) +
-Adaption: Thomas Pospiech (2007, Timing-Probleme geloest) +
- G. Gruhler, D. Chilachava (2009, Init Ports und Dokumentation) +
- Peter Blinzinger Libary umgebaut für SimulIDE, kompatibel mit dem Mexle2020 Board +
- +
-Version: 1.3 vom 26.04.2020 +
- +
-=============================================================================*/+
  
 +Header-Files: lcd_lib_de.h (Library zur Ansteuerung LCD-Display Ver. 1.3)
  
 +=============================================================================*/ 
 +</sxh> \\ Ändern Sie die folgenden Informationen, je nach Programm: 
 +    - ''Autor'': Der folgende Code basiert auf eine Version verschiedener Autoren, diese sind hier angegeben. Wenn Sie einen eigenen Code generieren sollte hier Ihr Name stehen. Dies ermöglicht eine Nachvollziehbarkeit bei Unklarheiten
 +    - ''Version'': Um die Aktualität der Software zu erkennen sollte mindestens das Datum angegeben und bei Änderung immer aktualisiert werden
 +    - ''Hardware'': Die getestete bzw. verwendete Hardware sollte angegeben werden, um nachvollziehen zu können, wie der Code getestet werden kann. Bei Simulationen sollte hier mindestens der verwendete Chipsatz (z.B. ATmega88) angegeben werden. 
 +    - ''Software'': Zum weiterverwenden des Codes ist die Angabe der Entwicklungsumgebung (engl. integated Development environment [[https://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung|IDE]]) wichtig. Nicht selten gibt es bei größeren Projekten Schwierigkeiten, wenn IDE und Compiler geändert werden.
 +    - ''Funktion'': Die Funktion des Programms sollte kurz erklärt werden. Damit wird dem Leser bereits vor dem Code schon Hinweise gegeben
 +    - ''Display-Anzeige'': Ähnlich der Funktion ist auch eine Darstellung der (erwartbaren) Anzeige sinnvoll.
 +    - ''Tastenfunktion'': Bei zukünftigen Anwendungen kann eine Eingabe von Tastenstellungen sinnvoll sein. Dies sollte hier angegeben werden
 +    - ''Jumperstellungen'': [[https://de.wikipedia.org/wiki/Jumper_(Elektrotechnik)|Jumper]] bieten die Möglichkeit unterschiedliche Schaltungsteile der Hardware zu verbinden oder zu trennen. Damit können Hardwarefunktionalitäten aktiviert oder deaktiviert werden. Wenn verschiedene Jumperstellungen für ein Programm wichtig sind, so sollten diese angegeben werden.
 +    - ''Fuses im uC'': Beim Microcontroller (auch μC oder uC abgekürzt) bieten die Möglichkeit interne Konfigurationen anzupassen. Diese werden über [[https://de.wikipedia.org/wiki/Fuse-Bit|Fuses]] eingestellt werden. Sind hier Funktionen für das Programm notwendig, so sollten diese angegeben werden
 +    - ''Header-Files'': Werden weitere Softwareteile genutzt, so sollten diese über [[https://de.wikipedia.org/wiki/Header-Datei|Header-Dateien]] eingebunden. Diese sollten bereits schon vor dem eigentlichen Codeteil kurz erklärt werden. \\
 +  - Nach der Beschreibung steht im Code der Deklarationsbereich: <sxh c; first-line: 40>
 // Deklarationen ============================================================== // Deklarationen ==============================================================
  
 // Festlegung der Quarzfrequenz // Festlegung der Quarzfrequenz
- +#ifndef F_CPU                   // optional definieren 
-#ifndef F_CPU // optional definieren +#define F_CPU 18432000UL        // MiniMEXLE nutzt einen ATmega88 mit 18,432 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 <util/delay.h> // Definition von Delays (Wartezeiten
-#include <avr/interrupt.h> // globale Interrupts definieren (sei() und cli()) +#include "lcd_lib_de.h" // Funktionsbibliothek zum LCD-Display
-#include <stdint.h> // Definition von Typen (int, char, ...+
-#include <stdbool.h> // Definition von 1-Bit-Variablentypen (bool) +
-#include <util/delay.h> // Definition von Delays (Wartezeiten) +
  
 // Konstanten // Konstanten
- +#define MIN_PER     143          // minimale Periodendauer in "Timerticks" 
-#define CLEAR_DISPLAY 1 // Instruction Code fuer LCD: Loeschen des Displays +#define MAX_PER     239         // maximale Periodendauer in "Timerticks" 
- +#define WAIT_TIME   2000        // Wartezeit zwischen Flanken in ms
- +
-// Port-Bits +
- +
-#define E PD4 // Enable-Signal zum Display: Port D, PD4 +
-#define RS PD7 // Register-Select zum Display: Port D, PD5 +
  
 // Makros // Makros
-#define Datenregister DDRD //Datenrichtungsregister  für Datenport zum LCD (Verwendung der Bits 0 bis 3+#define SET_BIT(BYTE, BIT) ((BYTE) |=  (1 << (BIT))) // Bit Zustand in Byte setzen 
-#define Steuerregister DDRD //Datenrichtungsregister  für Steuerport zum LCD +#define CLR_BIT(BYTE, BIT) ((BYTE) &= ~(1 << (BIT))) // Bit Zustand in Byte loeschen 
-#define P_DATA   PORTD // Port ist Datenport zum LCD (Verwendung der Bits 0 bis 3) +#define TGL_BIT(BYTE, BIT)  ((BYTE^=  (1 << (BIT))) // Bit Zustand in Byte wechseln (toggle)
-#define P_STEUER  PORTD // Port ist Steuerport zum LCD +
  
 // Funktionsprototypen // Funktionsprototypen
 +void initDisplay(void); // Initialisierung Display und Startanzeige
 +void initPorts(void); // Initialisierung der I/O-Ports
 +void initTimer(void); // Timer 0 initialisieren (Soundgenerierung)
 +void init(void); // generelle Initialisierungsfunktion
  
-void lcd_enable (void); +</sxh> \\ Bei den Deklarationen werden Vorgaben gemacht, welche wichtig sind, bevor der Code vor dem eigentlichen Prozessor oder Controller ausgeführt werden. Die Deklarationen weisen den Präprozessor an, bestimmte Vorgaben zu nutzen (Details zu Präprozessor und Compiler-Direktiven sind [[https://de.wikibooks.org/wiki/C-Programmierung:_Pr%C3%A4prozessor|hier]] zu finden). Folgende Punkte sollten mindestens angegeben werden: 
-void lcd_write (unsigned char byte); +    - ''Quarzfrequenz'': Die Taktfrequenz des Microcontrollers kann entweder intern oder extern definiert werden. Diese Frequenz sollte immer angegeben werden. Wird dies nicht vorgenommen, kann es Probleme bei der Handhabung von Wartezeiten ("Delays"geben. In Simulide kann die Frequenz des externen Quarz eingegeben werden - diese sollte zum in der Software angegebenen Frequenz passen. Die Angabe ''#ifndef'' ist hier eine Compiler-Direktive und keine C-Code. Wie alle anderen Deklarationen sind alle Zeilen nach der einem ''#'' __vor__ der Ausführung des Codes im Controller zur Zeit der hexfile-Erstellung im Compiler wichtig. ''#ifndef'' prüft hierbei, ob ein Symbol bereits in einem anderen File definiert wurde. 
-void lcd_init (void)+    - ''Header includes'': Header-Dateien sollten bereits aus der Informatik 2 bekannt sein. Bei IDEs wird häufig zwischen Dateien unterschieden,  welche in den Ordnern der IDE und Dateien, welche im Projektordner liegen. Hier sollen folgende Header-Dateien genutzt werden: 
-void lcd_putc (unsigned char zeichen)+      - ''<avr/io.h>'': Header-Datei, welche Input/Output Bezeichner für Pins und Ports definiert. Da im Folgenden bestimmte Ports angesprochen werden sollen, ist diese Header-Datei wichtig. Die Header-Datei liegt im Unterordner ''avr'' in den Ordnern der IDE. Diese wurde bereits schon im Bespiel [[1_hello_blinking_world]] verwendet. 
-void lcd_putstr (char *string); +      - ''<util/delay.h>'': Header-Datei, welche einen einfachen Umgang mit Wartezeiten ermöglicht. Diese wurde bereits schon im Bespiel [[1_hello_blinking_world]] verwendet. 
-void lcd_gotoxy (unsigned char lineunsigned char pos); +      - ''%%"lcd_lib_de.h"%%'': Diese Header-Datei sollte im Projektordner eingefügt sein. Bei einem neuen Projekt ist sie dies noch nicht. <WRAP right>{{microcontrollertechnik:atmelstudio_addexistingitem.jpg?400}}</WRAP> <panel type="info" title="To Do: notwendige header-Dateien">**Bitte fügen Sie die Datei lcd_lib_de.h in den Projektordner ein** \\ Dazu sollten Sie im Solution Explorer auf das Projekt rechts-klicken (hier ''2. Sound und Timer''>> Add >> Existing Item... (siehe Bild rechts). \\ Die gewünschte Datei (hier: die heruntergeladene ''lcd_lib_de.h''auswählen und mit Add hinzufügen. Die Datei sollte nun im Solution Explorer angezeigt werden.</panel> 
-void lcd_clearDisplay(void); +    - ''#defines'': Über ''#defines'' kann vorgegeben werdenwelcher Text durch den Präprozessor im Code ersetzt werden soll. Damit können Konstanten oder kurze Codeersetzungen (Makrosvorgegeben werden. In diesem Programm soll ein maximale und minimale Periodendauer, sowie eine Haltedauer für den höchsten und niedrigsten Ton vorgegeben werden. Zusätzlich sind drei Standardmakros vorgegeben, um  
-void lcd_clearline (unsigned char line); +      - ein Bit in einem Byte zu setzen (''SET_BIT(BYTE, BIT)''),  
-void lcd_displayMessage(char *stringunsigned char, unsigned char);+      - ein Bit in einem Byte zu löschen (''CLR_BIT(BYTE, BIT)''), oder 
 +      - ein Bit in einem Byte zu invertieren (''TGL_BIT(BYTEBIT)'').  
 +    - ''Funktionsprototypen'': Wie regulär bei der C-Programmierung sollten die verwendeten Funktion dem Compiler bekanntgemacht werden. \\ 
 +  - Als nächstes folgt das Hauptprogramm:<sxh cfirst-line: 69>
  
- +// Hauptprogramm ============================================================== 
-// LCD-Ansteuerfunktionen ===================================================== +int main()
- +
-// ---------------------------------------------------------------------------- +
-// LCD_ENABLE: Erzeugt einen HIGH-Impuls des Enable-Signals +
-// ---------------------------------------------------------------------------- +
- +
-void lcd_enable (void)+
 { {
- P_STEUER |= (1 << E); // E=1   1  +-+ init();                     // Ports und Timer 0 initialisieren 
- _delay_us (1); + initDisplay();              // Display aktivieren 
- P_STEUER &= ~(1 << E); // E=0   0--+ +---+  
 + while(1)                    // Start der unendlichen Schleife 
 +
 + for (OCR0A=MAX_PEROCR0A>MIN_PER; OCR0A--) // Frequenz erhöhen 
 +
 + _delay_ms(10);                          // in Schritten von 10ms 
 +
 + _delay_ms(WAIT_TIME);                       // Wartezeit hohe Frequenz 
 + TGL_BIT(PORTB,PB2); 
 +  
 + for (OCR0A=MIN_PER; OCR0A<MAX_PER; OCR0A++)  // Frequenz absenken 
 +
 + _delay_ms(10);                          // in Schritten von 10 ms 
 +
 + _delay_ms(WAIT_TIME);                       // Wartezeit niedrige Frequenz 
 + TGL_BIT(PORTB,PB2); 
 + }                           // Ende der unendlichen Schleife
 } }
 +</sxh> Das Hauptprogramm besteht aus folgenden Teilen:
 +    - **Initialisierungsteil**: Zu Beginn werden einmalig-abzuarbeitende Programmteile ausgeführt. Darunter fällt insbesondere die Konfiguration der Hardware. Für die Ausgabe eines Signals muss das Direction-Register vorbereitet werden. Zusätzlich muss das Timer-Counter-Modul für die Ausgabe eines Wechselsignals (Pulsweiten-moduliertes Signal, PWM-Signal) vorbereitet werden. Diese wird über die Unterfunktionen ''init()'' und ''initDisplay()'' vorgenommen
 +    - **Endlosschleife**: damit ein Programm vom Microcontroller dauerhaft ausgeführt wird, muss dies in einer Schleife eingebunden sein. Diese wird durch das Konstrukt ''while(1){''...''}'' vorgegeben.
 +    - In der Endlosschleife sind scheinen die Zeilen 77..82 und 84..89 ganz ähnlich auszusehen. 
 +      - Dort wird zunächst in einer for-Schleife das Register ''OCR0A'' von der maximalen Periodendauer ''MAX_PER'' zur minimalen ''MIN_PER'' heruntergezählt und beim Zählschritt jeweils 10 Millisekunden gewartet (''_delay_ms(10)''). Wie im Video dargestellt, bietet es sich an für die Details zum Output Compare Register (''OCR0A'') den entsprechenden Teil des [[https://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48_88_168_megaAVR-Data-Sheet-40002074.pdf|ATmega88]]-Datenblatts durchzulesen. Als leichten Einstieg kann auch die [[https://www-user.tu-chemnitz.de/~heha/viewchm.php/hs/ATmegaX8.chm/|deutsche Übersetzung des ATmega88-Datenblatts]] per Index nach ''OCR0A'' durchsucht werden.
 +      - Nachdem bis zur kürzesten Periode gezählt wurde, soll der höchste Ton die Dauer von ''WAIT_TIME'' Millisekunden gehalten werden. 
 +      - Der Zustand der LED soll dann gewechselt werden.
 +      - In den Zeilen 84..89 ist das gleiche für eine länger werdende Periodendauer eingefügt. Der einzige Unterschied besteht darin, das in der for-Schleife nun herauf statt herunter gezählt wird. \\
 +  - Nach dem Hauptprogramm sind die Unterfunktionen aufgelistet: <sxh c; first-line: 93>
 +// Funktionen =================================================================
  
- +// Generelle Initialisierungsfunktion 
-// ---------------------------------------------------------------------------- +void init()
-// LCD_WRITE: Schreibt ein Byte im 4-Bit-Modus in das LCD +
-// ---------------------------------------------------------------------------- +
- +
-void lcd_write (unsigned char byte) // Ausgabewert 8 Bit in "byte"+
 { {
- unsigned char temp; // Definition lokale Variable "temp" + initPorts(); // Ports auf Ausgang schalten 
- + initTimer(); // Timer zur Sounderzeugung starten
- temp = byte; // Ausgabewert zwischenspeichern +
- +
- P_DATA &= 0xF0; // Untere 4 Bit auf Datenport loeschen +
- P_DATA |= (temp>>4); // Ausgabewert 4 Bit nach rechts schieben +
- //    oberes Nibble auf Daten-Port LCD schreiben +
- +
- lcd_enable(); // Erzeugung Enable-Impuls zur Datenspeicherung +
- // keine Wartezeit zwischen Nibbles notwendig +
- +
- byte &= 0x0F; // Unteres Nibble Ausgabewert extrahieren +
- +
- P_DATA &= 0xF0; // Untere 4 Bit auf Datenport loeschen +
- P_DATA |= byte; // unteres Nibble auf Daten-Port LCD schreiben +
- +
- lcd_enable(); // Erzeugung Enable-Impuls zur Datenspeicherung+
 } }
  
- +// Initialisierung der I/O-Ports 
-// ---------------------------------------------------------------------------- +void initPorts()
-// LCD_INIT: Initialisiert das LCD  +
-// ---------------------------------------------------------------------------- +
- +
-void lcd_init (void)+
 { {
- cli(); //globale Interrupts deaktivieren + DDRB |= (1<<DDB2); // Port BPin 0 (zur LED) auf Ausgang 
- + DDRD |= (1<<DDD5); // Port DPin 5 (zum Buzzer) auf Ausgang
- Datenregister |= 0x0f; // Bit 0..3 (LCD-Daten) auf Output +
- Steuerregister |= ((1<<E) | (1<<RS)); // Bit RS: LCD Register Select und Bit E: LCD Enable auf Output +
- P_DATA |= 0x0f; // Port, Bit0..3 (LCD-DatenSET  +
- +
- // Steuersignale auf LOW +
- P_STEUER &~((1<<E) | (1<<RS)); // E und RS auf 0 setzen +
- _delay_ms (50); +
- +
- // Display in 4-bit Modus initialisieren +
- P_DATA &= 0xF0; +
- P_DATA |= 0x03; +
- lcd_enable(); +
- _delay_ms (10); +
- lcd_enable (); +
- _delay_ms (10); +
- lcd_enable (); +
-  +
- P_DATA &= 0xF0;//0xF1; +
- P_DATA |=0x02; +
- _delay_ms (2); +
- lcd_enable(); +
- _delay_us (50); +
-  +
- // 2 Zeilen, 5 x 8 Pixel +
- lcd_write (0x28)+
- _delay_us (40); +
-  +
- // Display einschalten +
- lcd_write (0x0C); +
- _delay_us (50); +
-  +
- //P_DATA &= 0xF1; +
- //lcd_enable(); +
- //_delay_us (50); +
-  +
- // Cursor auf "increment mode" schalten +
- lcd_write (0x06);//(0x02); +
- _delay_us (50); +
- +
- // Display loeschen (funktioniert nur, wenn es 2x aufgerufen wird) +
- lcd_write (0x01); +
- _delay_ms (3); +
- lcd_write (0x01); +
- _delay_ms (3); +
- +
- sei(); // globale Interrrupts aktivieren+
 } }
  
- +// Intialisierung des Timers 0 fuer Sounderzeugung 
-// ---------------------------------------------------------------------------- +void initTimer()
-// LCD_PUTC: Schreibt ein Zeichen an die entsprechende Speicherstelle +
-// ---------------------------------------------------------------------------- +
- +
-void lcd_putc (unsigned char character) // Ausgabewert 8-Bit in "character"+
 { {
- P_STEUER |= (1<<RS); // Register Select auf HIGH: "Daten ausgeben" + TCCR0A = (1<<WGM01) |(1<<COM0B0); // CTC Mode waehlen und Toggle Mode nur für OC0B aktivieren 
-  + TCCR0B = (1<<CS01 | 1<<CS00); // Timer-Vorteiler /64
- lcd_write (character); // Zeichen ausgeben+
  
- _delay_us (55); // Verzoegerung 55 us (interne Verarbeitung)+ OCR0A = MAX_PER; // Start mit tiefstem Ton
 } }
 +</sxh> 
 +    - ''void init()'': Bei längeren Programmen bietet es sich an eine übergeordnete init-Funktion anzulegen, aus welcher die einzelnen Initialisierungen von Sensoren und ähnlichem aus aufgerufen werden. 
 +    - ''void initPorts()'': In dieser Funktion werden die Data Direction Register der Ports B und D korrekt zugewiesen. 
 +    - ''void initTimer()'': für das Timer Modul muss der gewünschte "Clear Timer on Compare" Modus und Hardware-Vorteiler gewählt werden. \\ Mit dem Teiler $r_{\rm prescaler}=64$ ergibt sich für die Timer-Schritte pro Sekunde: \\ \begin{align*} f_{\rm Timer}= f_{\rm Quarz} / r_{\rm prescaler} = 18'432'000 ~\rm Hz / 64 =288'000 ~\rm Hz \end{align*} Da mit ''COM0B0 = 0'' ein Invertieren des Ausgangs eingestellt wurde, wäre die höchste ausgegebene Frequenz $f_{\rm out, max}= f_{\rm Timer}/2 = 144'000 ~\rm Hz$. \\ Diese würde sich ergeben, wenn der Timer angewiesen würde nur einen Schritt zu zählen. Für eine Frequenz von $f_{\rm out}= 1'000~\rm Hz$ muss ''OCR0A'' wiefolgt gesetzt werden: \begin{align*} {\rm OCR0A}=f_{\rm out, max}/f_{\rm out}-1=144'000 ~\rm Hz / 1'000~\rm Hz - 1= 143 \end{align*}  Dies entspricht gerade ''MIN_PER = 143''. \\ \\ 
 +  - Ansprechen des Displays: <sxh c; first-line: 118>
  
- +// Initialisierung der Display-Anzeige 
-// ---------------------------------------------------------------------------- +void initDisplay() // Start der Funktion
-// LCD_PUTSTR: Schreibt einen String auf das LCD +
-// ---------------------------------------------------------------------------- +
- +
-void lcd_putstr (char *string) // Pointer auf String in "string"+
 { {
- while (*string) // solange nicht Stringendezeichen 0x00 + lcd_init(); // Initialisierungsroutine aus der lcd_lib 
- { +  
- lcd_putc (*string); // Zeichen aus String holen und ausgeben+ lcd_gotoxy(0,0);         // Cursor auf 1. Zeile, 1. Zeichen 
 + lcd_putstr("- Experiment 2 -"); // Ausgabe Festtext: 16 Zeichen
  
- string ++; // Pointer auf naechstes Zeichen setzen + lcd_gotoxy(1,0);         // Cursor auf 2. Zeile, 1. Zeichen 
- + lcd_putstr(" Creating Sound "); // Ausgabe Festtext: 16 Zeichen
-}+
  
 +} // Ende der Funktion
 +</sxh> In der Funktion ''void initDisplay'' wird das Display angewiesen Daten auszugeben
 +    - ''lcd_init()'': Diese Unterfunktion sollte immer ausgeführt werden, bevor das Display angesprochen werden soll. 
 +    - ''lcd_gotoxy(x,y)'': Diese Funktion weist das Display an die kommende Ausgabe an der Position x,y auszugeben.
 +    - ''lcd_putstr(string)'': Gibt einen vordefinierten Text an der aktuellen Position aus.
  
-// ---------------------------------------------------------------------------- +<-- 
-// LCD_GOTOXY: Verschiebt den Curser an die angegebene Position +--> IV. Ausführung in Simulide # 
-// ----------------------------------------------------------------------------+  Geben Sie die oben dargestellten Codezeilen nacheinander ein und Kompilieren Sie den Code. 
 +  Öffnen Sie Ihre hex-Datei in SimulIDE und testen Sie, ob diese die gleiche Ausgabe erzeugt
  
-void lcd_gotoxy (unsigned char line, unsigned char pos) +<-- 
-{ +\\ 
- P_STEUER &= ~(1<<RS); // Register Select auf LOW"Control ausgeben" +Sie sollten sich nach der Übung die ersten Kenntnisse mit dem Umgang der Umgebung angeeignet haben. Bitte arbeiten Sie folgende Aufgaben durch:
-  +
- lcd_write((1 << 7) + 0x40 * line + pos); // Adresse Cursor in DDRAM-Adresse +
  
- _delay_us (50); // Verzoegerung 50 us fuer Interne Verarbeitung  +--> Aufgaben# 
-}+  - Klicken Sie mit rechter Maustaste bei ''main()'' auf ''WAIT_TIME'' und dann auf Goto implementation. Sie werden feststellen, dass der Cursor auf die Deklaration des Wertes springt. Versuchen Sie selbiges bei ''initDisplay'' an ''lcd_putstr'' und wählen Sie die Variante, welche ein ''**{...}**'' angefügt hat. Hier sehen Sie die den Code in der header-Datei, der für die Übergabe des Strings an das Display verantwortlich ist. Dort kann in gleicher Art ''lcd_putc'' und ''lcd_write'' weiterverfolgt werden. In ''lcd_write'' und ''lcd_enable'' wird die Übergabe der Werte an das Display abgearbeitet.  Dazu werden zunächst die Daten am Datenport ausgegeben und anschließend die Steuerleitung gepulst aktiviert. \\ Verfolgen Sie ''lcd_gotoxy'' nach. Wie wird das übertragen? 
 +  - Wieso wird an Pin B5 überhaupt was ausgegeben? Im Programm wird doch nirgends PORTB gesetzt, oder?  
 +    - Versuchen Sie mit dem [[http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-9365-Automotive-Microcontrollers-ATmega88-ATmega168_Datasheet.pdf#page=75|Datenblatt]] (Seite 75ff insbesondere Kapitel 12.4) herauszufinden wie das funktioniert.  
 +    - Prüfen Sie dazu im Datenblatt auch nach, was an Pin B5 noch für Funktionen hängen (Kapitel 1. Pin Configurations). 
 +    - Warum wird zwar ''OCR0**A**'' als Vorgabe genutzt, aber ''OC0**B**'' als Ausgabe gewählt (siehe Zeile: ''TCCR0A = (1<nowiki><<</nowiki>WGM01) |(1<nowiki><<</nowiki>**COM0B0**)'')? 
 +  - Wie ist es möglich bei aufsteigender und abfallender Frequenz einen entsprechenden Text am Display auszugeben? Ändern Sie den Code geeignet. 
 +  - Versuchen Sie das Programm so zu variieren, dass es ein Martinshorn ausgibt. Suchen Sie dazu zunächst die benötigten Frequenzen und ändern Sie das Programm passend ab. 
 +  - Können Sie eine kleine Melodie ausgeben? Versuchen Sie z.B. "Alle meine Entchen", oder eine Melodie ihrer Wahl.
  
 +<--
  
-// ---------------------------------------------------------------------------- 
-// LCD_CLEARDISPLAY: Loescht den gesamten Display-Inhalt 
-// ---------------------------------------------------------------------------- 
  
-void lcd_clearDisplay(void) 
-{ 
- P_STEUER &= ~(1 << RS); // Register Select auf LOW: "Control ausgeben" 
-  
- lcd_write(CLEAR_DISPLAY); // Befehlscode an Display ausgeben 
  
- _delay_ms (2); // Verzoegerung 2 ms fuer interne Verarbeitung 
  
-}+  * Diese [[https://www.falstad.com/circuit/circuitjs.html?ctz=CQAgzCCsB0AsBMkywOz3egDNgjAUwFoBOEHaFbeTMIo2bOzeKTKEWCSQnHAKACUQrWAA4QBHGABs7MThDMcIjlWwLokdZtaYNvKilJUFI1jkywTYywGEAyvF4AZI63inX4CwqEgAZgCGADYAznhsmM6kkMzuZjFelsysgaHh2vqYhjgJcaTSVuwg9nwGpMomZlJi7tbFdpEuSkkezYk+8qlhEbwA7uUtZhVUYpEAsiBSUoOT0+2xei4iYLEey8xg3sn+wd0ZZeuVICI4MrVFADohKLwAHscc4KggRIjgkMIKlgDyNvyYAEFMoZlDU1itCpYrlIoqCjnDNklfF10kJYR48iIPIiOjs0j0Dhi1nNzlCQrBgccSWtRJCQFdILDqawRHMcdsUT0XK8wawefNkbtUZEyvy8kQcKs6ldSlkXrAZmKsZcQo15YqFQLOkKuS9JUcJRstqQ8Xs0aL9ZiiGdlWTHAdrfCidKQmBYY6rTJ2YL8RkJtU3B4AwL4HoJihLR4I0akaHGf6PUHHd647xw1JA6wUBmQ2GQChs0cC17janw5q8ihNSm82hefn3LnGS5pFVWGACqc3CbORl7lJIJoOyQUBDkMwkpYACo2AByU7VOUUOckMi7PhSOoyTQSc1XkyRm99aP6NGYBFp8AhF9GfQU18vELmkXutHANFIRCHCCK8GnNj+TAACE72jWQXhzWlIn6ChLEgGQv2YeCT0mR05joSxnzvaoxDQF4CjwyJBFZSwCExDwyI8HR2FYbRfF0Rk2iXA9P2YPdwF4U5JxYp8kgsEhzAiNg6Lo2i2E5aDokUQtmPXSTmMdPDHXkhIeGYVp9UkvCcE1VpNUkvTLA05I71kxtlUlW9+gs8y5ELAy7JkbT7NM1TNUdHTLEkjz3LOTArIghR-IbIKAuYtYWR0O8IuOYQAr-ULfBGFC3GCuKUvAjwoNc1Z4liU4UOY+ACtUBQCsk0rir81L4pK4KqoUBKKpKhLJTcJrTOMdBLDao5vLcyxEKgGRvMgsRrTMRtRsm8aKkslDrTEAhZtIgLFtIBDqnENbCxW44FsLBKiF2haKghIhhi80DjHoF4KlurTG3Os6TJggojsOq6YM1Ar1vKzipmOArKJZBKQaC2ASBEXgAEJigAewAWwABwCAAnAIABd4bR3wAElMAAGiuPGcGJkI8fgcm8bAcmACkiauOmyaZqmmYgABFBGUfRrGcaEbBBewC4AEccAuAA7QXzFwUXxalzAZcVzA5cl3AZZ4VWpaVmWteV8wDb1nh1ZVsW1Z4A3NbNiWdcFrWNY1+39eVp2LcV8XreN93hc9y3Dd9v3Tfli2Q49+WAH5I6jyPRZViXMj2gglNecRtO51GMex3GRWCi7MMGlP2JsJGM753HGX6Q0vj5fUbwWxtxQbrDK+8C8+S2bLK8jGvYmQgyPWQkRHQICEHKWhKsRqZuXgb2kiA7gKsUzY41kXpSZBEPD4GnzfYjmEiFB3kl9+ZFC4UxS8++iy+N5JK-rLv2+eu8AyIUxN-O+OD+xBEZC-0Xv+tJf5rk0pxD4pALCjAgYRE02wK4QOvHISB21CrIKQRCMK1B1IILYl9SYyp-74Nwq9WYk4xA4S+AFKYMxqGUJQlIAeMgGFMLwcGRATDGH0KJKwNh99UJnDmMwvqoEtiCI9NPWCw18yiLwWBSs+pP51kPpYJReRHpuDmKoiRN0sxdW0TUZCSjR7XQMU5CsfCqwzEsQoCx70VF2ICtmZeTi6FaQrLdax-0yiqKjJGOobpvEVijA3W0ChKTFiLDmUk5o5QuMrEEuospDBCLyGw0JjJvHd34XSCkZQ0k8OpHUGEeTT7TDBHUG4lctroQqNPdayp1p1N2nyCoVE7zHU2i8Zpp1n6DQqMpaKyE1J3R6qAh+vSRkQLwbvQKHTAoORZONLaypRpLSUhUJOJD1p122YRdphYCDITzuIPhcy25dJkIcka7SNnPVIg9aKyoyJ9NIh1ayw87niGMS3e5fIDkPJgjoqAhYAXAq9MwIxJDIAbIKpAA5-1+jQu4ki8QCKoApzrnCy5n8UUJVHGcPBkAMW0iJcuFCpKNr5h+tcxF91cIKICiiklrSoqIpToY7wfCUUeCxbFclKdhkUr4RmHhmE0KsOVHhDMxDCpXnPK0eAw82n9B4O9IZ+41GdTfnuOV4g3muA0T1XV28rplDasvHgwxQk2G+GMQEi4NUaQKN6I8Zoc7ZEdWYXq0SbV2oBHwJolUFVqG9NqY88kg2TTUCatE9wLYkGQJNHITwIDcRnIBIEExJCajImoSQGzKpaE6sDHVw8sI5DXIqy5rQwC11aFASkB8JDLKeacOoM55wqxCAAN2CAAVzwJSBUNRbrDoUHhSwABjIIeB0aUl1XXZKdcp1BAANYLiHbSZt7AwYFUsAAEwAJZo14NAEAABVZGAAReGvQJbFz7RLTGeA0YiCAoezGvgICCUkCAAARvDTG2NEbsEGuAYoTgADSG4fAc3bF+kAHN5DJvkJzRQJANiIYgFecDnMWhFE5kOTg4GOZeiYSRwwsB5CGAgPwAAonYNgGGQDY2RuwCAYgIDnoAAqTFgSAOmkGABiQRD3IxE-DZGdGgiIxlFceAcnXRXFgAyC4aM8YS27S+59aNpOyZCFIK4KA1MAglvugA4ljPAemjPKauCINT3w0aWefTZkIDmQiShlOLNGpmLNWbc2AaEMoFNoycPDAA5oeydGnkZ9sxm5nzfmXPWZkzKSAIWZQqbRk5lLiWgueZU55lWvmzN5bS+5mUhnPNBdK-51zFWcBECyzKBzOXnMBca8ZzzHnmt1fK-pyQ8mu04GM2FyL0XvjxbiwlirtXwtRcnVNzGM3EsZbRoJkTYmJNSca+LEICnPP7ZyFV1TG3hOifE0ESTiWu2HfMDKZrB2u3rc25dnbbmnuHa+wVv8Z3kudcG91v7B2fO5cB-J-b6B5PrYBw1-TV5WvydC297b13dsI4ywdmH8mPOKv+2ViHoP5NfcM+1gb8nqvwG65sEzhP4e4+R-JsbqOrs3bm3dq4tPXQFeQAT+rqWEfVb566MHHWGei654dsAsP6eC6579mnKOLto-Z-pmX8mudY+kFz7rsuBeBf22AGnbXwcS7AB5mgymStw-l66YX0u+us4+xV+gmvyRdqo8pw762FuTem-FtziPxuLeW6txrfW-dLYD7N9XZOo9h8D67nzCeY+BfmxN6PK2k8I7a7btzXv7cK8ZwdgrTX0tc+U7V2cOMKfkiN8L37eOy9PZO0p8kmELhXC7SrbvGgu8hCx+LTXqnVOeYHwp0fg+5Mj9VAPrHk-x9XBRPPgfI2J9r9X0v7HU+h8b93zPnfc+x-D6Pxlk-+-p9j8X3GWft+DOb4f934Lz-t+L-P9Pt-q+L+z975-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-eSWye-SBLJYVRaVJfkFIK9VII9RFeAAKgkPQNZdBZJAqHlKBggyhGOsxGOjUShHsTCXsXXJJPg7SGOgQ3eBSoKjJGMmCm3ZhLkXgscp5C8ANAtHkYNNSnuRhBtC0nLRwwRMwBpWuC5JXJ2IWAw0I5MMFFKkXeI+MeidQ3I1pA4vmFEoou4lmJ9HuREtg1o8qnqOePOUtJ-EPDaCyOItMmYyvFPOY0xQhJaKck3INLPGtJaLdJw9g95Go+qMIpcSgEPApUOIrO8I9bJVkJKeYBvDwIfCZPDKQAWDBvQG+LoFIG8LoELB0vBCkx0HE26DE6NoeDRBdBENAMhqQLwEAA|Falstad Schaltung]] skizziert die Struktur des Timer/Counters im CTC Mode
  
- 
-// ---------------------------------------------------------------------------- 
-// LCD_CLEARLINE: Loescht den Inhalt einer Display-Zeile 
-// ---------------------------------------------------------------------------- 
- 
-void lcd_clearline (unsigned char line) 
-{ 
- switch(line) 
- { 
- case 0: lcd_gotoxy(0,0); // Beginn erste Zeile addressieren 
- lcd_putstr ("                "); // Leerzeichen ausgeben 
- break; 
- 
- case 1: lcd_gotoxy(1,0); // Beginn zweite Zeile addressieren  
- lcd_putstr ("                "); // Leerzeichen ausgeben 
- break; 
- } 
-} 
- 
- 
-// ---------------------------------------------------------------------------- 
-// LCD_DISPLAYMESSAGE: Anzeige einer Stringvariablen auf dem Display 
-// ---------------------------------------------------------------------------- 
- 
-void lcd_displayMessage(char* mess, unsigned char line, unsigned char pos) 
-{ 
- lcd_gotoxy(line,pos); // Cursor positionieren 
- lcd_putstr(mess); // String ausgeben 
-} 
-</code> 
- 
-<WRAP right><panel type="default">  
-<imgcaption pic1| einfache Diodenschaltung in SimulIDE> 
-</imgcaption> 
-{{drawio>SimulIDE_einfache_Diodenschaltung}} 
-</panel></WRAP> 
-</WRAP> </WRAP>