Der Systemtakt beträgt 4Mhz. Bei Betätigung der Taste T0 soll ein Leuchtpunkt von L0 bis L7 wandern, Verweildauer bei der jeweiligen LED 200ms und dann von L6 zurück nach L0, Verweildauer 50ms. Am Ende sind alle LED wieder aus. Die nicht entprellten Taster T0..T2 sind gegen GND verschaltet, interne PullUp-Widerstände sind notwendig. Die LED sind als Matrix verschaltet.
Erstellen Sie eine PAP-Skizze um Ihre Gedanken zu ordnen.
Ist ein explizites Entprellen von T0 notwendig? Begründen Sie.
Erstellen Sie ein Programm. Initialisieren Sie die notwendigen PORT-Ausgänge und PullUp-Widerstände für T0..T2. Lösung anzeigen..
Erstellen Sie ein Struktogramm und ein Zustandsdiagramm für die raffiniertere Lösung.
Lösungen
Ist bei dieser Lösung ein Entprellen notwendig? Begründen Sie.
Pulsweitenmodulation einer LED mit Software
Verwenden Sie ZylonEffektlicht2.ino für weitere Bearbeitung. LED15 soll pulsweitenmoduliert entsprechend i heller und dunkler in einer ISR geschaltet werden. Der Helligkeitswert wird mit einer globalen Variablen helligkeit mit dem Maximalwert MAXLED an die ISR übergeben.
Erstellen Sie Programmcode für Initialisierung des CTC-Timer0 Aufruf mit 1000 Hz (1ms).
Messen Sie mit Hilfe eines Oszilloskops oder eines Frequenzzählers die Signalzeiten für PD0 und PD1.
Machen Sie eine zweite Messung an PD1 mit deaktiviertem Timer-Interrupt.
Typische Ergebnisse
ISR-Zeiten an PD0:
Periodendauer 100µs
Zeit PD0 = 1: 5µs
_delay_ms()-Dauer an PD1:
Mit ISR: 11,56ms
Ohne ISR: 10ms
Entwickeln Sie eine Funktion my_delay_ms(int n) unter Verwendung der CTC-ISR, deren Genauigkeit unabhängig von zwischenzeitlichen Interrupts ist.
Zwei Musterfolgen ausgeben
Zwei Musterfolgen sollen ausgegeben werden. Die Umschaltung der Muster erfolgt über Taste T0. Im weiteren Verlauf kann die Ausgabegeschwindigkeit mit Taste an T1 verändert werden.
Zylonenauge: ATtiny 2313 @ 4Mhz
Musterwechsel zunächst alle 400ms mit _delay_ms(400)
Zur prellfreien Tastenabfrage keycheck() verwenden
Die Länge der Musterfolgen wird als erstes Array-Element gespeichert
Quellcode anständig formatieren und kommentieren!
Erstellen Sie ein Array muster[][] für die zwei Muster.
Das Feld muster beginnt bei Adresse 0x60. Wie sieht die Speicherbelegung für das Feld aus?
Erstellen Sie ein Unterprogramm wechsleMuster(), das bei jedem Aufruf das nächste Muster ausgibt.
Duplizieren Sie das Projekt als zylon-muster2. Der Musterwechsel soll nun mittels Timer0 CTC-Interrupt erfolgen, in dessen ISR wechsleMuster() aufgerufen wird. Modifizieren Sie den Quelltext entsprechend.
Was passiert, wenn bei Muster 0011 die Taste gedückt wird, wie sieht der Übergang aus?
Duplizieren Sie das Projekt als zylon-muster3. Die Ausgabegeschwindigkeit soll nun mittels Taste T1 umgeschaltet werden können. Ein Array mit verschiedenen Geschwindigkeitsstufen ist gegeben:
musterAnzeigendauer[]={400,200,100,50}; // Zeiten des Wartens in ms bis naechstes Muster
Welchen Datentyp muss das Feld haben?
Die Wartezeiten sollen mit einer eigenem Delay my_delay_ms(unsigned int n) realisiert werden, das einen Tick-Zähler in der ISR verwendet.
Ändern Sie die Einstellungen des Timers für einen Aufruf jede ms. Im Timer wird eine Variable ticks hochgezählt, die in my_delay_ms(..) verwendet wird.
Wie und wo muss ticks definiert werden, Begründen Sie.
Im Hauptprogramm wird bei Druck auf Taste T1 eine Variable anzeigendauerIndex hochgezählt bzw. wieder auf 0 gesetzt.
In der TimerISR wird wechsleMuster() entsprechend des anzeigedauerIndex aufgerufen.
Für einen Hörtest sollen Töne mit einem Mikrocontroller erzeugt werden. Hier wird das Z-Eye verwendet, ich habe die ursprüngliche Aufgabenstellung modifiziert, einen C-Quelltext vorgegeben.
Der Systemtakt beträgt 1MHz.
Die Erzeugung des Rechtecksignals bzw. Tons erfolgt mittels Timer-Interrupt durch zyklisches Invertieren von PB4 an dem ein Lautsprecher angeschlossen ist.
Mit jedem Tastendruck am zunächst prellfreien Taster T0 kann einer von 10 Zeitwerten für den Timer gewählt werden.
Die Zeitwerte sind in einem zusammenhängenden Speicherbereich zeitwert hinterlegt.
Hauptprogramm (Main-Loop)
In der Main-Loop des Hauptprogramms wird der Taster T0 zyklisch abgefragt (Polling). Jedes Mal, wenn der Taster losgelassen wird, soll eine Variable (ein Register) ton inkrementiert werden. Mit Hilfe dieser Variablen wird später durch das Unterprogramm (die Funktion) zeitwerte ein Zeitwert aus Tabelle zeitwert gelesen. Nach Erreichen des Wertes 9 soll die Variable ton wieder mit 0 geladen werden.
Entwerfen Sie den Programmablaufplan (PAP) oder ein Struktogramm für die Main-Loop.
Lösung
Schreiben Sie das Assemblerprogramm für den PAP bzw. C-Programm entsprechend des Struktogramms für die Main-Loop. (Lösung unten)
Erklären Sie, weshalb ein prellfreier Taster verwendet werden sollte. Wie kann das Problem softwaremäßig gelöst werden, wenn kein prellfreier Taster zur Verfügung steht.
Lösung
Durch das Prellen entstehen beim Tastendurck mehrere Impulse, daduch wird ton um mehr als einen Wert verändert. Abhilfe schafft eine Verzögerung, länger als die Prellzeit, z.B. mittels Delay-Funktion nach dem Tastendruck.
Unterprogramm Zeitwerte
Über die Variable (Register) ton können 10 verschiedene Werte aus einer Tabelle zeitwert im Speicher gelesen werden. Der Wert stellt Interruptzeit des Timers dar. Ausserdem soll eine LED Ln (n=15-ton) leuchten. Eine Tabelle ledausgabe für die Ausgabe auf der LED-Matrix ist vorgegeben.
Schreiben Sie den Programmcode. (Lösung unten)
Timer-Interrupt
Der 16-Bit Timer wird mit Systemtakt betrieben. Die ISR soll nach zeitwert vielen Takten aufgerufen werden.
Schreiben Sie den Code für die Timerinitalisierung und die Interruptserviceroutine in Assembler oder C. (Lösung unten)
Berechnung der Zeitwerte
Berechnen sie die Ausgangsfrequenz für ton = 0 und ton = 9.
Lösung
Die Zeitwerte geben die halbe Periodendauer in µs der Frequenzen vor.
ton = 0: 1/(2000µs*2) = 250 Hz
ton = 9: 1/(30µs*2) = 16667 Hz
Vor allem bei der höchsten Frequenz konnte im Oszillogramm ein Jitter festgestellt werden, die Frequenz ist nicht stabil. Erläutern Sie wodurch dieses Problem entstehen kann und schlagen Sie eine Lösung vor.
Lösung
Mögliche Ursachen
Die ISR braucht zu lange. Bei der höchsten Frequenz wird die ISR alle 30µs aufgerufen. Ein wiederholter ISR-Aufruf mit Rücksprung benötigt mindestens 1+3+2+4 = 10 Takte. In der ISR wird lediglich PB4 invertiert der entsprechende Maschinenbefehl sollte 2 Takte benötigen. Die 30µs müssten ausreichen.
Ein weiterere ISR verzögert den Aufruf der Timer-ISR. Entfällt hier.
Der beim Eintreten der ISR unterbrochene Befehl braucht unterschiedlich lange bis er fertig ist (1..4 Takte) und in die ISR verzweigt werden kann.
Ein Blick auf den von der Arduino-Software erzeugen Assembler-Code offenbart:
ISR(TIMER1_COMPA_vect){
84: 1f 92 push r1
86: 0f 92 push r0
88: 0f b6 in r0, 0x3f ; 63
8a: 0f 92 push r0
8c: 11 24 eor r1, r1
8e: 8f 93 push r24
PINB=1<<PB4; // Ausgang PB4 invertieren
90: 80 e1 ldi r24, 0x10 ; 16
92: 86 bb out 0x16, r24 ; 22
}
94: 8f 91 pop r24
96: 0f 90 pop r0
98: 0f be out 0x3f, r0 ; 63
9a: 0f 90 pop r0
9c: 1f 90 pop r1
9e: 18 95 reti
Dieser Code-Unfug braucht sicher mehr als 30µs, somit kommt die ISR nicht mehr hinter her!
Lösung: Mit Inline-Assembler eine bessere (schnellere) ISR programmieren. Der Jitter durch unterschiedliche Beendignungszeit des unterbrochenen Befehls wird dabei jedoch nicht behoben.
Lösung: Die PWM-Ausgabemöglichkeit des µC nutzen, dabei ist keine ISR zur Erzeugung des Signals notwendig.
Die Tabellen zeitwert und ledausgabe werden bei der C-Lösung im SRAM angelegt, modifizieren Sie den Code so, dass sie sich im Programmspeicher befinden.
Modifizieren Sie die C-Lösung so, dass die PWM-Möglichkeiten des µC für die Tonausabe genutzt werden.
Erstellen Sie eine Assembler-Lösung für den Hörtest.