1.9 🤩 Kurztests
🍼 Einstiegsaufgaben
- Ordentlich geübt und willst wissen, ob Du fit für eine Klassenarbeit bist?
- Verwende nur die beiden Formelsammlungen als Hilfsmittel.
- Suche Dir eine ungestörte stille Ecke.
- Löse die Aufgaben auf Papier ganz wie bei einer Klassenarbeit.
🍼 SP. Ein Startpieper 🛫
Nach druck auf Taster Start sollen drei tiefe und ein längerer hoher Ton auf einem Piezo-Lautsprecher ausgegeben werden. Während der Ausgabe des tiefen Tones leuchtet die LED LC0, beim hohen Ton LC1. Dieser Quellcode ist schon gegeben:
#define P_PIEZO // Piezo-Lautsprecher an Arduino Pin D11
#define P_LED_RT // LED LC0
#define P_LED_GN // LED LC1
#define P_START // Taster an PA1 nach VCC
void tonTief(){ // tiefen Ton ausgeben
tone(P_PIEZO,600); // Ton mit Frequenz 600 Hz auf P_PIEZO ausgeben
// LC0 an
delay(300);
// LC0 aus
noTone(P_PIEZO); // Tonausgabe beenden
delay(200);
}
void loop(){
tonHoch();
}
🍼 SP.1 Ergänzen Sie die fehlenden Teile!
Typische Fehler(check this!)
- Pinbelegung bei #define vergessen
- setup() fehlt
- P_START braucht PULLDOWN
- tonHoch() fehlt
- P_START wird in loop nicht mit digitalRead() richtig abgefragt
Lösungsvorschlag
#define P_PIEZO 11 // Piezo-Lautsprecher an Arduino Pin D11
#define P_LED_RT PC0 // LED LC0
#define P_LED_GN PC1 // LED LC1
#define P_START PA1 // Taster an PA1 nach VCC
void setup(){
pinMode(P_START, INPUT_PULLDOWN); // Pin Eingang mit internem PullDown Widerstand gegen Floating des Eingangs
pinMode(P_LED_RT, OUTPUT); // Pin als Ausgang
pinMode(P_LED_GN, OUTPUT); // Pin als Ausgang
}
void tonTief(){ // tiefen Ton ausgeben
tone(P_PIEZO,600); // Ton mit Frequenz 600 Hz auf P_PIEZO ausgeben
digitalWrite(P_LED_RT,1); // LC0 an geht auch mit true,HIGH
delay(300);
digitalWrite(P_LED_RT,0); // LC0 aus geht auch mit false,LOW
noTone(P_PIEZO); // Tonausgabe beenden
delay(200);
}
void tonHoch(){
tone(P_PIEZO,1100);
digitalWrite(P_LED_GN,1);
delay(500);
digitalWrite(P_LED_GN,0);
noTone(P_PIEZO);
}
// Lösung 1
void loop(){
while(!digitalRead(P_START));
tonTief();
tonTief();
tonTief();
tonHoch();
}
// Lösung 2
void loop(){
while(digitalRead(P_START)){
tonTief();
tonTief();
tonTief();
tonHoch();
}
}
// Lösung 3
void loop(){
if(digitalRead(P_START)){
tonTief();
tonTief();
tonTief();
tonHoch();
}
}
Mit Zustandsdiagramm
🍼 LM. Leuchtmuster auf LEDs ausgeben 🔦
🍼 LM.1 Die 3 LEDs an PC0..PC2 sollen abwechselnd mit einer Pause von 200ms nacheinander leuchten. Ergänze den Quellcode.
#define ZEIT 200 // Zeit für delay()
void setup() {
pinMode(PC0, OUTPUT);
...
}
void loop() {
delay(ZEIT);
digitalWrite(PC0,0); // LOW, false
digitalWrite(PC1,1); // HIGH, true
...
}
Lösung
#define ZEIT 200 // Zeit für delay()
void setup() {
pinMode(PC0, OUTPUT);
pinMode(PC1, OUTPUT);
pinMode(PC2, OUTPUT);
}
void loop() {
delay(ZEIT);
digitalWrite(PC0,0); // LOW, false
digitalWrite(PC1,1); // HIGH, true
delay(ZEIT);
digitalWrite(PC1,0);
digitalWrite(PC2,1);
delay(ZEIT);
digitalWrite(PC2,0);
digitalWrite(PC0,1);
}
🍼 LM.2 PC0..PC7 sollen als Ausgang für die LEDs LC0..LC7 verwendet werden können. Schreibe zwei Varianten zur Initialisierung.
Lösung
void setup() {
pinMode(PC0, OUTPUT);
pinMode(PC1, OUTPUT);
pinMode(PC2, OUTPUT);
...
pinMode(PC7, OUTPUT);
}
void setup(){
pinMode(PC0, OUTPUT); // ohne diese Zeile klappts nicht
GPIOC->MODER = 0x5555; // PC0..PC7 als Ausgang (zu faul für 8* pinMode(..))
}
🍼 LM.3 Leuchtpunkt bei LC0 beginnend zu LC7, läuft nach links. Verwende GPIOC->ODR. Erstelle Quellcode für loop().
Lösungsvorschlag
#define ZEIT 200 // Zeit für delay()
void setup(){
pinMode(PC0, OUTPUT); // ohne diese Zeile klappts nicht
GPIOC->MODER = 0x5555; // PC0..PC7 als Ausgang (zu faul für 8* pinMode(..))
}
int muster = 1;
void loop() {
GPIOC->ODR=muster;
delay(ZEIT);
if(muster>=0x80) muster=1;
else muster <<= 1; // muster = muster << 1
}
🍼 LM.4 Leuchtbalken baut sich nach links auf. Erstelle Quellcode für loop().
Lösungsvorschlag
#define ZEIT 200 // Zeit für delay()
void setup(){
pinMode(PC0, OUTPUT); // ohne diese Zeile klappts nicht
GPIOC->MODER = 0x5555; // PC0..PC7 als Ausgang (zu faul für 8* pinMode(..))
}
int muster = 1;
void loop() {
GPIOC->ODR=muster;
delay(ZEIT);
if(muster>=0x80) muster=1;
else muster = (muster << 1) + 1;
}
🍼 LM.5 Leuchtpunkt läuft bei LC7 beginnend zu LC0, nach rechts. Erstelle Quellcode für loop().
Lösungsvorschlag
#define ZEIT 200 // Zeit für delay()
void setup(){
pinMode(PC0, OUTPUT); // ohne diese Zeile klappts nicht
GPIOC->MODER = 0x5555; // PC0..PC7 als Ausgang (zu faul für 8* pinMode(..))
}
int muster = 0x80; // 0b10000000 128
void loop() {
GPIOC->ODR=muster;
delay(ZEIT);
if(muster<=1) muster=0x80;
else muster = (muster >> 1);
}
🍼 LM.6 Leuchtbalken baut sich nach rechts auf. Erstelle Quellcode für loop().
Lösungsvorschlag
#define ZEIT 200 // Zeit für delay()
void setup(){
pinMode(PC0, OUTPUT); // ohne diese Zeile klappts nicht
GPIOC->MODER = 0x5555; // PC0..PC7 als Ausgang (zu faul für 8* pinMode(..))
}
int muster = 0x80; // 0b10000000 128
void loop() {
GPIOC->ODR=muster;
delay(ZEIT);
if(muster>=0xff) muster=0x80;
else muster = (muster >> 1)+0x80;
}
🍼 LM.7 Zwei Leuchtpunkte sollen im Entengang von LC0 bis LC7 wandern. Erstelle Lösung unter Verwendung eines Arrays. Codevorgabe:
#define ZEIT 200 // Zeit für delay()
int ente[]={0b1,0b11,0b110,...}; // Ausgabemuster
int n = 0; // position im muster
int laenge = sizeof(ente)/sizeof(ente[0]); // Anzahl der Arrayeinträge
void setup(){
pinMode(PC0, OUTPUT); // ohne diese Zeile klappts nicht
GPIOC->MODER = 0x5555; // PC0..PC7 als Ausgang (zu faul für 8* pinMode(..))
}
void loop() {
...
delay(ZEIT);
if(n>=laenge-1) n=0;
else n++;
}
Lösung
#define ZEIT 200 // Zeit für delay()
int ente[]={0b1,0b11,0b110,0b1100,0b11000,0b110000,0b1100000,0b11000000}; // Ausgabemuster
int n = 0; // position im muster
int laenge = sizeof(ente)/sizeof(ente[0]); // Anzahl der Arrayeinträge
void setup(){
pinMode(PC0, OUTPUT); // ohne diese Zeile klappts nicht
GPIOC->MODER = 0x5555; // PC0..PC7 als Ausgang (zu faul für 8* pinMode(..))
}
void loop() {
GPIOC->ODR=ente[n];
delay(ZEIT);
if(n>=laenge-1) n=0;
else n++;
}
🍼 LM.8 7Segment Ausgabe. Auf der 7Segmentanzeige Einerstelle soll von 0 bis 9 gezählt werden.
Entwickle den Code dafür.
Anfang der Umrechnungstabelle: int bcd_7seg[]={0x3f,...};
Lösungsvorschlag
#define ZEIT 400 // Zeit für delay()
int bcd_7seg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; // Aufgabe 1 Umrechnung
int n = 0; // position im muster
int laenge = sizeof(bcd_7seg)/sizeof(bcd_7seg[0]); // Anzahl der Arrayeinträge
void setup(){
pinMode(PC0, OUTPUT); // ohne diese Zeile klappts nicht
GPIOC->MODER = 0x5555; // PC0..PC7 als Ausgang (zu faul für 8* pinMode(..))
pinMode(PC11, OUTPUT); // Einerstelle Ausgang
}
void loop() {
GPIOC->ODR=bcd_7seg[n] | 1<<11 ; // Ziffer auf Einerstelle ausgeben
delay(ZEIT);
if(n>=laenge-1) n=0;
else n++;
}
🍼 LM.9 7Segment Ausgabe 0..F. Erweitere auf Hexziffern A,b,C,d,E,F
hex_7Seg
int hex_7seg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

