# INGIM - Klausurvorbereitung
## 1. Architekturen
### 1.1 Von-Neumann-Architektur:
#### ~~1.1.1 Grundlegender Aufbau:~~

#### ~~1.1.2 Vor- und Nachteile~~
~~* Vorteile: geringer Hardware- und Speicheraufwand, Programm kann während der Laufzeit verändert werden~~
~~* Nachteile: nur ein Bussystem -> alles wird sequentiell transportiert, bei falscher Adressierung können Daten verändert werden, die nicht verändert werden sollen.Weil das Programm während der Laufzeit verändert werden kann, macht es das anfälliger für Viren und Trojaner.~~
#### 1.1.3 5-Phasen von-Neumann Zyklus:
1. Fetch: holt nächsten Befehl aus Adresse des Befehlszähler
2. Decode: löst diesen in Schaltinstruktion auf
3. Fetch Operands: holt die Operanden
4. Execute: Eigentliche Befehlsausführung
5. Write back: Ergebnis zurückschreiben
### 1.2 Harvard-Architektur:
#### ~~1.2.1 Grundlegender Aufbau:~~

~~* Vorteile: getrennter Programm- und Datenspeicher mit seperatem Bussystem und somit getrenntem Adressraum~~
~~* Nachteile:~~
#### 1.2.2 Harvard vs. Neumann
* Gemeinsamkeiten:
* Befehle werden sequentiell abgearbeitet
* Unterschied:
* Hardware-/Speicheraufwand: $Harvard > Neumann$
* Harvard:
* hat 2 Daten-/Adress-/Steuerbusse, Programmspeicher separat zu Datenspeicher und Ein-/Ausgabebaustein
* Neumann:
* hat 1 Daten-/Adress-/Steuerbus, alles hängt an diesen (falsche Adressierung führt zu Datacorruption)
* Programm kann während Laufzeit verändert werden (Angriffsfläche für Trojaner und Viren)
## 2. Microcontroller
### 2.1 Allgemeines zur Hardware
#### 2.1.1 Speicherarten:
* ROM: Speicher der nur gelesen werden kann
* RAM: sehr schnell und beliebig oft lesbar und schreibbar
* Register: sehr schneller Speicher, Zugriff ohne Bustransfer
#### 2.1.2 ADC - Analog Digital Converter
* wandelt analoge Spannung in einen binären Wert um, der der Amplitude der Messgröße zur Messzeit entspricht
* befähigt Microcontroller zur digitalen Verarbeitung analoger Messgrößen
##### ADC-Beispielaufgabe: "5V MCU, 10-Bit ADC, Welchen Wert gibt der ADC aus bei 3.3V ?"
$ADC = (1023 * \frac{3,3V}{5V}) = 675,18 =676$
#### 2.1.3 Unterschiede MCU <-> CPU:
| MCU | CPU |
| -------- | -------- |
| Kern der CPU und zus. Peripheriegruppen für Mess-, Steuerungs- und Kommunikationsaufgaben | hat keine Peripheriegruppen |
| | Arithmetik-Prozessoren, Signalprozessoren, Krypthografieprozessoren |
~~#### 2.1.4 Einsatzgebiete GPIO~~
~~* Digitale Ein-/Ausgabe (General Purpose Input Output)~~
~~* Schnittstelle zwischen analogen und digitalen Systemen~~
### 2.2 Speziell Atmega
#### 2.2.1 Allgemeine Eigenschaften Atmega328PB
* RISC-Architektur
* Harvard-Architektur
~~* 1.8 - 5.5V Betriebsspannung~~
~~* 2kB Programmspeicher~~
~~* 32kB Datenspeicher~~
* 8-Bit (Wortbreite)
~~* 27 GPIO-Pins~~
~~* 4 Ports~~
* Register eines GPIO + Funktion:
1. Data Direction Register x => Steuerregister
2. PORTx Register => Datenregister
3. PINx => Statusregister
~~* INT1 liegt auf Pin PD3~~
* ADC-Wandlungsprinzip: successive approximation
* Timer-Baustein kann eingesetzt werden für:
* Generieren eines PWM Signals (OUT)
* Zählen von externen Impulsen (IN)
* Interne Zeitsteuerungsaufgaben (INTERN)
## 3. Programmierung von MCUs
### 3.1 Allgemeines zur Software
Generelle Struktur eines Mikroprozessorprogramms:
```c
#define F_CPU => Frequenz der CPU
#include <stdlib.h> => Libraries //stdlib als Beispiel
global variables (volatile)
Funktionen, ISR, etc.
“int main(void)”-Funktion mit:
[Initialisierungen]
[while(1)-Schleife]
sowie aufrufen der obigen Funktionen
```
### 3.2 Bitweise Operatoren in C
& $=> AND$
$| => OR$
^ $=> XOR$
~ $=> NOT$
$<<$ $=> Shift Left$
$>>$ $=> Shift Right$
### 3.3 Diagramm "Endlicher Automat/State-Machine"
Mealy Struktur und Notation

