XMC: PWM (LED und Servo), UART (DMX und Debug) (Tutorial für Keil uVision 5)

Wechseln zu: Navigation, Suche

von Mathias Imming

in Aktion

Einführung

Der Einstieg in die Welt der Infineon XMC Serie mag für Anfänger oder Umsteiger von Mikroprozessoren (Atmel o.a.) mit eingigen Hürden verbunden. Über 800 Seiten Handbuch zzgl. Datenblatt laden auch nicht gerade ein, „mal eben“ ein Projekt umzusetzen.
Dabei ist besonders das preiswerte Evaluationboard Infineon_XMC_2Go für Anfänger ein Grund, sich den XMC anzuschauen.
Mit der Entwicklungsumgebung Dave 3 von Infineon ist ein funktionsfähiges Programm anhand der guten Tutorials auch schnell erstellt. Dennoch greift man hier auf vorgefertigte Bibliotheken zurück - ohne die Hinergründe zu verstehen.

Die Entwicklungsumgebung Keil uVision kann sowohl ein mit Dave 3 erstelltes Grundgerüst importieren, als auch dieses selbst erstellen.
Weiterhin bietet auch die kostenlose Version von Keil die Möglichkeit ein Echtzeitbetriebssystem (CMSIS RTOS RTX) zu nutzen.
Leider gibt es bisher nur wenige Anleitungen zur Verwendung von Keil uVision.
Dieses Tutorial soll dazu dienen den Umgang mit dem XMC und Keil zuzeigen. Deshalb wurde bewusst auf den Einsatz von Dave verzichtet und ein Projekt in Keil uVision erzeugt.

Als Projekt soll dazu der Bau eines Modells eines Movinglights dienen.
Anhand dessen wird gezeigt, wie Servos und LEDs angesteuert werden und wie eine serielle Kommunikation mit dem XMC umzusetzen ist.
An dieser Stelle sei erwähnt, dass die Idee dazu von „Orbital“ kommt, der seine -modellbauerisch deutlich bessere Variante - hier dokumentiert hat: [1]

Features

Funktionsfähiges Modell eines Movinglights Einsatz des XMC2Go Bewegung der Achsen (Pan + Tilt) über Modellbauservos Leuchtmittel über RGB Leds Ansteuerung über DMX und PC-UART Demo Modus

Entwicklungsumgebung Keil

Nach der Installation von Keil müssen erst noch die Prozessorinformationen herunter geladen werden. Dies geschieht mit dem Pack-Installer. Solltet ihr Dave 3 vonInfineon nicht installiert haben, fehlen euch auch noch die Debugger Treiber (J-Link) für den XMC2Go. Diese findet man auch einzeln im Internet.

Nachdem dies geschehen ist, kann ein neues Projekt erzeugt werden.

Nachdem ein Projektname vergeben worden ist, fragt Keil nach dem Prozessortyp. In dieser Liste tauchen nur Prozessoren auf, die mittels pack Installer installiert worden sind.

Im folgenden Bildschirm müssen noch die Komponenten ausgewählt werden, die im Projekt Anwendung finden sollen. Mindestens sind hier CMSIS->Core und Device->Startup auszu wählen. Weiterhin wurde hier das Echtzeitbetriebssystem RTX ausgewählt. Stellt Keil fest, dass einige Komponenten andere benötigen, werden im unteren Bereich des Fensters diese angezeigt.

Target-Setup

Um eine bessere Struktur in unserem Projektordner zu haben, werden die Output-Files der Builds in einem Unterordner abgelegt.

Auch auf dem Reiter Listing den Pfad ebenfalls auf den Ordner „output“ ändern

Im Reiter Debug die Debugger-Schnittstelle als „J-Link / J-Trace Cortex“ festlegen. Danach mit Klick auf den Button Settings die Einstellungen wie folgt ändern: Port: SW Dies geht jedoch nur bei angeschlossenem XMC2Go und installierten Treibern.

Immer noch in den „Settings“ im Reiter „Flash Download“ kontrollieren, ob ein Programmin Algorithm eingetragen ist. Wenn nicht, für den XMC1100 mit dem Button Add einen hinzufügen.

Wieder in der Hauptansicht findet sich Links eine Baumstruktur.
Neben dem beim Projekt angegeben Komponenten findet sich auch der Ordner „Source Group 1“. Über das Kontextmenü lassen sich neue Dateien erstellen oder Vorhandene hinzufügen. Vorhandene Header Dateien müssen nicht explizit hinzugefügt werden; nach dem ersten Kompilieren werden diese automatisch unter der entsprechenden Source angelegt.

Da das Projekt mit 32Mhz Taktfrequenz laufen soll, wird diese in der startup_xmc1100.s angepasst. Zwar ist dies nur eine Textdatei, jedoch bietet Keil dafür auch einen Configuration Wizard an.

Software

Gegliedert ist die Software auf verschiedene Dateien, um die Übersichtlichkeit zu erhöhen.

main.c

