Einen eigenen Timer programmieren
Wenn man die Aufgabe eines Mikrocontrollers auf innerste Wesen, auf des Pudels Kern, zu reduzieren versucht merkt man das es faktisch immer um ein bestimmtes Verhalten in einer bestimmten Zeit geht. Im Fach-Slang Timing genannt. Timing und Timer sind für Embedded-Entwickler untrennbar verbunden. Die Anzahl und Möglichkeiten der Timer eines Mikrocontrollers stellen ein wesentliches Leistungsmerkmal dar. Mit den SysTick-Experimenten und dem Erzeugen eines PWM-Signals haben wir eigentlich schon Timer angewendet. In diesem Beispiel wollen wir einen Timer nutzen um ein eigenes Timing per Timer-Interrupt zu generieren. Der Timer soll das Hochzählen eines 8-Bit-Zählers und das senden des Zählers an das SiSy-ControlCenter triggern.
Die Aufgabe
Es ist eine Mikrocontrolleranwendung zu entwickeln, bei der ein Timer als Trigger für einen Zähler fungiert und der Zählerwert an den PC übertragen wird.
Die Anforderungen an die Lösung sind:
- Der Timer-Interrupt soll alle 50 Millisekunden ausgelöst werden
- Der Zähler soll eine vorzeichnlose 8-Bit Zahl sein
- Die Datenübertragung soll mit 19200 Baud erfolgen
- Die übertragenen Werte sollen pure Binärdaten sein
Vorbereitung
Führen Sie folgende Vorbereitungsarbeiten durch:
- neues Klassendiagramm anlegen
- Zielsprache ARM C++
- Zielplattform MM32L073 myMM32 Board light
- Diagrammvorlage Application Grundgerüst für PEC Anwendungen (XMC, STM32, AVR) laden
- Treiberpaket für MM32L0 zuweisen
Lösungsansatz
Die Aufgabe besteht darin einen eigenen Timer für das Auslösen (Triggern) einer Aktion des Controllers zu bauen. Die auszulösende Aktion wird durch das hochzählen eines Wertes und das Senden des Wertes per UART an den PC repräsentiert. Das Auslösen dieser Aktion soll regelmäßig in 50 Millisekunden Abständen erfolgen. Diesmal haben wir die Besonderheit, dass ein Systembaustein nicht als sichtbares Element auf dem Systemboard präsent ist sondern interner Baustein des Controllers ist. Damit ergeben sich für unser System folgende Systembausteine:
In der PEC-Bibliothek finden wir die Basisbaustein PecTimer. Er bietet neben einer virtuellen Operation onTimer() für die Behandlung des Timer-Interrupts (Eventhandler) auch verschiedene Alternativen für die Initialisierung des Timers configHz(), configMs(), configUs(). Damit wird dem entwickler die übliche Timer-Rechnerei mit Vorteilern Zählerwerten usw. so ziemlich abgenommen.
Aus dem bisher dargelegtem ergibt sich folgender Grobentwurf der Anwendungslösung.
Dieser Grobentwurf lässt sich wie folgt lesen:
Die Klasse Controller hat einen Trigger und ein Terminal. Der Trigger ist ein PecTimer. Das Terminal ist eine PecUart mit baudrate19200.
MERKE: interner Systembaustein = Systembaustein
Realisierung
Die Realisierung sollte die im obigen Entwurf beschriebenen Elemente beinhalten. Zusätzlich müssen folgende Modellelemente ergänzt werden:
- der konkrete Timer zum Beispiel Timer2
- die genutzte UART Uart 1 an Port A9
- ein 8 Bit Zähler als Attribut der Klasse Trigger
- das Überschreiben der Operation onTimer der Klasse Trigger
Orientieren Sie sich bei diesen Arbeitsschritten an dem folgenden Klassendiagramm.
Die Initialisierung des Timers auf die geforderten 50 Millisekunden erfolgt in der Startsequenz des Controllers. Notieren sie folgenden Code in der Operation onStart() der Klasse Controller.
Controller::onStart():void// boot sequence after start SysTick trigger.configMs(50);
Die auszulösende Aktion Wert hochzählen und an das PC-Terminal senden notieren wir in der Operation onTimer() der Klasse Trigger wie folgt:
Trigger::onTimer():voidcounter++; app.terminal.writeByte(counter);
Jetzt kann diese Anwendungslösung getestet werden. Variieren Sie die Initialisierung des Timers zum Beispiel auf 5 Millisekunden und überprüfen das Ergebnis im SiSy-Controlcenter.
Test
Übersetzen Sie das Programm. Korrigieren Sie ggf. Schreibfehler. Übertragen Sie das lauffähige Programm in den Programmspeicher des Controllers.
- Systemboard mit dem PC verbinden
- Anwendungslösung Erstellen (Kompilieren und Linken)
- Anwendungslösung Übertragen (Brennen)
- SiSy-Controlcenter öffnen und konfigurieren (COMx, 19200 Baud)
- Verbinden und in Oszi-Ansicht wechseln
Videozusammenfassung
Erlernte und gefestigte Arbeitsschritte:
- Klassendiagramm anlegen und öffnen
- Diagrammvorlage für PEC Applikation auswählen, laden und Treiberpaket für MM32L0 einfügen
- im Explorer PEC-Bausteine aus der Bibliothek suchen
- gewünschte Bibliotheksbausteine und ins Diagramm ziehen
- Klassen verbinden (Aggregation, Realisierung)
- den nötigen Quellcode in den Operationen erstellen
- Erstellen und Brennen einer MM32 Applikation im Klassendiagramm
Und weil es so schön war hier das Ganze noch mal als Video.
Übung 8
Erweitern Sie zur Übung die Anwendung um eine LED die bei jedem Trigger-Event umschaltet (toggle).