Start Code:
```
enum PUSHSTATES {NOTPUSHED,PROBABLY,PUSHED};
enum PUSHSTATES gPushStates = NOTPUSHED;
uint8_t pos_edge = 0;
int main(void){
switch(gPushStates){...}
}
```
### 3.4 Aufgaben:
##### 3.4.1. Bit in Register setzen/rücksetzen
**wichtig**
* REG_A &= ~(1<<BIT4); //rücksetzen
* REG_A |= (1<<BIT0); //setzen
##### 3.4.2. Schreiben Sie ein C-Programm, das einen HIGH-Pegel an Pin PB4 generiert, falls am Pin PB2 ein LOW-Pegel anliegt, ansonsten soll an PB4 der LOW-Pegel ausgegeben werden.
```cpp
int main(void){
DDRB |= (1 << DDRB4);
while(1){
if((PINB & (1<< PINB2)) == 0){
PORTB |= (1 << PORTB4)
} else {
PORTB &= ~(1<<PORTB4);
}
}
return 0;
}
```
##### ~~3.4.3. C-Ausdruck "a = 5|12":~~
```
5 = 0000 0101
12 = 0000 1100
a = 0000 1101 = 13
```
##### ~~3.4.4. C-Ausdruck "a = 5&12":~~
```
5 = 0000 0101
12 = 0000 1100
a = 0000 0100
```
##### ~~3.4.5. C-Ausdruck "a = 5^12":~~
```
5 = 0000 0101
12 = 0000 1100
a = 0000 1001
```
##### 3.4.6. C-Programm "High-Pegel an PB4, falls Low-Pegel an PB2, else Low-Pegel an PB4":
```cpp
if(PINB & (1<<PB2)){
PORTB &= ~(1<<PB4);
}else{
PORTB |= (1<<PB4);
}
```
##### 3.4.7. C-Ausdruck a=(1<<3), Welchen Wert hat a?
```
a = 0b00000100
```
##### ~~3.4.8. C-Ausdruck a=(27>>2), Welchen Wert hat a?~~
```
a = 0b00000110 = 6
```
##### ~~3.4.9. C-Ausdruck a=(1&3), Welchen Wert hat a?~~
```
a = 1
```
##### ~~3.4.10. C-Ausdruck a=(10|3), Welchen Wert hat a~~
```
a = 0b00001011
```
##### 3.4.11. C-Ausdruck char a = 1025, Welchen Wert hat a?
```
a = 1
```
##### 3.4.12. Zweierkomplement-Darstellung Addition
```
100 + 28
100 = 0110 0100
28 = 0001 1100
ÜBTR= 1111 1
SUM = 1000 0000
(Overflow, da Vorzeichenwechsel, bei Zweierkomplement kein Carry)
```
## 4. Architekturen
### 4.1 MIPS:
* (Ursprünglich) 32-Bit -> 32-Bit Wortbreite, Instruktion hat 32Bit
### 4.2 Adresse xtes Speicherwort:
Man fängt bei 0x00 an und zählt in 4er-Schritten hoch: 0x00, 0x04...
### 4.3 Instruktionen
~~* Eine Instruktion umfasst 32 Bit~~
#### 4.3.1 Instruktionskomponenten:
<style type="text/css">
.tg {border-collapse:collapse;border-spacing:0;}
.tg td{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;
overflow:hidden;padding:10px 5px;word-break:normal;}
.tg th{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;
font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}
.tg .tg-c3ow{border-color:inherit;text-align:center;vertical-align:top}
.tg .tg-0pky{border-color:inherit;text-align:left;vertical-align:top}
</style>
<table class="tg">
<thead>
<tr>
<th class="tg-0pky" rowspan="2">Name</th>
<th class="tg-0pky" colspan="6">Bit Fields</th>
<th class="tg-0pky">Notes</th>
</tr>
<tr>
<th class="tg-0pky">6 bits</th>
<th class="tg-0pky">5 bits</th>
<th class="tg-0pky">5 bits</th>
<th class="tg-0pky">5 bits</th>
<th class="tg-0pky">5 bits</th>
<th class="tg-0pky">6 bits</th>
<th class="tg-0pky">{32 bits total}</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tg-0pky">R-Format</td>
<td class="tg-c3ow">op</td>
<td class="tg-c3ow">rs</td>
<td class="tg-c3ow">rt</td>
<td class="tg-c3ow">rd</td>
<td class="tg-c3ow">shamt</td>
<td class="tg-c3ow">funct</td>
<td class="tg-0pky">Arithmetic, logic</td>
</tr>
<tr>
<td class="tg-0pky">I-Format</td>
<td class="tg-c3ow">op</td>
<td class="tg-c3ow">rs</td>
<td class="tg-c3ow">rt</td>
<td class="tg-c3ow" colspan="3">immediate</td>
<td class="tg-0pky">branch, immediate</td>
</tr>
<tr>
<td class="tg-0pky">Load/Store</td>
<td class="tg-c3ow">op</td>
<td class="tg-c3ow">rs</td>
<td class="tg-c3ow">rt</td>
<td class="tg-c3ow" colspan="3">address</td>
<td class="tg-0pky">Load/Store</td>
</tr>
<tr>
<td class="tg-0pky">J-Format</td>
<td class="tg-c3ow">op</td>
<td class="tg-c3ow" colspan="5">Target address(26)</td>
<td class="tg-0pky">Jump</td>
</tr>
</tbody>
</table>
### 4.4 RISC <-> CISC
| RISC | CISC |
| -------------------------------- | ---------------------------------- |
| Reduced Instruction Set Computer | Complex Instruction Set Computers |
| feste Schaltung für jeden Befehl | "Zusammenschaltung" d. Schaltungen |
| ein Takt pro Befehl | einfachere Compiler |
| weniger Transistoren | kürzerer Maschinencode |
| sehr Energieeffizient / kühler | |
### 4.5 RISC-Befehlssatz Charakteristika
* Befehlssatz umfasst nur "einfache" Operationen
* Gleichförmiges Befehlsformat (1 Befehl pro Taktzyklus möglich)
* Operanden liegen immer in Registern (load/store architecture)
### 4.6 LOAD-STORE-Architektur
* nur Load- und Store-Befehle greifen auf Hauptspeicher zu
* Alle anderen Befehle arbeiten ausschließlich mit Registeroperanden und Literalen
* L-/S-Befehle besitzen keine komplexen Adressmodi, stattdessen werden die Adressen in frei verwendbaren Registern berechnet
(MIPS ist eine Load-Store-Architektur)
## 5. Rechenaufgaben
### 5.1 Periodendauern/Zyklen
* Dauer Befehlssequenz mit n Takten bei best. Prozessortakt
* Prozessortakt umrechnen zu Taktzeit: $$T_{CPU} = \frac{1}{f_{CPU}}$$
* Taktzeit mal Anzahl benötigte Takte n: $$t = n*T_{CPU}$$
### 5.2 Zahlensysteme(Hex, Bin, Oct, so what?)
#### 5.2.1. Zahl mit n = 2, k = 3, d = 10101. Welcher Wert für die Basis b=2,8,10,16?
**Wichtig**
* b=2: $2^1*1 + 2^0*0 + 2^{-1}*1 + 2^{-2}*0 + 2^{-3}*1 = 2,625$
* n: Anzahl Stellen vor dem Komma (hier 2, d.h. hoch 1 und hoch 0)
* k: Anzahl Nachkommastellen (hier 3, d.h. hoch -1, hoch -2 und hoch -3)
* d ist die Zahl, die jeweilige Stelle wird mit dem korrespondierenden Zahlenwert multipliziert
#### ~~5.2.2. Geben Sie die Hexadezimal- und die Octaldarstellung von 0111011010111011₂ an.~~
~~* Umrechnen in Oktal: Man unterteilt die Binärzahl in Dreierkomplemente, angefangen von hinten: 0 111 011 010 111 011
Nun kann man die Komplemente ins Oktalsystem umrechnen und aneinander fügen: 7 3 2 7 3 = 73273~~
~~* Umrechnen in Hexadezimal: Man unterteilt die Binärzahl in Viererkomplemente, angefangen von hinten: 0111 0110 1011 1011
Man kann die Komplente ins Hex-System umrechnen und aneinander fügen: 7 6 B B = 76BB~~
### 5.3 Fließkommazahl nach IEEE 754
~~Drei Komponenten einer Fließkommazahl:~~
~~1. Mantisse~~
~~2. Exponent~~
~~3. Vorzeichen~~
~~Berechnung Wert aus normalisierter Fließkommazahl~~
~~* Das erste Bit ist der Vorzeichenexponent S: -1^S~~
~~* Die nächsten 8 Bit ergeben den Exponenten, man muss den errechneten Wert minus 127 rechnen: Exponent - 127~~
~~* Die hinteren 23 Bit ergeben die Nachkommastellen der Mantisse in der Form 0.xxxxxxxxxxxxxxxxxxxxxxx~~
~~* Da hier eine normalisierte Fließkommazahl vorliegt, wird der Wert der Mantisse zu 1.xxxxxxxxxxxxxxxxxxxxxxx~~
~~* (-1)^S*Mantisse*2^{Exponent}~~
#### 5.3.1 Addition und Multiplikation von Fließkommazahlen:
* Addition:
1. Gleiche den kleineren Exponent an den größeren an
2. Addiere die Mantissen
3. Normalisiere
4. Nach jedem Schritt wird gerundet
* Multiplikation
1. Multipliziere die Vorzeichen
2. Multipliziere die Mantissen
3. Addiere die Exponenten (und subtrahiere die Bias)
4. Normalisiere, runde falls nötig
#### 5.3.2 Rechnen mit IEEE 754
1. Wandeln Sie die Dezimalzahlen a = 3.4 bzw. b = 10.25 in Gleitkommazahlen mit single precision (IEEE 754 standard) um.
~~* **3.4:**
Der Vorzeichenexponent S ist hier 0
Nun teilt man die Zahl auf in 3 und 0.4
Man teilt erst die 3 durch 2:
$3/2 = 1$ Rest 1
$1/2 = 0$ Rest 1
Man liest die Zahl von unten nach oben: $3 = 11$
Die 0.4 rechnet man mal 2:
$0.4 * 2 = 0.8$ Übertrag 0
$0.8 * 2 = 1.6$ Übertrag 1
$0.6 * 2 = 1.2$ Übertrag 1
$0.2 * 2 = 0.4$ Übertrag 0 -> es gibt eine Wiederholung der Folge $0110$
Man liest die Zahl von oben nach unten: $0.4 = 0.011001100110...$
Daraus ergibt sich: $3.4 = 11.01100110...$
Um den Exponent zu bestimmen, muss man die Bitzahl so schieben, dass sie wie folgt aussieht: $1.xxx...$ Die Anzahl an Stellen, um die man schieben muss um auf diese Form zu kommen ist der Exponent. In diesem Fall ist das eine Stelle nach links, was bedeutet, dass unser Exponent $E = 1$ ist.
Für den normalisierten Exponenten addieren wir $1+127 = 128$
Diesen Wert kann man nun in eine 8-Bit Zahl umrechenen: $128 = 10000000$
Die Mantisse ist der oben errechnete und verschobene Wert, wobei nur die Zahlen nach dem Komma relevant sind.
$M = 10110011001100110011001|1$
Man sieht, dass eine 1 abgeschnitten wird, da nur die ersten 23 Bit gespeichert werden. Hier kann man aufrunden:
$M = 10110011001100110011010$
Die gesamte Gleitkommazahl ergibt sich somit zu:
$0.10000000.10110011001100110011010$~~
* **10.25**
Wie oben: $S = 0$,
$10/2 = 5$ Rest 0
$5/2 = 2$ Rest 1
$2/2 = 1$ Rest 0
$1/2 = 0$ Rest 1
$10 = 1010$
Und dasselbe mit den Nachkommastellen:
$0.25 * 2 = 0.5$ "Rest" 0
$0.5 * 2 = 1$ "Rest" 1
Damit: $0.25 = 01$
Gesamt: $10.25 = 1010.01$
Verschieben: $1.01001$ -> 3 Stellen nach Links geschoben, $E = 3$
E normalisiert ist $3+127=130$
Umrechnen in Binär: $130 = 10000010$
Mantisse bestimmt sich zu: $01001000...$ -> Die restlichen freien Bits werden mit 0 aufgefüllt.
Zusammen: $0.10000010.01001000000000000000000$
2. Gegeben sei die folgende IEEE 754 Gleitkommazahl in Binär- und Hexadezimaldarstellung. Rechnen Sie die Gleitkommazahl schrittweise in die übliche Dezimaldarstellung um.
* $0xC17D0000$
Jede Hex-Stelle entspricht vier Bit. Man wandelt jede Stelle nun um und schreibt sie zusammen, danach teilt man die erhaltene Binärzahl im Sinne von IEEE754 auf:
$C = 1100$
$1 = 0001$
$7 = 0111$
$D = 1101$
$0 = 0000$
Damit ergibt sich die Fließkommazahl zu:
$1.10000010.11111010000000000000000$
Vorzeichenbit $S = 1$
Exponent $e_n = 130$
Denormalisierter Exponent ist $E = 130 - 127 = 3$
Mantisse +1 rechnen:
$1.xxxx...$
Zahl der Mantisse um 3 Stellen nach links verschieben:
$1111.1101$
Zahl vor dem Komma und nach dem Komma ausrechnen:
$Z_v = 15$
$Z_n = 0.8125$
Zahlen zusammenrechnen, Vorzeichen beachten:
$Z = -15.8125$
#### 5.3.3 Rundungsfehler
* Binärsystem kann manche Kommazahlen nicht richtig darstellen
* Wenn die Fließkommazahl mehr als 23 Bit benötigt, wird der Rest abgeschnitten
* Je größer die Zahl, desto weniger Nachkommastellen können dargestellt werden -> der Rundungsfehler wird größer
#### 5.3.4 Spezialfälle:
|Type (>0)|Sign|Exponennt|Mantisse|Value|
|---------|----|---------|--------|-----|
|Big normal|0|11111110|11111111111111111111111|$2^{127}*(2-2^{-23})$|
|Smol normal|0|00000001|00000000000000000000000|$2^{-126}$|
|Big denormal|0|00000000|11111111111111111111111|$(2-2^{-22})*2^{-127}$|
|Smol denormal|0|00000000|00000000000000000000001|$2^{-149}$|
## 6. Assembler
### 6.1 MIPS-Assembler-Code Aufgaben:
#### 6.1.1. MIPS-Assembler Code für $y = (a + b) - (c - 4)$ mit y, a, b, c in den Registern s0, s1, s2, s3:
```
add $t0, $s1, $s2
addi $t1, $s3, -4
sub $s0, $t0, $t1
```
#### 6.1.2. (32-bit Architektur) MIPS-Assember Code für: short A[20]; A[6] = A[6] + 17; Startadresse in s0.
```
short = 2 Byte
mal die Stelle im Array
2 * 6 für A[6]
addi $t0, $s0, 12
lw $t1, ($t0)
addi $t1, $t1, 17 #addiere A[6] + 17 und schreibe in t1
sw $t1, ($t0)
```
#### 6.1.3. C --> ASM:
|g|h|i|f|
|---|---|---|---|
|$a0|$a1|$a2|$s0|
tipp: $tx müssen nicht auf dem Stack zwischengespeichert werden
```
int leaf_example(int g, int h, int i){
int f;
if (g==h){
f = g + h + i;
}
return f;
}
leaf_example:
addi $sp, $sp, -4 #Platz im Stack für ein Wort generieren
sw $s0, 0($sp) #Inhalt von $s0 im Stack sichern
beq $a0, $a1, IF #springt zu Label IF wenn a0==a1
j EXIT #springt zu Label EXIT
IF: add $t0, $a0, $a1 #temporäres Speichern der Addition von a0 und a1
add $s0, $t0, $a2 #s0 mit der Addition von t0 und a2 überschreibe
EXIT:add $v0, $s0, $zero #ins Rückgaberegister s0 schreiben
lw $s0, 0($sp) #s0 mit altem Wert überschreiben
addi $sp, $sp, 4 #Stackpointer zurück auf Anfang pointen
jr $ra #Rücksprung zum Funktionsaufruf
```
```
lw $s0, 4($s2) #lädt in Register s0 den Wert, welcher sich auf der Adresse MEM_ADDR[4+Wert(s2)] befindet
bne $a1, $a2, IF2 #springt zu Label IF2 wenn a1!=a2
```
#### 6.1.4. C --> ASM:
| a | b | c | i | j |
|---|---|---|---|---|
|$s0|$s1|$s2|$s3|$s4|
```
if (i == j) {
a = b + c;
} else {
a = b – c;
}
```
```
bne $s3, $s4, uwu # if-Bedingung (springe zu uwu, falls $s3 != $s4)
add $s0, $s1, $s2 #wird ausgeführt falls §S3 == §s4
j Exit
uwu: sub $s0 $s1 $s2
Exit: … # end of whatever, bye
```
### 6.2. Stack Pointer
Adresspointer, zeigt auf oberste Adresse des Stacks
## 7 Computersysteme
### 7.1 Die vier zentralen Bestandteile eines Computersystems:
* Mikroprozessor (Central Processing Unit)
* Programmspeicher
* Datenspeicher
* Ein-/Ausgabeeinheiten (I/O-Ports)
### 7.2 Hauptaufgaben einer CPU (=Zentraleinheit):
* Datenverarbeitung
* Steuerung aller notwendigen Funktionseinheiten
* Sicherung des korrekten Voranschreitens des Systemzustandes
### 7.3 Essentielle Komponenten eines Prozessorkerns (CPU):
* Steuerwerk
* Operationswerk
* Registersatz
* Adresswerk
* Systembus-Schnittstelle
### 7.4 Maschinentakt:
* Regelmäßiges elektrisches Rechtecksignal
* Synchronisierung aller Komponenten
### 7.5 Programmzähler:
* Enthält die Adresse des nächsten auszuführenden Befehls
### 7.6 Befehlssatz:
* direktes Abbild aller Operationen die der Prozessor ausführen kann
* Anzahl der Operanden
* Operanden aus Registern / Speicher
* Addressierungsmodi **(Hatten wir noch nicht)**
* Länge von Befehlen
* (kann 1:1 in Assemblersprache abgebildet werden)
### 7.7 Cross-Compiler vs Compiler
| Compiler | Cross-Compiler|
| -------- | -------- |
| kompiliert Programme für das Host-System, auf dem er läuft| kann Programme für andere Computersysteme kompilieren, als das auf dem er läuft |
* Wie muss eine Variable abc definiert werden, die durch den Compiler bzw. Cross-Compiler keine Optimierungen erfahren soll?
```
volatile int abc = 0;
```
## 8. Interrupts
* Werden beim PC vom OS im Bootvorgang freigeschaltet
* Beim Mikrocontroller muss der Anwender Interrupts die er benötigt selbst freischalten
* Globale Interrupts enablen, häufig mit Funktion "sei();"
* Interrupts im jeweiligen Control Register einschalten
* ISR einrichten und code kurz halten
* Um Peripheriegeräten das auslösen von Interrupts zu ermöglichen, werden zwei Leitungen benötigt: **Interrupt acknowledge (IACK) und Interrupt request(IRQ)**
### 8.1 Funktionsprinzip
1. Interruptquelle wird ausgelöst
2. Der laufende Befehl/Low-Power-Mode wird beendet
3. Hardware übermittelt auf den unteren 5 Bits des internen Datenbusses Nummer des ausgelösten Interrupts an CPU -> berechnet, auf welche Interrupt-Vektor-Tabelle zugegriffen werden muss
4. Program Counter (PC) und Statusregister (SREG) werden gespeichert
5. Falls mehrere Interrupts anstehen, wird der mit der höchsten Priorität ausgewählt (niedrigste Adresse in Vektortabelle)
6. Statusregister wird gelöscht -> verhindert weitere Interrupts
7. ISR wird aufgerufen und ausgeführt
8. Letzter Befehl ISR: gespeicherte Zustandswort&Rücksprungadresse vom Stack holen und in die jeweiligen Register schreiben
9. Interrupts werden wieder enabled, Programm läuft an unterbrochener Stelle weiter
### 8.2 Polling vs Interrupts
| ISR | Polling |
| -------- | -------- |
| Aufruf wenn Flag gesetzt wurde | Zyklische Abfrage eines Moduls |
| Programm wird unterbrochen | Keine Programmunterbrechung |
| Sprung zur ISR sobald der aktuelle Befehl beendet wurde | Je nach Länge des Programms können zeitkritische Ereignisse verpasst werden/zu spät ausgeführt werden|
|Beim 328PB werden Interrupts ignoriert, wenn man bereits in einer ISR ist|Ereignisse werden schneller oder langsamer abgefragt, je nachdem, in welchem Programmabschnitt sich das Programm befindet|
### 8.3 Programmbeispiele
#### 8.3.1. C-Variable tick, die zur Kommunikation zwischen ISR und dem Hauptprogramm genutzt werden kann?
```c
volatile char tick = 0;
```
#### 8.3.2. ISR für 328PB, bei INT0-Interrupt Pin PC4 toggelt
```c
ISR(INT0_vect){
PORTC ^= (1 << PINC4);
}
```
~~#### 8.3.3. Wie muss ein Interrupt konfiguriert werden (welche Bits in welchem Register), so dass durch einen Übergang vom HIGH zum LOW-Pegel am Pin PD3 eine ISR ausgeführt wird?~~
~~sei();
ISR(INT1_vect){
lcd.printf(“Vogt hat wieder geklaut.”);
}
EIMSK |= (1 << INT1);
EICRA |= (1 << 3);~~
#### 8.3.4. TIMER0_OVF-Interrupt wird mit 100Hz ausgelöst. Schreiben Sie TIMER0_OVF-ISR und while(1) in C, so dass task1() mit 10Hz und task2() mit 2Hz ausgeführt werden. Alle Variablen global definieren.
```
volatile int count = 0;
ISR(TIMER0_OVF_vect){
count++;
}
while(1){
if(count%10 == 0){
task1();
}
if(count%50 == 0){
task2();
count = 0;
}
}
```
## 9. Timer
### 9.1 Prescaler
Der Prescaler teilt den Prozessortakt und kann dadurch langsamere Vorgänge mit Timern steuern. Der Prozessortakt kann nur durch bestimmte 2-er Potenzen geteilt werden und demzufolge nur 2-er Potenzen annehmen.
### ~~9.2 Timer-Interrupts~~
~~Bits für Aktivierung eines Timer-Overflow-Interrupts:~~
~~1. Globales Interrupt Enable Bit aktivieren~~
~~2. Spezifischen Interruptregisterbit setzen (z.B. Timer0 Overflow Interrupt enable)~~
### 9.3 Pulsweitenmodulation (PWM)
* Regelung von ON- und OFF-Zeiten eines bestimmten GPIOs durch einen Timer
* Tastverhältnis: Verhältnis von PWM_ON zu PWM-Taktlänge:
$g=\frac{t_{ON}}{t{ges}}$
### 9.4 Aufgaben
#### 9.4.1. Programm 1MHz Taktfrequenz nutzt Timer, um Uhr mit Auflösung 100ms machen. Welche Timerparameter mit welchen Werten?
* 8- oder 16-Bit Timer?
* Maximalwerte: 8-Bit: $MAX = 2^8-1 = 255$; 16-Bit: $MAX = 2^{16} - 1 = 65535$
* Prescaler: ${\frac{f_{CPU}*100ms}{2^{8-Bit}}} = 390.625$
* Wert auf nächstgrößere Zweierpotenz aufrunden: Prescaler = $390.625 => 512$
* Start-/Comparewert: $\frac{100ms}{T_{CPU}*512} = 195.3125 => 195$
* Startwert: $2^{8-Bit} - 195 = 256 - 195 = 61$
* Comparewert: $195 - 1 = 194$
#### 9.4.2. LED an 328PB soll mit 75% max Helligkeit leuchten. Prinzipielles Vorgehen?
* Timer Mode Fast PWM
* Timer-Interrupt on Compare enablen
* Timer-Interrupt on Timer-Overflow enablen
* TOP = 63 (8-Bit Timer)
* LED-GPIO bei erreichen von TOP in der ISR einschalten
* LED-GPIO bei erreichen von Overflow in der ISR ausschalten
#### 9.4.3. TIMER0_OVF-Interrupt mit f = 100Hz ausgelöst. TIMER0_OVF-ISR und while(1) in C, so dass task1() mit 10Hz und task2() mit 2Hz ausgeführt werden. Alle Variablen global definieren.
```
#define PERIODE_TASK1 10 // 10 Takte fuer 10 Hz
#define PERIODE_TASK2 50 // 50 Takte fuer 2 Hz
volatile char gTime1 = PERIODE_TASK1;
volatile char gTime2 = PERIODE_TASK2;
ISR(TIMER0_OVF_vect){
if(gTime1>0){--gTime1;}
if(gTime2 > 0){--gTime2;}
}
void main{
sei();
while(1){
if(gTime1 == 0){
gTime1 == PERIODE_TASK1;
task1();
}
if(gTime2 == 0){
gTime2 == PERIODE_TASK2;
task2();
}
}
}
```
#### 9.4.4. Vorgehen, aus einem Programm eine LED-Blinkfrequenz zu errechnen
1. Clocktakte bis CompareMatch berechnen: $(OCRA+1)*Prescaler = Anz_{Clocktakte}$
2. Clocktakte bis Interrupt-Zähler 0 erreicht: $Anz_{Clocktakte}*Taskperiode = Totalticks$
3. Frequenz der Task: $\frac{f_{CPU}}{Totalticks}=f_{task}$
4. **Wichtig: $f_{LED}=\frac{f_{task}}{2}$**
#### 9.4.5. Änderungen Programm bei Veränderung Periodendauer größer 255
```
volatile char gTime muss zu volatile int angepasst werden
tmpTime durch gTime ersetzen
cli();
if(gTime1 == 0){
gTime1 = …;
sei();
task();
}
```
## 10. Datenübertragungsprotokolle
|Betriebsart|Funktion|
|--------|--------|
|Simplex|Datenübertragung in eine Richtung (SDI)|
|Duplex|Datenübertragung in beide Richtungen (UART)|
|Halbduplex|Daten können abwechselnd in beide Richtungen übertragen werden (I²C)|
### 10.1 I²C (Halbduplex)
#### 10.1.1 Eigenschaften:
- 2-Adrige Verbindung SDA und SCL
- Master - Slave
- Master stellt anfrage an Slave
- Open Drain mit externen Pull_UP
#### 10.1.2 Ablauf
| START | 7-Bit slave address | R/W | ACK | 8-Bit DATA |ACK | ... | STOP |
|-------|---------------------|-----|-----|------------|----|-----|------|
Mit jedem LOW Puls auf SCL (Serial Clock) wird das moentane Bit auf der SDA-Leitung (Serial-Data) Übertragen.
Start Sequenz: Data runter ziehen, Clock runter ziehen
### 10.2 UART und RS-232 (Vollduplex)
#### 10.2.1 Baudrate
Die Baudrate Bestimmt wie viele ZEICHEN/secunde übertragen werden können
bsp.: 9600 baud = 9600 Zeichen/Secunde
Ein Zeichen sind 5-8 Bit
#### 10.2.2 Unterschiede
UART: 0V/5V (je nach MCU auch 3.3V)
RS232: üblicherweise +12V/-12V