In der main.c befinden sich nur die main-Schleife und ein Interrupt-Handler für die Fehlerbehandlung.
In der main- Schleife erfolgt nur die Initialisierung. Durch den Einsatz des RTX ist die obligatorische while-Schleife am Ende eigentlich unnötig: bis hierhin kommt der Prozessor durch das osDelay(osWaitForever); gar nicht.
Der HardFault_Handler schaltet die LED des XMC an Port 1.0 an und lässt eine Farbe des Movinglight blinken. Das Blinken ist mit einfachsten Mitteln realisiert, da man sich im Fehlerfall nicht auf die Peripherie verlassen sollte.
Solch ein Fault_Handler lässt gerade beim Entwickeln Fehler schneller erkennen, wie bspw. das Schreiben auf ungerade Adressbereich etc.

GPIO.h

Dieser Header ist nicht von mir erstellt, sondern stammt von aus Dave 3 erzeugtem Code.(?) Dennoch ist dieser sehr nützlich, bietet er doch schnellen Zugriff zum Konfigurieren und Schalten einzelner GPIO.
Die wichtigen Funktionen
Px_y_set_mode: konfiguriert das IOCR Register (In, Out oder Sonderfunktion)
Px_y_set/ Px_y_reset/ Px_y_toogle
Px_y_read()
Px_y_enable_digital/ Px_y_disable_digital: Digitale oder analoge Funktionen (nicht für jeden Port verfügbar)

CC4x.c

In der CC4x.c werden alle Funktionen der CaptureCompare Unit abgehandelt. In diesem Fall als die PWM-Erzeugung. Neben einer allgemeinen Init()-Routine, erhält jeder PWM-Kanal seine Eigene.

Servo-Ansteuerung

Ein Servo brauch nur ca. alle 20ms einen Impuls von 1-2ms Länge. Über die Länge des Impulses wird der Stellwinkel des Servos vorgegeben.
Da der XMC1100 nur die CC40-Unit mit vier PWM-Channels hat, drei davon jedoch schon für die RGB LEDs benötigt werden, müssen sich die beiden Servos einen PWM-Channel teilen.

PWM für Servos mit einem PWM-Channel

Dies geschieht in der Interrupt Routine. Eine Interrupt-Routine ist schnell definiert, da diese einen festen Namen haben, hier CCU40_0_IRQHandler.
Der erste Teil des Namens bezieht sich auf die Peripherie, aus der der Interrupt kommt. Die _0_ gibt die Service Request- Linie an (SR). Jede Peripherie hat eine bestimmte Anzahl dieser SR - jede CaptureCompare Unit bspw. hat insgesamt vier (0..3). Welcher Interrupt welche SR auslöst, ist über entsprechende Register definierbar.
Die PWM für die Servos ist eigentlich ein PWM mit einer Dauer von 10ms, nur wird nach jedem Zyklus der Output-Pin der PWM getauscht. So entsteht am Output eine PWM mit 20ms Frequenz.

LED-Ansteuerung

Die PWMs für die LED-Ansteuerung werden nur Initialisiert und laufen dann autark.
Soll sich ein Wert ändern, wird dieser durch die entsprechende Quelle gesetzt.
Der zusetzende Wert wird dabei aus einer LookUp Tabelle entnommen. Diese macht eine logarithmische Umsetzung der 8Bit-Werte des DMX Signales in die 12Bit der PWM. (siehe dazu auch LED-Fading)

Theoretisch ist eine 16Bit PWM möglich. Hier wird jedoch die PWM auf 12Bit (PWM_RESOLTION = 0x0FFF) beschränkt, um einen schnelleren Takt zu bekommen. Taktdauer = 1/32Mhz * 4096
Der Zähler der PWM zählt von 0 bis 4095 hoch. Ist der Wert größer oder gleich als der Compare-Value, wird der Ausgang geschaltet. Um zu vermeiden, dass bei gewünschter Nicht-Ansteuerung doch ein kurz Impuls erfolgt, wird der Compare-Value künstlich um eins erhöht. Ist PWMTABLE = 0 ist CR(S) immer noch größer als PR(S): der Output wird nicht geschaltet.

// Period Value
CCU40_CC41->PRS = PWM_RESOLTION;
// Compare Value
CCU40_CC41->CRS = PWM_RESOLTION - PWMTABLE[dim1_m] +1;

Wichtig ist noch anzumerken, dass nach dem Schreiben der neuen Werte in das Shadow-Compare-Register CRS noch mit dem entsprechendem Bit im Register GCSS der Transfer gestartet werden muss.

In der CC4x.c kommt zudem das RTX zum Einsatz. Mit dem RTX wird die dim_task gestartet. Deren Endlos-Schleife läuft mit einem konstanten Takt von 50ms. Im Demo Modus - wenn Port 2.9 auf low gezogen ist - dimmt diese Task die LEDs auf uns ab, so dass ein Farblauf entsteht.

usic.c

