diff --git a/20211115/Makefile b/20211115/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..7ae33df99f68fcf460324cfbb008f3f7a3863638 --- /dev/null +++ b/20211115/Makefile @@ -0,0 +1,8 @@ +%.elf: %.c + avr-gcc -Wall -Os -mmcu=atmega328p $< -o $@ + +%.hex: %.elf + avr-objcopy -O ihex $< $@ + +download: + ./download.sh diff --git a/20211115/aufgabe-2.c b/20211115/aufgabe-2.c new file mode 100644 index 0000000000000000000000000000000000000000..1afa7b1260506cb307aff5f929c6357c7bdcb708 --- /dev/null +++ b/20211115/aufgabe-2.c @@ -0,0 +1,15 @@ +#include <avr/io.h> + +int main (void) +{ + DDRA = 0xff; + DDRB = 0xff; + DDRC = 0xff; + DDRD = 0xff; + PORTA = 0x1f; + PORTB = 0x10; + PORTD = 0x10; + PORTC = 0xfc; + while (1); + return 0; +} diff --git a/20211115/aufgabe-3.c b/20211115/aufgabe-3.c new file mode 100644 index 0000000000000000000000000000000000000000..9ae72941b931c04f3c380cb3bbcd64bec7f08c20 --- /dev/null +++ b/20211115/aufgabe-3.c @@ -0,0 +1,18 @@ +#include <stdio.h> +#include <string.h> + +void insert_into_string (char src, char *target, int pos) +{ + int len = strlen (target); + for (int i = pos; i < len; i++) + target[i+1] = target[i]; + target[pos] = src; +} + +int main (void) +{ + char test[100] = "Hochshule Bochum"; + insert_into_string ('c', test, 5); + printf ("%s\n", test); + return 0; +} diff --git a/20211115/blink-0.c b/20211115/blink-0.c new file mode 100644 index 0000000000000000000000000000000000000000..b0022c681fd1482ed0a6d9fded7bb0a54699de32 --- /dev/null +++ b/20211115/blink-0.c @@ -0,0 +1,9 @@ +#include <avr/io.h> + +int main (void) +{ + DDRD = 0x40; /* binär: 0100 0000 */ + PORTD = 0x40; /* binär: 0100 0000 */ + while (1); + return 0; +} diff --git a/20211115/blink-1.c b/20211115/blink-1.c new file mode 100644 index 0000000000000000000000000000000000000000..6d28dce84f94375094c98479c30a54ace1b2a9d9 --- /dev/null +++ b/20211115/blink-1.c @@ -0,0 +1,18 @@ +#include <avr/io.h> + +#define F_CPU 16000000l +#include <util/delay.h> + +int main (void) +{ + DDRD = 0x01; + PORTD |= 0x01; + while (1) + { + _delay_ms (500); + PORTD &= ~0x01; + _delay_ms (500); + PORTD |= 0x01; + } + return 0; +} diff --git a/20211115/blink-2.c b/20211115/blink-2.c new file mode 100644 index 0000000000000000000000000000000000000000..b00eaf522563b1e8fa75f80e784de5b9f1af58e9 --- /dev/null +++ b/20211115/blink-2.c @@ -0,0 +1,16 @@ +#include <avr/io.h> + +#define F_CPU 16000000l +#include <util/delay.h> + +int main (void) +{ + DDRD = 0x02; + PORTD = 0x02; + while (1) + { + _delay_ms (250); + PORTD ^= 0x02; + } + return 0; +} diff --git a/20211115/blink-3.c b/20211115/blink-3.c new file mode 100644 index 0000000000000000000000000000000000000000..5268e7977f0f2a99b2005a81a2fa7560dfea481f --- /dev/null +++ b/20211115/blink-3.c @@ -0,0 +1,17 @@ +#include <avr/io.h> + +#define F_CPU 16000000 +#include <util/delay.h> + +int main (void) +{ + DDRD = 0x01; + PORTD = 0x01; + while (1) + { + while ((PIND & 0x02) == 0) + ; /* just wait */ + PORTD ^= 0x01; + } + return 0; +} diff --git a/20211115/blink-4.c b/20211115/blink-4.c new file mode 100644 index 0000000000000000000000000000000000000000..7344aa7ce19086d6e0a0dc4f8de78499f280931b --- /dev/null +++ b/20211115/blink-4.c @@ -0,0 +1,18 @@ +#include <avr/io.h> + +#define F_CPU 16000000 +#include <util/delay.h> + +int main (void) +{ + DDRD = 0x01; + PORTD = 0x01; + while (1) + { + while ((PIND & 0x02) == 0) + ; /* just wait */ + PORTD ^= 0x01; + _delay_ms (200); + } + return 0; +} diff --git a/20211115/download.sh b/20211115/download.sh new file mode 100755 index 0000000000000000000000000000000000000000..770c3b5dca74ac09778be055c9d6f5adb0df293b --- /dev/null +++ b/20211115/download.sh @@ -0,0 +1,3 @@ +port=$(ls -rt /dev/ttyACM* | tail -1) +echo avrdude -P $port -c arduino -p m328p -U flash:w:$(ls -rt *.hex | tail -1) +avrdude -P $port -c arduino -p m328p -U flash:w:$(ls -rt *.hex | tail -1) 2>/dev/null diff --git a/20211115/hp-20211115.pdf b/20211115/hp-20211115.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d8829973c09d12dd155894ae248cd1938f9c2685 Binary files /dev/null and b/20211115/hp-20211115.pdf differ diff --git a/20211115/hp-20211115.tex b/20211115/hp-20211115.tex new file mode 100644 index 0000000000000000000000000000000000000000..5494681e9d2eb0569d24e5f7971e90f2bef9034c --- /dev/null +++ b/20211115/hp-20211115.tex @@ -0,0 +1,1122 @@ +% hp-20211115.pdf - Lecture Slides on Low-Level Programming +% Copyright (C) 2012, 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021 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: I/O-Ports, Interrupts + +\documentclass[10pt,t]{beamer} + +\usepackage{pgslides} +\usepackage{pdftricks} +\usepackage{tikz} + +\begin{psinputs} + \usepackage[utf8]{inputenc} + \usepackage[german]{babel} + \usepackage[T1]{fontenc} + \usepackage{helvet} + \renewcommand*\familydefault{\sfdefault} + \usepackage{pstricks,pst-grad} +\end{psinputs} + +\title{Hardwarenahe Programmierung} +\author{Prof.\ Dr.\ rer.\ nat.\ Peter Gerwinski} +\date{15.\ November 2021} + +\begin{document} + +\maketitleframe + +\nosectionnonumber{\inserttitle} + +\begin{frame} + + \shownosectionnonumber + + \begin{itemize} + \item[\textbf{1}] \textbf{Einführung} + \hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp}}} + \item[\textbf{2}] \textbf{Einführung in C} + \begin{itemize} + \vspace*{-\smallskipamount} + \item[\dots] + \item[2.12] Strukturen + \item[2.13] Dateien und Fehlerbehandlung + \color{medgreen} + \item[2.14] Parameter des Hauptprogramms + \item[2.15] String-Operationen + \end{itemize} + \item[\textbf{3}] \textbf{Bibliotheken} + \item[\textbf{4}] \textbf{Hardwarenahe Programmierung} + \begin{itemize} + \color{medgreen} + \item[4.1] Bit-Operationen + \color{orange} + \item[4.2] I/O-Ports + \color{red} + \item[4.3] Interrupts + \vspace*{-0.1cm} + \item[\dots] + \end{itemize} + \item[\textbf{5}] \textbf{Algorithmen} + \vspace*{-\smallskipamount} + \item[\textbf{\dots}] + \end{itemize} + +\end{frame} + +\setcounter{section}{1} +\section{Einführung in C} +\setcounter{subsection}{13} +\subsection{Parameter des Hauptprogramms} + +\begin{frame}[fragile] + + \showsubsection + + \vspace*{-\bigskipamount} + + \begin{lstlisting} + #include <stdio.h> + + int main (int argc, char **argv) + { + printf ("argc = %d\n", argc); + for (int i = 0; i < argc; i++) + printf ("argv[%d] = \"%s\"\n", i, argv[i]); + return 0; + } + \end{lstlisting} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + \vspace*{-\bigskipamount} + + \begin{lstlisting} + #include <stdio.h> + + int main (int argc, char **argv) + { + printf ("argc = %d\n", argc); + for (int i = 0; *argv; i++, argv++) + printf ("argv[%d] = \"%s\"\n", i, *argv); + return 0; + } + \end{lstlisting} + +\end{frame} + +\subsection{String-Operationen} + +\begin{frame}[fragile] + + \showsubsection + + \vspace*{-\bigskipamount} + + \begin{lstlisting} + #include <stdio.h> + #include <string.h> + + int main (void) + { + char hello[] = "Hello, world!\n"; + + printf ("%s\n", hello); + printf ("%zd\n", strlen (hello)); + + printf ("%s\n", hello + 7); + printf ("%zd\n", strlen (hello + 7)); + + hello[5] = 0; + printf ("%s\n", hello); + printf ("%zd\n", strlen (hello)); + + return 0; + } + \end{lstlisting} + \vspace*{-1cm} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + \vspace*{-\bigskipamount} + + \begin{lstlisting} + #include <stdio.h> + #include <string.h> + + int main (void) + { + char *anton = "Anton"; + char *zacharias = "Zacharias"; + + printf ("%d\n", strcmp (anton, zacharias)); + printf ("%d\n", strcmp (zacharias, anton)); + printf ("%d\n", strcmp (anton, anton)); + + char buffer[100] = "Huber "; + strcat (buffer, anton); + printf ("%s\n", buffer); + + return 0; + } + \end{lstlisting} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + \vspace*{-\bigskipamount} + + \begin{lstlisting} + #include <stdio.h> + #include <string.h> + + int main (void) + { + char buffer[100] = ""; + sprintf (buffer, "Die Antwort lautet: %d", 42); + printf ("%s\n", buffer); + + char *answer = strstr (buffer, "Antwort"); + printf ("%s\n", answer); + printf ("found at: %zd\n", answer - buffer); + + return 0; + } + \end{lstlisting} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + \vspace*{-\bigskipamount} + + \begin{lstlisting} + #include <stdio.h> + #include <string.h> + + int main (void) + { + char buffer[100] = ""; + snprintf (buffer, 100, "Die Antwort lautet: %d", 42); + printf ("%s\n", buffer); + + char *answer = strstr (buffer, "Antwort"); + printf ("%s\n", answer); + printf ("found at: %zd\n", answer - buffer); + + return 0; + } + \end{lstlisting} + +\end{frame} + +\begin{frame} + + \showsection + + Sprachelemente weitgehend komplett + + \bigskip + Es fehlen: + \begin{itemize} + \item + Ergänzungen (z.\,B.\ ternärer Operator, \lstinline{union}, \lstinline{unsigned}, \lstinline{volatile}) + \item + Bibliotheksfunktionen (z.\,B.\ \lstinline{malloc()}) + \arrowitem + werden eingeführt, wenn wir sie brauchen + \bigskip + \item + Konzepte (z.\,B.\ rekursive Datenstrukturen, Klassen selbst bauen) + \arrowitem + werden eingeführt, wenn wir sie brauchen, oder: + \arrowitem + Literatur\\[\smallskipamount] + (z.\,B.\ Wikibooks: C-Programmierung,\\ + Dokumentation zu Compiler und Bibliotheken) + \bigskip + \item + Praxiserfahrung + \arrowitem + Übung und Praktikum: nur Einstieg + \arrowitem + selbständig arbeiten + \end{itemize} +\end{frame} + +\nosectionnonumber{\inserttitle} + +\begin{frame} + + \shownosectionnonumber + + \begin{itemize} + \item[\textbf{1}] \textbf{Einführung} + \hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp.git}}} + \item[\textbf{2}] \textbf{Einführung in C} + \item[\textbf{3}] \textbf{Bibliotheken} + \item[\textbf{4}] \textbf{Hardwarenahe Programmierung} + \begin{itemize} + \color{medgreen} + \item[4.1] Bit-Operationen + \color{orange} + \item[4.2] I/O-Ports + \color{red} + \item[4.3] Interrupts + \item[4.4] volatile-Variable + \item[4.6] Byte-Reihenfolge -- Endianness + \item[4.7] Binärdarstellung negativer Zahlen + \item[4.8] Speicherausrichtung -- Alignment + \end{itemize} + \item[\textbf{5}] \textbf{Algorithmen} + \item[\textbf{\dots}] +% \item[\textbf{4}] \textbf{Hardwarenahe Programmierung} +% \item[\textbf{5}] \textbf{Algorithmen} +% \item[\textbf{6}] \textbf{Ergänzungen und Ausblicke} + \end{itemize} + \vspace*{-1cm} + +\end{frame} + +\setcounter{section}{4} +\section{Hardwarenahe Programmierung} +\subsection{Bit-Operationen} +\subsubsection{Zahlensysteme} + +\begin{frame}[fragile] + + \showsection + \vspace*{-\smallskipamount} + \showsubsection + \vspace*{-\medskipamount} + \showsubsubsection + + \begin{tabular}{rlrl} + Basis & Name & Beispiel & Anwendung \\[\smallskipamount] + 2 & Binärsystem & 1\,0000\,0011 & Bit-Operationen \\ + 8 & Oktalsystem & \lstinline,0403, & Dateizugriffsrechte (Unix) \\ + 10 & Dezimalsystem & \lstinline,259, & Alltag \\ + 16 & Hexadezimalsystem & \lstinline,0x103, & Bit-Operationen \\ + 256 & (keiner gebräuchlich) & 0.0.1.3 & IP-Adressen (IPv4) + \end{tabular} + + \bigskip + + \begin{itemize} + \item + Computer rechnen im Binärsystem. + \item + Für viele Anwendungen (z.\,B.\ I/O-Ports, Grafik, \dots) ist es notwendig,\\ + Bits in Zahlen einzeln ansprechen zu können. + \end{itemize} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsubsection + + \begin{tabular}{rlrlrc} + \qquad 000 & \bf 0 \hspace*{1.5cm} & 0000 & \bf 0 & \quad 1000 & \bf 8\\ + 001 & \bf 1 & 0001 & \bf 1 & 1001 & \bf 9\\ + 010 & \bf 2 & 0010 & \bf 2 & 1010 & \bf A\\ + 011 & \bf 3 & 0011 & \bf 3 & 1011 & \bf B\\[\smallskipamount] + 100 & \bf 4 & 0100 & \bf 4 & 1100 & \bf C\\ + 101 & \bf 5 & 0101 & \bf 5 & 1101 & \bf D\\ + 110 & \bf 6 & 0110 & \bf 6 & 1110 & \bf E\\ + 111 & \bf 7 & 0111 & \bf 7 & 1111 & \bf F\\ + \end{tabular} + + \medskip + + \begin{itemize} + \item + Oktal- und Hexadezimalzahlen lassen sich ziffernweise\\ + in Binär-Zahlen umrechnen. + \item + Hexadezimalzahlen sind eine Kurzschreibweise für Binärzahlen,\\ + gruppiert zu jeweils 4 Bits. + \item + Oktalzahlen sind eine Kurzschreibweise für Binärzahlen,\\ + gruppiert zu jeweils 3 Bits. + \item + Trotz Taschenrechner u.\,ä.\ lohnt es sich,\\ + die o.\,a.\ Umrechnungstabelle \textbf{auswendig} zu kennen. + \end{itemize} + +\end{frame} + +\subsubsection{Bit-Operationen in C} + +\begin{frame}[fragile] + + \showsubsubsection + + \begin{tabular}{lll} + C-Operator & Verknüpfung & Anwendung \\[\smallskipamount] + \lstinline,&, & Und & Bits gezielt löschen \\ + \lstinline,|, & Oder & Bits gezielt setzen \\ + \lstinline,^, & Exklusiv-Oder & Bits gezielt invertieren \\ + \lstinline,~, & Nicht & Alle Bits invertieren \\[\smallskipamount] + \lstinline,<<, & Verschiebung nach links & Maske generieren \\ + \lstinline,>>, & Verschiebung nach rechts & Bits isolieren + \end{tabular} + + \bigskip + + Numerierung der Bits: von rechts ab 0 + + \medskip + + \begin{tabular}{ll} + Bit Nr.\ 3 auf 1 setzen: & + \lstinline,a |= 1 << 3;, \\ + Bit Nr.\ 4 auf 0 setzen: & + \lstinline,a &= ~(1 << 4);, \\ + Bit Nr.\ 0 invertieren: & + \lstinline,a ^= 1 << 0;, + \end{tabular} + + \smallskip + + ~~Abfrage, ob Bit Nr.\ 1 gesetzt ist:\quad + \lstinline{if (a & (1 << 1))} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsubsection + + C-Datentypen für Bit-Operationen: + \smallskip\par + \lstinline{#include <stdint.h>} + \medskip\par + \begin{tabular}{lllll} + & 8 Bit & 16 Bit & 32 Bit & 64 Bit \\ + mit Vorzeichen & \lstinline,int8_t, + & \lstinline,int16_t, + & \lstinline,int32_t, + & \lstinline,int64_t, \\ + ohne Vorzeichen & \lstinline,uint8_t, + & \lstinline,uint16_t, + & \lstinline,uint32_t, + & \lstinline,uint64_t, + \end{tabular} + + \bigskip + \bigskip + + Ausgabe: + \smallskip\par + \begin{lstlisting} + #include <stdio.h> + #include <stdint.h> + #include <inttypes.h> + ... + uint64_t x = 42; + printf ("Die Antwort lautet: %" PRIu64 "\n", x); + \end{lstlisting} + +\end{frame} + +\subsection{I/O-Ports} + +\begin{frame}[fragile] + +% \showsection + \showsubsection + \vspace*{-1.5\medskipamount} + {\large\textbf{\color{structure}5.3\quad Interrupts}} + + \bigskip + + Kommunikation mit externen Geräten + + \bigskip + + \begin{center} + \includegraphics{io-ports-and-interrupts.pdf} + \end{center} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + In Output-Port schreiben = Aktoren ansteuern + + Beispiel: LED + + \medskip + + \begin{lstlisting} + #include <avr/io.h> + ... + DDRC = 0x70; + PORTC = 0x40; + \end{lstlisting} + \begin{picture}(0,0) + \put(3,0.67){\begin{minipage}{3cm} + \color{red}% + binär: 0111\,0000\\ + binär: 0100\,0000 + \end{minipage}} + \put(10,0.67){\makebox(0,0)[r]{\color{red}Herstellerspezifisch!}} + \end{picture} + + \bigskip + + \lstinline{DDR} = Data Direction Register\\ + Bit = 1 für Output-Port\\ + Bit = 0 für Input-Port + + \bigskip + + \emph{Details: siehe Datenblatt und Schaltplan} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + Aus Input-Port lesen = Sensoren abfragen + + Beispiel: Taster + + \medskip + + \begin{lstlisting} + #include <avr/io.h> + ... + DDRC = 0xfd; + while ((PINC & 0x02) == 0) + ; /* just wait */ + \end{lstlisting} + \begin{picture}(0,0)(-1.5,-0.42) + \put(3,0.67){\begin{minipage}{3cm} + \color{red}% + binär: 1111\,1101\\ + binär: 0000\,0010 + \end{minipage}} + \put(10,0.67){\makebox(0,0)[r]{\color{red}Herstellerspezifisch!}} + \end{picture} + + \bigskip + + \lstinline{DDR} = Data Direction Register\\ + Bit = 1 für Output-Port\\ + Bit = 0 für Input-Port + + \bigskip + + \emph{Details: siehe Datenblatt und Schaltplan} + + \bigskip + + Praktikumsaufgabe: Druckknopfampel + +\end{frame} + +\subsection{Interrupts} + +\begin{frame}[fragile] + + \showsubsection + + Externes Gerät ruft (per Stromsignal) Unterprogramm auf + + Zeiger hinterlegen: "`Interrupt-Vektor"' + + Beispiel: eingebaute Uhr\hfill + \makebox(0,0)[tr]{% + \only<1->{\begin{minipage}[t]{4.7cm} + \vspace*{-0.3cm}% + statt Zählschleife (\lstinline{_delay_ms}):\\ + Hauptprogramm kann\\ + andere Dinge tun + \end{minipage}}% + } + + \medskip + + \begin{lstlisting} + #include <avr/interrupt.h> + + ... + + + ISR (TIMER0B_COMP_vect) + { + PORTD ^= 0x40; + } + \end{lstlisting} + \begin{picture}(0,0) + \color{red} + \put(1.9,3.1){\makebox(0,0)[tr]{\tikz{\draw[-latex](0,0)--(-1.4,-1.0);}}} + \put(2.0,3.2){\makebox(0,0)[l]{"`Dies ist ein Interrupt-Handler."'}} + \put(2.3,2.6){\makebox(0,0)[tr]{\tikz{\draw[-latex](0,0)--(-0.6,-0.55);}}} + \put(2.4,2.6){\makebox(0,0)[l]{Interrupt-Vektor darauf zeigen lassen}} + \end{picture} + + Initialisierung über spezielle Ports: + \lstinline{TCCR0B}, \lstinline{TIMSK0} + + \bigskip + + \emph{Details: siehe Datenblatt und Schaltplan} + + \vspace*{-2.5cm}\hfill + {\color{red}Herstellerspezifisch!}% + \hspace*{1cm} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + Externes Gerät ruft (per Stromsignal) Unterprogramm auf + + Zeiger hinterlegen: "`Interrupt-Vektor"' + + Beispiel: Taster\hfill + \makebox(0,0)[tr]{% + \begin{minipage}[t]{4.7cm} + \vspace*{-0.3cm}% + statt \newterm{Busy Waiting\/}:\\ + Hauptprogramm kann\\ + andere Dinge tun + \end{minipage}} + + \medskip + + \begin{lstlisting} + #include <avr/interrupt.h> + ... + + ISR (INT0_vect) + { + PORTD ^= 0x40; + } + \end{lstlisting} + + \medskip + + Initialisierung über spezielle Ports: + \lstinline{EICRA}, \lstinline{EIMSK} + + \bigskip + + \emph{Details: siehe Datenblatt und Schaltplan} + + \vspace*{-2.5cm}\hfill + {\color{red}Herstellerspezifisch!}% + \hspace*{1cm} + +\end{frame} + +\subsection{volatile-Variable} + +\begin{frame}[fragile] + + \showsubsection + + Externes Gerät ruft (per Stromsignal) Unterprogramm auf + + Zeiger hinterlegen: "`Interrupt-Vektor"' + + Beispiel: Taster + + \vspace*{-2.5pt} + + \begin{minipage}[t]{5cm} + \begin{onlyenv}<1> + \begin{lstlisting}[gobble=8] + ¡#include <avr/interrupt.h> + ... + + uint8_t key_pressed = 0; + + ISR (INT0_vect) + { + key_pressed = 1; + }¿ + \end{lstlisting} + \end{onlyenv} + \begin{onlyenv}<2> + \begin{lstlisting}[gobble=8] + ¡#include <avr/interrupt.h> + ... + + volatile uint8_t key_pressed = 0; + + ISR (INT0_vect) + { + key_pressed = 1; + }¿ + \end{lstlisting} + \end{onlyenv} + \end{minipage}\hfill + \begin{minipage}[t]{6cm} + \begin{lstlisting}[gobble=6] + ¡int main (void) + { + ... + + while (1) + { + while (!key_pressed) + ; /* just wait */ + PORTD ^= 0x40; + key_pressed = 0; + } + return 0; + }¿ + \end{lstlisting} + \end{minipage} + + \pause + \begin{picture}(0,0) + \color{red} + \put(10.3,4.0){\makebox(0,0)[b]{\begin{minipage}{6cm} + \begin{center} + \textbf{volatile}:\\ + Speicherzugriff\\ + nicht wegoptimieren + \end{center} + \end{minipage}}} + \put(10.3,3.95){\makebox(0,0)[tr]{\tikz{\draw[-latex](0,0)--(-0.5,-0.9);}}} + \end{picture} + +\end{frame} + +\iffalse + +\begin{frame}[fragile] + + \showsubsection + + Was ist eigentlich \lstinline{PORTD}? + + \bigskip + \pause + + \lstinline[style=cmd]{avr-gcc -Wall -Os -mmcu=atmega328p blink-3.c -E} + + \bigskip + \pause + \lstinline{PORTD = 0x01;}\\ + \textarrow\quad + \lstinline[style=terminal]{(*(volatile uint8_t *)((0x0B) + 0x20)) = 0x01;}\\ + \pause + \begin{picture}(0,2)(0,-1.7) + \color{red} + \put(5.75,0.3){$\underbrace{\rule{2.95cm}{0pt}}_{\mbox{Zahl: \lstinline|0x2B|}}$} + \pause + \put(1.55,0.3){$\underbrace{\rule{4.0cm}{0pt}}_{\mbox{\shortstack[t]{Umwandlung in Zeiger\\ + auf \lstinline|volatile uint8_t|}}}$} + \pause + \put(1.32,-1){\makebox(0,0)[b]{\tikz{\draw[-latex](0,0)--(0,1.3)}}} + \put(1.12,-1.1){\makebox(0,0)[tl]{Dereferenzierung des Zeigers}} + \end{picture} + + \pause + \textarrow\quad + \lstinline|volatile uint8_t|-Variable an Speicheradresse \lstinline|0x2B| + + \pause + \bigskip + \bigskip + + \textarrow\quad + \lstinline|PORTA = PORTB = PORTC = PORTD = 0| ist eine schlechte Idee. + +\end{frame} + +\fi + +\subsection{Byte-Reihenfolge -- Endianness} +\subsubsection{Konzept} + +\begin{frame}[fragile] + + \showsubsection + \showsubsubsection + + Eine Zahl geht über mehrere Speicherzellen.\\ + Beispiel: 16-Bit-Zahl in 2 8-Bit-Speicherzellen + + \smallskip + + Welche Bits liegen wo? + + \pause + \bigskip + + $1027 = 1024 + 2 + 1 = 0000\,0100\,0000\,0011_2 = 0403_{16}$ + + \pause + \bigskip + Speicherzellen: + + \medskip + \begin{tabular}{|c|c|l}\cline{1-2} + \raisebox{-0.25ex}{04} & \raisebox{-0.25ex}{03} & \strut Big-Endian "`großes Ende zuerst"' \\\cline{1-2} + \multicolumn{2}{c}{} & \pause für Menschen leichter lesbar \pause \\ + \multicolumn{3}{c}{} \\[-5pt]\cline{1-2} + \raisebox{-0.25ex}{03} & \raisebox{-0.25ex}{04} & \strut Little-Endian "`kleines Ende zuerst"' \\\cline{1-2} + \multicolumn{2}{c}{} & \pause bei Additionen effizienter + \end{tabular} + + \pause + \medskip + \textarrow\ Geschmackssache + \pause\\ + \quad\textbf{\dots\ außer bei Datenaustausch!} + +% \pause +% \bigskip +% +% Aber: nicht verwechseln! \qquad $0304_{16} = 772$ + +\end{frame} + +\begin{frame} + + \showsubsection + \showsubsubsection + + Eine Zahl geht über mehrere Speicherzellen.\\ + Beispiel: 16-Bit-Zahl in 2 8-Bit-Speicherzellen + + \smallskip + + Welche Bits liegen wo? + + \medskip + + \textarrow\ Geschmackssache\\ + \textbf{\dots\ außer bei Datenaustausch!} + + \begin{itemize} + \item + Dateiformate + \item + Datenübertragung + \end{itemize} + +\end{frame} + +\subsubsection{Dateiformate} + +\begin{frame} + + \showsubsection + \showsubsubsection + + Audio-Formate: Reihenfolge der Bytes in 16- und 32-Bit-Zahlen + \begin{itemize} + \item + RIFF-WAVE-Dateien (\file{.wav}): Little-Endian + \item + Au-Dateien (\file{.au}): Big-Endian + \pause + \item + ältere AIFF-Dateien (\file{.aiff}): Big-Endian + \item + neuere AIFF-Dateien (\file{.aiff}): Little-Endian + \end{itemize} + + \pause + \bigskip + + Grafik-Formate: Reihenfolge der Bits in den Bytes + \begin{itemize} + \item + PBM-Dateien: Big-Endian\only<4->{, MSB first} + \item + XBM-Dateien: Little-Endian\only<4->{, LSB first} + \end{itemize} + \only<4->{MSB/LSB = most/least significant bit} + +\end{frame} + +\subsubsection{Datenübertragung} + +\begin{frame} + + \showsubsection + \showsubsubsection + + \begin{itemize} + \item + RS-232 (serielle Schnittstelle): LSB first + \item + I$^2$C: MSB first + \item + USB: beides + \pause + \medskip + \item + Ethernet: LSB first + \item + TCP/IP (Internet): Big-Endian + \end{itemize} + +\end{frame} + +\subsection{Binärdarstellung negativer Zahlen} + +\begin{frame}[fragile] + + \showsubsection + + Speicher ist begrenzt!\\ + \textarrow\ feste Anzahl von Bits + + \medskip + + 8-Bit-Zahlen ohne Vorzeichen: \lstinline{uint8_t}\\ + \textarrow\ Zahlenwerte von \lstinline{0x00} bis \lstinline{0xff} = 0 bis 255\\ + \pause + \textarrow\ 255 + 1 = 0 + + \pause + \medskip + + 8-Bit-Zahlen mit Vorzeichen: \lstinline{int8_t}\\ + \lstinline{0xff} = 255 ist die "`natürliche"' Schreibweise für $-1$.\\ + \pause + \textarrow\ Zweierkomplement + + \pause + \medskip + + Oberstes Bit = 1: negativ\\ + Oberstes Bit = 0: positiv\\ + \textarrow\ 127 + 1 = $-128$ + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + Speicher ist begrenzt!\\ + \textarrow\ feste Anzahl von Bits + + \medskip + + 16-Bit-Zahlen ohne Vorzeichen: + \lstinline{uint16_t}\hfill\lstinline{uint8_t}\\ + \textarrow\ Zahlenwerte von \lstinline{0x0000} bis \lstinline{0xffff} + = 0 bis 65535\hfill 0 bis 255\\ + \textarrow\ 65535 + 1 = 0\hfill 255 + 1 = 0 + + \medskip + + 16-Bit-Zahlen mit Vorzeichen: + \lstinline{int16_t}\hfill\lstinline{int8_t}\\ + \lstinline{0xffff} = 66535 ist die "`natürliche"' Schreibweise für $-1$.\hfill + \lstinline{0xff} = 255 = $-1$\\ + \textarrow\ Zweierkomplement + + \medskip + + Oberstes Bit = 1: negativ\\ + Oberstes Bit = 0: positiv\\ + \textarrow\ 32767 + 1 = $-32768$ + + \bigskip + Literatur: \url{http://xkcd.com/571/} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + Frage: \emph{Für welche Zahl steht der Speicherinhalt\, + \raisebox{2pt}{% + \tabcolsep0.25em + \begin{tabular}{|c|c|}\hline + \rule{0pt}{11pt}a3 & 90 \\\hline + \end{tabular}} + (hexadezimal)?} + + \pause + \smallskip + Antwort: \emph{Das kommt darauf an.} ;--) + + \pause + \medskip + Little-Endian: + + \smallskip + + \begin{tabular}{lrl} + als \lstinline,int8_t,: & $-93$ & (nur erstes Byte)\\ + als \lstinline,uint8_t,: & $163$ & (nur erstes Byte)\\ + als \lstinline,int16_t,: & $-28509$\\ + als \lstinline,uint16_t,: & $37027$\\ + \lstinline,int32_t, oder größer: & $37027$ + & (zusätzliche Bytes mit Nullen aufgefüllt) + \end{tabular} + + \pause + \medskip + Big-Endian: + + \smallskip + + \begin{tabular}{lrl} + als \lstinline,int8_t,: & $-93$ & (nur erstes Byte)\\ + als \lstinline,uint8_t,: & $163$ & (nur erstes Byte)\\ + als \lstinline,int16_t,: & $-23664$\\ + als \lstinline,uint16_t,: & $41872$\\ als \lstinline,int32_t,: & $-1550843904$ & (zusätzliche Bytes\\ + als \lstinline,uint32_t,: & $2744123392$ & mit Nullen aufgefüllt)\\ + als \lstinline,int64_t,: & $-6660823848880963584$\\ + als \lstinline,uint64_t,: & $11785920224828588032$\\ + \end{tabular} + + \vspace*{-1cm} + +\end{frame} + +\subsection{Speicherausrichtung -- Alignment} + +\begin{frame}[fragile] + + \showsubsection + + \begin{lstlisting} + #include <stdint.h> + + uint8_t a; + uint16_t b; + uint8_t c; + \end{lstlisting} + + \pause + \bigskip + + Speicheradresse durch 2 teilbar -- "`16-Bit-Alignment"' + \begin{itemize} + \item + 2-Byte-Operation: effizienter + \pause + \item + \dots\ oder sogar nur dann erlaubt + \pause + \arrowitem + Compiler optimiert Speicherausrichtung + \end{itemize} + + \medskip + + \pause + \begin{minipage}{3cm} + \begin{lstlisting}[gobble=6] + ¡uint8_t a; + uint8_t dummy; + uint16_t b; + uint8_t c;¿ + \end{lstlisting} + \end{minipage} + \pause + \begin{minipage}{3cm} + \begin{lstlisting}[gobble=6] + ¡uint8_t a; + uint8_t c; + uint16_t b;¿ + \end{lstlisting} + \end{minipage} + + \pause + \vspace{-1.75cm} + \strut\hfill + \begin{minipage}{6.5cm} + Fazit: + \begin{itemize} + \item + \textbf{Adressen von Variablen\\ + sind systemabhängig} + \item + Bei Definition von Datenformaten\\ + Alignment beachten \textarrow\ effizienter + \end{itemize} + \end{minipage} + +\end{frame} + +\nosectionnonumber{\inserttitle} + +\begin{frame} + + \shownosectionnonumber + + \begin{itemize} + \item[\textbf{1}] \textbf{Einführung} + \hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp}}} + \item[\textbf{2}] \textbf{Einführung in C} + \begin{itemize} + \vspace*{-\smallskipamount} + \item[\dots] + \item[2.14] Parameter des Hauptprogramms + \item[2.15] String-Operationen + \end{itemize} + \item[\textbf{3}] \textbf{Bibliotheken} + \item[\textbf{4}] \textbf{Hardwarenahe Programmierung} + \begin{itemize} + \item[4.1] Bit-Operationen + \color{medgreen} + \item[4.2] I/O-Ports + \item[4.3] Interrupts + \item[4.4] volatile-Variable + \color{red} + \item[4.6] Byte-Reihenfolge -- Endianness + \item[4.7] Binärdarstellung negativer Zahlen + \item[4.8] Speicherausrichtung -- Alignment + \end{itemize} + \item[\textbf{5}] \textbf{Algorithmen} + \item[\textbf{\dots}] + \end{itemize} + +\end{frame} + +\end{document} diff --git a/20211115/hp-musterloesung-20211115.pdf b/20211115/hp-musterloesung-20211115.pdf new file mode 100644 index 0000000000000000000000000000000000000000..df7200de50936fd484c8353512876f910317bf5b Binary files /dev/null and b/20211115/hp-musterloesung-20211115.pdf differ diff --git a/20211115/hp-musterloesung-20211115.tex b/20211115/hp-musterloesung-20211115.tex new file mode 100644 index 0000000000000000000000000000000000000000..c9dc97835ada978af0da32a80219a01c97e8257d --- /dev/null +++ b/20211115/hp-musterloesung-20211115.tex @@ -0,0 +1,554 @@ +% hp-musterloesung-20211115.pdf - Solutions to the Exercises on Low-Level Programming +% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021 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: Zahlensysteme, Mikrocontroller, Einfügen in Strings + +\documentclass[a4paper]{article} + +\usepackage{pgscript} + +\begin{document} + + \section*{Hardwarenahe Programmierung\\ + Musterlösung zu den Übungsaufgaben -- l5.\ November 2021} + + \exercise{Zahlensysteme} + + Wandeln Sie ohne Hilfsmittel + + \begin{minipage}[t]{0.3\textwidth} + \begin{itemize} + \item + nach Dezimal: + \begin{itemize} + \item[(a)] + 0010\,0000$_2$ + \item[(b)] + 42$_{16}$ + \item[(c)] + 17$_8$ + \end{itemize} + \end{itemize} + \end{minipage}\hfill + \begin{minipage}[t]{0.3\textwidth} + \begin{itemize} + \item + nach Hexadezimal: + \begin{itemize} + \item[(d)] + 0010\,0000$_2$ + \item[(e)] + 42$_{10}$ + \item[(f)] + 192.168.20.254$_{256}$ + \end{itemize} + \end{itemize} + \end{minipage}\hfill + \begin{minipage}[t]{0.3\textwidth} + \begin{itemize} + \item + nach Binär: + \begin{itemize} + \item[(g)] + 750$_8$ + \item[(h)] + 42$_{10}$ + \item[(i)] + AFFE$_{16}$ + \end{itemize} + \end{itemize} + \end{minipage} + + \medskip + + Berechnen Sie ohne Hilfsmittel: + \begin{itemize} + \item[(j)] + 750$_8$ \& 666$_8$ + \item[(k)] + A380$_{16}$ + B747$_{16}$ + \item[(l)] + AFFE$_{16} >> 1$ + \end{itemize} + + Die tiefgestellte Zahl steht für die Basis des Zahlensystems. + Jede Teilaufgabe zählt 1 Punkt. \addtocounter{points}{12} + + (In der Klausur sind Hilfsmittel zugelassen, + daher ist dies \emph{keine\/} typische Klausuraufgabe.) + + \solution + + Wandeln Sie ohne Hilfsmittel + + \begin{itemize} + \item + nach Dezimal: + \begin{itemize} + \item[(a)] + $0010\,0000_2 = 32_{10}$ + + Eine Eins mit fünf Nullen dahinter steht binär für $2^5 = 32$:\\ + mit $1$ anfangen und fünfmal verdoppeln. + \item[(b)] + $42_{16} = 4 \cdot 16 + 2 \cdot 1 = 64 + 2 = 66$ + \item[(c)] + $17_8 = 1 \cdot 8 + 7 \cdot 1 = 8 + 7 = 15$ + \end{itemize} + Umwandlung von und nach Dezimal ist immer rechenaufwendig. + Umwandlungen zwischen Binär, Oktal und Hexadezimal gehen ziffernweise + und sind daher wesentlich einfacher. + \item + nach Hexadezimal: + \begin{itemize} + \item[(d)] + $0010\,0000_2 = 20_{16}$ + + Umwandlung von Binär nach Hexadezimal geht ziffernweise:\\ + Vier Binärziffern werden zu einer Hex-Ziffer. + \item[(e)] + $\rm 42_{10} = 32_{10} + 10_{10} = 20_{16} + A_{16} = 2A_{16}$ + \item[(f)] + $\rm 192.168.20.254_{256} = C0\,A8\,14\,FE_{16}$ + + Umwandlung von der Basis 256 nach Hexadezimal geht ziffernweise:\\ + Eine 256er-Ziffer wird zu zwei Hex-Ziffern. + + Da die 256er-Ziffern dezimal angegeben sind, + müssen wir viermal Dezimal nach Hexadezimal umwandeln. + Hierfür bieten sich unterschiedliche Wege an. + + $\rm 192_{10} = 128_{10} + 64_{10} = 1100\,0000_{2} = C0_{16}$ + + $\rm 168_{10} = 10_{10} \cdot 16_{10} + 8_{10} = A_{16} \cdot 10_{16} + 8_{16} = A8_{16}$ + + $20_{10} = 16_{10} + 4_{10} = 10_{16} + 4_{16} = 14$ + + $\rm 254_{10} = 255_{10} - 1_{10} = FF_{16} - 1_{16} = FE_{16}$ + \end{itemize} + \item + nach Binär: + \begin{itemize} + \item[(g)] + $750_8 = 111\,101\,000_2$ + + Umwandlung von Oktal nach Binär geht ziffernweise:\\ + Eine Oktalziffer wird zu drei Binärziffern. + \item[(h)] + $\rm 42_{10} = 2A_{16}$ (siehe oben) $= 0010\,1010_{16}$ + + Umwandlung von Hexadezimal nach Binär geht ziffernweise:\\ + Eine Hex-Ziffer wird zu vier Binärziffern. + \item[(i)] + $\rm AFFE_{16} = 1010\,1111\,1111\,1110_2$ + + Umwandlung von Hexadezimal nach Binär geht ziffernweise:\\ + Eine Hex-Ziffer wird zu vier Binärziffern. + \end{itemize} + \end{itemize} + + \medskip + + Berechnen Sie ohne Hilfsmittel: + \begin{itemize} + \item[(j)] + $750_8\,\&\,666_8 + = 111\,101\,000_2\,\&\,110\,110\,110_2 + = 110\,100\,000_2 + = 640_8$ + + Binäre Und-Operationen lassen sich am leichtesten + in binärer Schreibweise durchführen. + Umwandlung zwischen Oktal und Binär geht ziffernweise: + Eine Oktalziffer wird zu drei Binärziffern und umgekehrt. + + Mit etwas Übung funktionieren diese Operationen + auch direkt mit Oktalzahlen im Kopf. + + \item[(k)] + $\rm\phantom{+}A380_{16}$\\ + $\rm+\kern2ptB747_{16}$\\[-\medskipamount] + \rule{1.4cm}{0.5pt}\\ + $\rm 15AC7_{16}$ + \begin{picture}(0,0) + \put(-1.4,0.35){\mbox{\scriptsize\bf 1}} + \end{picture} + + Mit Hexadezimalzahlen (und Binär- und Oktal- und sonstigen Zahlen) + kann man genau wie mit Dezimalzahlen schriftlich rechnen. + Man muß nur daran denken, daß der "`Zehner"'-Überlauf nicht bei + $10_{10}$ stattfindet, sondern erst bei $10_{16} = 16_{10}$ + (hier: $\rm 8_{16} + 4_{16} = C_{16}$ und + $\rm 3_{16} + 7_{16} = A_{16}$, aber + $\rm A_{16} + B_{16} = 10_{10} + 11_{10} + = 21_{10} = 16_{10} + 5_{10} = 10_{16} + 5_{16} = 15_{16}$). + + \item[(l)] + $\rm AFFE_{16} >> 1 + = 1010\,1111\,1111\,1110_2 >> 1 + = 0101\,0111\,1111\,1111_2 + = 57FF_{16}$ + + Bit-Verschiebungen lassen sich am leichtesten + in binärer Schreibweise durchführen. + Umwandlung zwischen Hexadezimal und Binär geht ziffernweise: + Eine Hex-Ziffer wird zu vier Binärziffern und umgekehrt. + + Mit etwas Übung funktionieren diese Operationen + auch direkt mit Hexadezimalzahlen im Kopf. + + \end{itemize} + + \exercise{Mikrocontroller} + + \begin{minipage}[t]{10cm} + An die vier Ports eines ATmega16-Mikrocontrollers sind Leuchtdioden angeschlossen: + \begin{itemize} + \item + von links nach rechts an die Ports A, B, C und D, + \item + von oben nach unten an die Bits Nr.\ 0 bis 7. + \end{itemize} + + Wir betrachten das folgende Programm (\gitfile{hp}{2021ws/20211115}{aufgabe-2.c}): + + \begin{lstlisting}[gobble=6] + #include <avr/io.h> + + int main (void) + { + DDRA = 0xff; + DDRB = 0xff; + DDRC = 0xff; + DDRD = 0xff; + PORTA = 0x1f; + PORTB = 0x10; + PORTD = 0x10; + PORTC = 0xfc; + while (1); + return 0; + } + \end{lstlisting} + \end{minipage}\hfill + \begin{minipage}[t]{3cm} + \strut\\[-\baselineskip] + \includegraphics[width=3cm]{leds.jpg} + \end{minipage} + + \vspace*{-3cm} + + \strut\hfill + \begin{minipage}{11.8cm} + \begin{itemize} + \item[(a)] + Was bewirkt dieses Programm? \points{4} + \item[(b)] + Wozu dienen die ersten vier Zeilen des Hauptprogramms? \points{2} + \item[(c)] + Was würde stattdessen die Zeile \lstinline{DDRA, DDRB, DDRC, DDRD = 0xff;} bewirken? + \points{2} + \item[(d)] + Schreiben Sie das Programm so um, + daß die durch das Programm dargestellte Figur spiegelverkehrt erscheint. \points{3} + \item[(e)] + Wozu dient das \lstinline{while (1)}? \points{2} + \item + Alle Antworten bitte mit Begründung. + \end{itemize} + \end{minipage} + + \solution + + \begin{itemize} + \item[(a)] + \textbf{Was bewirkt dieses Programm?} + + \newcommand{\x}{$\bullet$} + \renewcommand{\o}{$\circ$} + + \begin{minipage}[t]{0.75\textwidth}\parskip\smallskipamount + Es läßt die LEDs in dem rechts abgebildeten Muster aufleuchten,\\ + das z.\,B.\ als die Ziffer 4 gelesen werden kann. + + (Das Zeichen \x\ steht für eine leuchtende, \o\ für eine nicht leuchtende LED.) + + Die erste Spalte (Port A) von unten nach oben gelesen (Bit 7 bis 0)\\ + entspricht der Binärdarstellung von \lstinline{0x1f}: 0001\,1111. + + Die dritte Spalte (Port C) von unten nach oben gelesen (Bit 7 bis 0)\\ + entspricht der Binärdarstellung von \lstinline{0xfc}: 1111\,1100. + + Die zweite und vierte Spalte (Port B und D) von unten nach oben gelesen\\ + (Bit 7 bis 0) entsprechen der Binärdarstellung von \lstinline{0x10}: 0001\,0000. + + Achtung: Die Zuweisung der Werte an die Ports erfolgt im Programm\\ + \emph{nicht\/} in der Reihenfolge A B C D, sondern in der Reihenfolge A B D C. + \end{minipage}\hfill + \begin{minipage}[t]{0.15\textwidth} + \vspace*{-0.5cm}% + \begin{tabular}{cccc} + \x & \o & \o & \o \\ + \x & \o & \o & \o \\ + \x & \o & \x & \o \\ + \x & \o & \x & \o \\ + \x & \x & \x & \x \\ + \o & \o & \x & \o \\ + \o & \o & \x & \o \\ + \o & \o & \x & \o \\ + \end{tabular} + \end{minipage} + + \item[(b)] + \textbf{Wozu dienen die ersten vier Zeilen des Hauptprogramms?} + + Mit diesen Zeilen werden alle jeweils 8 Bits aller 4 Ports + als Output-Ports konfiguriert. + + \item[(c)] + \textbf{Was würde stattdessen die Zeile \lstinline{DDRA, DDRB, DDRC, DDRD = 0xff;} bewirken?} + + Der Komma-Operator in C bewirkt, daß der erste Wert berechnet + und wieder verworfen wird und stattdessen der zweite Wert weiterverarbeitet wird. + Konkret hier hätte das zur Folge, + daß \lstinline{DDRA}, \lstinline{DDRB} und \lstinline{DDRC} + gelesen und die gelesenen Werte ignoriert werden; + anschließend wird \lstinline{DDRD} der Wert \lstinline{0xff} zugewiesen. + Damit würde also nur einer von vier Ports überhaupt konfiguriert. + + Da es sich bei den \lstinline{DDR}-Variablen + um \lstinline{volatile}-Variable handelt, + nimmt der Compiler an, daß der Lesezugriff schon irgendeinen Sinn hätte. + Der Fehler bliebe also unbemerkt. + + \item[(d)] + \textbf{Schreiben Sie das Programm so um, + daß die durch das Programm dargestellte Figur spiegelverkehrt erscheint.} + + Hierzu vertauschen wir die Zuweisungen + an \lstinline{PORTA} und \lstinline{PORTD} + sowie die Zuweisungen + an \lstinline{PORTB} und \lstinline{PORTC}: + + \begin{lstlisting}[gobble=8] + PORTD = 0x1f; + PORTC = 0x10; + PORTA = 0x10; + PORTB = 0xfc; + \end{lstlisting} + + Damit ergibt sich eine Spiegelung an der vertikalen Achse. + + Alternativ kann man auch an der horizontalen Achse spiegeln. + Dafür muß man die Bits in den Hexadezimalzahlen umdrehen: + + \begin{lstlisting}[gobble=8] + PORTA = 0xf8; + PORTB = 0x08; + PORTD = 0x08; + PORTC = 0x3f; + \end{lstlisting} + + Die Frage, welche der beiden Spiegelungen gewünscht ist, + wäre übrigens \emph{auch in der Klausur zulässig}. + + \item[(e)] + \textbf{Wozu dient das \lstinline{while (1)}?} + + Mit dem \lstinline{return}-Befehl am Ende des Hauptprogramms + gibt das Programm die Kontrolle an das Betriebssystem zurück. + + Dieses Programm jedoch läuft auf einem Mikrocontroller, + auf dem es kein Betriebssystem gibt. + Wenn das \lstinline{return} ausgeführt würde, + hätte es ein undefiniertes Verhalten zur Folge. + + Um dies zu verhindern, endet das Programm in einer Endlosschleife, + mit der wir den Mikrocontroller anweisen, + nach der Ausführung des Programms \emph{nichts mehr\/} zu tun + (im Gegensatz zu: \emph{irgendetwas Undefiniertes\/} zu tun). + + \end{itemize} + + \exercise{Einfügen in Strings} + + Wir betrachten das folgende Programm (\gitfile{hp}{2021ws/20211115}{aufgabe-2.c}): +% \begin{lstlisting}[style=numbered] + \begin{lstlisting} + #include <stdio.h> + #include <string.h> + + void insert_into_string (char src, char *target, int pos) + { + int len = strlen (target); + for (int i = pos; i < len; i++) + target[i+1] = target[i]; + target[pos] = src; + } + + int main (void) + { + char test[100] = "Hochshule Bochum"; + insert_into_string ('c', test, 5); + printf ("%s\n", test); + return 0; + } + \end{lstlisting} + Die Ausgabe des Programms lautet: + \lstinline[style=terminal]{Hochschhhhhhhhhhh} + + \begin{enumerate}[\quad(a)] + \item + Erklären Sie, wie die Ausgabe zustandekommt. + \points{3} +% \workspace{12} + \item + Schreiben Sie die Funktion \lstinline|insert_into_string()| so um, + daß sie den Buchstaben \lstinline{src} an der Stelle \lstinline{pos} + in den String \lstinline{target} einfügt.\par + Die Ausgabe des Programms müßte dann + \lstinline[style=terminal]{Hochschule Bochum} lauten. + \points{2} +% \workspace{13} + \item + Was kann passieren, wenn Sie die Zeile + \lstinline{char test[100] = "Hochshule Bochum";}\\ + durch + \lstinline{char test[] = "Hochshule Bochum";} ersetzen? + Begründen Sie Ihre Antwort. + \points{2} +% \workspace{10} + \item + Was kann passieren, wenn Sie die Zeile + \lstinline{char test[100] = "Hochshule Bochum";}\\ + durch + \lstinline{char *test = "Hochshule Bochum";} ersetzen? + Begründen Sie Ihre Antwort. + \points{2} +% \workspace{10} +% \item +% Schreiben Sie eine Funktion +% \lstinline{void insert_into_string_sorted (char src, char *target)}, +% die voraussetzt, daß der String \lstinline{target} alphabetisch sortiert ist +% und den Buchstaben \lstinline{src} an der alphabetisch richtigen Stelle +% einfügt. Diese Funktion darf die bereits vorhandene Funktion +% \lstinline|insert_into_string()| aufrufen.\\ +% \points{4}\par +% Zum Testen eignen sich die folgenden Zeilen im Hauptprogramm: +% \begin{lstlisting}[gobble=8] +% char test[100] = ""; +% insert_into_string_sorted ('c', test); +% insert_into_string_sorted ('a', test); +% insert_into_string_sorted ('d', test); +% insert_into_string_sorted ('b', test); +% \end{lstlisting} +% Danach sollte \lstinline{test[]} die Zeichenfolge \lstinline{"abcd"} enthalten. +% \workspace{14} +% \item +% Wie schnell (Landau-Symbol in Abhängigkeit von der Länge $n$ des Strings) +% arbeitet Ihre Funktion +% \lstinline{void insert_into_string_sorted (char src, char *target)} +% und warum? +% \points{1} +% \workspace{10} +% \item +% Beschreiben Sie -- in Worten oder als C-Quelltext --, wie man die Funktion\\ +% \lstinline{void insert_into_string_sorted (char src, char *target)} +% so gestalten kann,\\ +% daß sie in $\mathcal{O}(\log n)$ arbeitet. +% \points{3} +% \workspace{35} + \end{enumerate} + + \solution + + \begin{enumerate}[\quad(a)] + \item + \textbf{Erklären Sie, wie die Ausgabe zustandekommt.} + + In der Schleife wird \emph{zuerst\/} der nächste Buchstabe \lstinline{target[i + 1]} + gleich dem aktuellen gesetzt + und \emph{danach\/} der Zähler \lstinline{i} erhöht. + Dadurch wird im nächsten Schleifendurchlauf der bereits verschobene Buchstabe + noch weiter geschoben und letztlich alle Buchstaben in \lstinline{target[]} + durch den an der Stelle \lstinline{pos} ersetzt. + + \item + \textbf{Schreiben Sie die Funktion \lstinline|insert_into_string()| so um, + daß sie den Buchstben \lstinline{src} an der Stelle \lstinline{pos} + in den String \lstinline{target} einfügt.}\par + \textbf{Die Ausgabe des Programms müßte dann + \lstinline[style=terminal]{Hochschule Bochum} lauten.} + + Um im String "`Platz zu schaffen"', muß man von hinten beginnen, + also die Schleife umdrehen\\ + (siehe: \gitfile{hp}{2021ws/20211115}{loesung-3.c}): + \begin{lstlisting}{gobble=8} + for (int i = len; i >= pos; i--) + target[i + 1] = target[i]; + \end{lstlisting} + + \item + \textbf{Was kann passieren, wenn Sie die Zeile + \lstinline{char test[100] = "Hochshule Bochum";}\\ + durch + \lstinline{char test[] = "Hochshule Bochum";} + ersetzen und warum?} + + Die Schreibweise \lstinline{test[]} bedeutet, + daß der Compiler selbst zählt, wieviel Speicherplatz der String benötigt, + un dann genau die richtige Menge Speicher reserviert + (anstatt, wie wir es manuell getan haben, pauschal Platz für 100 Zeichen). + + Wenn wir nun in den String ein zusätzliches Zeichen einfügen, + ist dafür kein Speicherplatz reserviert worden, + und wir \textbf{überschreiben} dann Speicher, an dem sich andere Variable befinden, + was zu einem \textbf{Absturz} führen kann. + + Da wir hier nur ein einziges Zeichen schreiben, + wird dieser Fehler nicht sofort auffallen. + Dies ist schlimmer, als wenn das Programm direkt beim ersten Test abstürzt, + denn dadurch entsteht bei uns der Eindruck, es sei in Ordnung. + Wenn danach der Fehler in einer Produktivumgebung auftritt, + kann dadurch Schaden entstehen -- je nach Einsatzgebiet der Software + u.\,U.\ erheblicher Vermögens-, Sach- und/oder Personenschaden + (z.\,B.\ Absturz eines Raumflugkörpers). + + \item + \textbf{Was kann passieren, wenn Sie + \lstinline{char test[100] = "Hochshule Bochum";}\\ + durch + \lstinline{char *test = "Hochshule Bochum";} + ersetzen und warum?} + + In diesem Fall wird der Speicher für den eigentlichen String + in einem unbenannten, \textbf{nicht schreibbaren} Teil des Speichers reserviert. + Unser Versuch, dorthin ein zusätzliches Zeichen zu schreiben, + fürt dann normalerweise zu einem \textbf{Absturz}. + + In manchen Systemen (Betriebssystem, Compiler, \dots) + ist der Speicherbereich tatsächlich sehr wohl schreibbar. + In diesem Fall tritt der Absturz nicht immer und nicht immer sofort auf -- + genau wie in Aufgabenteil (c). + + \end{enumerate} + +\end{document} diff --git a/20211115/hp-uebung-20211115.pdf b/20211115/hp-uebung-20211115.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e6f02edcd4c7a85b62499452779465c42256e74b Binary files /dev/null and b/20211115/hp-uebung-20211115.pdf differ diff --git a/20211115/hp-uebung-20211115.tex b/20211115/hp-uebung-20211115.tex new file mode 100644 index 0000000000000000000000000000000000000000..5bf88f85f23462397d24d1d4d784909bdfcdd852 --- /dev/null +++ b/20211115/hp-uebung-20211115.tex @@ -0,0 +1,262 @@ +% hp-uebung-20211115.pdf - Exercises on Low-Level Programming +% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021 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: Zahlensysteme, Mikrocontroller, Einfügen in Strings (Ergänzung) + +\documentclass[a4paper]{article} + +\usepackage{pgscript} + +\begin{document} + +% \thispagestyle{empty} + + \section*{Hardwarenahe Programmierung\\ + Übungsaufgaben -- 15.\ November 2021} + + Diese Übung enthält Punkteangaben wie in einer Klausur. + Um zu "`bestehen"', müssen Sie innerhalb von 85 Minuten + unter Verwendung ausschließlich zugelassener Hilfsmittel + 17 Punkte (von insgesamt \totalpoints) erreichen. + + \exercise{Zahlensysteme} + + Wandeln Sie ohne Hilfsmittel + + \begin{minipage}[t]{0.3\textwidth} + \begin{itemize} + \item + nach Dezimal: + \begin{itemize} + \item[(a)] + 0010\,0000$_2$ + \item[(b)] + 42$_{16}$ + \item[(c)] + 17$_8$ + \end{itemize} + \end{itemize} + \end{minipage}\hfill + \begin{minipage}[t]{0.3\textwidth} + \begin{itemize} + \item + nach Hexadezimal: + \begin{itemize} + \item[(d)] + 0010\,0000$_2$ + \item[(e)] + 42$_{10}$ + \item[(f)] + 192.168.20.254$_{256}$ + \end{itemize} + \end{itemize} + \end{minipage}\hfill + \begin{minipage}[t]{0.3\textwidth} + \begin{itemize} + \item + nach Binär: + \begin{itemize} + \item[(g)] + 750$_8$ + \item[(h)] + 42$_{10}$ + \item[(i)] + AFFE$_{16}$ + \end{itemize} + \end{itemize} + \end{minipage} + + \medskip + + Berechnen Sie ohne Hilfsmittel: + \begin{itemize} + \item[(j)] + 750$_8$ \& 666$_8$ + \item[(k)] + A380$_{16}$ + B747$_{16}$ + \item[(l)] + AFFE$_{16} >> 1$ + \end{itemize} + + Die tiefgestellte Zahl steht für die Basis des Zahlensystems. + Jede Teilaufgabe zählt 1 Punkt. \addtocounter{points}{12} + + (In der Klausur sind Hilfsmittel zugelassen, + daher ist dies \emph{keine\/} typische Klausuraufgabe.) + + \exercise{Mikrocontroller} + + \begin{minipage}[t]{10cm} + An die vier Ports eines ATmega16-Mikrocontrollers sind Leuchtdioden angeschlossen: + \begin{itemize} + \item + von links nach rechts an die Ports A, B, C und D, + \item + von oben nach unten an die Bits Nr.\ 0 bis 7. + \end{itemize} + + Wir betrachten das folgende Programm (\gitfile{hp}{2021ws/20211115}{aufgabe-2.c}): + + \begin{lstlisting}[gobble=6] + #include <avr/io.h> + + int main (void) + { + DDRA = 0xff; + DDRB = 0xff; + DDRC = 0xff; + DDRD = 0xff; + PORTA = 0x1f; + PORTB = 0x10; + PORTD = 0x10; + PORTC = 0xfc; + while (1); + return 0; + } + \end{lstlisting} + \end{minipage}\hfill + \begin{minipage}[t]{3cm} + \strut\\[-\baselineskip] + \includegraphics[width=3cm]{leds.jpg} + \end{minipage} + + \vspace*{-3cm} + + \strut\hfill + \begin{minipage}{11.8cm} + \begin{itemize} + \item[(a)] + Was bewirkt dieses Programm? \points{4} + \item[(b)] + Wozu dienen die ersten vier Zeilen des Hauptprogramms? \points{2} + \item[(c)] + Was würde stattdessen die Zeile \lstinline{DDRA, DDRB, DDRC, DDRD = 0xff;} bewirken? + \points{2} + \item[(d)] + Schreiben Sie das Programm so um, + daß die durch das Programm dargestellte Figur spiegelverkehrt erscheint. \points{3} + \item[(e)] + Wozu dient das \lstinline{while (1)}? \points{2} + \item + Alle Antworten bitte mit Begründung. + \end{itemize} + \end{minipage} + + \exercise{Einfügen in Strings} + + Wir betrachten das folgende Programm (\gitfile{hp}{2021ws/20211115}{aufgabe-3.c}): +% \begin{lstlisting}[style=numbered] + \begin{lstlisting} + #include <stdio.h> + #include <string.h> + + void insert_into_string (char src, char *target, int pos) + { + int len = strlen (target); + for (int i = pos; i < len; i++) + target[i+1] = target[i]; + target[pos] = src; + } + + int main (void) + { + char test[100] = "Hochshule Bochum"; + insert_into_string ('c', test, 5); + printf ("%s\n", test); + return 0; + } + \end{lstlisting} + Die Ausgabe des Programms lautet: + \lstinline[style=terminal]{Hochschhhhhhhhhhh} + + \begin{enumerate}[\quad(a)] + \item + Erklären Sie, wie die Ausgabe zustandekommt. + \points{3} +% \workspace{12} + \item + Schreiben Sie die Funktion \lstinline|insert_into_string()| so um, + daß sie den Buchstaben \lstinline{src} an der Stelle \lstinline{pos} + in den String \lstinline{target} einfügt.\par + Die Ausgabe des Programms müßte dann + \lstinline[style=terminal]{Hochschule Bochum} lauten. + \points{2} +% \workspace{13} + \item + Was kann passieren, wenn Sie die Zeile + \lstinline{char test[100] = "Hochshule Bochum";}\\ + durch + \lstinline{char test[] = "Hochshule Bochum";} ersetzen? + Begründen Sie Ihre Antwort. + \points{2} +% \workspace{10} + \item + Was kann passieren, wenn Sie die Zeile + \lstinline{char test[100] = "Hochshule Bochum";}\\ + durch + \lstinline{char *test = "Hochshule Bochum";} ersetzen? + Begründen Sie Ihre Antwort. + \points{2} +% \workspace{10} +% \item +% Schreiben Sie eine Funktion +% \lstinline{void insert_into_string_sorted (char src, char *target)}, +% die voraussetzt, daß der String \lstinline{target} alphabetisch sortiert ist +% und den Buchstaben \lstinline{src} an der alphabetisch richtigen Stelle +% einfügt. Diese Funktion darf die bereits vorhandene Funktion +% \lstinline|insert_into_string()| aufrufen.\\ +% \points{4}\par +% Zum Testen eignen sich die folgenden Zeilen im Hauptprogramm: +% \begin{lstlisting}[gobble=8] +% char test[100] = ""; +% insert_into_string_sorted ('c', test); +% insert_into_string_sorted ('a', test); +% insert_into_string_sorted ('d', test); +% insert_into_string_sorted ('b', test); +% \end{lstlisting} +% Danach sollte \lstinline{test[]} die Zeichenfolge \lstinline{"abcd"} enthalten. +% \workspace{14} +% \item +% Wie schnell (Landau-Symbol in Abhängigkeit von der Länge $n$ des Strings) +% arbeitet Ihre Funktion +% \lstinline{void insert_into_string_sorted (char src, char *target)} +% und warum? +% \points{1} +% \workspace{10} +% \item +% Beschreiben Sie -- in Worten oder als C-Quelltext --, wie man die Funktion\\ +% \lstinline{void insert_into_string_sorted (char src, char *target)} +% so gestalten kann,\\ +% daß sie in $\mathcal{O}(\log n)$ arbeitet. +% \points{3} +% \workspace{35} + \end{enumerate} + + \begin{flushright} + \textit{Viel Erfolg!} + \end{flushright} + + \makeatletter + \immediate\write\@mainaux{\string\gdef\string\totalpoints{\arabic{points}}} + \makeatother + +\end{document} diff --git a/20211115/io-ports-and-interrupts.pdf b/20211115/io-ports-and-interrupts.pdf new file mode 120000 index 0000000000000000000000000000000000000000..bcd46f7afb35605b20bdb05637e6de0a039893ec --- /dev/null +++ b/20211115/io-ports-and-interrupts.pdf @@ -0,0 +1 @@ +../common/io-ports-and-interrupts.pdf \ No newline at end of file diff --git a/20211115/leds.jpg b/20211115/leds.jpg new file mode 120000 index 0000000000000000000000000000000000000000..5e66b77c5c428129f6f4abcc80ae48f0c9a53c35 --- /dev/null +++ b/20211115/leds.jpg @@ -0,0 +1 @@ +../common/leds.jpg \ No newline at end of file diff --git a/20211115/loesung-3.c b/20211115/loesung-3.c new file mode 100644 index 0000000000000000000000000000000000000000..85abfcf3e1e4bacf454acd10f6832b757a64ac35 --- /dev/null +++ b/20211115/loesung-3.c @@ -0,0 +1,18 @@ +#include <stdio.h> +#include <string.h> + +void insert_into_string (char src, char *target, int pos) +{ + int len = strlen (target); + for (int i = len; i >= pos; i--) + target[i + 1] = target[i]; + target[pos] = src; +} + +int main (void) +{ + char test[100] = "Hochshule Bochum"; + insert_into_string ('c', test, 5); + printf ("%s\n", test); + return 0; +} diff --git a/20211115/logo-hochschule-bochum-cvh-text-v2.pdf b/20211115/logo-hochschule-bochum-cvh-text-v2.pdf new file mode 120000 index 0000000000000000000000000000000000000000..4aa99b8f81061aca6dcaf43eed2d9efef40555f8 --- /dev/null +++ b/20211115/logo-hochschule-bochum-cvh-text-v2.pdf @@ -0,0 +1 @@ +../common/logo-hochschule-bochum-cvh-text-v2.pdf \ No newline at end of file diff --git a/20211115/logo-hochschule-bochum.pdf b/20211115/logo-hochschule-bochum.pdf new file mode 120000 index 0000000000000000000000000000000000000000..b6b9491e370e499c9276918182cdb82cb311bcd1 --- /dev/null +++ b/20211115/logo-hochschule-bochum.pdf @@ -0,0 +1 @@ +../common/logo-hochschule-bochum.pdf \ No newline at end of file diff --git a/20211115/pgscript.sty b/20211115/pgscript.sty new file mode 120000 index 0000000000000000000000000000000000000000..95c888478c99ea7fda0fd11ccf669ae91be7178b --- /dev/null +++ b/20211115/pgscript.sty @@ -0,0 +1 @@ +../common/pgscript.sty \ No newline at end of file diff --git a/20211115/pgslides.sty b/20211115/pgslides.sty new file mode 120000 index 0000000000000000000000000000000000000000..5be1416f4216f076aa268901f52a15d775e43f64 --- /dev/null +++ b/20211115/pgslides.sty @@ -0,0 +1 @@ +../common/pgslides.sty \ No newline at end of file diff --git a/README.md b/README.md index 303e60b0bd2da78bdb310474fd1ee9ee9ae216b9..0fdab69c32b1a9723c599b401766c4c8a0200cac 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ Vortragsfolien und Beispiele: * [18.10.2021: Einführung in C: Arrays und Strings, Strukturen](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211018/hp-20211018.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2021ws/20211018/) * [25.10.2021: Einführung in C: Arrays und Strings und Zeichen, Strukturen, Dateien und Fehlerbehandlung](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211025/hp-20211025.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2021ws/20211025/) * [08.11.2021: Parameter des Hauptprogramms, String-Operationen, Bit-Operationen, I/O-Ports](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211108/hp-20211108.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2021ws/20211108/) + * [15.11.2021: I/O-Ports, Interrupts](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211115/hp-20211115.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2021ws/20211115/) * [alle in 1 Datei](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/hp-slides-2021ws.pdf) Übungsaufgaben: @@ -31,6 +32,7 @@ Vortragsfolien und Beispiele: * [18.10.2021: Seltsame Programme, Kalender-Berechnung](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211018/hp-uebung-20211018.pdf) * [25.10.2021: Strings, Programm analysieren, fehlerhaftes Primzahl-Programm](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211025/hp-uebung-20211025.pdf) * [08.11.2021: Arrays mit Zahlen, Datum-Bibliothek](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211108/hp-uebung-20211108.pdf) + * [15.11.2021: Zahlensysteme, Mikrocontroller, Einfügen in Strings (Ergänzung)](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211115/hp-uebung-20211115.pdf) Musterlösungen: --------------- @@ -38,10 +40,11 @@ Musterlösungen: * [18.10.2021: Seltsame Programme, Kalender-Berechnung](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211018/hp-musterloesung-20211018.pdf) * [25.10.2021: Strings, Programm analysieren, fehlerhaftes Primzahl-Programm](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211025/hp-musterloesung-20211025.pdf) * [08.11.2021: Arrays mit Zahlen, Datum-Bibliothek](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211108/hp-musterloesung-20211108.pdf) + * [15.11.2021: Zahlensysteme, Mikrocontroller, Einfügen in Strings](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211115/hp-musterloesung-20211115.pdf) Tafelbilder: ------------ - * [08.11.2021: Beispiele für Bit-Manipulation](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211108/photo-20211108-172458.jpg) +(keine) Praktikumsunterlagen: --------------------- diff --git a/hp-slides-2021ws.pdf b/hp-slides-2021ws.pdf index 049705c884b363245e198c6404a0218f5241d431..e6892010ce91be1cafd3621c238bcbaf11fff821 100644 Binary files a/hp-slides-2021ws.pdf and b/hp-slides-2021ws.pdf differ diff --git a/hp-slides-2021ws.tex b/hp-slides-2021ws.tex index f6723f56f017a470d18843c67c3ee2222b3b8bf1..cfd6bb634dd89821a8d4c9c39f78ae50fad24711 100644 --- a/hp-slides-2021ws.tex +++ b/hp-slides-2021ws.tex @@ -20,4 +20,6 @@ \includepdf[pages=-]{20211025/hp-20211025.pdf} \pdfbookmark[1]{08.11.2021: Parameter des Hauptprogramms, String-Operationen, Bit-Operationen, I/O-Ports}{20211108} \includepdf[pages=-]{20211108/hp-20211108.pdf} + \pdfbookmark[1]{15.11.2021: I/O-Ports, Interrupts}{20211115} + \includepdf[pages=-]{20211115/hp-20211115.pdf} \end{document}