diff --git a/20211115/hp-musterloesung-20211115.pdf b/20211115/hp-musterloesung-20211115.pdf index df7200de50936fd484c8353512876f910317bf5b..b62059f04deb28163701faba47ad57e36117fca6 100644 Binary files a/20211115/hp-musterloesung-20211115.pdf and b/20211115/hp-musterloesung-20211115.pdf differ diff --git a/20211115/hp-musterloesung-20211115.tex b/20211115/hp-musterloesung-20211115.tex index c9dc97835ada978af0da32a80219a01c97e8257d..74b71ae076fc762cc6451a408dbd1c7a1beb9788 100644 --- a/20211115/hp-musterloesung-20211115.tex +++ b/20211115/hp-musterloesung-20211115.tex @@ -29,7 +29,7 @@ \begin{document} \section*{Hardwarenahe Programmierung\\ - Musterlösung zu den Übungsaufgaben -- l5.\ November 2021} + Musterlösung zu den Übungsaufgaben -- 15.\ November 2021} \exercise{Zahlensysteme} diff --git a/20211115/hp-uebung-20211115.tex b/20211115/hp-uebung-20211115.tex index 5bf88f85f23462397d24d1d4d784909bdfcdd852..b95fb80eac13e1765c80769a830ac6507471891a 100644 --- a/20211115/hp-uebung-20211115.tex +++ b/20211115/hp-uebung-20211115.tex @@ -20,7 +20,7 @@ % 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) +% README: Zahlensysteme, Mikrocontroller, Einfügen in Strings \documentclass[a4paper]{article} diff --git a/20211122/Makefile b/20211122/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..7ae33df99f68fcf460324cfbb008f3f7a3863638 --- /dev/null +++ b/20211122/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/20211122/aufgabe-2.c b/20211122/aufgabe-2.c new file mode 100644 index 0000000000000000000000000000000000000000..d0b065941fbc0082bf867d872527299dca97b98f --- /dev/null +++ b/20211122/aufgabe-2.c @@ -0,0 +1,18 @@ +#include <string.h> + +int fun_1 (char *s) +{ + int x = 0; + for (int i = 0; i < strlen (s); i++) + x += s[i]; + return x; +} + +int fun_2 (char *s) +{ + int i = 0, x = 0; + int len = strlen (s); + while (i < len) + x += s[i++]; + return x; +} diff --git a/20211122/aufgabe-3.c b/20211122/aufgabe-3.c new file mode 100644 index 0000000000000000000000000000000000000000..4c95eb6ad4881c904448309c6b7c46fa101cc109 --- /dev/null +++ b/20211122/aufgabe-3.c @@ -0,0 +1,33 @@ +#include <stdint.h> +#include <avr/io.h> +#include <avr/interrupt.h> + +uint8_t counter = 1; +uint8_t leds = 0; + +ISR (TIMER0_COMP_vect) +{ + if (counter == 0) + { + leds = (leds + 1) % 8; + PORTC = leds << 4; + } + counter++; +} + +void init (void) +{ + cli (); + TCCR0 = (1 << CS01) | (1 << CS00); + TIMSK = 1 << OCIE0; + sei (); + DDRC = 0x70; +} + +int main (void) +{ + init (); + while (1) + ; /* do nothing */ + return 0; +} diff --git a/20211122/blink-0.c b/20211122/blink-0.c new file mode 100644 index 0000000000000000000000000000000000000000..b0022c681fd1482ed0a6d9fded7bb0a54699de32 --- /dev/null +++ b/20211122/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/20211122/blink-0a.c b/20211122/blink-0a.c new file mode 100644 index 0000000000000000000000000000000000000000..45e90fe4568e357cc9342a0d7369be6312a83e64 --- /dev/null +++ b/20211122/blink-0a.c @@ -0,0 +1,9 @@ +#include <avr/io.h> + +int main (void) +{ + DDRD = 0xff; /* binär: 1111 1111 */ + PORTD = 0x40; /* binär: 0100 0000 */ + while (1); + return 0; +} diff --git a/20211122/blink-1.c b/20211122/blink-1.c new file mode 100644 index 0000000000000000000000000000000000000000..6d28dce84f94375094c98479c30a54ace1b2a9d9 --- /dev/null +++ b/20211122/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/20211122/blink-2.c b/20211122/blink-2.c new file mode 100644 index 0000000000000000000000000000000000000000..9389b19b1bf46d5ca90bac823e3f94269fe02878 --- /dev/null +++ b/20211122/blink-2.c @@ -0,0 +1,16 @@ +#include <avr/io.h> + +#define F_CPU 16000000l +#include <util/delay.h> + +int main (void) +{ + DDRD = 0x02; /* binär: 0000 0010 */ + PORTD = 0x02; + while (1) + { + _delay_ms (250); + PORTD ^= 0x02; + } + return 0; +} diff --git a/20211122/blink-2a.c b/20211122/blink-2a.c new file mode 100644 index 0000000000000000000000000000000000000000..a226654a35eb061364dab1cf6a035eb6c5dd4df0 --- /dev/null +++ b/20211122/blink-2a.c @@ -0,0 +1,16 @@ +#include <avr/io.h> + +#define F_CPU 16000000l +#include <util/delay.h> + +int main (void) +{ + DDRD = 0x02; /* binär: 0000 0010 */ + PORTD = 0x02; + while (1) + { + _delay_ms (500); + PORTD = PORTD ^ 0x02; + } + return 0; +} diff --git a/20211122/blink-2b.c b/20211122/blink-2b.c new file mode 100644 index 0000000000000000000000000000000000000000..90ed36c2f976050b898458e3efd6b818ecf8e775 --- /dev/null +++ b/20211122/blink-2b.c @@ -0,0 +1,16 @@ +#include <avr/io.h> + +#define F_CPU 16000000l +#include <util/delay.h> + +int main (void) +{ + DDRB = 1 << 5; + PORTB = 1 << 5; + while (1) + { + _delay_ms (500); + PORTB ^= 1 << 5; + } + return 0; +} diff --git a/20211122/blink-3.c b/20211122/blink-3.c new file mode 100644 index 0000000000000000000000000000000000000000..5268e7977f0f2a99b2005a81a2fa7560dfea481f --- /dev/null +++ b/20211122/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/20211122/blink-4.c b/20211122/blink-4.c new file mode 100644 index 0000000000000000000000000000000000000000..ceafab6b1e7462497fde98b7a12e72cc34132bbe --- /dev/null +++ b/20211122/blink-4.c @@ -0,0 +1,18 @@ +#include <avr/io.h> + +#define F_CPU 16000000 +#include <util/delay.h> + +int main (void) +{ + DDRD = 0x01; /* binär: 0000 0001 */ + PORTD = 0x01; /* ^ Ouptut */ + while (1) /* ^ Input */ + { + while ((PIND & 0x02) == 0) /* binär: 0000 0010 */ + ; /* just wait */ + PORTD ^= 0x01; + _delay_ms (200); + } + return 0; +} diff --git a/20211122/download.sh b/20211122/download.sh new file mode 100755 index 0000000000000000000000000000000000000000..770c3b5dca74ac09778be055c9d6f5adb0df293b --- /dev/null +++ b/20211122/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/20211122/hp-20211122.pdf b/20211122/hp-20211122.pdf new file mode 100644 index 0000000000000000000000000000000000000000..029ba1ad0d26847b158f81dd269a40877254922d Binary files /dev/null and b/20211122/hp-20211122.pdf differ diff --git a/20211122/hp-20211122.tex b/20211122/hp-20211122.tex new file mode 100644 index 0000000000000000000000000000000000000000..ba182dc0a57ff755f298d6d05545e1c535073b78 --- /dev/null +++ b/20211122/hp-20211122.tex @@ -0,0 +1,890 @@ +% hp-20211122.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{22.\ 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.git}}} + \item[\textbf{2}] \textbf{Einführung in C} + \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 + \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/20211122/hp-musterloesung-20211122.pdf b/20211122/hp-musterloesung-20211122.pdf new file mode 100644 index 0000000000000000000000000000000000000000..0569714886f2c558e6bd0d2dbdc16a9b6b66008c Binary files /dev/null and b/20211122/hp-musterloesung-20211122.pdf differ diff --git a/20211122/hp-musterloesung-20211122.tex b/20211122/hp-musterloesung-20211122.tex new file mode 100644 index 0000000000000000000000000000000000000000..7e8d77398c4ef19de65c13e1152f7934a81bce85 --- /dev/null +++ b/20211122/hp-musterloesung-20211122.tex @@ -0,0 +1,447 @@ +% 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: Ausgabe von Hexadezimalzahlen, Einfügen in Strings, LED-Blinkmuster + +\documentclass[a4paper]{article} + +\usepackage{pgscript} + +\begin{document} + + \section*{Hardwarenahe Programmierung\\ + Musterlösung zu den Übungsaufgaben -- 22.\ November 2021} + + \exercise{Ausgabe von Hexadezimalzahlen} + + Schreiben Sie eine Funktion \lstinline{void print_hex (uint32_t x)}, + die eine gegebene vorzeichenlose 32-Bit-Ganzzahl \lstinline{x} + als Hexadezimalzahl ausgibt. + (Der Datentyp \lstinline{uint32_t} ist mit \lstinline{#include <stdint.h>} verfügbar.) + + Verwenden Sie dafür \emph{nicht\/} \lstinline{printf()} mit + der Formatspezifikation \lstinline{%x} als fertige Lösung, + sondern programmieren Sie die nötige Ausgabe selbst. + (Für Tests ist \lstinline{%x} hingegen erlaubt und sicherlich nützlich.) + + Die Verwendung von \lstinline{printf()} + mit anderen Formatspezifikationen wie z.\,B.\ \lstinline{%d} + oder \lstinline{%c} oder \lstinline{%s} ist hingegen zulässig. + + \points{8} + + (Hinweis für die Klausur: Abgabe auf Datenträger ist erlaubt und erwünscht, + aber nicht zwingend.) + + \solution + + Um die Ziffern von \lstinline{x} zur Basis 16 zu isolieren, + berechnen wir \lstinline{x % 16} (modulo 16 = Rest bei Division durch 16) + und dividieren anschließend \lstinline{x} durch 16, + solange bis \lstinline{x} den Wert 0 erreicht. + + Wenn wir die auf diese Weise ermittelten Ziffern direkt ausgeben, + sind sie \emph{Little-Endian}, erscheinen also in umgekehrter Reihenfolge. + Die Datei \gitfile{hp}{2021ws/20211122}{loesung-1-1.c} setzt diesen Zwischenschritt um. + + Die Ausgabe der Ziffern erfolgt in \gitfile{hp}{2021ws/20211122}{loesung-1-1.c} + über \lstinline{printf ("%d")} + für die Ziffern 0 bis 9. Für die darüberliegenden Ziffern + wird der Buchstabe \lstinline{a} um die Ziffer abzüglich 10 inkrementiert + und der erhaltene Wert mit \lstinline{printf ("%c")} als Zeichen ausgegeben. + + Um die umgekehrte Reihenfolge zu beheben, + speichern wir die Ziffern von \lstinline{x} + in einem Array \lstinline{digits[]} zwischen + und geben sie anschließend in einer zweiten Schleife + in umgekehrter Reihenfolge aus (siehe \gitfile{hp}{2021ws/20211122}{loesung-1-2.c}). + Da wir wissen, daß \lstinline{x} eine 32-Bit-Zahl ist + und daher höchstens 8 Hexadezimalziffern haben kann, + ist 8 eine sinnvolle Länge für das Ziffern-Array \lstinline{digits[8]}. + + Nun sind die Ziffern in der richtigen Reihenfolge, + aber wir erhalten zusätzlich zu den eigentlichen Ziffern führende Nullen. + Da in der Aufgabenstellung nicht von führenden Nullen die Rede war, + sind diese nicht verboten; \gitfile{hp}{2021ws/20211122}{loesung-1-2.c} ist daher + eine richtige Lösung der Aufgabe. + + \breath + + Wenn wir die führenden Nullen vermeiden wollen, + können wir die \lstinline{for}-Schleifen durch \lstinline{while}-Schleifen ersetzen. + Die erste Schleife zählt hoch, solange \lstinline{x} ungleich 0 ist; + die zweite zählt von dem erreichten Wert aus wieder herunter + -- siehe \gitfile{hp}{2021ws/20211122}{loesung-1-3.c}. + Da wir wissen, daß die Zahl \lstinline{x} höchstens 32 Bit, + also höchstens 8 Hexadezimalziffern hat, + wissen wir, daß \lstinline{i} höchstens den Wert 8 erreichen kann, + das Array also nicht überlaufen wird. + + Man beachte, daß der Array-Index nach der ersten Schleife "`um einen zu hoch"' ist. + In der zweiten Schleife muß daher \emph{zuerst\/} der Index dekrementiert werden. + Erst danach darf ein Zugriff auf \lstinline{digit[i]} erfolgen. + + \breath + + Alternativ können wir auch mitschreiben, + ob bereits eine Ziffer ungleich Null ausgegeben wurde, + und andernfalls die Ausgabe von Null-Ziffern unterdrücken + -- siehe \gitfile{hp}{2021ws/20211122}{loesung-1-4.c}. + + \breath + + Weitere Möglichkeiten ergeben sich, wenn man bedenkt, + daß eine Hexadezimalziffer genau einer Gruppe von vier Binärziffern entspricht. + Eine Bitverschiebung um 4 nach rechts + ist daher dasselbe wie eine Division durch 16, + und eine Und-Verknüpfung mit 15$_{10}$ = f$_{16}$ = 1111$_2$ + ist dasselbe wie die Operation Modulo 16. + Die Datei \gitfile{hp}{2021ws/20211122}{loesung-1-5.c} ist eine in dieser Weise abgewandelte Variante + von \gitfile{hp}{2021ws/20211122}{loesung-1-3.c}. + + Mit dieser Methode kann man nicht nur auf die jeweils unterste Ziffer, + sondern auf alle Ziffern direkt zugreifen. + Damit ist kein Array als zusätzlicher Speicher mehr nötig. + Die Datei \gitfile{hp}{2021ws/20211122}{loesung-1-6.c} setzt dies auf einfache Weise um. + Sie gibt wieder führende Nullen mit aus, + ist aber trotzdem eine weitere richtige Lösung der Aufgabe. + + Die führenden Nullen ließen sich auf die gleiche Weise vermeiden + wie in \gitfile{hp}{2021ws/20211122}{loesung-1-4.c}. + + Die Bitverschiebungsmethode hat den Vorteil, + daß kein zusätzliches Array benötigt wird. + Auch wird die als Parameter übergebene Zahl \lstinline{x} nicht verändert, + was bei größeren Zahlen, die über Zeiger übergeben werden, von Vorteil sein kann. + Demgegenüber steht der Nachteil, + daß diese Methode nur für eine ganze Anzahl von Bits funktioniert, + also für Basen, die Zweierpotenzen sind (z.\,B.\ 2, 8, 16, 256). + Für alle anderen Basen (z.\,B.\ 10) eignet sich nur die Methode + mit Division und Modulo-Operation. + + \exercise{Länge von Strings} + + Strings werden in der Programmiersprache C durch Zeiger auf \lstinline{char}-Variable realisiert. + + Beispiel: \lstinline{char *hello_world = "Hello, world!\n"} + + Die Systembibliothek stellt eine Funktion \lstinline{strlen()} zur Ermittlung der Länge von Strings\\ + zur Verfügung (\lstinline{#include <string.h>}). + + \begin{itemize} + \item[(a)] + Auf welche Weise ist die Länge eines Strings gekennzeichnet? + \points{1} + \item[(b)] + Wie lang ist die Beispiel-String-Konstante \lstinline{"Hello, world!\n"}, + und wieviel Speicherplatz belegt sie?\\ + \points{2} + \item[(c)] + Schreiben Sie eine eigene Funktion \lstinline{int strlen (char *s)}, + die die Länge eines Strings zurückgibt.\\ + \points{3} + \end{itemize} + + Wir betrachten nun die folgenden Funktionen (Datei: \gitfile{hp}{2021ws/20211122}{aufgabe-2.c}): + \begin{center} + \begin{minipage}{8cm} + \begin{lstlisting}[gobble=8] + int fun_1 (char *s) + { + int x = 0; + for (int i = 0; i < strlen (s); i++) + x += s[i]; + return x; + } + \end{lstlisting} + \end{minipage}% + \begin{minipage}{6cm} + \vspace*{-1cm} + \begin{lstlisting}[gobble=8] + int fun_2 (char *s) + { + int i = 0, x = 0; + int len = strlen (s); + while (i < len) + x += s[i++]; + return x; + } + \end{lstlisting} + \vspace*{-1cm} + \end{minipage} + \end{center} + \begin{itemize} + \item[(d)] + Was bewirken die beiden Funktionen? + \points{2} + \item[(e)] +% Von welcher Ordnung (Landau-Symbol) sind die beiden Funktionen +% hinsichtlich der Anzahl ihrer Zugriffe auf die Zeichen im String -- und warum? +% Sie dürfen für \lstinline{strlen()} Ihre eigene Version der Funktion voraussetzen. +% \points 3 +% \item[(f)] + Schreiben Sie eine eigene Funktion, + die dieselbe Aufgabe erledigt wie \lstinline{fun_2()},\\ + nur effizienter. + \points{4} + \end{itemize} + + \solution + + \begin{itemize} + \item[(a)] + \textbf{Auf welche Weise ist die Länge eines Strings gekennzeichnet?} + + Ein String ist ein Array von \lstinline{char}s. + Nach den eigentlichen Zeichen des Strings enthält das Array + \textbf{ein Null-Symbol} (Zeichen mit Zahlenwert 0, + nicht zu verwechseln mit der Ziffer \lstinline{'0'}) als Ende-Markierung. + Die Länge eines Strings ist die Anzahl der Zeichen + \emph{vor\/} diesem Symbol. + + \item[(b)] + {\bf Wie lang ist die Beispiel-String-Konstante \lstinline{"Hello, world!\n"}, + und wieviel Speicherplatz belegt sie?} + + Sie ist 14 Zeichen lang (\lstinline{'\n'} ist nur 1 Zeichen; + das Null-Symbol, das das Ende markiert, zählt hier nicht mit) + und belegt Speicherplatz für 15 Zeichen + (15 Bytes -- einschließlich Null-Symbol / Ende-Markierung). + + \item[(c)] + \textbf{Schreiben Sie eine eigene Funktion \lstinline{int strlen (char *s)}, + die die Länge eines Strings zurückgibt.} + + Siehe die Dateien \gitfile{hp}{2021ws/20211122}{loesung-2c-1.c} (mit Array-Index) + und \gitfile{hp}{2021ws/20211122}{loesung-2c-2.c} (mit Zeiger-Arithmetik). + Beide Lösungen sind korrekt und arbeiten gleich schnell. + + Die Warnung \lstinline[style=terminal]{conflicting types for built-in function "strlen"} + kann normalerweise ignoriert werden; + auf manchen Systemen (z.\,B.\ MinGW) hat jedoch die eingebaute Funktion \lstinline{strlen()} + beim Linken Vorrang vor der selbstgeschriebenen, + so daß die selbstgeschriebene Funktion nie aufgerufen wird. + In solchen Fällen ist es zulässig, die selbstgeschriebene Funktion + anders zu nennen (z.\,B.\ \lstinline{my_strlen()}). + + \item[(d)] + \textbf{Was bewirken die beiden Funktionen?} + + Beide addieren die Zahlenwerte der im String enthaltenen Zeichen + und geben die Summe als Funktionsergebnis zurück. + + Im Falle des Test-Strings \lstinline{"Hello, world!\n"} + lautet der Rückgabewert 1171 (siehe \gitfile{hp}{2021ws/20211122}{loesung-2d-1.c} und \gitfile{hp}{2021ws/20211122}{loesung-2d-2.c}). + + \item[(e)] +% \textbf{Von welcher Ordnung (Landau-Symbol) sind die beiden Funktionen +% hinsichtlich der Anzahl ihrer Zugriffe auf die Zeichen im String -- und warum? +% Sie dürfen für \lstinline{strlen()} Ihre eigene Version der Funktion voraussetzen.} +% +% Vorüberlegung: \lstinline{strlen()} greift in einer Schleife +% auf alle Zeichen des Strings der Länge $n$ zu, +% hat also $\mathcal{O}(n)$. +% +% \lstinline{fun_1()} ruft in jedem Schleifendurchlauf +% (zum Prüfen der \lstinline{while}-Bedingung) einmal \lstinline{strlen()} auf +% und greift anschließend auf ein Zeichen des Strings zu, +% hat also $\mathcal{O}\bigl(n\cdot(n+1)\bigr) = \mathcal{O}(n^2)$. +% +% \lstinline{fun_2()} ruft einmalig \lstinline{strlen()} auf +% und greift anschließend in einer Schleife auf alle Zeichen des Strings zu, +% hat also $\mathcal{O}(n+n) = \mathcal{O}(n)$. +% +% \item[(f)] + \textbf{Schreiben Sie eine eigene Funktion, + die dieselbe Aufgabe erledigt wie \lstinline{fun_2()}, + nur effizienter.} + + Die Funktion wird effizienter, + wenn man auf den Aufruf von \lstinline{strlen()} verzichtet + und stattdessen die Ende-Prüfung in derselben Schleife vornimmt, + in der man auch die Zahlenwerte der Zeichen des Strings aufsummiert. + + Die Funktion \lstinline{fun_3()} in der Datei \gitfile{hp}{2021ws/20211122}{loesung-2e-1.c} + realisiert dies mit einem Array-Index, + Die Funktion \lstinline{fun_4()} in der Datei \gitfile{hp}{2021ws/20211122}{loesung-2e-2.c} + mit Zeiger-Arithmetik. + Beide Lösungen sind korrekt und arbeiten gleich schnell. + +% \textbf{Bemerkung:} Die effizientere Version der Funktion +% arbeitet doppelt so schnell wie die ursprüngliche, +% hat aber ebenfalls die Ordnung $\mathcal{O}(n)$. + + \end{itemize} + + \exercise{LED-Blinkmuster} + + Wir betrachten das folgende Programm für einen ATmega32-Mikro-Controller + (Datei: \gitfile{hp}{2021ws/20211122}{aufgabe-3.c}). + + \begin{minipage}[t]{7cm} + \begin{lstlisting}[gobble=6] + #include <stdint.h> + #include <avr/io.h> + #include <avr/interrupt.h> + + uint8_t counter = 1; + uint8_t leds = 0; + + ISR (TIMER0_COMP_vect) + { + if (counter == 0) + { + leds = (leds + 1) % 8; + PORTC = leds << 4; + } + counter++; + } + \end{lstlisting} + \end{minipage}\hfill\begin{minipage}[t]{8.5cm} + \begin{lstlisting}[gobble=6] + void init (void) + { + cli (); + TCCR0 = (1 << CS01) | (1 << CS00); + TIMSK = 1 << OCIE0; + sei (); + DDRC = 0x70; + } + + int main (void) + { + init (); + while (1) + ; /* do nothing */ + return 0; + } + \end{lstlisting} + \end{minipage} + + An die Bits Nr.\ 4, 5 und 6 des Output-Ports C des Mikro-Controllers sind LEDs angeschlossen.\\ + Sobald das Programm läuft, blinken diese in charakteristischer Weise: + \begin{quote} + \newcommand{\tdn}[1]{\raisebox{-2pt}{#1}} + \begin{tabular}{|c|c|c|c|}\hline + \tdn{Phase} & \tdn{LED oben (rot)} & \tdn{LED Mitte (gelb)} & \tdn{LED unten (grün)} \\[2pt]\hline + 1 & aus & aus & an \\\hline + 2 & aus & an & aus \\\hline + 3 & aus & an & an \\\hline + 4 & an & aus & aus \\\hline + 5 & an & aus & an \\\hline + 6 & an & an & aus \\\hline + 7 & an & an & an \\\hline + 8 & aus & aus & aus \\\hline + \end{tabular} + \end{quote} + Jede Phase dauert etwas länger als eine halbe Sekunde. + Nach 8 Phasen wiederholt sich das Schema. + + Erklären Sie das Verhalten des Programms anhand des Quelltextes: + \vspace{-\medskipamount} + \begin{itemize}\itemsep0pt + \item[(a)] + Wieso macht das Programm überhaupt etwas, + wenn doch das Hauptprogramm nach dem Initialisieren lediglich eine Endlosschleife ausführt, + in der \emph{nichts} passiert? + \points{1} + \item[(b)] + Wieso wird die Zeile \lstinline|PORTC = leds << 4;| überhaupt aufgerufen, + wenn dies doch nur unter der Bedingung \lstinline|counter == 0| passiert, + wobei die Variable \lstinline|counter| auf 1 initialisiert, + fortwährend erhöht und nirgendwo zurückgesetzt wird? + \points{2} + \item[(c)] + Wie kommt das oben beschriebene Blinkmuster zustande? + \points{2} + \item[(d)] + Wieso dauert eine Phase ungefähr eine halbe Sekunde? + \points{2} + \item[(e)] + Was bedeutet "`\lstinline|ISR (TIMER0_COMP_vect)|"'? + \points{1} + \end{itemize} + + \goodbreak + Hinweis: + \vspace{-\medskipamount} + \begin{itemize}\itemsep0pt + \item + Die Funktion \lstinline|init()| sorgt dafür, daß der Timer-Interrupt Nr.\ 0 des Mikro-Controllers + etwa 488mal pro Sekunde aufgerufen wird. + Außerdem initialisiert sie die benötigten Bits an Port C als Output-Ports. + Sie selbst brauchen die Funktion \lstinline|init()| nicht weiter zu erklären. + \end{itemize} + + \solution + + \begin{itemize}\itemsep0pt + \item[(a)] + \textbf{Wieso macht das Programm überhaupt etwas, + wenn doch das Hauptprogramm nach dem Initialisieren lediglich eine Endlosschleife ausführt, + in der \emph{nichts} passiert?} + + Das Blinken wird durch einen Interrupt-Handler implementiert. + Dieser wird nicht durch das Hauptprogramm, + sondern durch ein Hardware-Ereignis (hier: Uhr) aufgerufen. + + \item[(b)] + \textbf{Wieso wird die Zeile \lstinline|PORTC = leds << 4;| überhaupt aufgerufen, + wenn dies doch nur unter der Bedingung \lstinline|counter == 0| passiert, + wobei die Variable \lstinline|counter| auf 1 initialisiert, + fortwährend erhöht und nirgendwo zurückgesetzt wird?} + + Die vorzeichenlose 8-Bit-Variable \lstinline{counter} kann nur + Werte von 0 bis 255 annehmen; bei einem weiteren + Inkrementieren springt sie wieder auf 0 (Überlauf), + und die \lstinline{if}-Bedingung ist erfüllt. + + \item[(c)] + \textbf{Wie kommt das oben beschriebene Blinkmuster zustande?} + + In jedem Aufruf des Interrupt-Handlers wird die Variable + \lstinline{leds} um 1 erhöht und anschließend modulo 8 genommen. + Sie durchläuft daher immer wieder die Zahlen von 0 bis 7. + + Durch die Schiebeoperation \lstinline{leds << 4} werden die 3 Bits + der Variablen \lstinline{leds} an diejenigen Stellen im Byte + geschoben, an denen die LEDs an den Mikro-Controller + angeschlossen sind (Bits 4, 5 und 6). + + Entsprechend durchläuft das Blinkmuster immer wieder + die Binärdarstellungen der Zahlen von 0 bis 7 + (genauer: von 1 bis 7 und danach 0). + + \item[(d)] + \textbf{Wieso dauert eine Phase ungefähr eine halbe Sekunde?} + + Der Interrupt-Handler wird gemäß Hinweis 488mal pro Sekunde aufgerufen. + Bei jedem 256sten Aufruf ändert sich das LED-Muster. + Eine Phase dauert somit $\frac{256}{488} \approx 0.52$ Sekunden. + + \item[(e)] + \textbf{Was bedeutet "`\lstinline|ISR (TIMER0_COMP_vect)|"'?} + + Deklaration eines Interrupt-Handlers für den Timer-Interrupt Nr.\ 0 + \end{itemize} + +\end{document} diff --git a/20211122/hp-uebung-20211122.pdf b/20211122/hp-uebung-20211122.pdf new file mode 100644 index 0000000000000000000000000000000000000000..46601e585d752ed9fc18b0a632beecfa0cb9735f Binary files /dev/null and b/20211122/hp-uebung-20211122.pdf differ diff --git a/20211122/hp-uebung-20211122.tex b/20211122/hp-uebung-20211122.tex new file mode 100644 index 0000000000000000000000000000000000000000..6e031dd149fdd13f3f11954d86f618491c988053 --- /dev/null +++ b/20211122/hp-uebung-20211122.tex @@ -0,0 +1,236 @@ +% hp-uebung-20211122.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: Ausgabe von Hexadezimalzahlen, Einfügen in Strings, LED-Blinkmuster + +\documentclass[a4paper]{article} + +\usepackage{pgscript} + +\begin{document} + +% \thispagestyle{empty} + + \section*{Hardwarenahe Programmierung\\ + Übungsaufgaben -- 22.\ November 2021} + + Diese Übung enthält Punkteangaben wie in einer Klausur. + Um zu "`bestehen"', müssen Sie innerhalb von 80 Minuten + unter Verwendung ausschließlich zugelassener Hilfsmittel + 14 Punkte (von insgesamt \totalpoints) erreichen. + + \exercise{Ausgabe von Hexadezimalzahlen} + + Schreiben Sie eine Funktion \lstinline{void print_hex (uint32_t x)}, + die eine gegebene vorzeichenlose 32-Bit-Ganzzahl \lstinline{x} + als Hexadezimalzahl ausgibt. + (Der Datentyp \lstinline{uint32_t} ist mit \lstinline{#include <stdint.h>} verfügbar.) + + Verwenden Sie dafür \emph{nicht\/} \lstinline{printf()} mit + der Formatspezifikation \lstinline{%x} als fertige Lösung, + sondern programmieren Sie die nötige Ausgabe selbst. + (Für Tests ist \lstinline{%x} hingegen erlaubt und sicherlich nützlich.) + + Die Verwendung von \lstinline{printf()} + mit anderen Formatspezifikationen wie z.\,B.\ \lstinline{%d} + oder \lstinline{%c} oder \lstinline{%s} ist hingegen zulässig. + + \points{8} + + (Hinweis für die Klausur: Abgabe auf Datenträger ist erlaubt und erwünscht, + aber nicht zwingend.) + + \exercise{Länge von Strings} + + Strings werden in der Programmiersprache C durch Zeiger auf \lstinline{char}-Variable realisiert. + + Beispiel: \lstinline{char *hello_world = "Hello, world!\n"} + + Die Systembibliothek stellt eine Funktion \lstinline{strlen()} zur Ermittlung der Länge von Strings\\ + zur Verfügung (\lstinline{#include <string.h>}). + + \begin{itemize} + \item[(a)] + Auf welche Weise ist die Länge eines Strings gekennzeichnet? + \points{1} + \item[(b)] + Wie lang ist die Beispiel-String-Konstante \lstinline{"Hello, world!\n"}, + und wieviel Speicherplatz belegt sie?\\ + \points{2} + \item[(c)] + Schreiben Sie eine eigene Funktion \lstinline{int strlen (char *s)}, + die die Länge eines Strings zurückgibt.\\ + \points{3} + \end{itemize} + + Wir betrachten nun die folgenden Funktionen (Datei: \gitfile{hp}{2021ws/20211121}{aufgabe-2.c}): + \begin{center} + \begin{minipage}{8cm} + \begin{lstlisting}[gobble=8] + int fun_1 (char *s) + { + int x = 0; + for (int i = 0; i < strlen (s); i++) + x += s[i]; + return x; + } + \end{lstlisting} + \end{minipage}% + \begin{minipage}{6cm} + \vspace*{-1cm} + \begin{lstlisting}[gobble=8] + int fun_2 (char *s) + { + int i = 0, x = 0; + int len = strlen (s); + while (i < len) + x += s[i++]; + return x; + } + \end{lstlisting} + \vspace*{-1cm} + \end{minipage} + \end{center} + \begin{itemize} + \item[(d)] + Was bewirken die beiden Funktionen? + \points{2} + \item[(e)] +% Von welcher Ordnung (Landau-Symbol) sind die beiden Funktionen +% hinsichtlich der Anzahl ihrer Zugriffe auf die Zeichen im String -- und warum? +% Sie dürfen für \lstinline{strlen()} Ihre eigene Version der Funktion voraussetzen. +% \points 3 +% \item[(f)] + Schreiben Sie eine eigene Funktion, + die dieselbe Aufgabe erledigt wie \lstinline{fun_2()},\\ + nur effizienter. + \points{4} + \end{itemize} + + \exercise{LED-Blinkmuster} + + Wir betrachten das folgende Programm für einen ATmega32-Mikro-Controller + (Datei: \gitfile{hp}{2021ws/20211121}{aufgabe-3.c}). + + \begin{minipage}[t]{7cm} + \begin{lstlisting}[gobble=6] + #include <stdint.h> + #include <avr/io.h> + #include <avr/interrupt.h> + + uint8_t counter = 1; + uint8_t leds = 0; + + ISR (TIMER0_COMP_vect) + { + if (counter == 0) + { + leds = (leds + 1) % 8; + PORTC = leds << 4; + } + counter++; + } + \end{lstlisting} + \end{minipage}\hfill\begin{minipage}[t]{8.5cm} + \begin{lstlisting}[gobble=6] + void init (void) + { + cli (); + TCCR0 = (1 << CS01) | (1 << CS00); + TIMSK = 1 << OCIE0; + sei (); + DDRC = 0x70; + } + + int main (void) + { + init (); + while (1) + ; /* do nothing */ + return 0; + } + \end{lstlisting} + \end{minipage} + + An die Bits Nr.\ 4, 5 und 6 des Output-Ports C des Mikro-Controllers sind LEDs angeschlossen.\\ + Sobald das Programm läuft, blinken diese in charakteristischer Weise: + \begin{quote} + \newcommand{\tdn}[1]{\raisebox{-2pt}{#1}} + \begin{tabular}{|c|c|c|c|}\hline + \tdn{Phase} & \tdn{LED oben (rot)} & \tdn{LED Mitte (gelb)} & \tdn{LED unten (grün)} \\[2pt]\hline + 1 & aus & aus & an \\\hline + 2 & aus & an & aus \\\hline + 3 & aus & an & an \\\hline + 4 & an & aus & aus \\\hline + 5 & an & aus & an \\\hline + 6 & an & an & aus \\\hline + 7 & an & an & an \\\hline + 8 & aus & aus & aus \\\hline + \end{tabular} + \end{quote} + Jede Phase dauert etwas länger als eine halbe Sekunde. + Nach 8 Phasen wiederholt sich das Schema. + + Erklären Sie das Verhalten des Programms anhand des Quelltextes: + \vspace{-\medskipamount} + \begin{enumerate}[\quad(a)] + \item + Wieso macht das Programm überhaupt etwas, + wenn doch das Hauptprogramm nach dem Initialisieren lediglich eine Endlosschleife ausführt, + in der \emph{nichts} passiert? + \points{1} + \item + Wieso wird die Zeile \lstinline|PORTC = leds << 4;| überhaupt aufgerufen, + wenn dies doch nur unter der Bedingung \lstinline|counter == 0| passiert, + wobei die Variable \lstinline|counter| auf 1 initialisiert, + fortwährend erhöht und nirgendwo zurückgesetzt wird? + \points{2} + \item + Wie kommt das oben beschriebene Blinkmuster zustande? + \points{2} + \item + Wieso dauert eine Phase ungefähr eine halbe Sekunde? + \points{2} + \item + Was bedeutet "`\lstinline|ISR (TIMER0_COMP_vect)|"'? + \points{1} + \end{enumerate} + + Hinweis: + \vspace{-\medskipamount} + \begin{itemize}\itemsep0pt + \item + Die Funktion \lstinline|init()| sorgt dafür, daß der Timer-Interrupt Nr.\ 0 des Mikro-Controllers + etwa 488mal pro Sekunde aufgerufen wird. + Außerdem initialisiert sie die benötigten Bits an Port C als Output-Ports. + Sie selbst brauchen die Funktion \lstinline|init()| nicht weiter zu erklären. + \end{itemize} + + \begin{flushright} + \textit{Viel Erfolg!} + \end{flushright} + + \makeatletter + \immediate\write\@mainaux{\string\gdef\string\totalpoints{\arabic{points}}} + \makeatother + +\end{document} diff --git a/20211122/io-ports-and-interrupts.pdf b/20211122/io-ports-and-interrupts.pdf new file mode 120000 index 0000000000000000000000000000000000000000..bcd46f7afb35605b20bdb05637e6de0a039893ec --- /dev/null +++ b/20211122/io-ports-and-interrupts.pdf @@ -0,0 +1 @@ +../common/io-ports-and-interrupts.pdf \ No newline at end of file diff --git a/20211122/loesung-1-1.c b/20211122/loesung-1-1.c new file mode 100644 index 0000000000000000000000000000000000000000..98b2f03f19d21aa2a794fef1f3f98feff95f5142 --- /dev/null +++ b/20211122/loesung-1-1.c @@ -0,0 +1,22 @@ +#include <stdio.h> +#include <stdint.h> + +void print_hex (uint32_t x) +{ + while (x) + { + int digit = x % 16; + if (digit < 10) + printf ("%d", digit); + else + printf ("%c", 'a' + digit - 10); + x /= 16; + } +} + +int main (void) +{ + print_hex (0xcafe42); + printf ("\n"); + return 0; +} diff --git a/20211122/loesung-1-2.c b/20211122/loesung-1-2.c new file mode 100644 index 0000000000000000000000000000000000000000..35aa3b3aea6fc8faaa55c7d5382f0a8de9282aee --- /dev/null +++ b/20211122/loesung-1-2.c @@ -0,0 +1,26 @@ +#include <stdio.h> +#include <stdint.h> + +void print_hex (uint32_t x) +{ + char digit[8]; + for (int i = 0; i < 8; i++) + { + digit[i] = x % 16; + x /= 16; + } + for (int i = 7; i >= 0; i--) + { + if (digit[i] < 10) + printf ("%d", digit[i]); + else + printf ("%c", 'a' + digit[i] - 10); + } +} + +int main (void) +{ + print_hex (0xcafe42); + printf ("\n"); + return 0; +} diff --git a/20211122/loesung-1-3.c b/20211122/loesung-1-3.c new file mode 100644 index 0000000000000000000000000000000000000000..2462f2b537896722d8d1774a5d47f374ee5ef7fa --- /dev/null +++ b/20211122/loesung-1-3.c @@ -0,0 +1,29 @@ +#include <stdio.h> +#include <stdint.h> + +void print_hex (uint32_t x) +{ + char digit[8]; + int i = 0; + while (x) + { + digit[i] = x % 16; + x /= 16; + i++; + } + while (i > 0) + { + i--; + if (digit[i] < 10) + printf ("%d", digit[i]); + else + printf ("%c", 'a' + digit[i] - 10); + } +} + +int main (void) +{ + print_hex (0xcafe42); + printf ("\n"); + return 0; +} diff --git a/20211122/loesung-1-4.c b/20211122/loesung-1-4.c new file mode 100644 index 0000000000000000000000000000000000000000..5083dcb865c86beafd43ce3e8837510b13cbe850 --- /dev/null +++ b/20211122/loesung-1-4.c @@ -0,0 +1,31 @@ +#include <stdio.h> +#include <stdint.h> + +void print_hex (uint32_t x) +{ + char digit[8]; + for (int i = 0; i < 8; i++) + { + digit[i] = x % 16; + x /= 16; + } + int printing = 0; + for (int i = 7; i >= 0; i--) + { + if (printing || digit[i] != 0) + { + printing = 1; + if (digit[i] < 10) + printf ("%d", digit[i]); + else + printf ("%c", 'a' + digit[i] - 10); + } + } +} + +int main (void) +{ + print_hex (0xcafe42); + printf ("\n"); + return 0; +} diff --git a/20211122/loesung-1-5.c b/20211122/loesung-1-5.c new file mode 100644 index 0000000000000000000000000000000000000000..e3446edb4a40348ac14da420f344c208f8916f7e --- /dev/null +++ b/20211122/loesung-1-5.c @@ -0,0 +1,29 @@ +#include <stdio.h> +#include <stdint.h> + +void print_hex (uint32_t x) +{ + char digit[8]; + int i = 0; + while (x) + { + digit[i] = x & 0x0000000f; + x >>= 4; + i++; + } + while (i > 0) + { + i--; + if (digit[i] < 10) + printf ("%d", digit[i]); + else + printf ("%c", 'a' + digit[i] - 10); + } +} + +int main (void) +{ + print_hex (0xcafe42); + printf ("\n"); + return 0; +} diff --git a/20211122/loesung-1-6.c b/20211122/loesung-1-6.c new file mode 100644 index 0000000000000000000000000000000000000000..7b8e8e1a9d7285b8a1e02ff1a91310f1dc02ed5b --- /dev/null +++ b/20211122/loesung-1-6.c @@ -0,0 +1,23 @@ +#include <stdio.h> +#include <stdint.h> + +void print_hex (uint32_t x) +{ + int i = 32; + while (i > 0) + { + i -= 4; + int digit = (x >> i) & 0x0000000f; + if (digit < 10) + printf ("%d", digit); + else + printf ("%c", 'a' + digit - 10); + } +} + +int main (void) +{ + print_hex (0xcafe42); + printf ("\n"); + return 0; +} diff --git a/20211122/loesung-2.c b/20211122/loesung-2.c new file mode 100644 index 0000000000000000000000000000000000000000..85abfcf3e1e4bacf454acd10f6832b757a64ac35 --- /dev/null +++ b/20211122/loesung-2.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/20211122/loesung-2c-1.c b/20211122/loesung-2c-1.c new file mode 100644 index 0000000000000000000000000000000000000000..69ddd0e4e749f6ca31bfa3d4f929c333648ef6ea --- /dev/null +++ b/20211122/loesung-2c-1.c @@ -0,0 +1,15 @@ +#include <stdio.h> + +int strlen (char *s) +{ + int l = 0; + while (s[l]) + l++; + return l; +} + +int main (void) +{ + printf ("%d\n", strlen ("Hello, world!\n")); + return 0; +} diff --git a/20211122/loesung-2c-2.c b/20211122/loesung-2c-2.c new file mode 100644 index 0000000000000000000000000000000000000000..e783c474e485e80d08a6e86f8ae6e179f5a294f4 --- /dev/null +++ b/20211122/loesung-2c-2.c @@ -0,0 +1,15 @@ +#include <stdio.h> + +int strlen (char *s) +{ + char *s0 = s; + while (*s) + s++; + return s - s0; +} + +int main (void) +{ + printf ("%d\n", strlen ("Hello, world!\n")); + return 0; +} diff --git a/20211122/loesung-2d-1.c b/20211122/loesung-2d-1.c new file mode 100644 index 0000000000000000000000000000000000000000..57521382c21fb743c6f5f5c65320bc4ac9360b1a --- /dev/null +++ b/20211122/loesung-2d-1.c @@ -0,0 +1,34 @@ + +#include <stdio.h> + +int strlen (char *s) +{ + int l = 0; + while (s[l]) + l++; + return l; +} + +int fun_1 (char *s) +{ + int x = 0; + for (int i = 0; i < strlen (s); i++) + x += s[i]; + return x; +} + +int fun_2 (char *s) +{ + int i = 0, x = 0; + int len = strlen (s); + while (i < len) + x += s[i++]; + return x; +} + +int main (void) +{ + printf ("%d\n", fun_1 ("Hello, world!\n")); + printf ("%d\n", fun_2 ("Hello, world!\n")); + return 0; +} diff --git a/20211122/loesung-2d-2.c b/20211122/loesung-2d-2.c new file mode 100644 index 0000000000000000000000000000000000000000..5f3f0961129aa16fc9c4510ae21bb77b69913b12 --- /dev/null +++ b/20211122/loesung-2d-2.c @@ -0,0 +1,34 @@ + +#include <stdio.h> + +int strlen (char *s) +{ + char *s0 = s; + while (*s) + s++; + return s - s0; +} + +int fun_1 (char *s) +{ + int x = 0; + for (int i = 0; i < strlen (s); i++) + x += s[i]; + return x; +} + +int fun_2 (char *s) +{ + int i = 0, x = 0; + int len = strlen (s); + while (i < len) + x += s[i++]; + return x; +} + +int main (void) +{ + printf ("%d\n", fun_1 ("Hello, world!\n")); + printf ("%d\n", fun_2 ("Hello, world!\n")); + return 0; +} diff --git a/20211122/loesung-2e-1.c b/20211122/loesung-2e-1.c new file mode 100644 index 0000000000000000000000000000000000000000..74f5add0c5f62cccb8f817d40f860893f496db11 --- /dev/null +++ b/20211122/loesung-2e-1.c @@ -0,0 +1,15 @@ +#include <stdio.h> + +int fun_3 (char *s) +{ + int i = 0, x = 0; + while (s[i]) + x += s[i++]; + return x; +} + +int main (void) +{ + printf ("%d\n", fun_3 ("Hello, world!\n")); + return 0; +} diff --git a/20211122/loesung-2e-2.c b/20211122/loesung-2e-2.c new file mode 100644 index 0000000000000000000000000000000000000000..b223d2d17c261d7cf1373a8379def8911a45ccb7 --- /dev/null +++ b/20211122/loesung-2e-2.c @@ -0,0 +1,15 @@ +#include <stdio.h> + +int fun_4 (char *s) +{ + int x = 0; + while (*s) + x += *s++; + return x; +} + +int main (void) +{ + printf ("%d\n", fun_4 ("Hello, world!\n")); + return 0; +} diff --git a/20211122/logo-hochschule-bochum-cvh-text-v2.pdf b/20211122/logo-hochschule-bochum-cvh-text-v2.pdf new file mode 120000 index 0000000000000000000000000000000000000000..4aa99b8f81061aca6dcaf43eed2d9efef40555f8 --- /dev/null +++ b/20211122/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/20211122/logo-hochschule-bochum.pdf b/20211122/logo-hochschule-bochum.pdf new file mode 120000 index 0000000000000000000000000000000000000000..b6b9491e370e499c9276918182cdb82cb311bcd1 --- /dev/null +++ b/20211122/logo-hochschule-bochum.pdf @@ -0,0 +1 @@ +../common/logo-hochschule-bochum.pdf \ No newline at end of file diff --git a/20211122/pgscript.sty b/20211122/pgscript.sty new file mode 120000 index 0000000000000000000000000000000000000000..95c888478c99ea7fda0fd11ccf669ae91be7178b --- /dev/null +++ b/20211122/pgscript.sty @@ -0,0 +1 @@ +../common/pgscript.sty \ No newline at end of file diff --git a/20211122/pgslides.sty b/20211122/pgslides.sty new file mode 120000 index 0000000000000000000000000000000000000000..5be1416f4216f076aa268901f52a15d775e43f64 --- /dev/null +++ b/20211122/pgslides.sty @@ -0,0 +1 @@ +../common/pgslides.sty \ No newline at end of file diff --git a/README.md b/README.md index 496ea72b5b42cea1ee8913a9670d37e4b4545f50..93225d529b18636d0f5f055b42be021d8dc67904 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,8 @@ 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/) + * [15.11.2021: I/O-Ports](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211115/hp-20211115.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2021ws/20211115/) + * [22.11.2021: I/O-Ports, Interrupts](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211122/hp-20211122.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2021ws/20211122/) * [alle in 1 Datei](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/hp-slides-2021ws.pdf) Übungsaufgaben: @@ -32,7 +33,8 @@ 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) + * [15.11.2021: Zahlensysteme, Mikrocontroller, Einfügen in Strings](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211115/hp-uebung-20211115.pdf) + * [22.11.2021: Ausgabe von Hexadezimalzahlen, Einfügen in Strings, LED-Blinkmuster](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211122/hp-uebung-20211122.pdf) Musterlösungen: --------------- @@ -41,6 +43,7 @@ Musterlösungen: * [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) + * [22.11.2021: Ausgabe von Hexadezimalzahlen, Einfügen in Strings, LED-Blinkmuster](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211122/hp-musterloesung-20211122.pdf) Tafelbilder: ------------ diff --git a/hp-slides-2021ws.pdf b/hp-slides-2021ws.pdf index e6892010ce91be1cafd3621c238bcbaf11fff821..7e50ab34a5d1e358c88372581d7a338486146a8b 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 cfd6bb634dd89821a8d4c9c39f78ae50fad24711..08153151954859c4133dff7c20e5c2370513b217 100644 --- a/hp-slides-2021ws.tex +++ b/hp-slides-2021ws.tex @@ -20,6 +20,8 @@ \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} + \pdfbookmark[1]{15.11.2021: I/O-Ports}{20211115} \includepdf[pages=-]{20211115/hp-20211115.pdf} + \pdfbookmark[1]{22.11.2021: I/O-Ports, Interrupts}{20211122} + \includepdf[pages=-]{20211122/hp-20211122.pdf} \end{document}