Grundlagen der Mikrocontrollertechnik im Sommersemester 2026
(EN google-translate)
(PL google-translate)
|
04_SoSe2026 -- Einstiegsseite zum Sommersemester 2026 mit Angaben zu Räumen, Zeiten und den Prüfungen der einzelnen Fächer.
#1 Di, 24.03.2026
THEMEN HEUTE
|
1. Worum geht es?
Mikrocontroller sind aus der heutigen Welt nicht mehr wegzudenken. Sie bilden typischerweise das Kernstück s.g. Eingebetteter Systeme. Das sind technische Komponenten, die typischerweise dauerhaft steuer- und regelungstechnische Aufgaben in technischen Systemen übernehmen, die zuvor von elektronischen, bzw. elektromechanischen Komponenten übernommen wurden.
2. Motivation -- Warum ist das wichtig?
Viele Aufgaben, die zuvor durch mechanische Systeme übernommen wurden, wurden zunächst durch Elektromechanische Systeme ersetzte und noch später durch Eingebettete Systeme. Der Vorteil dieser Entwicklung liegt vor allem darin, dass das Verhalten der Eingebetteten Systeme durch ein Computerprogramm festgelegt wird und nicht mehr durch elektronische Schaltungen, oder mechanische Komponenten. Dadurch können die gleichen Grundsysteme in sehr vielen Geräten eingesetzt werden. Was sie voneinander unterscheidet ist dann das Programm, dass auf ihnen läuft. Das wiederum hat zur Folge, dass Mikrocontroller in sehr hohen Stückzahlen hergestellt werden können und damit eine sehr preiswerte Produktion möglich wird.
Zudem können Updates, Anpassungen und Fehlerbehebungen oft einfach durch eine Veränderung der Software, die auf dem System läuft vorgenommen werden, anstatt eine neue Schaltung zu entwickeln, oder eine neue Mechanik entwickeln zu müssen.
Eingebettete Systeme finden Sie beispielsweise...
|
Als exemplarisches Beispiel für die Einsatzmöglichkeit eines Mikrocontrollers, sieht man hier, wie dieser werden kann, um einfache regelungstechnische Aufgaben bei kleinen autonomen Vehikeln zu übernehmen, um eine Linie zu verfolgen, oder auf einer Achse zu balancieren:
Bild 0-1: Schwarmvehikel, die eine Linie verfolgen können und auf das Auftauchen von Hindernissen reagieren.
Bild 0-2: Einachser (Vehikel, das auf einer Achse balanciert)
ÜBUNG
Versuchen Sie die nachfolgenden Fragen zu beantworten:
|
3. Welche Themen werden behandelt?
|
4. Welche Leistungen sollten Sie erbringen? / Organisatorisches
|
Neben dieser Prüfung wird es Miniprojekte geben, die in Zweiergruppen zu bearbeiten sind und die dazu dienen sollen, die erlernte Theorie anzuwenden.
|
5. Einstieg
|
40_Mikrocontroller/01_Einfuehrung/02_Maschinensprache -- Unterschied zwischen Mikrocontroller und PC
|
40_Mikrocontroller/01_Einfuehrung/01_Entwicklungsgeschichtliches -- Grundidee eines Computers
|
40_Mikrocontroller/01_Einfuehrung/03_Assemblerbeispiel -- Registerbefehle
|
96_Arduino/02_Taster -- Computerprogramm für einen Arduino Mikrocontroller
|
01_Einfuehrung/05_Praxis/01_Digital_IO -- Übersicht zu Registerbefehlen im Zusammenhang mit digitalen Ein- und Ausgängen
40_Mikrocontroller/01_Einfuehrung/05_Praxis/02_Byteoperationen -- Registerbefehl-basiertes Programm
96_Arduino/22_Universal/02_LED_Leiste -- PORTB beim Arduino Micro
6. Hands on -- Die erste Übung
Aufgabe 1
|
96_Arduino/02_Taster
|
Aufgabe 2
|
96_Arduino/22_Universal/02_LED_Leiste -- PORTB beim Arduino Micro
void setup()
{
}
void loop()
{
DDRB = 255;
PORTB = 255;
}
Code 0-1: Testprogramm.
void setup()
{
}
void loop()
{
DDRB = 255;
PORTB = 1;
delay(100);
PORTB = 2;
delay(100);
PORTB = 4;
delay(100);
PORTB = 8;
delay(100);
PORTB = 16;
delay(100);
PORTB = 32;
delay(100);
PORTB = 64;
delay(100);
PORTB = 128;
delay(100);
}
Code 0-2: Lauflicht Musterlösung 2
void setup()
{
DDRB = 255;
PORTB = 255;
}
int x = 0;
void loop()
{
DDRB = 255;
PORTB = 1<<x;
x++;
x%=8;
delay(100);
}
Code 0-3: Lauflicht Musterlösung 2.
|
#2 Di, 31.03.2026
Themen diese Woche:
|
1. Quiz
|
2. Die Schildkröten des Walter Grey
|
zu 4. Quelle: Bundestag Einzelanfrage: Einzelfragen zurHalbleiterproduktion, Seite 10. Web 21.03.2023: https://www.bundestag.de/resource/blob/900450/25b9b36d92928f932b242efc8578386a/WD-5-004-22-pdf-data.pdf
Hersteller in Europa: NXP, ST, Infineon. Japan: Renesas. USA: Microchip.
3. Angaben zur Syntax von C/C++ bei der Mikrocontrollerprogrammierung
4. Basisregister für die Programmierung digitaler Ein- und Ausgänge
|
Verwendung der internen Pullup-Widerstände -- 40_Mikrocontroller/03_DigitalIO/02_Pullup_Widerstaende
Bitmasken für den Eingang -- 40_Mikrocontroller/03_DigitalIO/03_Bitmasken_Eingang
Bild 0-3: Schaltung.
BEISPIELPROGRAMME: Mit oberer Taste untere LED steuern:
void setup()
{
pinMode(11,OUTPUT);
//digitalWrite(11,HIGH);
pinMode(8,INPUT);
digitalWrite(8,HIGH);//Pullup
}
void loop()
{
if(digitalRead(8)==0)
digitalWrite(11,HIGH);
else
digitalWrite(11,LOW);
}
Code 0-4: Arduino-Befehls-Variante.
void setup()
{
//pinMode(11,OUTPUT);
DDRB = DDRB | 0b10000000; // PB7 auf 1 setzen
//pinMode(8,INPUT);
DDRB = DDRB & 0b11101111; // PB4 auf 0 setzen
//digitalWrite(8,HIGH);//Pullup
PORTB = PORTB | 0b00010000; // PB4 setzen, PULLUP
}
void loop()
{
if( (PINB & 0b00010000) == 0 )
PORTB = PORTB | 0b10000000;
else
PORTB = PORTB & 0b01111111;
}
Code 0-5: Register-Befehls-Variante.
5. Bitoperationen zur Manipulation von Mikrocontroller-Registern
& bitweise logische UND-Verknüpfung | bitweise logische ODER-Verknüpfung ~ NICHT (Invertieren aller Bits) << Links-Shift-Operator: x=1<<3; //Beispiel shiftet die 1 dreimal nach links, ergibt dezimal 8. >> Rechts-Shift-Operator: y=12>>1; //Beispiel shiftet die 12 einmal nach rechts, ergibt dezimal 6, entspricht Division durch 2.
Code 0-6: Liste mit Bitoperationen
Manipulation einzelner Bits bei Register-Befehlen durch Verwendung von Bitmasken
void setup()
{
//DDRB = 0b10000000; //PB7 als Ausgang konfigurieren.
//NUR PB7 setzen, ohne die anderen Bits zu verändern!:
DDRB = DDRB | 0b10000000; //Bitweises ODER-Verknüpfen eines Registers mit einer Bitmaske
}
void loop() {
PORTB = PORTB | 0b10000000; // 5 Volt auf Digitalpin 11 'rausschicken, bzw. auf PB7
delay(500);
PORTB = PORTB & 0b01111111;
delay(500);
}
Code 0-7: Nur höchstwertigstes Bit manipulieren (PB7), mit Hilfe von Bitmasken und Bitoperationen.
6. Umsetzung eines Lauflicht-Programms auf der Basis von Mikrocontroller-Registern in Kombination mit Bitoperationen
7. ÜBUNG
Aufgabe 1
Bauen Sie die angegebene Schaltung ohne den Entfernungssensor auf und testen die weiter oben besprochenen Programme:
Bild 0-4: Schaltung.
Aufgabe 2
|
Aufgabe 3
|
Di, 07.04.2026 -- keine Lehrveranstaltung wegen Ostern
#3 Di, 14.04.2026
Themen heute:
|
1. Lösungen zur Fussgängerampel-Aufgabe
void setup()
{
pinMode(10,OUTPUT);
pinMode(11,OUTPUT);
digitalWrite(10,HIGH);
pinMode(8,INPUT);
digitalWrite(8,HIGH);//Pullup
}
void loop()
{
if(digitalRead(8)==0)
{
digitalWrite(11,HIGH);
digitalWrite(10,LOW);
delay(2000);
digitalWrite(10,HIGH);
digitalWrite(11,LOW);}
else
{
digitalWrite(10,HIGH);
}
}
Code 0-8: Studentische Lösung.
void setup()
{
//pinMode(10,OUTPUT);
//pinMode(11,OUTPUT);
DDRB = DDRB | 0b11000000; // PB6 und PB7 auf 1 setzen
//pinMode(8,INPUT);
DDRB = DDRB & 0b11101111; // PB4 auf 0 setzen
//digitalWrite(8,HIGH);//Pullup
PORTB = PORTB | 0b00010000; // PB4 setzen, PULLUP
}
void loop()
{
if( (PINB & 0b00010000) == 0 )
{
PORTB = PORTB | 0b10000000;
PORTB = PORTB & 0b10111111;
delay(2000);
PORTB = PORTB & 0b01111111;
PORTB = PORTB | 0b01000000;
}
else
{
PORTB = PORTB | 0b01000000;
}
}
Code 0-9: Studentische Lösung mit Registerbefehlen.
2. Bussysteme
Bussysteme -- 40_Mikrocontroller/06_UART/01_Bussysteme
3. Die UART Schnittstelle
UART - Universal Asynchronous Receiver Transmitter -- 40_Mikrocontroller/06_UART
UART -- 40_Mikrocontroller/06_UART/02_UART
RS232 -- 40_Mikrocontroller/06_UART/03_RS232
Hardware - Verbinden eines ATmega32 mit einem PC über die RS232 Schnittstelle -- 40_Mikrocontroller/06_UART/04_Hardware
Senden -- 40_Mikrocontroller/06_UART/05_Senden
4. Übung Datenaustausch zwischen Mikrocontroller und Arduino
|
|
Damit die Übetragung nicht zu schnell läuft, wird die delay-Funktion benötigt.
void setup()
{
Serial.begin(9600);
}
void loop()
{
Serial.write('H');
Serial.write('a');
Serial.write('l');
Serial.write('l');
Serial.write('o');
Serial.write('!');
Serial.write('\n');
delay(500);
}
Code 0-10: Im Unterricht entwickeltes Programm "Hallo!".
void setup()
{
DDRB |= 0b10000000;
PORTB &= 0b01111111;
Serial.begin(9600);
}
void loop()
{
if(Serial.available())
{
int x = Serial.read();
if(x=='1')
{
PORTB |= 0b10000000;
}
else if(x=='0')
{
PORTB &= 0b01111111;
}
}
}
Code 0-11: Im Unterricht entwickeltes Programm LED Fernsteuerung.
AUFGABE 1
|
| Schalter PB5 geschlossen | Schalter PB4 geschlossen | an PC senden |
|---|---|---|
| NEIN | NEIN | 0 |
| NEIN | JA | 1 |
| JA | NEIN | 2 |
| JA | JA | 3 |
Tabelle 0-1: Binäre Kodierung der Schalterzustände.
|
AUFGABE 2
|
AUFGABE 3
|
#4 Di, 21.04.2026
Themen heute:
|
1. Besprechung der Übungsaufgaben von letzter Woche
void setup()
{
DDRD = DDRB | 0b11000000;
// DDRD |= 0b11000000;
PORTB = PORTB & 0b00111111;
Serial.begin(9600);
}
void loop()
{
// 0 1 2 3
// 00 01 10 11
if(Serial.available()>0)
{
int incomingByte = Serial.read();
Serial.print("I recerived: ");
Serial.println((char)incomingByte);
if(incomingByte=='0')
{
PORTB = PORTB & 0b00111111;
}
else if(incomingByte=='1')
{
PORTB = PORTB & 0b01111111; //PB7 aus
PORTB = PORTB | 0b01000000; //PB6 an
}
else if(incomingByte=='2')
{
PORTB = PORTB & 0b10111111; //PB6 aus
PORTB = PORTB | 0b10000000; //PB7 an
}
else if(incomingByte=='3')
{
PORTB = PORTB | 0b11000000; //PB6 und PB7 an
}
}
}
Code 0-12: Fernsteuern zweier LEDs studentische Lösung.
void setup()
{
DDRD = DDRB | 0b11000000;
// DDRD |= 0b11000000;
PORTB = PORTB & 0b00111111;
Serial.begin(9600);
}
void loop()
{
// 0 1 2 3
// 00 01 10 11
if(Serial.available()>0)
{
int incomingByte = Serial.read();
Serial.print("I recerived: ");
Serial.println((char)incomingByte);
// '0'==48 '1'==49 '2'==50 '3'==51
// incomingByte - '0'; =>
// 0 1 2 3
// 00 01 10 11
// 00000011 ist
// 11000000 soll
incomingByte = incomingByte - '0'; // '0'==48
//PORTB = incomingByte << 6;
//Untere 6 Bits nicht manipulieren:
PORTB |= (incomingByte << 6);
PORTB &= (incomingByte << 6) + 0b00111111;
}
}
Code 0-13: Zweite Lösung unter Verwendung von Bitshiftoperatoren.
2. Objektorientierte Programmierung mit dem Arduino Mikrocontroller
40_Mikrocontroller/08_OOP -- Motivation zu OOP.
40_Mikrocontroller/08_OOP/01_Probleme -- was es im Zusammenhang mit Mikrocontrollern bei OOP zu beachten gilt.
40_Mikrocontroller/08_OOP/02_Konzept -- Grundkonzept Singleton als UML-Klassendiagramm.
3. Anwendungsbeispiel Bussysteme: Verbindung zu einem IMU-Sensor (MPU6050)
Verwendung eines IMU vom Typ MPU6050 über das I2C (aus patentrechtlichen Gründen im Datenblatt TWI -- Two Wire Interface -- genannt) Bussystem genannt
|
96_Arduino/31_day_by_day -- siehe "Verwendung eines MPU6050 Beschleunigungssensors"
15_Einachser/02_Bauanleitung/06_MPU6050 -- Anwendungsfall Einachser
4. Übungen
Aufgabe 1 (gemeinsam)
------------- |LED | ------------- |+on() : bool| |+off(): bool| -------------
Code 0-14: UML Klassendiagramm zur LED Klasse
|
30_Informatik3/02_UML/02_UML_Klassendiagramm
Variante:
#include "Led.h"
Led gruen(7);
Led rot(6);
void setup()
{
Serial.begin(9600);
}
void loop()
{
if(Serial.available())
{
int zeichen = Serial.read();
if(zeichen=='r')
{
rot.on();
gruen.off();
}
else if(zeichen=='g')
{
rot.off();
gruen.on();
}
}
}
Code 0-15: Hauptprogramm.
class Led
{
public:
Led(int aktuellesBit)
{
meinBit = aktuellesBit;
}
void on()
{
PORTB |= (1<<meinBit);
}
void off()
{
PORTB &= ~(1<<meinBit); // ~ Tilde invertiert bitweise das Bitmuster
}
private:
int meinBit;
};
Code 0-16: Klasse in Led.h
LEDoop2.zip -- Obige Variante.
Aufgabe 2
|
------------- |IMU | ------------- |+start() | |+acx(): int | |+acy(): int | |+acz(): int | -------------
Code 0-17: UML Klassendiagramm zur IMU Klasse
Aufgabe 3
|
#include<math.h>
#include<Wire.h>
//MPU6050:
const int MPU=0x68; // I2C address of the MPU-6050
int16_t AcX,AcY,AcZ;
int x,y,z;
void setup()
{
//MPU6050
Wire.begin();
Wire.beginTransmission(MPU);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
Serial.begin(9600);
pinMode(12,1);
digitalWrite(12,0);
}
void loop()
{
// put your main code here, to run repeatedly:
Wire.beginTransmission(MPU);
Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU,6,true); // request a total of 14 registers
AcX=Wire.read()<<8|Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
AcY=Wire.read()<<8|Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
AcZ=Wire.read()<<8|Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
x = (AcX/163);
if(x>100) x=100;
if(x<-100) x=-100;
y = (AcY/163);
if(y>100) y=100;
if(y<-100) y=-100;
z = (AcZ/163);
if(z>100) z=100;
if(z<-100) z=-100;
Serial.print(x);
Serial.print(" ");
Serial.print(y);
Serial.print(" ");
Serial.println(z);
if(z<90)
digitalWrite(12,1);
else
digitalWrite(12,0);
delay(200);
}
Code 0-18: Musterlösung Verkippwarner nicht objektorientiert.
OOP Lösung
#include<math.h>
//#include<Wire.h>
#include "IMU.h"
IMU imu; // Singleton
int x,y,z;
void setup()
{
Serial.begin(9600);
imu.start();
pinMode(12,1);
digitalWrite(12,0);
}
void loop()
{
// put your main code here, to run repeatedly:
imu.update();
x = (imu.getacx()/163);
if(x>100) x=100;
if(x<-100) x=-100;
y = (imu.getacy()/163);
if(y>100) y=100;
if(y<-100) y=-100;
z = (imu.getacz()/163);
if(z>100) z=100;
if(z<-100) z=-100;
Serial.print(x);
Serial.print(" ");
Serial.print(y);
Serial.print(" ");
Serial.println(z);
if(z<90)
digitalWrite(12,1);
else
digitalWrite(12,0);
delay(200);
}
Code 0-19: Hauptprogramm.
#include<Wire.h>
class IMU
{
private:
//MPU6050:
const int MPU=0x68; // I2C address of the MPU-6050
int16_t AcX,AcY,AcZ;
public:
void start()
{
//MPU6050
Wire.begin();
Wire.beginTransmission(MPU);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
}
void update()
{
Wire.beginTransmission(MPU);
Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU,6,true); // request a total of 14 registers
AcX=Wire.read()<<8|Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
AcY=Wire.read()<<8|Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
AcZ=Wire.read()<<8|Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
}
int getacx()
{
return AcX;
}
int getacy()
{
return AcY;
}
int getacz()
{
return AcZ;
}
};
Code 0-20: IMU.h
IMUtest002.zip -- OOP Projekt.
#5 Di, 28.04.2026
Themen heute:
|
1. Besprechung studentischer Lösungen zu Klasse für IMU und Verkippwarner.
Siehe: Code 0-6: MPU6050 testen. Hier: 96_Arduino/31_day_by_day
2. Wiederholung OOP
40_Mikrocontroller/08_OOP
96_Arduino/24_OOP
3. Das Datenblatt zum ATmega32u4
96_Arduino
4. Register zu DIO im Datenblatt
96_Arduino/22_Universal/02_LED_Leiste
40_Mikrocontroller/03_DigitalIO
45_Mikro17/03_DigitalIO
5. Einführung zu Timer
45_Mikro17/04_Timer/01_Generierung
6. Der 16-Bit Timer 1 im ATmega32u4 im Datenblatt
45_Mikro17/04_Timer/02_Timer1_Servo
7. PWM mittels Registerkonfiguration / PWM allgemein
40_Mikrocontroller/04_PWM/01_Prinzip
40_Mikrocontroller/04_PWM/02_Nutzen
40_Mikrocontroller/04_PWM/08_LoesungUE3 -- Servos
45_Mikro17/04_Timer/02_Timer1_Servo
8. Übungen mit Modellbau-Servos
Aufgabe 1
|
Aufgabe 2
|
Code Code 0-1: Datei servofein.ino hier: 45_Mikro17/04_Timer/02_Timer1_Servo
Aufgabe 3
|
Aufgabe 4
|
#6 Di, 05.05.2026
Themen heute: Vertiefung Timer Konfiguration
|
1. Ergänzungen zur Analyse des PWM-Gebers mit Timer 1
|
2. Möglichkeit einer genaueren Servo-Ansteuerung (Aufgabe 4 letzte Woche)
|
3. Timer 2 und CTC-Mode
45_Mikro17/10_ADW/02_Zaehler -- Timer als frei laufender Zähler
ACHTUNG: while(TCNT2<36); wird womöglich vom Compiler wegrationalisiert. Besser: while(TCNT2<36) PORTB|=PORTB;
4. Effiziente Echtzeit-Programmierung mittels State-Machine
|
67_Echtzeitsysteme/12_Zustandsmaschine -- Konzept einer Zustandsmaschine umgesetzt mit switch und case.
|
5. Übungen
Aufgabe 1 gemeinsam
|
Aufgabe 2
|
HINWEISE: Arbeiten Sie immer zu zweit an dem Thema. Eine Entwurfs-Skizze wird im Unterricht entwickelt. Gliedern Sie die Aufgabe in Teilzielen auf und arbeiten diese nacheinander ab.