Skip to content
Snippets Groups Projects
Commit 783b0e9c authored by Peter Gerwinski's avatar Peter Gerwinski
Browse files

Musterlösungen 12. und 19.12.2019

parent 408f46f6
No related branches found
No related tags found
No related merge requests found
File added
% hp-musterloesung-20191212.pdf - Solutions to the Exercises on Low-Level Programming
% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020 Peter Gerwinski
%
% This document is free software: you can redistribute it and/or
% modify it either under the terms of the Creative Commons
% Attribution-ShareAlike 3.0 License, or under the terms of the
% GNU General Public License as published by the Free Software
% Foundation, either version 3 of the License, or (at your option)
% any later version.
%
% This document is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this document. If not, see <http://www.gnu.org/licenses/>.
%
% You should have received a copy of the Creative Commons
% Attribution-ShareAlike 3.0 Unported License along with this
% document. If not, see <http://creativecommons.org/licenses/>.
% README: Kondensator, hüpfender Ball
\documentclass[a4paper]{article}
\usepackage{pgscript}
\usepackage{gnuplot-lua-tikz}
\begin{document}
\section*{Hardwarenahe Programmierung\\
Musterlösung zu den Übungsaufgaben -- 12.\ Dezember 2019}
\exercise{Kondensator}
Ein Kondensator der Kapazität $C = 100\,\mu{\rm F}$
ist auf die Spannung $U_0 = 5\,{\rm V}$ aufgeladen
und wird über einen Widerstand $R = 33\,{\rm k}\Omega$ entladen.
\begin{enumerate}[(a)]
\item
Schreiben Sie ein C-Programm, das
den zeitlichen Spannungsverlauf in einer Tabelle darstellt.
\points{5}
\item
Schreiben Sie ein C-Programm, das ermittelt,
wie lange es dauert, bis die Spannung unter $0.1\,{\rm V}$ gefallen ist.
\points{4}
\item
Vergleichen Sie die berechneten Werte mit der exakten theoretischen Entladekurve:
\begin{math}
U(t) = U_0 \cdot e^{-\frac{t}{RC}}
\end{math}\\
\points{3}
\end{enumerate}
Hinweise:
\begin{itemize}
\item
Für die Simulation zerlegen wir den Entladevorgang in kurze Zeitintervalle $dt$.
Innerhalb jedes Zeitintervalls betrachten wir den Strom $I$ als konstant
und berechnen, wieviel Ladung $Q$ innerhalb des Zeitintervalls
aus dem Kondensator herausfließt.
Aus der neuen Ladung berechnen wir die Spannung am Ende des Zeitintervalls.
\item
Für den Vergleich mit der exakten theoretischen Entladekurve
benötigen Sie die Exponentialfunktion \lstinline{exp()}.
Diese finden Sie in der Mathematik-Bibliothek:
\lstinline{#include <math.h>} im Quelltext,
beim \lstinline[style=cmd]{gcc}-Aufruf \lstinline[style=cmd]{-lm} mit angeben.
\item
$Q = C \cdot U$,\quad $U = R \cdot I$,\quad $I = \frac{dQ}{dt}$
\end{itemize}
\solution
\begin{itemize}
\item
\textbf{Schreiben Sie ein C-Programm, das
den zeitlichen Spannungsverlauf in einer Tabelle darstellt.}
In dem Programm \gitfile{hp}{20191212}{loesung-1a.c}
arbeiten wir, dem ersten Hinweis folgend,
mit einem Zeitintervall von \lstinline{dt = 0.01}.
Mit dieser Schrittweite lassen wir uns eine Tabelle ausgeben,
die jeweils die Zeit und durch die Simulation berechnete Spannung ausgibt.
Wir simulieren, wie die Ladung $Q = C \cdot U$ des Kondensators
im Laufe der Zeit abfließt.
Dazu berechnen wir in jedem Zeitschritt zunächst den Strom $I = U / R$,
der aus dem Kondensator fließt.
Dieser Strom bewirkt, daß innerhalb des Zeitintervalls $dt$
die Ladung $dQ = I \cdot dt$ aus dem Kondensator abfließt.
Am Ende des Zeitintervalls berechnen wir die zur neuen Ladung $Q$
gehörende neue Spannung $U = Q / C$.
Für eine einfache Ausgabe der Tabelle
verwenden wir die Formatspezifikationen \lstinline{%10.3lf} für drei
bzw.\ \lstinline{%15.8lf} für acht Nachkommastellen Genauigkeit.
Damit schreiben wir jeweils eine \emph{lange Fließkommazahl\/} (\lstinline{%lf})
rechtsbündig in ein Feld der Breite 10 bzw.\ 15
und lassen uns 3 bzw.\ 8 Nachkommastellen ausgeben.
Wir compilieren das Programm mit:
\lstinline[style=cmd]{gcc -Wall -O loesung-1a.c -o loesung-1a}
\item
\textbf{Schreiben Sie ein C-Programm, das ermittelt,
wie lange es dauert, bis die Spannung unter \boldmath $0.1\,{\rm V}$ gefallen ist.}
Wir ändern das Programm \gitfile{hp}{20191212}{loesung-1a.c} so ab,
daß zum einen die Schleife abbricht, sobald die Spannung
den Wert $0.1\,{\rm V}$ unterschreitet (\gitfile{hp}{20191212}{loesung-1b.c}),
und daß zum anderen nicht jedesmal eine Zeile für die Tabelle ausgegeben wird,
sondern erst am Ende die Zeit (und die Spannung).
Der Ausgabe entnehmen wir, daß die Spannung bei etwa $t = 12.90\,{\rm s}$
den Wert $0.1\,{\rm V}$ unterschreitet.
\item
\textbf{Vergleichen Sie die berechneten Werte
mit der exakten theoretischen Entladekurve:\\
\boldmath
\begin{math}
U(t) = U_0 \cdot e^{-\frac{t}{RC}}
\end{math}}
Wir ändern das Programm \gitfile{hp}{20191212}{loesung-1a.c} so ab,
daß es zusätzlich zur Zeit und zur simulierten Spannung
die exakte Spannung $U_0 \cdot e^{-\frac{t}{RC}}$
gemäß der theoretischen Entladekurve ausgibt (\gitfile{hp}{20191212}{loesung-1c.c}),
Da dieses Programm die Exponentialfunktion verwendet, müssen wir nun
beim Compilieren zusätzlich \lstinline[style=cmd]{-lm}\hspace{1pt}
für das Einbinden der Mathematik-Bibliothek angeben.
Der erweiterten Tabelle können wir entnehmen,
daß die durch die Simulation berechnete Spannung
mit der Spannung $U_0 \cdot e^{-\frac{t}{RC}}$
gemäß der theoretischen Entladekurve
bis auf wenige Prozent übereinstimmt.
Dies ist für viele praktische Anwendungen ausreichend,
wenn auch nicht für Präzisionsmessungen.
Wenn Sie die Ausgabe des Programms, z.\,B.\ mit
\lstinline{./loesung-1c > loesung-1c.dat},
in einer Datei \gitfile{hp}{20191212}{loesung-1c.dat} speichern,
können Sie sich die beiden Kurven graphisch darstellen lassen,
z.\,B.\ mit \file{gnuplot} und dem folgenden Befehl:\\
\lstinline[style=cmd]{plot "loesung-1c.dat" using 1:2 with lines title "Simulation",}\\
\lstinline[style=cmd]{ "loesung-1c.dat" using 1:3 with lines title "Theorie"}
\begin{center}
\input{loesung-1c.tikz}
\end{center}
Der Unterschied zwischen der simulierten und der theoretischen Entladungskurve
ist mit bloßem Auge nicht sichtbar.
\end{itemize}
\vfill
\exercise{Fehlerhaftes Programm: Hüpfender Ball}
Das auf der nächsten Seite abgedruckte GTK+-Programm
(Datei: \gitfile{hp}{20191212}{aufgabe-2.c}) soll einen
hüpfenden Ball darstellen, ist jedoch fehlerhaft.
\begin{enumerate}[\quad(a)]
\item
Warum sieht man lediglich ein leeres Fenster?
Welchen Befehl muß man ergänzen, um diesen Fehler zu beheben?
\points{3}
\item
Nach der Fehlerbehebung in Aufgabenteil (a)
zeigt das Programm einen unbeweglichen Ball.
Welchen Befehl muß man ergänzen, um diesen Fehler zu beheben, und warum?
\points{2}
\item
Erklären Sie das merkwürdige Hüpfverhalten des Balls.
Wie kommt es zustande?
Was an diesem Verhalten ist korrekt, und was ist fehlerhaft? \points{5}
\item
Welche Befehle muß man in welcher Weise ändern,
um ein realistischeres Hüpf-Verhalten zu bekommen? \points{2}
\end{enumerate}
Hinweis: Das Hinzuziehen von Beispiel-Programmen aus der Vorlesung
ist ausdrücklich erlaubt -- auch in der Klausur.
Allgemeiner Hinweis:
Wenn Sie die Übungsaufgaben zu dieser Lehrveranstaltung
als PDF-Datei betrachten und darin auf die Dateinamen klicken,
können Sie die Beispiel-Programme direkt herunterladen.
Dadurch vermeiden Sie Übertragungsfehler.
\clearpage
\vbox to \textheight{\vspace*{-0.5cm}\begin{lstlisting}
#include <gtk/gtk.h>
#define WIDTH 320
#define HEIGHT 240
double t = 0.0;
double dt = 0.2;
int r = 5;
double x = 10;
double y = 200;
double vx = 20;
double vy = -60;
double g = 9.81;
gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data)
{
GdkRGBA blue = { 0.0, 0.5, 1.0, 1.0 };
gdk_cairo_set_source_rgba (c, &blue);
cairo_arc (c, x, y, r, 0, 2 * G_PI);
cairo_fill (c);
return FALSE;
}
gboolean timer (GtkWidget *widget)
{
t += dt;
x += vx * dt;
y += vy * dt;
vx = vx;
vy = 0.5 * g * (t * t);
if (y + r >= HEIGHT)
vy = -vy * 0.9;
if (x + r >= WIDTH)
vx = -vx * 0.9;
if (x - r <= 0)
vx = -vx * 0.9;
gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
g_timeout_add (50, (GSourceFunc) timer, widget);
return FALSE;
}
int main (int argc, char **argv)
{
gtk_init (&argc, &argv);
GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_show (window);
gtk_window_set_title (GTK_WINDOW (window), "Hello");
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
GtkWidget *drawing_area = gtk_drawing_area_new ();
gtk_widget_show (drawing_area);
gtk_container_add (GTK_CONTAINER (window), drawing_area);
gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT);
gtk_main ();
return 0;
}
\end{lstlisting}\vss}
\solution
\begin{enumerate}[\quad(a)]
\item
\textbf{Warum sieht man lediglich ein leeres Fenster?
Welchen Befehl muß man ergänzen, um diesen Fehler zu beheben?}
Die für das Zeichnen zuständige Callback-Funktion wurde zwar geschrieben,
aber nicht installiert.
Um dies zu beheben, ergänze man den folgenden Befehl im Hauptprogramm:
\lstinline{g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);}
Dies erkennt man sehr schnell durch Vergleich mit dem Beispiel-Programm
\gitfile{hp}{20191205}{gtk-16.c}.
\item
\textbf{Nach der Fehlerbehebung in Aufgabenteil (a)
zeigt das Programm einen unbeweglichen Ball.
Welchen Befehl muß man ergänzen, um diesen Fehler zu beheben, und warum?}
Die Timer-Callback-Funktion wurde zwar geschrieben, aber nicht installiert.
Um dies zu beheben, ergänze man den folgenden Befehl im Hauptprogramm:
\lstinline{g_timeout_add (50, (GSourceFunc) timer, drawing_area);}
Auch dies erkennt man sehr schnell durch Vergleich mit dem Beispiel-Programm
\gitfile{hp}{20191205}{gtk-16.c}.
\item
\textbf{Erklären Sie das merkwürdige Hüpfverhalten des Balls.
Wie kommt es zustande?
Was an diesem Verhalten ist korrekt, und was ist fehlerhaft?}
Die Geschwindigkeit in $y$-Richtung wächst immer weiter.
Der Grund dafür ist, daß die $y$-Komponente der Geschwindigkeit
nicht auf physikalisch sinnvolle Weise berechnet wird.
In der dafür zuständigen Zeile
\lstinline{vy = 0.5 * g * (t * t);}
wird stattdessen der Weg in $y$-Richtung bei einer gleichmäßig
beschleunigten Bewegung berechnet und als Geschwindigkeit verwendet.
\item
\textbf{Welche Befehle muß man in welcher Weise ändern,
um ein realistischeres Hüpf-Verhalten zu bekommen?}
Da der Ball am Boden abprallen soll, ist es \emph{nicht\/} sinnvoll,
die $y$-Komponente der Geschwindigkeit über die bekannte physikalische
Formel $v_y = -g\cdot t$ für die Geschwindigkeit in einer
gleichmäßig beschleunigten Bewegung zu berechnen.
Stattdessen ist es sinnvoll, die \emph{Geschwindigkeitsänderung\/}
innerhalb des Zeitintervalls \lstinline{dt}
zur Geschwindigkeitskomponente zu addieren:
\lstinline{vy += g * dt;}
Auch dies erkennt man sehr schnell durch Vergleich mit dem Beispiel-Programm
\gitfile{hp}{20191205}{gtk-16.c}.
\end{enumerate}
\end{document}
#include <stdio.h>
#include <math.h>
int main (void)
{
double C = 0.0001;
double U0 = 5.0;
double U = U0;
double R = 33000.0;
double t = 0.0;
double dt = 0.01;
double Q = C * U;
while (U > 0.09)
{
printf ("%10.3lf%15.8lf\n", t, U);
double I = U / R;
Q -= I * dt;
U = Q / C;
t += dt;
}
return 0;
}
#include <stdio.h>
#include <math.h>
int main (void)
{
double C = 0.0001;
double U0 = 5.0;
double U = U0;
double R = 33000.0;
double t = 0.0;
double dt = 0.01;
double Q = C * U;
while (U >= 0.1)
{
double I = U / R;
Q -= I * dt;
U = Q / C;
t += dt;
}
printf ("%10.3lf%15.8lf\n", t, U);
return 0;
}
#include <stdio.h>
#include <math.h>
int main (void)
{
double C = 0.0001;
double U0 = 5.0;
double U = U0;
double R = 33000.0;
double t = 0.0;
double dt = 0.01;
double Q = C * U;
while (U > 0.09)
{
printf ("%10.3lf%15.8lf%15.8lf\n", t, U, U0 * exp (-t / (R * C)));
double I = U / R;
Q -= I * dt;
U = Q / C;
t += dt;
}
return 0;
}
This diff is collapsed.
This diff is collapsed.
File added
% hp-musterloesung-20191219.pdf - Solutions to the Exercises on Low-Level Programming
% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020 Peter Gerwinski
%
% This document is free software: you can redistribute it and/or
% modify it either under the terms of the Creative Commons
% Attribution-ShareAlike 3.0 License, or under the terms of the
% GNU General Public License as published by the Free Software
% Foundation, either version 3 of the License, or (at your option)
% any later version.
%
% This document is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this document. If not, see <http://www.gnu.org/licenses/>.
%
% You should have received a copy of the Creative Commons
% Attribution-ShareAlike 3.0 Unported License along with this
% document. If not, see <http://creativecommons.org/licenses/>.
% README: Trickprogrammierung, Thermometer-Baustein an I²C-Bus
\documentclass[a4paper]{article}
\usepackage{pgscript}
\usepackage{gensymb}
\newcommand{\ItwoC}{I\raisebox{0.5ex}{\footnotesize 2}C}
\newcommand{\ITWOC}{I\raisebox{0.5ex}{\normalsize 2}C}
\begin{document}
\section*{Hardwarenahe Programmierung\\
Musterlösung zu den Übungsaufgaben -- 19.\ Dezember 2019}
\exercise{Trickprogrammierung}
Wir betrachten das folgende Programm (Datei: \gitfile{hp}{20191219}{aufgabe-1.c}):
\begin{lstlisting}
#include <stdio.h>
#include <stdint.h>
int main (void)
{
uint64_t x = 4262939000843297096;
char *s = &x;
printf ("%s\n", s);
return 0;
}
\end{lstlisting}
Das Programm wird compiliert und auf einem 64-Bit-Little-Endian-Computer ausgeführt:
\begin{lstlisting}[style=terminal]
$ ¡gcc -Wall -O aufgabe-1.c -o aufgabe-1¿
aufgabe-1.c: In function `main':
aufgabe-1.c:7:13: warning: initialization from incompatible pointer type [...]
$ ¡./aufgabe-1¿
Hallo
\end{lstlisting}
\begin{itemize}
\item[(a)]
Erklären Sie die Warnung beim Compilieren. \points{2}
\item[(b)]
Erklären Sie die Ausgabe des Programms. \points{5}
\item[(c)]
Wie würde die Ausgabe des Programms auf einem 64-Bit-Big-Endian-Computer lauten? \points{3}
\end{itemize}
Hinweis: Modifizieren Sie das Programm
und lassen Sie sich Speicherinhalte ausgeben.
\solution
\begin{itemize}
\item[(a)]
\textbf{Erklären Sie die Warnung beim Compilieren.}
Zeile 7 des Programms enthält eine Zuweisung von \lstinline{&x}
an die Variable \lstinline{s}.
Der Ausdruck \lstinline{&x} steht für die Speicheradresse der Variablen \lstinline{x},
ist also ein Zeiger auf \lstinline{x},
also ein Zeiger auf eine \lstinline{uint64_t}.
Die Variable \lstinline{s} hingegen ist ein Zeiger auf \lstinline{char},
also ein Zeiger auf eine viel kleinere Zahl,
also ein anderer Zeigertyp.
\item[(b)]
\textbf{Erklären Sie die Ausgabe des Programms.}
Die 64-Bit-Zahl (\lstinline{uint64_t}) \lstinline{x}
belegt 8 Speicherzellen (Bytes) von jeweils 8 Bit.
Um herauszufinden, was diese enthalten,
lassen wir uns \lstinline{x} als Hexadezimalzahl ausgeben,
z.\,B.\ mittels \lstinline{printf ("%lx\n", x)}
(auf 32-Bit-Rechnern: \lstinline{"%llx\n"})
oder mittels \lstinline{printf ("%" PRIx64 "\n", x)}
(erfordert \lstinline{#include <inttypes.h>}
-- siehe die Datei \gitfile{hp}{20191219}{loesung-1-1.c}).
Das Ergebnis lautet:
\begin{lstlisting}[style=terminal,gobble=8]
3b29006f6c6c6148
\end{lstlisting}
Auf einzelne Bytes verteilt:
\begin{lstlisting}[style=terminal,gobble=8]
3b 29 00 6f 6c 6c 61 48
\end{lstlisting}
Auf einem Little-Endian-Rechner
ist die Reihenfolge der Bytes in den Speicherzellen genau umgekehrt:
\begin{lstlisting}[style=terminal,gobble=8]
48 61 6c 6c 6f 00 29 3b
\end{lstlisting}
Wenn wir uns diese Bytes als Zeichen ausgeben lassen
(\lstinline{printf()} mit \lstinline{%c} -- siehe die Datei \gitfile{hp}{20191219}{loesung-1-2.c}),
erhalten wir:
\begin{lstlisting}[style=terminal,gobble=8]
H a l l o ) ;
\end{lstlisting}
Das Zeichen hinter "`Hallo"' ist ein Null-Symbol (Zahlenwert 0)
und wird von \lstinline{printf ("%s")} als Ende des Strings erkannt.
Damit ist die Ausgabe \lstinline[style=terminal]{Hallo}
des Programms erklärt.
\goodbreak
\item[(c)]
\textbf{Wie würde die Ausgabe des Programms auf einem 64-Bit-Big-Endian-Computer lauten?}
Auf einem Big-Endian-Computer (egal, wieviele Bits die Prozessorregister haben)
ist die Reihenfolge der Bytes in den Speicherzellen genau umgekehrt
wie auf einem Little-Endian-Computer, hier also:
\begin{lstlisting}[style=terminal,gobble=8]
3b 29 00 6f 6c 6c 61 48
\end{lstlisting}
\lstinline{printf ("%s")} gibt in diesem Fall die Hexadezimalzahlen
\lstinline[style=terminal]{3b} und \lstinline[style=terminal]{29}
als Zeichen aus. Danach steht das String-Ende-Symbol mit Zahlenwert 0,
und die Ausgabe bricht ab.
Da, wie oben ermittelt, die Hexadezimalzahl \lstinline[style=terminal]{3b}
für das Zeichen \lstinline[style=terminal]{;}
und \lstinline[style=terminal]{29}
für das Zeichen \lstinline[style=terminal]{)} steht,
lautet somit die Ausgabe:
\begin{lstlisting}[style=terminal,gobble=8]
;)
\end{lstlisting}
Um die Aufgabe zu lösen, können Sie übrigens auch
auf einem Little-Endian-Computer (Standard-Notebook)
einen Big-Endian-Computer simulieren,
indem Sie die Reihenfolge der Bytes in der Zahl \lstinline{x} umdrehen
-- siehe die Datei \gitfile{hp}{20191219}{loesung-1-3.c}.
\end{itemize}
\exercise{Thermometer-Baustein an \ITWOC-Bus}
Eine Firma stellt einen elektronischen Thermometer-Baustein her,
den man über die serielle Schnittstelle (RS-232) an einen PC anschließen kann,
um die Temperatur auszulesen.
Nun wird eine Variante des Thermo"-meter-Bausteins entwickelt,
die die Temperatur zusätzlich über einen \ItwoC-Bus bereitstellt.
Um das neue Thermometer zu testen, wird es in ein Gefäß mit heißem Wasser gelegt,
das langsam auf Zimmertemperatur abkühlt.
Alle 10 Minuten liest ein Programm, das auf dem PC läuft,
die gemessene Temperatur über beide Schnittstellen aus
und erzeugt daraus die folgende Tabelle:
\begin{center}
\renewcommand{\arraystretch}{1.2}
\begin{tabular}{|c|c|c|}\hline
Zeit /\,min. & Temperatur per RS-232 /\,\degree C & Temperatur per \ItwoC\ /\,\degree C \\\hline\hline
\phantom{0}0 & 94 & 122 \\\hline
10 & 47 & 244 \\\hline
20 & 30 & 120 \\\hline
30 & 24 & \phantom{0}24 \\\hline
40 & 21 & 168 \\\hline
\end{tabular}
\end{center}
\begin{itemize}
\item[(a)]
Aus dem Vergleich der Meßdaten läßt sich
auf einen Fehler bei der \ItwoC-Übertragung schließen.\\
Um welchen Fehler handelt es sich,
und wie ergibt sich dies aus den Meßdaten?
\points{5}
\item[(b)]
Schreiben Sie eine C-Funktion \lstinline{uint8_t repair (uint8_t data)},
die eine über den \ItwoC-Bus empfangene fehlerhafte Temperatur \lstinline{data} korrigiert.
\points{5}
\end{itemize}
\solution
\begin{itemize}
\item[(a)]
\textbf{Aus dem Vergleich der Meßdaten läßt sich
auf einen Fehler bei der \ItwoC-Übertragung schließen.
Um welchen Fehler handelt es sich,
und wie ergibt sich dies aus den Meßdaten?}
Sowohl RS-232 als auch \ItwoC\ übertragen die Daten Bit für Bit.
Für die Fehlersuche ist es daher sinnvoll,
die Meßwerte als Binärzahlen zu betrachten:
\begin{center}
\renewcommand{\arraystretch}{1.2}
\begin{tabular}{|c|c|c|}\hline
Zeit /\,min. & Temperatur per RS-232 /\,\degree C & Temperatur per \ItwoC\ /\,\degree C \\\hline\hline
\phantom{0}0 & 94$_{10}$ = 01011110$_2$ & 122$_{10}$ = 01111010$_2$ \\\hline
10 & 47$_{10}$ = 00101111$_2$ & 244$_{10}$ = 11110100$_2$ \\\hline
20 & 30$_{10}$ = 00011110$_2$ & 120$_{10}$ = 01111000$_2$ \\\hline
30 & 24$_{10}$ = 00011000$_2$ & \phantom{0}24$_{10}$ = 00011000$_2$ \\\hline
40 & 21$_{10}$ = 00010101$_2$ & 168$_{10}$ = 10101000$_2$ \\\hline
\end{tabular}
\end{center}
Man erkennt, daß die Reihenfolge der Bits in den (fehlerhaften) \ItwoC-Meßwerten
genau die umgekehrte Reihenfolge der Bits in den (korrekten) RS-232-Mewßwerten ist.
Der Übertragungsfehler besteht also darin,
daß die Bits in der falschen Reihenfolge übertragen wurden.
Dies paßt gut damit zusammen,
daß die Bit-Reihenfolge von \ItwoC\ \emph{MSB First}, die von RS-232 hingegen \emph{LSB First\/} ist.
Offenbar haben die Entwickler der \ItwoC-Schnittstelle dies übersehen
und die \ItwoC-Daten ebenfalls \emph{LSB First\/} übertragen.
\goodbreak
\item[(b)]
\textbf{Schreiben Sie eine C-Funktion \lstinline{uint8_t repair (uint8_t data)},
die eine über den \ItwoC-Bus empfangene fehlerhafte Temperatur \lstinline{data} korrigiert.}
Die Aufgabe der Funktion besteht darin,
eine 8-Bit-Zahl \lstinline{data} entgegenzunehmen,
die Reihenfolge der 8 Bits genau umzudrehen
und das Ergebnis mittels \lstinline{return} zurückzugeben.
Zu diesem Zweck gehen wir die 8 Bits in einer Schleife durch
-- siehe die Datei \gitfile{hp}{20191219}{loesung-2.c}.
Wir lassen eine Lese-Maske \lstinline{mask_data} von rechts nach links
und gleichzeitig eine Schreib-Maske \lstinline{mask_result}
von links nach rechts wandern.
Immer wenn die Lese-Maske in \lstinline{data} eine 1 findet,
schreibt die Schreib-Maske diese in die Ergebnisvariable \lstinline{result}.
Da \lstinline{result} auf 0 initialisiert wurde,
brauchen wir Nullen nicht hineinzuschreiben.
Ansonsten wäre dies mit \lstinline{result &= ~mask_result} möglich.
Um die Schleife bis 8 zählen zu lassen,
könnte man eine weitere Zähler-Variable von 0 bis 7 zählen lassen,
z.\,B.\ \lstinline{for (int i = 0; i < 8; i++)}.
Dies ist jedoch nicht nötig, wenn man beachtet,
daß die Masken den Wert 0 annehmen,
sobald das Bit aus der 8-Bit-Variablen herausgeschoben wurde.
In \gitfile{hp}{20191219}{loesung-2.c} wird \lstinline{mask_data} auf 0 geprüft;
genausogut könnte man auch \lstinline{mask_result} prüfen.
Das \lstinline{return result} ist notwendig.
Eine Ausgabe des Ergebnisses per \lstinline{printf()} o.\,ä.\
erfüllt \emph{nicht\/} die Aufgabenstellung.
(In \gitfile{hp}{20191219}{loesung-2.c} erfolgt entsprechend \lstinline{printf()}
nur im Testprogramm \lstinline{main()}.)
\end{itemize}
\end{document}
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main (void)
{
uint64_t x = 4262939000843297096;
char *s = &x;
printf ("%lx\n", x);
printf ("%" PRIx64 "\n", x);
printf ("%s\n", s);
return 0;
}
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main (void)
{
uint64_t x = 4262939000843297096;
char *s = &x;
printf ("%lx\n", x);
printf ("%" PRIx64 "\n", x);
printf ("%c %c %c %c %c %c %c %c\n",
0x48, 0x61, 0x6c, 0x6c, 0x6f, 0x00, 0x29, 0x3b);
printf ("%s\n", s);
return 0;
}
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main (void)
{
uint64_t x = 0x48616c6c6f00293b;
char *s = &x;
printf ("%s\n", s);
return 0;
}
#include <stdio.h>
#include <stdint.h>
uint8_t repair (uint8_t data)
{
uint8_t result = 0;
uint8_t mask_data = 0x01;
uint8_t mask_result = 0x80;
while (mask_data)
{
if (data & mask_data)
result |= mask_result;
mask_data <<= 1;
mask_result >>= 1;
}
return result;
}
int main (void)
{
int data[] = { 122, 244, 120, 24, 168, -1 };
int i = 0;
while (data[i] >= 0)
printf ("%d\n", repair (data[i++]));
return 0;
}
...@@ -60,6 +60,8 @@ Musterlösungen: ...@@ -60,6 +60,8 @@ Musterlösungen:
* [14.11.2019: Ausgabe von Hexadezimalzahlen, Einfügen in Strings, Länge von Strings](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191114/hp-musterloesung-20191114.pdf) * [14.11.2019: Ausgabe von Hexadezimalzahlen, Einfügen in Strings, Länge von Strings](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191114/hp-musterloesung-20191114.pdf)
* [21.11.2019: Zahlensysteme, Mikrocontroller](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191121/hp-musterloesung-20191121.pdf) * [21.11.2019: Zahlensysteme, Mikrocontroller](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191121/hp-musterloesung-20191121.pdf)
* [28.11.2019: Datum-Bibliothek, Text-Grafik-Bibliothek, LED-Blinkmuster](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191128/hp-musterloesung-20191128.pdf) * [28.11.2019: Datum-Bibliothek, Text-Grafik-Bibliothek, LED-Blinkmuster](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191128/hp-musterloesung-20191128.pdf)
* [12.12.2019: Kondensator, hüpfender Ball](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191212/hp-musterloesung-20191212.pdf)
* [19.12.2019: Trickprogrammierung, Thermometer-Baustein an I²C-Bus](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191219/hp-musterloesung-20191219.pdf)
* [09.01.2020: Speicherformate von Zahlen, Zeigerarithmetik, Personen-Datenbank](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20200109/hp-musterloesung-20200109.pdf) * [09.01.2020: Speicherformate von Zahlen, Zeigerarithmetik, Personen-Datenbank](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20200109/hp-musterloesung-20200109.pdf)
* [16.01.2020: Fakultät, Länge von Strings (Neuauflage), objektorientierte Tier-Datenbank](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20200116/hp-musterloesung-20200116.pdf) * [16.01.2020: Fakultät, Länge von Strings (Neuauflage), objektorientierte Tier-Datenbank](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20200116/hp-musterloesung-20200116.pdf)
* [23.01.2020: Stack-Operationen, Iteratorfunktionen, dynamisches Bit-Array](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20200123/hp-musterloesung-20200123.pdf) * [23.01.2020: Stack-Operationen, Iteratorfunktionen, dynamisches Bit-Array](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20200123/hp-musterloesung-20200123.pdf)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment