lehrmaterial zu den lehrveranstaltungen ... · mit dem sensor-aktor-modul 11 ... in diesem...
Post on 11-Mar-2019
220 Views
Preview:
TRANSCRIPT
Technische Universität Ilmenau Fakultät für Maschinenbau Dr.-Ing. M. Braunschweig
Lehrmaterial zu den Lehrveranstaltungen "Mikrorechnertechnik" bzw. "Programmiersprachen"
im SS 2016
Zielstellung: Programmieren mit C++
Inhalt Seite
Microsoft Visual Studio 2015 Hilfestellung und erste praktische Schritte zur Einarbeitung in das Microsoft Visual Studio 2015
2
Hardwarebeschreibung des Sensor-Aktor Moduls
Überblick über die Hardware des im Seminar verwendeten Sensor-Aktor-Moduls
6
Funktionsbibliothek zur Steuerung des Sensor-Aktor-Moduls
Beschreibung der Funktionen zur Kommunikation mit dem Sensor-Aktor-Modul
11
Aufgabe 1: C-Dateiarbeit
Das Einlesen und Abspeichern von Textdateien und Binärdateien sind immer wiederkehrende Aufgaben für Programmierer. In diesem Versuch sollen die Grundlagen der Dateiarbeit anhand der Bearbeitung einer beispielhaften Messwertdatei vermittelt werden.
13
Aufgabe 2: Tonerzeugung
In diesem Praktikum sollen Hardwarekomponenten des PCs, speziell der Zähler-/Zeitgeberschaltkreis (CTC) angesprochen werden. Ziel ist die Erzeugung von Tönen über den PC-Lautsprecher.
14
Aufgabe 3: Peripheriesteuerung mit dem Sensor-Aktor-Modul
Der Versuch soll die Aspekte der Hardwareprogrammierung von Peripherie-Baugruppen am Beispiel des Sensor-Aktor-Moduls verdeutlichen.
17
Aufgabe 4: Klassen in C++ und Nutzung des .NET-Frameworks
C++ bietet einen objektorientierten Programmieransatz. Unter Verwendung des .NET-Frameworks soll dieser Versuch auf die Verwendung von Klassen und Objekten eingehen.
18
Demoprogramme C++ - Demoprogramme und Syntax-Hinweise 22
2
C++ Programmentwicklung mit Microsoft Visual Studio 2015 Einführung
Start:
Jedes Programm besteht aus mehreren Dateien, die in einem Projekt zusammengefasst werden. Mehrere Projekte werden in einer Solution abgespeichert. Also muss zuerst ein neues Projekt angelegt werden. Die dazu notwendigen Arbeitsschritte sind: File NewProject Wie abgebildet, ist "Visual C++ - General" und "Empty Project" auszuwählen.
Name: Ein selbst gewählter Projektname, hier z.B. Volumen Location: Bitte hier unbedingt C:\Kopie eintragen. Solution name: Visual Studio schlägt hier automatisch den Projektnamen vor. Das lassen wir so. Weiter: "Ok". Hinweis zu den entstehenden Verzeichnissen: Mit dem Anlegen des Projektes wird in C:\Kopie das Verzeichnis Volumen erzeugt. Dieses Verzeichnis heißt Solutionverzeichnis. Innerhalb des Solutionverzeichnisses liegt ein Verzeichnis, das ebenfalls den Namen Volumen hat. Dies ist das Projektverzeichnis. Ein wichtiges Fenster im Visual Studio ist der Solution Explorer. Im Solution Explorer ist die entstandene Struktur zu erkennen: Es gibt eine Solution, die ein Projekt enthält. Noch sind alle Unterordner im Solution Explorer leer (siehe Abbildung).
TU Ilmenau, Fakultät für Maschinenbau 22.03.2016
3
Im nächsten Schritt werden die Quellcodedateien (Source Files) zum Projekt hinzugefügt. Im ersten Beispiel ist das die vorbereitete Beispieldatei VOLUMEN.CPP. Die Datei steht im Verzeichnis "Aushang\VisualC++". Wir kopieren die Datei in das gerade neu entstandene Projektverzeichnis "C:\Kopie\Volumen\Volumen" und addieren die Datei VOLUMEN.CPP zu den Source Files des Projektes (Rechter Mausklick auf Source Files).
Durch Doppelklicken auf die Datei VOLUMEN.CPP im Solution Explorer wird der Editor geöffnet und die Datei angezeigt. Dann kann die Datei VOLUMEN.CPP editiert, kompiliert und gebunden werden. Starten Sie das Programm über Debug Start Without Debugging (Ctrl+F5) oder Debug Start Debugging (F5)!
4
Programmieraufgabe "Rechteck":
1. Ausgabe des Textes "Ich lerne C++" auf dem Bildschirm 2. Erstellen einer Funktion Rechteck(), an die die Seitenlängen als double-Zahlen
übergeben werden und die den Flächeninhalt eines Rechtecks berechnet und zurückgibt 3. Einlesen der Seitenlängen über die Tastatur 4. Aufrufen der Funktion Rechteck() in der Funktion main() 5. Anzeigen des Flächeninhalts auf dem Bildschirm
Im zweiten Beispiel wird ohne Musterdatei gearbeitet. Alles wird neu angelegt. Wir bilden zunächst ein ganz neues Projekt mit dem Namen "Rechteck". Dazu sind die Schritte zum Anlegen des Projektes wie im ersten Beispiel zu verwenden. Neu ist die Eingabe des Quellcodes (des Programms). Ein Programm steht in einer Datei. Also muss eine neue Datei angelegt werden. Der Dialogaufruf zum Öffnen einer neuen Datei erfolgt durch Auswahl des Ordners Source Files im Solution Explorer und Wählen von Add New Item im Kontextmenü (Drücken der rechten Maustaste).
Zu wählen ist als File Typ: C++ File und ein File Name: hier z.B. Rechteck. Die Dateinamenserweiterung (.cpp) wird automatisch angehängt. Ist das Programm fertig eingegeben, wird der Menüpunkt "Build" gewählt, und durch Anwahl des Unterpunktes "Build <Projektname>" das Programm fertig erstellt. Nach einem Compile- und Link-Prozess entsteht das Programm - hier Rechteck.exe. Der Projektname ist also auch der Programmname.
TU Ilmenau, Fakultät für Maschinenbau 22.03.2016
5
Aufgabe zur Einarbeitung Tastatureingabe, Bildschirmausgabe, Formelberechnung, Datentypen Für ein Kreissegment mit dem Radius r und dem Winkel α ist der Flächeninhalt A zu berechnen (siehe Skizze). Über die Tastatur sollen eingegeben werden:
Radius des Kreises r in m
Winkel für Kreissegment α in Grad. Die Eingabe soll solange wiederholt werden, solange ein Winkel größer als 180° eingegeben wird. Die Fläche A in m² soll nach folgender Formel (α in rad) berechnet und auf dem Bildschirm angezeigt werden.
𝐴 =𝑟2
2∙ (𝛼 − sin( α))
6
Hardwarebeschreibung des Sensor-Aktor-Moduls
Bild 1: Sensor-Aktor-Modul Oberseite ohne Gehäuse Bild 1 zeigt das im Seminar verwendete Sensor-Aktor-Modul (SAM). Im Bild 2 werden die wichtigsten Baugruppen, die in den Seminaren angesteuert werden, aufgezählt und die zur Verfügung stehenden C-Funktionen genannt.
Bild 2: Baugruppen des Sensor-Aktor-Moduls
ADC DIO (Ports)
I2C
USB
PC
OpenSAM() CloseSAM() WriteValue() ReadValue() ReadData() WriteData()
8 LEDs 8 Schalter
Mikrocontroller XE167 Infineon
Potentiometer
Gleichstrommotor mit Endstufe und Encoder
ADC – Analog/Digital Converter DIO – Digital Input/Output I2C – serieller Bus
Helligkeitssensor
Per
iph
erie
kom
po
nen
ten
Schrittmotor mit Endstufe und Lichtschranke
Lautsprecher und Verstärker
Beschleunigungssensor Barometer
Poti
TU Ilmenau, Fakultät für Maschinenbau 22.03.2016
7
Das Sensor-Aktor-Modul arbeitet wahlweise in einer von vier Betriebsarten (siehe Tab. 1). Nach dem Einschalten ist die Betriebsart 0 (Analog) voreingestellt. Zur Nutzung des Gleichstrom-motors z.B. muss auf die Betriebsart 3 umgeschaltet werden. Hinweis: Die Umschaltung dauert ca. 1s, d.h. ihr Programm kann erst fortgesetzt werden, wenn der eingelesene Status (siehe Tab. 1) auch die gewählte Betriebsart zurückliefert. Schalter, LEDs und die Sensoren können unabhängig von der Betriebsart benutzt werden. Display des Sensor-Aktor-Moduls Hinweis: Beachten Sie nach dem Einschalten bitte die Anzeige auf dem Display. Drehen Sie, wenn nötig, am Potentiometer zum Verlassen des Diagnosemodus. Das Display dient zur automatischen Zustandsanzeige. Stromversorgung Die Stromversorgung des Sensor-Aktor-Moduls erfolgt über die USB-Schnittstelle. Die Betriebsspannung Ub ist nicht konstant und hängt vom USB-Anschluß und von der konkreten Belastung durch die Hardware ab. Die aktuelle Betriebsspannung Ub wird auf dem Sensor-Aktor-Modul mit Hilfe einer bekannten Referenzspannung bestimmt und kann abgefragt werden. A/D – Wandlung
Analoge Spannungen werden zur Verarbeitung im Rechner mit Hilfe eines A/D-Wandlers in digitale Größen umgewandelt. Die analogen Spannungen werden in Abhängigkeit von der Bitbreite des Wandlers auf einen bestimmten Wertebereich abgebildet. Im Sensor-Aktor-Modul wird ein 10Bit A/D-Wandler verwendet. Damit beträgt der Wertebereich 0…1023. Der Wert 1023 entspricht der Betriebsspannung am Sensor-Aktor-Modul.
Bild 3: Wertebereich für die 10Bit A/D-Wandlung
Analoge Spannung U
Dig
ital
er A
/D-W
ert
AD
0
1023
Ub
ADx
Ux
8
Gleichstrommotorsteuerung und Encodernutzung am Sensor-Aktor-Modul Die Baugruppe Gleichstrommotorsteuerung des Sensor-Aktor-Moduls soll im Folgenden näher erläutert werden.
Bild 4: Prinzip der Gleichstrommotorsteuerung
Der Mikrocontroller erzeugt mit Hilfe einer Capture-Compare-Einheit ein pulsweiten-moduliertes Signal (PWM) für die Motorendstufe (siehe Bild 4). Die Hardware wurde so konfiguriert, dass die Pulsweite PW in 4096 Stufen eingestellt werden kann, bei Pulsweite PW = 0 liegt die negative Betriebsspannung -Ub am Motor an und bei Pulsweite PW= 4095 liegt die positive Betriebsspannung +Ub am Motor an (siehe Bild 5). Die Periodendauer T beträgt 4095 Zeiteinheiten = ca. 50µs, so dass sich auf Grund der Motorinduktivität ein Stromverlauf im Motor entsprechend der roten Linie im Bild 5 einstellt.
i,u
tTPW
Ub
-Ub
i,u
t
T
PW
Ub
-Ub
Bild 5: Klemmenspannung und Stromverlauf am Motor bei Ansteuerung mit zwei verschiedenen PWM-Signalen, T=4095 Zeiteinheiten Fall a: PW>2048 (>50% von T), Motor dreht sich vorwärts; Fall b: PW<2048 (<50% von T), Motor dreht sich rückwärts
Die Daten zum Setzen der Motorstellgröße über das Kommando DCM_SETVALUE können nach folgendem Diagramm ermittelt werden. Aus der Motorstellgröße berechnet der Mikrocontroller durch Addition von 2048 (Motor steht bei PW=2048) die Pulsweite PW.
µC PWM-Einheit
Counter
Motorendstufe Gleichstrom-motor mit integriertem Encoder
2 um 90⁰ phasenverschobene Impulsfolgen
PWM-Signal A/D-Wandler
A
B . .
Motorspannung
TU Ilmenau, Fakultät für Maschinenbau 22.03.2016
9
Bild 6: Motorspannung UM in Abhängigkeit von der Stellgröße für das Kommando DCM_SETVALUE An der Welle des Gleichstrommotors ist ein inkrementaler Impulsgeber - kurz: Encoder - befestigt. Dieser Encoder liefert zwei phasenverschobene Rechteckspannungsfolgen - die Encoderimpulse. Pro Umdrehung enthält jede Rechteckspannungsfolge 16 Rechteckperioden. Die Zähleinheit - der Counter - für die Encoderimpulse realisiert eine Drehrichtungserkennung und eine Vierfachauswertung (Zählen aller Rechteckflanken). Damit werden pro Umdrehung 64 Inkremente richtungsabhängig gezählt und im Counter gespeichert. Kommunikation zwischen dem PC und dem Mikrocontroller auf dem Sensor-Aktor-Modul
Bild 7: Datenfluss für das Beispiel der LED-Steuerung
Auf dem Sensor-Aktor-Modul befindet sich ein Mikrocontroller (µC), der die externe Hardware (z.B. die LEDs) ansteuert. Zur Ablaufsteuerung und zur Kommunikation mit dem Nutzer dient der PC. Die Kommunikation erfolgt über eine USB-Schnittstelle. Die auf dem Mikrocontrollerboard enthaltene Hardware realisiert die Umwandlung der USB-Signale in ein asynchrones serielles Protokoll (USB to Serial). Die Software für den PC muss ihrerseits die serielle Kommunikation über einen virtuellen COM-Port realisieren. Im Mikrocontroller dient eine Tabelle (ein Feld) von 16-Bit Zahlen (in C++ in Visual Studio dementsprechend short int, entspricht short) als Datenschnittstelle. Sowohl der Mikrocontroller als auch der PC können Daten in diese Tabelle schreiben bzw. auslesen. Die Position in der Tabelle - also der Feldindex - bestimmt dabei die Bedeutung der Daten. Um die Nutzung durch den Programmierer zu erleichtern, wird in der Tabelle 1 (s.u.) der Feldindex durch symbolische Konstanten, nachfolgend als Kommandos bezeichnet, angegeben. Aus dem entsprechenden Kommando ergibt sich die Bedeutung der übertragenen Daten (beachte: Lesen von Daten aus der Mikrocontroller-Tabelle oder Schreiben von Daten in die Mikrocontroller-Tabelle). Anwendungsbeispiel: Sendet der PC z.B. ein neues Bitmuster für die LEDs, so wird dieser Wert in der Mikrocontroller-Tabelle an der Position LED gespeichert und außerdem wird die Mikrocontroller-Software darüber informiert, dass ein neuer Sollwert vorliegt und die Steuerung entsprechend reagieren muss. Statusinformationen und Messwerte (z.B. die Schalterstellungen) werden vom
2047 Stellgröße
-Ub
Ub
UM
0 -2047
PC USB USB to Serial µC LED
10
Mikrocontroller ebenfalls in der Mikrocontroller-Tabelle abgelegt und zyklisch aktualisiert. Der PC kann diese Daten jederzeit abrufen.
Übersicht aller möglichen Kommandos Kommandos für die Funktion WriteValue(…)
Kommando
(command)
Bedeutung Daten
(data)
MODE Betriebsart setzen 0 Analog (Standard)
1 Lautsprecher
2 Schrittmotor
3 Gleichstrommotor
LED LEDs setzen Bitmuster (Bit 0…7)
Bit-Nummer = LED-Nummer
DCM_SETVALUE Stellgröße (Spannung) Motor
setzen
12-Bit PW
-2047 = -Ub (Betriebsspannung)
2047 = Ub
DCM_CLEAR Zähler Encoder löschen 0 = Zähler löschen
SPK_ON Lautsprecher Ein/Aus 1 = Ein, 0 = Aus
SPK_FREQ Tonfrequenz in Hz setzen Wertebereich 20…25000 Hz
STP_MODE Betriebsart des
Schrittmotors
Bit 0,1: Mikroschrittmodus (MSM):
00-Voll, 01-Halb, 10-Viertel,11-Achtel;
Bit 2: 0 = Start/Stop, 1 = Hochlauf;
Bit 3: Richtung: 0 = vorwärts
STEP Einzelschritt ausführen 1: 1 Schritt im Vollschrittmodus
HOME Nulllage Schrittmotor
anfahren
0 = Anfahren der Nulllage (immer rückwärts)
STP_FREQ Schrittfrequenz in Hz
vorgeben
Für Start/Stop-Betrieb, für Hochlaufbetrieb
wird immer auf max. 250 Hz beschleunigt.
Untere Grenze: 20 Hz
STP_STEPS Schrittzahl setzen 1 Umdrehung = 48 Vollschritte
STP_CLEAR Zähler löschen 0 = Absolute/relative Schrittzahl und Anzahl
Umdrehungen löschen
Kommandos für die Funktion ReadValue(…)
Kommando
(command)
Bedeutung Daten
(data)
STATUS Gerätestatus lesen Bit 0,1 enthalten die Betriebsart
VERSION Firmwareversion lesen Bit13..15: Hauptversion, Bit 8..12: Unterversion
Bit0..7: Geräte-ID
SWITCH Schalter lesen Bitmuster (Bit 0…7)
Bit-Nummer = Schalter-Nummer
UB Betriebsspannung lesen in mV
7 6 5 4 3 0 1 2
7 6 5 4 3 0 1 2
TU Ilmenau, Fakultät für Maschinenbau 22.03.2016
11
Argumente für die Funktion ReadData(…)
Startindex in der µC-Tabelle
(sourceindex)
Bedeutung Daten
(buffer)
R2_TABLE Startadresse des Verlaufs der
Motordrehzahl (in U/min)
60 Werte (short int) werden
nach der Vorgabe eines neuen
PWM-Wertes für den Gleich-
strommotor gespeichert (10
Werte pro s, neue Messung
wird nur gestartet, wenn
vorherige beendet wurde).
Tabelle 1: Sensor-Aktor-Modul Kommandos
Funktionsbibliothek zur Steuerung des Sensor-Aktor-Moduls
Visual Studio C++ Projekteigenschaften zur Nutzung der Sensor-Aktor-Funktionsbibliothek (LIB und DLL) Für die Kommunikation des PC‘s mit dem Mikrocontroller des Sensor-Aktor-Moduls werden Funktionen bereitgestellt, die die asynchrone serielle Kommunikation realisieren. Die Funktionen wurden zu einer DLL zusammengefasst, die in das aktuelle Projekt eingebunden werden muss.
MES_POTI Spannung am Dreh-
potentiometer lesen
in Inkrementen des 10 Bit A/D-Wandlers
MES_LDR Spannung am
Helligkeitssensor lesen
in Inkrementen des 10 Bit A/D-Wandlers
PRESSURE Luftdruck bezogen auf die
Temperatur im SAM
in hPa
I2C_ACC Beschleunigungen x, y, z siehe Datenblatt MMA8452Q
DCM_VOLTAGEA Brückenspannung A lesen UMA in Inkrementen des 10 Bit A/D-Wandlers
DCM_VOLTAGEB Brückenspannung B lesen UMB in Inkrementen des 10 Bit A/D-Wandlers
UMotor = UMB - UMA
DCM_COUNTER Zähler der Encoderimpulse
lesen
64 Impulse pro Umdrehung
STP_STATUS Schrittmotorstatus lesen Bit 0: 1 = inNulllage, Bit 1: 1 = isRunning,
Bit 2: 0 = no error (Anzahl Umdrehungen),
Bit 3: Pegel der Lichtschranke ( 1 = offen)
STP_RELSTEPS Relative Schrittzahl (SZ) lesen 1 Umdrehung = 48 Vollschritte.
(Wird gelöscht, wenn neue SZ vorgegeben
wird.)
STP_ABSSTEPS Absolute Schrittzahl lesen Wird nach der Fahrt in die Nulllage gelöscht.
STP_TURNS Anzahl Umdrehungen lesen Wird nach der Fahrt in die Nulllage gelöscht.
12
Ein Projekt für Visual Studio 2012, das alle notwendigen Dateien und Einstellungen enthält, liegt auf AUSHANG\VisualC++ und heißt A3_SensorAktorModul. Nutzen Sie dieses vorbereitete Visual Studio Projekt! Bereitgestellte Funktionen zur Kommunikation mit dem Sensor-Aktor-Modul In einer DLL (Funktionsbibliothek) werden für Ihr Programm folgende Funktionen, die für die Ansteuerung des Sensor-Aktor-Moduls notwendig sind, bereitgestellt (command und data siehe Tabelle 1):
1. Verbindung zum Modul herstellen bzw. trennen
int OpenSAM(void);
Nach Programmstart muss die Verbindung einmalig mit OpenSAM(); hergestellt werden. Der Rückgabewert dieser Funktion ist die Gerätenummer. void CloseSAM(void); Am Ende des Programms muss die Verbindung getrennt werden.
2. Einen Wert an das Modul senden int WriteValue(unsigned char command, short data); Beispiel: Schreiben des Wertes 3 für das Kommando MODE = Betriebsart setzen WriteValue(MODE,3);
3. Einen Wert vom Modul lesen int ReadValue(unsigned char command, short* data); Beispiel: Lesen des Status und Speichern des Wertes auf der Variablen status short status; ReadValue(STATUS,&status);
4. Schreiben und Lesen von Datenfeldern
int WriteData(unsigned char destinationindex, unsigned char count, unsigned char* buffer); // count in Byte, max. 126
int ReadData(unsigned char sourceindex, unsigned char count, unsigned char* buffer); // count in Byte, max. 126
Beispiel: Lesen der Drehzahlmesswertetabelle short drehzahl[60]; ReadData(R2_TABLE,120,(unsigned char *)drehzahl);
Wenn der Rückgabewert einer der genannten Funktionen negativ ist, ist ein Fehler aufgetreten.
TU Ilmenau, Fakultät für Maschinenbau 22.03.2016
13
Aufgabe 1: C-Dateiarbeit Ziel des Programms sind das Lesen und Schreiben von Textdateien und das Lesen und Schreiben von Binärdateien. Vorgegeben ist die Textdatei "Durchmesser.txt". Sie liegt auf "Aushang\VisualC++\Text_und_Binaerdateien". Sie speichert eine Menge von Durchmesser - Messwerten einschließlich Zusatzinformationen. Jede Zeile enthält das Datum, eine Nummer und den Messwert in mm. Der Dateiaufbau entspricht folgendem Muster: 17.09.2014 315 20.032 17.09.2014 316 19.997 18.09.2014 317 20.018 ……. Aufgaben: 1. Anzeige des Inhalts der Textdatei auf dem Bildschirm. Die Formatierung der Datei soll erhalten
bleiben.
2. Einlesen der Textdatei und Auswertung der Messwerte a. Erzeugen Sie eine neue Textdatei "Ausschuss.txt".
In dieser Datei sollen alle Zeilen von "Durchmesser.txt" gespeichert werden, deren Messwerte außerhalb einer Toleranz von ±0.05 mm um den Nennwert 20.0 mm liegen. Zeigen Sie die Anzahl der Zeilen mit Ausschuss an.
b. Erzeugen Sie eine neue Binärdatei "Messwerte.bin". In dieser Datei sollen nur die Messwerte abgespeichert werden, die in der vorgegebenen Toleranz liegen.
3. Ermitteln Sie den arithmetischen Mittelwert der Messwerte aus der Datei "Messwerte.bin"
und zeigen Sie diesen auf dem Bildschirm an.
14
Aufgabe 2: Tonerzeugung
Mit Hilfe des Zeitgeberschaltkreises 8253 und des Lautsprechers des PCs sollen Töne (Hardware siehe unten) erzeugt werden.
Aufgabe:
Erzeugen Sie eine einfache Melodie (8 -12 Töne), wobei die Notenfrequenzen (Tonhöhe) und die Notenlängen in Feldern abgespeichert werden sollen (Hinweise zu Feldern siehe Lehrmaterial). Für die Notendauer ist die Funktion Sleep() zu benutzen siehe C++-Hilfe.
Hardwarebeschreibung In jedem PC befindet sich ein CTC-Schaltkreis 8253. CTC heißt Counter-Timer-Circuit also Zähler-Zeitgeber-Schaltkreis. An den Clock Eingängen dreier, voneinander unabhängiger, Kanäle ist ein konstantes Rechtecksignal mit der Frequenz f0 angeschlossen. An den Ausgängen OUT kann eine (kleinere) Frequenz f entnommen werden. Diese ergibt sich aus der Division der Eingangsfrequenz f0 durch die programmierbare Zeitgeberkonstante n. n ist eine 16-Bit Zahl vom Datentyp unsigned short int. Für die Tonerzeugung steht der Kanal 2 zur Verfügung.
Clock0 Gate0 Clock1 Gate1 Clock 2 Gate2
Kanal0 Kanal1 Kanal2
Adresse 0X40 Adresse 0X41 Adresse 0X42
OUT0 OUT1 OUT2
Eingangsfrequenz (Quarz)
f0= 1193180 Hz
zum Interrupt-
Controller zum DMA-
Controller
Paralleler E/A-Baustein
8255 (Baustein wird vom Betriebs-
system konfiguriert)
PortB:Adresse 0X61
PortB Bit0
PortB Bit1
Ausgangsfrequenz
f= 1193180 Hz /n
AND Lautsprecher
Zeitgeberschaltkreis 8253
OUT2= 1193180 Hz / n
n-Zeitgeberzeitkonstante
Co
ntr
olr
egis
ter
Ad
ress
e 0
x43
1 heißt Ton freigeschaltet
T0=1/f0
Tn=1/f
Schwingquarzfrequenz
f0 = 1,19318 106 Hz
Frequenz f des Ausgangssignals
in Betriebsart 3 bei n=4.
Am Eingang Gate muß
Highpegel anliegen.
TU Ilmenau, Fakultät für Maschinenbau 22.03.2016
15
Beispielfrequenzen für ausgewählte Töne Beispiele für Notendauern
Ton Frequenz in Hz Note Dauer in ms
c 262 ganze Note 2560
d 294 halbe Note 1280
e 330 viertel Note 640
f 349 achtel Note 320
g 392 sechzehntel Note 160
a 440 zweiunddreißigstel Note 80
h 494 vierundsechzigstel Note 40
c² 523
Programmierung des CTC-Schaltkreises 8253
Zur Erzeugung der gewünschten Ausgangsfrequenz f muss der Schaltkreis programmiert werden. Dies erfolgt durch Ausgabe eines Bytes an das Control-Register des Schaltkreises. Das Control-Register hat die Adresse 0X43. Die einzelnen Bits dieses Bytes ergeben sich aus folgender Tabelle.
0 0 0 = Betriebsart 0
0 0 1 = Betriebsart 1
0 1 0 = Betriebsart 2
0 1 1 = Betriebsart 3
1 0 0 = Betriebsart 4
0 = Binär
1 = BCD
0 0 = Inhalt Counterregister -> Latchregister
0 1 = Nur MSB lesen/schreiben
1 0 = Nur LSB lesen/schreiben
1 1 = Erst LSB, dann MSB lesen/schreiben
0 0 = Kanal 0 programmieren
0 1 = Kanal 1 programmieren
1 0 = Kanal 2 programmieren
Controlregister ( Portadresse 0X43 )
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
Zur Erzeugung einer Frequenz f mit dem Tastverhältnis 1:1 wird der Kanal 2 in Betriebsart 3, Binär betrieben. Der Teilerfaktor n ist eine 16 Bit-Zahl. Es müssen also zwei 8 Bit-Werte, erst LSB ( least significant byte ), dann MSB ( most significant byte ) auf die Portadresse 0X42 geschrieben werden.
16
Hardwarezugriff unter Windows 7 64 Bit
Der Zugriff auf Hardwareressourcen ist unter Windows nur über entsprechende Treiber möglich.
Für den Zugriff auf die Ports des Zeitgeberschaltkreises wird für diesen Versuch der Treiber mit den zugehörigen Bibliotheken WinRing0 benutzt. WinRing0 ermöglicht den Hardwarezugriff unter Windows mit Hilfe der Funktionen WriteIoPortByte() und ReadIoPortByte().
Für die Nutzung des Treibers im Rechnerlabor MB (Treiber wurde installiert und automatisch gestartet.) wird das Projekt A2_Tonerzeugung unter Aushang\VisualC++ bereitgestellt. Kopieren Sie den Ordner A2_Tonerzeugung nach C:\Kopie und öffnen Sie die Solution.
Beispielcode #include <stdio.h> #include <windows.h> #include "OlsApi.h" // Deklaration der Funktionen void main(void) { InitializeOls(); int retval = 0;
retval = GetDllStatus(); printf("\nRueckgabewert: %d\n",retval); // 0 heißt o.k. //.... WriteIoPortByte(0x43,0xB6); // Ausgabe des Steuerworts an den Port 43H unsigned char b = 0;
b = ReadIoPortByte(0x61);// Lesen von Port 61H //....
DeinitializeOls(); }
TU Ilmenau, Fakultät für Maschinenbau 22.03.2016
17
Aufgabe 3: Peripheriesteuerung mit einem Sensor-Aktor-Modul
Aufgaben 1. Prüfen Sie, ob die Funktion OpenSam() eine gültige Gerätenummer aus dem Bereich 1…25
liefert. Wenn ja, zeigen Sie diese an, wenn nein, beenden Sie das Programm mit einer Fehlermeldung.
2. Setzen Sie die Betriebsart "Gleichstrommotor" und warten Sie anschließend, bis die entsprechenden Bits im Gerätestatus die Betriebsart "Gleichstrommotor" anzeigen.
3. Ermitteln Sie die Betriebsspannung Ub des Sensor-Aktor-Moduls und zeigen Sie diese an.
4. Programmieren Sie eine Schleife zur Vorgabe der Motorspannung.
Der Nutzer soll eine Motorspannung in Volt ( Maximalwert ist die Betriebsspannung Ub, Minimalwert ist -Ub ! ) über die Tastatur eingeben. Die Schleife soll beendet werden, wenn der Eingabewert außerhalb des Bereiches -Ub…Ub liegt. Jeder gültige Spannungswert soll am Gleichstrommotor des Sensor-Aktor-Moduls eingestellt werden.
5. Fügen Sie in die Schleife das Messen der Drehzahl und der Motorspannung ein. Ermitteln Sie die sich bei einer vorgegebenen Spannung einstellende Motordrehzahl mit Hilfe des Zählerstandes der Encoderimpulse. Zeigen Sie die Motordrehzahl in U/min auf dem Bildschirm an. Ermitteln Sie aus den beiden Brückenspannungen die tatsächliche Motorspannung. Zeigen Sie die Motorspannung in Volt auf dem Bildschirm an.
18
Aufgabe 4: Klassen in C++ und Nutzung des .NET Frameworks
Aufgabe: Erstellen Sie ein Programm zur Berechnung von Dreiecken, das folgende Teilaufgaben realisiert: 1. Einlesen der Seitenlängen (in mm) über die Tastatur
2. Prüfen, ob die eingegebenen Seitenlängen ein gültiges Dreieck ergeben
3. Wiederholung der Eingabe, solange die Seiten kein Dreieck ergeben
4. Prüfen, ob das Dreieck rechtwinklig ist und Anzeigen des Ergebnisses
5. Berechnen und Anzeigen des Flächeninhalts des Dreiecks
Zur Lösung der Aufgabe ist ein Programmgerüst, das Projekt P4_Klassen, vorgegeben. Dieses können Sie von AUSHANG\VISUALC++ kopieren.
Das Projekt P4_Klassen enthält die 3 Dateien
Triangle.h – Klassendeklaration
Triangle.cpp – Klassenimplementation
Start.cpp – Hauptprogramm
Wenn Sie das Projekt neu erstellen wollen, müssen Sie folgende Hinweise beachten:
Erstellen Sie ein leeres C++ Projekt
Schalten Sie ProjectPropertiesConfiguration PropertiesGeneralCommon Language Runtime support ein (/CLR)
Kopieren Sie die vorgegebenen Dateien in das Projektverzeichnis und fügen Sie diese zu Ihrem Projekt hinzu (Alternativ: Add Class zum Erzeugen einer neuen Klasse).
TU Ilmenau, Fakultät für Maschinenbau 22.03.2016
19
Triangle.h – Klassendeklaration
#pragma once ref class Triangle { private: double sideA; double sideB; double sideC; // auf diese Variable wird immer die größte Seite geladen double area; void CalculateArea(); public: Triangle(void); ~Triangle(void); bool SetValues(double sA, double sB, double sC); bool IsOrthogonal(); property double Area { double get() { CalculateArea(); return area; } /* set-Zweig hier nicht erforderlich void set(double value) { area=value; } */ } };
20
Triangle.cpp – Klassenimplementation
using namespace System; #include "Triangle.h" //Konstruktor Triangle::Triangle(void) { // Initialisieren der privaten Felder (Membervariablen) mit 1.0 // und Berechnung des Flächeninhalts } //Destruktor Triangle::~Triangle(void) { } bool Triangle::SetValues(double sA, double sB, double sC) { // die Werte sortieren, so dass der größte Wert in sC steht
// Prüfen, ob die eingegebenen Seiten ein Dreieck ergeben // wenn die Seiten ein Dreieck ergeben, die übergebenen Werte auf die // privaten Membervariablen setzen
} bool Triangle::IsOrthogonal() { // Prüfen, ob das Dreieck rechtwinklig ist } void Triangle::CalculateArea() { // Berechnen des Flächeninhalts // Flächeninhalt für beliebiges Dreieck: // A=sqrt(s*(s-a)*(s-b)*(s-c)) mit s=(a+b+c)/2 }
TU Ilmenau, Fakultät für Maschinenbau 22.03.2016
21
Start.cpp – Hauptprogramm // Datei: Start.cpp // Versuch 4: Klassen in C++ // C++ Console Projekt mit .NET // C++ .NET - muss in den Projekteigenschaften eingeschaltet werden // --> Common language runtime support einschalten! siehe Anleitung
using namespace System; #include "Triangle.h" void main(void) { String^ message="Programm zur Berechnung von Dreiecken"; Console::WriteLine(message); // Ein Objekt der Klasse Triangle anlegen // Seitenlängen über Tastatur eingeben mit Hilfe der Funktion // Console::ReadLine() // So lange wiederholen, bis die eingegebenen Seitenlängen ein // gültiges Dreieck ergeben // Prüfen, ob das Dreieck rechtwinklig ist und Anzeigen des Ergebnisses // Berechnen und Anzeigen des Flächeninhalts des Dreiecks Console::ReadKey(); // Warten auf Tastendruck }
22
Lehrmaterial Datentypen und Konstanten in C++
Typname Byte- anzahl
Kommentar Konstante (Beispiele)
Ganzzahlige Typen = integrale Typen
char / signed char
1 8-Bit mit Vorzeichen -128 bis +127
'A', '\n' '\x1B' = Escape
unsigned char 1 8-Bit ohne Vorzeichen 0 bis 255
0xFF (hexadezimal)
short int 2 16-Bit mit Vorzeichen -32.768 bis 32.767
2345
unsigned short int
2 16-Bit ohne Vorzeichen 0 bis 65.535
2345U 2345u
int / signed int
4 32-Bit mit Vorzeichen -2.147.483.648 bis 2.147.483.647
2345
unsigned int 4 32-Bit ohne Vorzeichen 0 bis 4.294.967.295
2345U 2345u
long int / signed long int
4 32-Bit mit Vorzeichen ( in C# 8 Byte ! ) -2.147.483.648 bis 2.147.483.647
2345L 2345l
unsigned long int 4 32-Bit ohne Vorzeichen 0 bis 4.294.967.295
2345UL 2345ul
long long / signed long long
8 64-Bit mit Vorzeichen ( 19 Stellen ) - 9.223.372.036.854.775.808 bis +9.223.372.036.854.775.807
unsigned long long
8 64-Bit ohne Vorzeichen ( 19 Stellen ) 0 bis 18.446.744.073.709.551.615
Gleitkommatypen
float 4 ±1.5 × 10-45 bis ±3.4 × 1038 7 Stellen
2.34F 2.34f
double 8 ±5.0 × 10-324 bis ±1.7 × 10308 15 Stellen
2.34 12E-2, 1.67e5
Unicodezeichen
wchar_t 2 Ein 16-Bit Zeichen aus der Unicodetabelle, 0 - 65535
L'A', L'\n'
Wahrheitswerte
bool 1 Schlüsselworte: true, false
true
TU Ilmenau, Fakultät für Maschinenbau 22.03.2016
23
Funktionen zur Anzeige auf dem Bildschirm - printf() und zur Tastatureingabe - scanf() Einlesen formatierter Daten von der Tastatur und formatierte Anzeige auf dem Bildschirm #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> void main() { int i; double x; char text[80]; printf("Geben Sie eine int-Zahl ein: "); scanf("%d", &i); printf("Geben Sie eine double-Zahl ein: "); scanf("%lf", &x); printf("Geben Sie eine Zeichenkette ein: "); scanf("%s", text); printf("Inhalt der Daten: %d %lf %s\n", i, x, text); }
Nutzung von _kbhit() und _getch() sowie der Taste Esc (Escape)
#include <conio.h> #include <stdio.h> void main() {
bool ende = false; // Taste Esc setzt ende auf true int taste = 0;
do { // Hier kommt das gesamte Programm printf("Ich rechne noch …\n"); if(_kbhit() != 0) // Test auf Tastendruck { // Ja, es wurde eine Taste gedrückt taste =_getch(); // Taste lesen if(taste == 0x1B) // War es die Esc-Taste? ende = true;// Ja, dann Ende der while-Schleife } } while(ende == false); }
24
Felder und Strukturen
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <conio.h> #include <string.h> void main() { char anzeigetext[80]; // Ein Feld für 80 Zeichen = Zeichenkette strcpy(anzeigetext,"Anzeige der Quadratzahlen von 0 bis 19\n"); int quadratzahlen[20]; // Ein Feld für 20 int-Zahlen for(int i=0; i<20; ++i) // Index läuft von 0 bis 19 quadratzahlen[i]=i*i; // Füllen des Feldes printf("%s",anzeigetext); for(int i=0; i<20; ++i) printf("%d x %d = %d\n",i,i,quadratzahlen[i]); _getch(); }
Anzeige: Anzeige der Quadratzahlen von 0 bis 19 0 x 0 = 0 1 x 1 = 1 2 x 2 = 4 …
#include <stdio.h> #include <conio.h> #include <string.h> struct student // Strukturdeklaration { int matrikelNr; double bafoeg; }; void main() { student meier; //Definition der Struktur meier vom Typ student meier.matrikelNr = 12345; // Zugriff auf eine Komponente der Struktur meier.bafoeg = 512.50; printf("Der Student mit der Matrikelnummer %d erhaelt %.2lf Euro Bafoeg.\n", meier.matrikelNr,meier.bafoeg); _getch(); }
Anzeige: Der Student mit der Matrikelnummer 12345 erhaelt 512.00 Euro Bafoeg.
TU Ilmenau, Fakultät für Maschinenbau 22.03.2016
25
Funktionen zur Dateiarbeit Formatiertes Schreiben und Lesen einer Datei im Textmodus (vergleiche: printf() und scanf() ) #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main() { FILE *stream1, *stream2; int i, zeilenzahl=0; double x; char name[80]; if((stream1=fopen("test.txt", "rt" )) == NULL) { printf("Datei konnte nicht geoeffnet werden!\n"); return(-1); } while(fscanf(stream1,"%d%lf%s", &i, &x, name) != EOF) ++zeilenzahl; printf("%d Zeilen wurden gelesen.\n", zeilenzahl); rewind(stream1); //Filepointer wieder an den Anfang der Datei setzen fscanf(stream1,"%d%lf%s", &i, &x, name); fclose(stream1); if((stream2=fopen("erstezeile.txt", "wt" )) == NULL) { printf("Datei konnte nicht erzeugt werden!\n"); return(-2); } fprintf(stream2,"%s: %lf\n", name, x); fclose(stream2); return(0); }
Aufbau der Datei "test.txt":
1 27.5 Temperatur … 27 1026 Druck
Aufbau der Datei "erstezeile.txt": Temperatur: 27.500000
26
Schreiben und Lesen im Binärmodus Demo 1: Ein Feld von 10 int-Zahlen schreiben und lesen und anzeigen #define _CRT_SECURE_NO_WARNINGS #include < stdio.h > #include <conio.h> void main () { FILE *fp; int testout[10], testin[10], i; for ( i = 0 ; i < 10 ; ++i ) testout[i] = 276 + i ; // Feld füllen (Demo Werte) fp = fopen ( "C:\\Kopie\\test.bin", "wb" ); // Datei im Binärmodus
// hier wird als Demo das ganze Feld // (10 int-Zahlen = 40 Byte) auf einmal geschrieben
fwrite ( testout, sizeof (testout), 1, fp ); fclose ( fp ); fp = fopen ( "C:\\Kopie\\test.bin", "rb" ); for (i=0; i<10; ++i) // hier wird als Demo jede int-Zahl = 4 Byte einzeln gelesen fread (&testin[i], sizeof (int), 1, fp ); fclose ( fp ); // Anzeigen for ( i = 0 ; i < 10 ; ++i ) printf ( "%d %d %d \n", i, testout[i], testin[i]); _getch(); }
Demo 2: Schreiben und Lesen eines Feldes aus Strukturen #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> struct messwert { int nr; char zeit[12]; double wert; }; void main() { struct messwert feld[5]={ {1,"12:27",3.45}, {2,"13:35",1.78}, {3,"10:56",5.96}, {4,"9:17",11.73}, {5,"14:27",-3.01}}; FILE * fp; fp=fopen("messwerte.bin","wb"); fwrite(feld, sizeof(feld), 1, fp); // ganzes Feld schreiben fclose(fp); //nur die erste Struktur einlesen fp=fopen("messwerte.bin", "rb"); struct messwert zeile; fread(&zeile, sizeof(zeile), 1, fp); printf("Erster Messwert: %lf\n", zeile.wert); fclose(fp); }
TU Ilmenau, Fakultät für Maschinenbau 22.03.2016
27
Ablaufsteuerung do-while-Schleife Syntax: do { < Anweisungen > } while ( < Bedingungstest > ) ; int k ; k = 12 ; do { printf( " k = % d \n " , k ); k = k-1; } while( k > 8 );
while-Schleife Syntax: while ( < Bedingungstest > ) { < Anweisungen > }
int k = 12; while( k > 8 ) { printf( "k = %d \n", k ); k = k-1; }
for-Schleife Syntax: for ( < Initialisierung > ; < Bedingungstest > ; < Modifizierung > ) { < Anweisungen > } for( int k = 12 ; k > 8 ; --k) { printf("k = %d \n", k );
}
28
if-Anweisung Syntax: if ( < Bedingungstest > ) { < Anweisungen > }
if - else Syntax: if ( < Bedingungstest > ) { /* Test liefert wahr */ < Anweisungen 1 > } else { /* Test liefert falsch */ < Anweisungen 2 > } taste = _getch( ); if( taste == 'p' ) printf("Ein kleines p !"); else printf("Kein kleines p !");
switch-Anweisung Syntax: switch ( < ganzzahliger Ausdruck > ) { case < ganzzahliger Ausdruck >:< Anweisungen > break; default : < Anweisungen > break; } #include <stdio.h> #include <conio.h> void main() { int taste; printf("Bitte Taste betaetigen "); taste = _getch(); switch( taste ) { case 'p' : printf("Taste p\n"); break ; case '\r': printf("Enter Taste! \n"); break ; default : printf("Ende !"); break ; } _getch(); }
TU Ilmenau, Fakultät für Maschinenbau 22.03.2016
29
Die Anweisung break ist in folgenden Fällen anwendbar - mit break kann man eine (nicht zwei) Schleife verlassen - wirkt bei switch, while, do - while und for - wirkt nicht auf if oder else #include <stdio.h> #include <conio.h> void main() { int taste; int flag = 1; printf("Druecken Sie eine Taste ( Ende mit der Tabulatortaste! )\n"); while(flag == 1) { taste = _getch(); if( taste == '\t' ) { printf("Das war die Tabulatortaste!\n\a"); break; } } }
Die Anweisung continue - mit continue kann man einen Schleifendurchlauf abbrechen - man springt zum Anfang (zur Modifizierung) der Schleife zurück
#include <stdio.h> void main() { int i; for ( i = 0 ; i < 10 ; ++i ) { if ( i > 3 ) continue ; printf( " i = %d \n ", i ); } printf(" i = %d \n ", i ); printf(" ok ! "); }
30
Arithmetische Operatoren * Multiplikation x = 5 * y / Division x = x/y % Modulo (Rest der ganzzahligen Division) x = 19 % 3 (Ergebnis: x = 1 ) + Addition - Subtraktion Vergleichsoperatoren < kleiner als < = kleiner gleich > größer als > = größer gleich = = Test auf Gleichheit ( Verwechselungsgefahr mit dem Zuweisungsoperator = ) ! = Test auf Ungleichheit Inkrement- und Dekrementoperatoren ++ bedeutet Inkrementieren des Operanden um eine Einheit, - - bedeutet Dekrementieren des Operanden um eine Einheit aber: Die Stellung der Operatoren ist zu beachten: - Präfixinkrementierung int x, y; x = 3; y = ++x ; // x = x + 1, y = x // also x = 4, y = 4
- Postfixinkrementierung int x, y; x = 3 y = x++ ; // y = x, x = x + 1 // also y = 3, x = 4
Bitweise Operatoren & UND ( Bits löschen, Bits ausblenden, Bits maskieren ) | ODER ( Bits setzen, Bits einblenden ) ^ exklusives ODER << Linksschieben >> Rechtsschieben ~ Einerkomplement
TU Ilmenau, Fakultät für Maschinenbau 22.03.2016
31
unsigned char x=0x33; // binär: x = 0011 0011 unsigned char y=0x0F; // y = 0000 1111 unsigned char z; z = x & y ; // 0011 0011 // & 0000 1111 // z = 0000 0011 = 0x03 Bit 4-7 auf 0 setzen z = x | y ; // 0011 0011 // | 0000 1111 // z = 0011 1111 = 0x3F Bit 0-3 auf 1 setzen z = x ^ y ; // 0011 0011 // ^ 0000 1111 // z = 0011 1100 = 0x3C einzelne Bits negieren unsigned char w = 0xB4; // binär: w = 1011 0100 w = ~w; // w = 0100 1011 alle Bits negieren w = w >> 2; // w = 0001 0010 um 2 Bit nach rechts schieben
Beispiel: Die Funktion liefert die Anzahl der Einsen in einem Byte. int AnzahlEins ( unsigned char wert ) { int anzahl=0; for ( int i = 0; i < 8; ++i ) { if ( (wert & 0X80) != 0 ) ++anzahl; wert = 2 * wert; } return anzahl; }
Logische Operatoren && logisches UND || logisches ODER ! logische Negation Beispiel: Test, ob eine Zahl z der Code eines ASCII-Buchstabens ist
int busta(int z) { if( z >= 'a' && z <= 'z' || z >= 'A' && z <= 'Z' ) return (1) ; else return (0) ; }
32
Adressoperatoren
& liefert die Speicheradresse eines Operanden
* - beeinflusst den Speicherinhalt, der unter einer Speicheradresse zu finden ist - beeinflusst also den Wert unter Benutzung der Adresse eines Operanden
sizeof – Operator Der sizeof – Operator liefert die Anzahl der in seinem Operanden enthaltenen Bytes. x = sizeof (int); // x = 4 bei 32/64-Bit-Windows char text [] = "C++"; x = sizeof (text); // x = 4 da 3 ASCII-Zeichen und das Endekennzeichen '\0'
new und delete - Operatoren zur dynamischen Anforderung von Speicher Beispiel: Speicher für eine double Zahl anfordern, nutzen und freigeben
double * px; px = new double; *px = 6.285; delete px;
Beispiel: Speicher für 10000 Byte anfordern, nutzen und freigeben
char * pc; pc = new char [10000]; strcpy( pc, "Neuer Speicher!"); printf("%s\n", pc); delete [] pc;
33
weitere Bibliotheksfunktionen (Beachte: einige Funktionen benötigen #define _CRT_SECURE_NO_WARNINGS)
Mathematische Funktionen, benötigte Headerdatei: #include <math.h> #define _USE_MATH_DEFINES vor #include <math.h> ermöglicht die Benutzung der Konstanten M_PI für π
Beschreibung Funktion Beispiel
Betrag einer int-Zahl int abs(int x); int value1 = abs(-3); //value1 = 3
Betrag einer double-Zahl double fabs(double x); double value2 = fabs(-3.1); //value2 = 3.1
Aufrunden double ceil(double x); value2 = ceil(3.4); //value2 = 4.0
Ganzzahliger Anteil einer double-Zahl (Abrunden)
double floor(double x); value2 = floor(3.6); //value2 = 3.0
Rest einer Division double fmod(double x, double y); value2 = fmod(4.1,2.0); //value2 = 0.1
Kosinus
Par
amet
er in
Bo
gen
maß
double cos(double x); value2 = cos(0.0); //value2 = 1.0
Sinus double sin(double x); value2 = sin(0.0); //value2 = 0.0
Tangens double tan(double x); value2 = tan(0.0); //value2 = 0.0
Arkuskosinus double acos(double x); value2 = acos(1.0); //value2 = 0.0
Arkussinus double asin(double x); value2 = asin(0.0); //value2 = 0.0
Arkustangens double atan(double x); value2 = atan(1.0); //value2 = 0.7853.. -->45°
Arkustangens mit Berücksichtigung des Quadranten
double atan2(double x, double y); value2 = atan2(-1.0,1.0); //value2 = -0.7853.. -->-45° value2 = atan2(1.0,0.0); //value2 = 1.570.. -->180°
natürliche Exponentialfunktion, e-Funktion 𝑒𝑥
double exp(double x); value2 = exp(1.0); //value2 = 2.718281..
natürlicher Logarithmus, 𝑙𝑜𝑔𝑒𝑥
double log(double x); value2 = log(2.718281); //value2 = 1.0
dekadischer Logarithmus, 𝑙𝑜𝑔10𝑥
double log10(double x); value2 = log10(1000.0); //value2 = 3.0
Potenzfunktion, 𝑥𝑦 double pow(double x, double y); value2 = pow(2.0,3.0); //value2 = 8.0 value2 = pow(27.0,1.0/3.0); //3. Wurzel aus 27: value2 = 3.0
Quadratwurzel double sqrt(double x); value2 = sqrt(16.0); //value2 = 4.0
34
Zeichenketten-Funktionen, benötigte Header-Datei: #include <string.h>
Beschreibung Funktion Beispiel
Anlegen einer Variable zum Speichern von Zeichenketten
- char str[80]; //Zeichenkette mit bis zu 79 Zeichen (+ Stringendekennzeichen)
Zeichenkette in eine andere kopieren
char *strcpy(char *ziel, const char *quelle); strcpy(str, "Hallo "); //str = "Hallo ", evtl. vorhandener //Inhalt wird überschrieben
Zeichenkette an eine andere anhängen
char *strcat(char *ziel, const char *quelle); strcat(str, "Welt!"); //str = "Hallo Welt!"
Zeichenketten vergleichen int strcmp(const char *str1, const char *str2);
int result = strcmp("Affe","Affe"); //result = 0 result = strcmp("Affe","affe"); //result = -1 result = strcmp("Affe","Zebra"); //result = -1 result = strcmp("Zebra","Affe"); //result = 1
Prüfen, ob ein Zeichen in einer Zeichenkette vorhanden ist
char *strchr(const char *str, int c); char *pos = strchr(str,'x'); //pos = NULL, da kein 'x' vorh. pos = strchr(str,'e'); //pos != NULL, "Adresse" von 'e' int index = pos – str; //Index von 'e' innerhalb von str ermitteln
Prüfen, ob Zeichenkette in einer anderen enthalten ist
char *strstr(char *str1, const char *str2); pos = strstr(str,"Affe"); //Bedeutung von pos: siehe strchr()
Länge einer Zeichenkette ermitteln
int strlen(const char *str); int len = strlen(str); //len = 11 (Länge ohne Stringendekennz.)
Sonstige Funktionen, benötigte Header-Dateien: für a: #include <windows.h> für b-e: #include <stdlib.h>
Beschreibung Funktion Beispiel
a Wartezeit, Programm anhalten
void Sleep(DWORD milliSeconds); Sleep(500); //wartet 500ms
b Zufallsgenerator initialisieren
void srand(unsigned int seed); srand(20); //Zufallszahlengenerator wird auf "pseudo"- zufälligen Startwert gesetzt
c Zufallszahl erzeugen int rand(void); int zuf = rand(); //zuf = Zufallszahl zwischen 0 und 32767 zuf = rand() % 100; //zuf = Zufallsz. zw. 0 und 99
d Zeichenkette in double-Zahl konvertieren
double atof(char *str); double wert = atof("3.141"); //wert = 3.141
e Zeichenkette in int-Zahl konvertieren
int atoi(char *str); int wert2 = atoi("128"); //wert2 = 128
35
Funktionen zur Dateiarbeit, benötigte Headerdatei: #include <stdio.h>
Für alle Dateien
Beschreibung Funktion Beispiel
Eine Datei öffnen FILE * fopen(const char * DateiName, const char * Modus);
FILE * fp = fopen("Messwerte.bin","rb"); //binär lesen FILE * fp2 = fopen("Messwerte.bin","wb"); //binär schreiben FILE * fp3 = fopen("Messwerte.txt","rt"); //Textdatei lesen FILE * fp4 = fopen("Messwerte.txt","wt"); //Textd. Schreiben // fopen liefert NULL, wenn Datei nicht geöffnet werden kann
Eine Datei schließen int fclose(FILE *DateiZeiger); fclose(fp);
Dateizeiger an Dateianfang setzen
void rewind(FILE *DateiZeiger); rewind(fp);
Dateizeiger an beliebige Stelle setzen
int fseek(FILE *DateiZeiger, long offsetInByte, int origin);
fseek(fp, 24L, SEEK_SET); //Dateizeiger auf Byte 24 (vom //Dateianfang aus) setzen fseek(fp, -8L, SEEK_CUR); //Dateizeiger 8 Byte zurücksetzen
Nur für Binärdateien
In eine Binärdatei schreiben size_t fwrite(const void *daten, size_t GroeßeInByte, size_t Anzahl, FILE *DateiZeiger); Rückgabewert = Anzahl geschriebener Elemente size_t = unsigned int
double messwert = 12.3; double alleWerte[5] = { 2.4, 3.5, 7.2, 8.1, 9.9};
//Eine Double-Zahl schreiben fwrite(&messwert, sizeof(double), 1, fp2);
//Ein ganzes Feld aus Double-Zahlen auf einmal schreiben fwrite(alleWerte, sizeof(alleWerte), 1, fp2);
Aus einer Binärdatei lesen size_t fread(const void *daten, size_t GroeßeInByte, size_t Anzahl, FILE *DateiZeiger); Rückgabewert = Anzahl gelesener Elemente. Rückg.w. = 0: kein Wert gelesen, z.B. am Dateiende.
//Eine Double-Zahl lesen fread(&alleWerte[0], sizeof(double), 1, fp);
//Ein ganzes Feld aus Double-Zahlen auf einmal lesen fread(alleWerte, sizeof(alleWerte), 1, fp);
//Solange eine Double-Zahl gelesen werden konnte, ... while (fread(&messwert, sizeof(double), 1, fp) > 0) ...
36
Nur für Textdateien
In eine Textdatei schreiben int fprintf(FILE *DateiZeiger, const char *format);
int i = 1; fprintf(fp4,"%d. Messwert:\t%lf\n", i, 23.67);
Aus einer Textdatei lesen int fscanf(FILE *DateiZeiger, const char *format);
//Eine Zeile mit obigem Aufbau lesen unsigned char text[20]; double wert; fscanf(fp3,"%d. %s %lf", &i, text, &wert); //Ein Zeichen aus Textdatei lesen, solange Dateiende //noch nicht erreicht ist unsigned char zeichen; while( fscanf(fp3, "%c", &zeichen) != EOF) ...
Funktionen für Bildschirmausgaben und Tastaturnutzung, benötigte Headerdateien: #include <stdio.h> #include <conio.h>
Bildschirmausgaben
Beschreibung Funktion Beispiel
Formatierte Ausgabe auf dem Bildschirm
int printf(const char *text [, argumente]);
int tag = 15; printf("Heute ist Mittwoch, der %d.%d.%d\n", tag, 10, 2014);
wichtige Escape-Sequenzen und Platzhalter \n neue Zeile %d Integer-Zahl \t Tabulator %lf Double-Zahl \b „Backspace“ %s Zeichenkette \r Cursor Zeilenanfang %c einzelnes (ASCII)-Zeichen
Ein Zeichen ausgeben int putch(int zeichen); putch(0x34); //Gibt die Ziffer 4 aus putch('a'); //Gibt ein kleines a aus
Tastaturnutzung
Formatiertes einlesen über die Tastatur (Eingaben müssen mit <Enter> abgeschlossen werden)
int scanf(const char *text [, argumente]);
double eingabe1, eingabe2; scanf("%lf", &eingabe1); scanf("%lf %lf", &eingabe1, &eingabe2);
Ein Zeichen lesen (wartet auf Drücken einer Taste!)
int _getch(void); int taste = _getch(); //ASCII-Zeichen steht in taste if(_getch() == 'a') ... else ... // Wenn 'a' gedrückt, ...
Prüfen, ob überhaupt eine Taste gedrückt wurde
int _kbhit(void); if(_kbhit() != 0) taste = _getch(); //_getch() nur aufrufen, wenn Taste gedr.
TU Ilmenau, Fakultät für Maschinenbau 22.03.2016 Univ.-Prof. Dr.-Ing. habil. M. Weiß
37
C++ - Klassendemo Schritt 1: Klassendeklaration using namespace System;
ref class CDate // die Klasse heisst also CDate { private: // drei private- Membervariablen vom Typ int int tag; int monat; int jahr; public: CDate(); // Konstruktor ~CDate(); // Destruktor void SetWerte( int t, int m, int j ); //eine Methode der Klasse String^ GetString(); // noch eine Methode
property int Jahr // eine property für jahr { int get() { return jahr; } void set(int value) { jahr=value; } } };
Schritt 2: Methodendefinition // Konstruktor, Aufgabe: Initialisierung aller Membervariablen (Felder) CDate::CDate() { tag=1; monat=1; jahr=2015; } // Destruktor, hat in diesem Beispiel keine Aufgabe CDate:: ~CDate() { }
38
// Eine Methode (Funktion) zum Setzen der privaten Variablen void CDate::SetWerte( int t, int m, int j ) { tag=t; monat=m; jahr=j; } // Eine Methode zum Erstellen eines Datumsstrings String^ CDate::GetString() { String^ dateString; dateString=tag + "." + monat + "." + jahr; return dateString; }
Schritt 3: Klassennutzung void main() { // Ein Objekt der Klasse CDate wird angelegt // Das Objekt heisst datum // Der Konstruktor wird automatisch abgearbeitet CDate datum; // Methodenaufruf durch Nutzung des Punktoperators String^ anzeige=datum.GetString(); // Aufruf einer statischen Methode der Klasse Console mit :: Operator Console::WriteLine(anzeige); // Änderung aller Werte und Anzeigen auf dem Bildschirm datum.SetWerte( 15, 5, 2016); Console::WriteLine(datum.GetString()); // Einlesen von der Tastatur mit Hilfe von .NET Klassen int jahreingabe; String^ input; Console::WriteLine("Bitte geben Sie das Jahr ein:"); input= Console::ReadLine(); jahreingabe=Convert::ToInt32(input); // Setzen des Jahres über die Property datum.Jahr=jahreingabe; // Anzeigen der geänderten Werte Console::WriteLine(datum.Jahr); Console::WriteLine("Neues Datum: {0}",datum.GetString()); Console::ReadKey(); //Warten auf Tastendruck } // Der Destruktor wird automatisch abgearbeitet
top related