Der Usic ist bei Infineon die Peripherie, um serielle Kommunikation abzuwickeln. In diesem Projekt wird davon nur die Funktionen des Asynchron Serial Channel (ASC) benutzt - sowohl für die Kommunikation über den XMC2Go mit dem PC als auch zum Empfang von DMX.
Die Kommunikation mit dem PC erfolgt über USIC0 Channel 0, zum DMX Empfang wird USIC0 Channel 1 eingesetzt. Dies ist vom XMC2Go so vorgegeben, da die Pins für die Kommunikation mit dem PC nur an Channel 0 geroutet werden können.
Die Initialiserung Routinen kommen aus einer Library von Uwe Becker [2] und wurden nur etwas angepasst bzw. um die Interrupt-Initialisierung erweitert. Wichitg ist bei der Initialisierung, dass mit P2_y_enable_digital die entsprechenden Pins des Ports 2 auf digital umgeschaltet werden. Sonst sind diese für den USIC nicht nutzbar.
Bei der Initialisierung kommen auch wieder die SR-Linien ins Tragen. Der DMX-Empfang wird auf SR1 umgeleitet; der Empfang vom PC bleibt auf SR0.

Der XMC mit seiner USIC-Peripherie ist besonders gut für den DMX Empfang geeinigt. Anders als bspw. Atmega-Prozessoren kann mit dieser Einheit der Break des DMX-Signals sauber erkannt werden und einen Interrupt auslösen.

Das DMX Signal ist ein 8N2-Signal mit 250.000bps. Vor jedem 513 Byte langem Datenframe wird ein Break zur Synchronisation gesendet. Dem folgt ein Byte Startcode, das die Art der folgenden Daten bezeichnet. Für einfache Lichtwerte ist die 0x00. Darauf folgen 512 Datenbyte, wobei jedes Byte im einfachsten Fall einem Kanal entspricht.

Oben: DMX mit Break, Unten PWM von DMX gesteuert

In der Interrupt Routine des DMX-Empfanges wird zuerst der Fifo-Leergelesen - auch wenn der Interrupt durch den Break ausgelöst wurde. So wird sicher gestellt, dass das Datenframe komplett in den Empfangsbuffer übernommen wird.
Wenn ein Break vorlag, wird der Zähler wieder zurückgesetzt. Kommt dann der nächste Empfangsinterrupt, wird davon ausgegangen, dass es wieder mit dem Startcode losgeht.
Im dmx_rbuf steht dann an der 0. Stelle der Startcode, ab 1. geht es mit den Lichtwerten los. Diese werden zudem auch gleich an die PWM übergeben, sofern es sich um die Werte 1-5 handelt.

Hardware

Elektrik

Schaltplan

Die Hardware ist ziemlich simpel. Der XMC steuert die Servos direkt an. Zwar arbeiten die Servos mit 4-6V (in diesem projekt mit 5V) Versorgungsspannung, erkennen die 3,3V des XMC2Go aber trotzdem als gültiges High-Signal.
Die LEDs hingegen werden über die Transistoren in Emitter-Schaltung angesteuert, um den höheren Strom nicht über die Portpins fließen zu lassen. Die LEDs haben eine Forward-Voltage von 2V (rot) bzw 3,2V (grün/blau). Die Vorwiderstände wurden auf 3,3V ausgelegt, sodass nur wenig Spannung an diesen abfallen muss. Zudem wurden die LEDs zwar parallel geschaltet, jedoch jeweils mit eigenen Vorwiderständen.
Die DMX-Schaltung wird über eine Optokoppler galvanisch getrennt. Die dazu notwendige Spannungsversorgung wird mit einem 5V/5V DCDC Wandler geliefert.

Die Schaltung wurde zunächst nur auf einem Steckbrett aufgebaut. Die DMX Schaltung wurde aus einem alten Projekt genommen und nur das RX Signal und die Versorgungspannung von/ auf das Steckbrett geführt.

Mechanik

Die Servos wurden direkt beim Modellieren des Movinglights aus Spachtelmasse mit eingespachtelt. Die LEDs wurden nachträglich mit Kupferlackdraht verdrahtet und eingebaut. Der Anschluss an das Steckbrett erfolgt mit Stiftleisten.

Verbesserungen

Softwareseitig ist der DMX-Empfang verbesserungs würdig. Momentan ist nicht getestet, ob dieser mit anderen Startcodes klar kommt.
Bei der Hardware könnte der auf dem XMC2Go verbaute 3,3V Spannungsregler an seine Grenze stoßen, da dieser zusätzlich die 3 RGB LEDs treiben muss.
Die DMX-Schaltung müsste Eingangsseitig noch abgesichert bzw. entstört werden, um auch mit Einstreuungen auf langen Leitungen klar zu kommen.
Dann gehört die Schaltung natürlich vom Steckbrett runter- mindestens auf eine Lochrasterplatine.

Downloads

Datei:XMC Tutorial Movinglight (PWM, DMX).zip

Quellen

[1]http://www.modelltruck.net/showthread.php?16462-iWash-575-EB-Movinglight-f%FCr-Open-Air-B%FChne [2]http://mikrocontroller.bplaced.net/wordpress/?page_id=3809#I06

Bilder