🏹 Aufgaben mit Zustandsdiagramm
🏹 DS. Diebstahlsicherung für Audiogeräte im Auto (HP11)
Audiogeräte im PKW müssen beim Einbau oder beim Batteriewechsel durch die Eingabe von vier Ziffern (0 bis 9) freigegeben werden. Die Freigabe erfolgt nur, wenn die eingegebenen Ziffern mit den vom Hersteller im Gerät gespeicherten Codeziffern (siehe Tabelle 1) übereinstimmen. Solange die Spannungsversorgung im Standby-Betrieb nicht unterbrochen wird, bleibt die einmalige Freigabe erhalten.
Drei Taster steuern die Entsperrung:
- UP zählt die Ziffer hoch, prellt high aktiv ohne externen Widerstand
- RESET setzt den Entsperrvorgang auf Anfang, prellt high aktiv ohne externen Widerstand
- WEITER verarbeitet den eingegebenen Code, entprellt low aktiv mit externen Widerstand
Es gibt einen nicht besonders hübschen Lösungsansatz und Code-Fragmente:

#define P_UP PA1 // Taster für Hochzählen
#define P_RESET PA6 // Taster für Reset
#define P_WEITER PC13 // User-Button entprellt mit PullUp-Widerstand low aktiv
#define T_UP digitalRead(P_UP) // Auslesen UP-Taster
#define T_RESET digitalRead(P_RESET) // Auslesen Reset-Taster
#define T_WEITER !digitalRead(P_WEITER) // Auslesen Weiter-Taster
int bcd_7seg[]={0x3f,...}; // Aufgabe 1 Umrechnung
int code[]={4,7,1,1};
int eingabe=0;
int stelle=0;
enum zustandstyp {RESET_ENTRY,CODE_EINGEBEN,UP,WEITER,FALSCH,ENTSPERRT}; // Aufzaehlungstyp
enum zustandstyp zustand=RESET_ENTRY;
void up(){ // Aufgabe 2
}
void ausgeben7Seg(){ // Aufgabe 3 Ziffer wird angezeigt
}
void entsperrt(){ // Aufgabe 4 nur Dezimalpunkt wird angezeigt
}
void setup() { // Aufgabe 5
pinMode(PC0, OUTPUT); // ohne diese Zeile klappts nicht
GPIOC->MODER = 0x5555; // PC0..PC7 als Ausgang (zu faul für 8* pinMode(..))
pinMode(PC11,OUTPUT); // Einer
Serial.begin(115200);
}
void loop() { // Aufgabe 6
switch (zustand) {
case RESET_ENTRY:
break;
}
}
🏹 DS.1 🍫 BCD-7Seg Anzeige Umrechnung
Vervollständigen Sie den Code für int bcd_7seg[]={0x3f,…};
🏹 DS.2 🔩 up()
Das Unterprogramm up() erhöht die die Variable eingabe um 1 wenn der Wert unter 9 ist, sonst wird sie auf 0 gesetzt. Erstellen Sie den Code.
🏹 DS.3 🔩 ausgeben7Seg() Ziffern anzeigen
Das UP ausgeben7Seg() gibt den aktuell eingestellten Wert von eingabe auf der Einerstelle der 7Seg-Anzeige aus. Erstellen Sie den Code.
🏹 DS.4 🔩 entsperrt()
Nur der Dezimalpunkt (dp PC7) der 7Seg-Anzeige leuchtet auf der Einerstelle. Erstellen Sie den Code.
🏹 DS.5 🔩 setup()
Im setup() sind noch nicht alle Komponenten initialisiert, ergänzen Sie die fehlenden Code-Zeilen.
🏹 DS.6 🔩 loop()
Ergänzen Sie den Code…
Lösungsvorschlag
#define P_UP PA1 // Taster für Hochzählen
#define P_RESET PA6 // Taster für Reset
#define P_WEITER PC13 // User-Button entprellt mit PullUp-Widerstand low aktiv
#define T_UP digitalRead(P_UP) // Auslesen UP-Taster
#define T_RESET digitalRead(P_RESET) // Auslesen Reset-Taster
#define T_WEITER !digitalRead(P_WEITER) // Auslesen Weiter-Taster
int bcd_7seg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; // Aufgabe 1 Umrechnung
int code[]={4,7,1,1};
int eingabe=0;
int stelle=0;
enum zustandstyp {RESET_ENTRY,CODE_EINGEBEN,UP,WEITER,FALSCH,ENTSPERRT}; // Aufzaehlungstyp
enum zustandstyp zustand=RESET_ENTRY;
void up(){ // Aufgabe 2
if(eingabe<9)eingabe++;
else eingabe = 0;
}
void ausgeben7Seg(){ // Aufgabe 3 Ziffer wird angezeigt
GPIOC->ODR = bcd_7seg[eingabe] | 1<<11; //
}
void entsperrt(){ // Aufgabe 4 nur Dezimalpunkt wird angezeigt
GPIOC->ODR = 1<<7 | 1<<11; // Dezimalpunkt
}
void setup() { // Aufgabe 5
pinMode(PC0, OUTPUT); // ohne diese Zeile klappts nicht
GPIOC->MODER = 0x5555; // PC0..PC7 als Ausgang (zu faul für 8* pinMode(..))
pinMode(PC11,OUTPUT); // Einer
pinMode(P_UP,INPUT_PULLDOWN);
pinMode(P_RESET,INPUT_PULLDOWN);
pinMode(P_WEITER,INPUT);
Serial.begin(115200);
}
void loop() { // Aufgabe 6
switch (zustand) {
case RESET_ENTRY:
eingabe = 0;
stelle = 0;
ausgeben7Seg();
zustand = CODE_EINGEBEN;
break;
case CODE_EINGEBEN:
if(T_UP){
up();
ausgeben7Seg();
delay(10);
zustand = UP;
}
if(T_WEITER){
Serial.printf("Stelle %d code: %d eingabe: %d\n",stelle,code[stelle],eingabe);
if(code[stelle]!=eingabe){
zustand = FALSCH;
Serial.println("Falsch");
} else {
if(stelle>=3){
entsperrt();
zustand=ENTSPERRT;
} else {
stelle++;
zustand = WEITER;
}
}
}
break;
case UP:
if(!T_UP){
delay(10);
zustand = CODE_EINGEBEN;
}
break;
case WEITER:
if(!T_WEITER) zustand = CODE_EINGEBEN;
break;
case FALSCH:
if(T_RESET) zustand = RESET_ENTRY;
break;
case ENTSPERRT:
if(T_RESET) zustand = RESET_ENTRY;
break;
}
}
🏹 DS.7 🏋️ Den Code knacken!
Wie groß ist der Aufwand den Code zu knacken, entwickeln Sie eine Strategie!
Lösungsidee
Da nach Eingabe einer falschen Ziffer bei Taste WEITER in den FEHLER-Zustand verzweigt wird und mit UP die Ziffern nicht mehr verändert werden können ist der Aufwand im schlechtesten Fall ca. 40 Versuche, 4 * 10 Versuche bei 4 Stellen.
- Aktuelle Stelle Ziffer 0, WEITER drücken, läßt sich Ziffer mit UP noch verändern, dann richtig sonst falsch.
- Wenn falsch drücke RESET und versuche nächste Ziffer.
- Wenn richtig versuche nächste Stelle bis alle Ziffern bekannt und entsperrt.
🏹 DS.8 🖥 Bessere Lösung entwickeln
Tipp: die Anzahl der Elemente von Code: int codelaenge = sizeof(code)/sizeof(code[0]);
Verbessern Sie das Programm:
- Der Code darf beliebig lang sein.
- Das Codeknacken sollte erschwert werden.
- Bedienung muss einfach bleiben und nicht nerven.
Lösungsvorschlag
#define P_UP PA1 // Taster für Hochzählen
#define P_RESET PA6 // Taster für Reset
#define P_WEITER PC13 // User-Button entprellt mit PullUp-Widerstand low aktiv
#define T_UP digitalRead(P_UP) // Auslesen UP-Taster
#define T_RESET digitalRead(P_RESET) // Auslesen Reset-Taster
#define T_WEITER !digitalRead(P_WEITER) // Auslesen Weiter-Taster
int bcd_7seg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; // Aufgabe 1 Umrechnung
int code[]={4,7,1,1};
int codelaenge = sizeof(code)/sizeof(code[0]);
int eingabe=0;
int stelle=0;
enum zustandstyp {RESET_ENTRY,CODE_EINGEBEN,WEITER,FALSCH,ENTSPERRT}; // Aufzaehlungstyp
enum zustandstyp zustand=RESET_ENTRY;
void up(){ // Aufgabe 2
if(eingabe<9)eingabe++;
else eingabe = 0;
}
void ausgeben7Seg(){ // Aufgabe 3 Ziffer wird angezeigt
GPIOC->ODR = bcd_7seg[eingabe] | 1<<11; //
}
void entsperrt(){ // Aufgabe 4 nur Dezimalpunkt wird angezeigt
GPIOC->ODR = 1<<7 | 1<<11; // Dezimalpunkt
}
void setup() { // Aufgabe 5
pinMode(PC0, OUTPUT); // ohne diese Zeile klappts nicht
GPIOC->MODER = 0x5555; // PC0..PC7 als Ausgang (zu faul für 8* pinMode(..))
pinMode(PC11,OUTPUT); // Einer
pinMode(P_UP,INPUT_PULLDOWN);
pinMode(P_RESET,INPUT_PULLDOWN);
pinMode(P_WEITER,INPUT);
Serial.begin(115200);
Serial.printf("Codelänge: %d\n",codelaenge);
}
void loop() { // Aufgabe 6
if(zustand!=ENTSPERRT){
if(T_UP){
up();
ausgeben7Seg();
delay(10); // Entprellen
while(T_UP); // solange gedrückt
delay(10); // Entprellen
}
}
switch (zustand) {
case RESET_ENTRY:
eingabe = 0;
stelle = 0;
ausgeben7Seg();
zustand = CODE_EINGEBEN;
break;
case CODE_EINGEBEN:
if(T_WEITER){
Serial.printf("Stelle %d code: %d eingabe: %d\n",stelle,code[stelle],eingabe);
if(code[stelle]!=eingabe){
zustand = FALSCH;
Serial.println("Falsch");
} else {
if(stelle>=codelaenge-1){ // beliebig lange Codes
entsperrt();
zustand=ENTSPERRT;
} else {
stelle++;
zustand = WEITER;
}
}
}
break;
case WEITER:
if(!T_WEITER) zustand = CODE_EINGEBEN;
break;
case FALSCH:
if(T_RESET) zustand = RESET_ENTRY;
break;
case ENTSPERRT:
if(T_RESET) zustand = RESET_ENTRY;
break;
}
}

Ein Kommentar
Die Kommentare sind geschlossen.