Einfache Ein- und Ausgaben mit dem XMC

Mit der zweiten Übung tasten wir uns, im wahrsten Sinne des Wortes, an die eigentliche Aufgabe eines jeden Controllers heran. Dieser soll Zeit seines Lebens fortlaufend Eingaben aus seiner Umgebung nach einer vorgegebenen Logik verarbeiten und entsprechend dieser Verarbeitung Ausgaben erzeugen. Es ist das allseits beliebte EVA-Prinzip, *gähn*. Spaß beiseite! Zum Gähnen ist das nur so lange, wie man mit der EVA nichts Praktisches anfängt *grins*. Es soll ein Taster auf dem XMC4500 Relax Kit ausgewertet und bei Tastendruck eine LED eingeschaltet werden.

Die Aufgabe

Es ist zunächst wieder wichtig, sich mit der konkreten Schaltung zu beschäftigen. Diese entnehmen wir der Produktbeschreibung zum Releax Kit (Schaltplan Seite 15). In der folgenden vereinfachten Darstellung ist das Wesentliche zusammengefasst.

Die gewünschte LED hängt überraschenderweise immer noch an Port 1 Bit 0 und der Taster ist diesmal an Port 1 Bit 15 angeschlossen. Die tatsächliche Tasterlogik wurde hier etwas vereinfacht als Umschalter abgebildet. Es ist also Folgendes zu tun, um die Aufgabe zu erfüllen:

  1. das Pin 1.0 als Ausgang konfigurieren
  2. das Pin 1.15 als Eingang ohne PullUp konfigurieren
  3. das Bit 15 von Port 1 einlesen
  4. wenn der Taster gedrückt ist, also Pin1.15 == 1
    • LED an Pin 1.0 auf High schalten
    • sonst auf Low schalten

Vorbereitung

Falls das Tutorial-Projekt nicht mehr offen ist, öffnen Sie dies. Legen Sie bitte ein neues kleines Programm an und laden das Grundgerüst ARM C++ Anwendung. Beachten Sie die Einstellungen für die Zielplattform XMC4500 Relax Kit.

Erstellen Sie die Programmkopfdokumentation. Übersetzen und übertragen Sie das noch leere Programm auf den Controller, um die Verbindung zu testen.

//----------------------------------------------------------------------
// Titel     : Beispiel intelligenter Lichtschalter 1 mit SiSy XMC
//----------------------------------------------------------------------
// Funktion  : ein Taster schaltet eine LED an
// Schaltung : LED an Pin1.0, Taster an Pin1.15
//----------------------------------------------------------------------
// Hardware  : XMC4500
// Takt      : 120 MHz
// Sprache   : ARM C++
// Datum     : heute
// Version   : 1
// Autor     : ich
//---------------------------------------------------------------------- 

Grundlagen

Zur Wiederholung hier noch mal die Struktur eines GPIO beim XMC.

Diesmal rücken zusätzlich die Eingabe betreffende Register in den Fokus unserer Betrachtung.

  • IOCR*, diesmal zur Konfiguration als Eingang
  • IN, zum Einlesen des betreffenden Pins

Im IOCR sind das Pin1.0 und Pin 1.15 zu konfigurieren:

  • Pin1.0 = XMC_GPIO_MODE_OUTPUT_PUSH_PULL
  • Pin1.15 = XMC_GPIO_MODE_INPUT_TRISTATE oder XMC_GPIO_MODE_INPUT_INVERTED_TRISTATE
    bzw. XMC_GPIO_MODE_INPUT_PULL_UP oder XMC_GPIO_MODE_INPUT_INVERTED_PULL_UP

Der Taster schaltet gegen Masse. Das heißt, die direkte Eingabe liefert bei gedrücktem Taster eine logische 0, welche in C den Wahrheitswert FALSE repräsentiert. Die unter Umständen nötige Umkehrung der Logik kann in der Software oder eben listigerweise in der Hardware erfolgen. Einen controllerinternen PullUp oder PullDown brauchen wir nicht aktivieren, da dieser auf dem Relax Kit extern, warum auch immer, bereits diskret bestückt ist. Nun ja, warum ist schon klar, die Benutzertaster auf dem Relax Kit werden mit einem PullUp-Widerstand von 10K bereit gegen High gezogen und sind mit einem Kondensator von 100nF hardwareseitig entprellt. Das macht es dem Anfänger etwas leichter. Er braucht den internen PullUp nicht per Software zu aktivieren und was viel schwerer wiegt, er braucht nicht per Software den Taster zu entprellen.

Entwurf

Zuerst wieder der Entwurf in Form von Kommentaren:

//----------------------------------------------------------------------
// Titel     : Beispiel intelligenter Lichtschalter 1 mit SiSy XMC
//----------------------------------------------------------------------
// Funktion  : ein Taster schaltet eine LED an
// Schaltung : LED an Pin1.0, Taster an Pin1.15
//----------------------------------------------------------------------
// Hardware  : XMC4500
// Takt      : 120 MHz
// Sprache   : ARM C++
// Datum     : heute
// Version   : 1
// Autor     : ich
//---------------------------------------------------------------------- 
#include <stddef.h>
#include <stdlib.h>
#include "hardware.h"
#include "xmc_gpio.h" 
 
void initApplication()
{
	SysTick_Config(SystemCoreClock/100);
 
	// Konfiguriere Pin1.0 als Ausgang
	// Konfiguriere Pin1.15 als Eingang ohne PullUp
 
}
 
int main(void)
{
	SystemInit();
	initApplication();
	do{
		// WENN Taster an Pin1.15 gedrückt DANN
		//  LED an Pin1.0 einschalten
		// SONST
		//  LED an Pin1.0 ausschalten 
 
	} while (true);
	return 0;
}
 
extern "C" void SysTickFunction(void)
{
	// hier nichts tun
}

Realisierung

Nachdem wir den Entwurf in Ruhe rekapituliert haben, kann es an die Umsetzung gehen. Die Konfiguration für die LED können wir einfach vom voran gegangenen Beispiel übernehmen.

PORT1->IOCR0 |= (XMC_GPIO_MODE_OUTPUT_PUSH_PULL<<0*8);

Für den Taster sollten wir uns nochmals die Position im IOCR-Registerblock vergegenwärtigen. Die entsprechende Konfiguration muss auf die Position des Pin1.15 in PORT1.IOCR12 gebracht werden. Dazu beauftragen wir den C-Kompiler die gewünschte Konfiguration auf die richtige Position zu schieben.

PORT1->IOCR12 |= (XMC_GPIO_MODE_INPUT_TRISTATE<<3*8);

Für das Einlesen des Tasterzustandes benutzen wir das IN-Register und Maskieren das gewünschte Bit mit einer AND-Verknüpfung.

PORT1->IN & BIT15

Für das EIN- und Ausschalten der LED benutzen wir bewährte Codes:

//  LED an Pin1.0 einschalten
PORT1->OUT |= BIT0;
//  LED an Pin1.0 ausschalten 
PORT1->OUT &= ~BIT0;

oder

//  LED an Pin1.0 einschalten
SET_BIT(PORT1->OUT,0);
//  LED an Pin1.0 ausschalten 
CLR_BIT(PORT1->OUT,0);

Wenn Sie Quelltexte lieber kopieren, können Sie das gern mit dem obigen Entwurf machen, aber die eigentlichen Befehle sollten Sie aus lernpsychologischen Überlegungen tatsächlich selbst und bewusst, demzufolge selbstbewusst, eintippen.

//----------------------------------------------------------------------
// Titel     : Beispiel intelligenter Lichtschalter 1 mit SiSy XMC
//----------------------------------------------------------------------
// Funktion  : ein Taster schaltet eine LED an
// Schaltung : LED an Pin1.0, Taster an Pin1.15
//----------------------------------------------------------------------
// Hardware  : XMC4500
// Takt      : 120 MHz
// Sprache   : ARM C++
// Datum     : heute
// Version   : 1
// Autor     : ich
//---------------------------------------------------------------------- 
#include <stddef.h>
#include <stdlib.h>
#include "hardware.h"
#include "xmc_gpio.h" 
 
 
void initApplication()
{
	// SystemTimer auf 10ms konfigurieren
	SysTick_Config(SystemCoreClock/100);
	// weitere Initialisierungen durchführen
 
	// Konfiguriere Pin1.0 als Ausgang 
	PORT1->IOCR0 |= (XMC_GPIO_MODE_OUTPUT_PUSH_PULL<<0*8);
 
	// Konfiguriere Pin1.15 als Eingang ohne PullUp
	PORT1->IOCR12 |= (XMC_GPIO_MODE_INPUT_TRISTATE <<3*8);
 
}
int main(void)
{
	SystemInit();
	initApplication();
	do{
 
		// Beachte umgekehrte Logik!
		// WENN Taster an Pin1.15 gedrückt DANN
		if ( ! (PORT1->IN & BIT15) )
		{
			//  LED an Pin1.0 einschalten
			PORT1->OUT |= BIT0;
		}
		else	// SONST
		{
			//  LED an Pin1.0 ausschalten 
			PORT1->OUT &= ~BIT0;
		}
 
	} while (true);
	return 0;
}
extern "C" void SysTick_Handler(void)
{
	// hier nichts tun
}

Test

Übersetzen Sie das Programm. Korrigieren Sie ggf. Schreibfehler. Übertragen Sie das lauffähige Programm in den Programmspeicher des Controllers.

  1. Kompilieren
  2. Linken
  3. Brennen

Die LED auf dem XMC Relax Kit leuchtet jetzt immer so lange, wie der Taster gedrückt ist.

Videozusammenfassung

Und hier diesen Abschnitt dann auch als Videozusammenfassung.

Variante mit invertierter Hardwarelogik

Den Umstand, dass der Taster negative Logik besitzt, also eigentlich ein FALSE liefert, haben wir in der Softwarelösung dadurch gewürdigt, dass wir die Bedingung negiert haben.

if ( !(PORT1->IN & BIT15) )

Diese Arbeit können wir durch entsprechende Konfiguration auch die Hardware erledigen lassen.

PORT1->IOCR12 |= (XMC_GPIO_MODE_INPUT_INVERTED_TRISTATE<<3*8)

Variieren Sie das Beispiel entsprechend.

//----------------------------------------------------------------------
// Titel     : Beispiel intelligenter Lichtschalter 1b mit SiSy XMC
//----------------------------------------------------------------------
// Funktion  : ein Taster schaltet eine LED an
// Schaltung : LED an Pin1.0, Taster an Pin1.15
//----------------------------------------------------------------------
// Hardware  : XMC4500
// Takt      : 120 MHz
// Sprache   : ARM C++
// Datum     : heute
// Version   : 1
// Autor     : ich
//---------------------------------------------------------------------- 
#include <stddef.h>
#include <stdlib.h>
#include "hardware.h"
#include "xmc_gpio.h" 
 
void initApplication()
{
	// u.a. nötig für waitMs(..) und waitUs(..)
	SysTick_Config(SystemCoreClock/100);
 
	// Konfiguriere Pin1.0 als Ausgang 
	PORT1->IOCR0 |= (XMC_GPIO_MODE_OUTPUT_PUSH_PULL<<0);	
	// Konfiguriere Pin1.15 als Eingang ohne PullUp
	PORT1->IOCR12 |= (XMC_GPIO_MODE_INPUT_INVERTED_TRISTATE<<3*8); 
 
}
int main(void)
{
	SystemInit();
	initApplication();
	do{
 
		// WENN Taster an Pin1.15 gedrückt DANN
		// alt: if ( !(PORT1->IN & BIT15) )
		if ( PORT1->IN & BIT15 )
		{
			//  LED an Pin1.0 einschalten
			PORT1->OUT |= BIT0;
		}
		else // SONST
		{
			//  LED an Pin1.0 ausschalten 
			PORT1->OUT &= ~BIT0;
		}
 
	} while (true);
	return 0;
}
extern "C" void SysTick_Handler(void)
{
	// Application SysTick
}

Variante mit internem Pull-Up

Wir wollen uns den Umstand zu Nutze machen, dass auf dem XMC4500 Zusatzboard die Taster ohne PullUp und Kondensator bestückt sind. Damit können wir den internen PullUp des XMC ausprobieren. Dazu verbinden wir mit einem der Patchkabel den Taster 1 auf dem Zusatzboard mit Pin1.13 des XMC.

Variieren sie die Anwendung wie folgt:

//----------------------------------------------------------------------
// Titel     : Beispiel intelligenter Lichtschalter 1c mit SiSy XMC
//----------------------------------------------------------------------
// Funktion  : ein Taster schaltet eine LED an
// Schaltung : LED an Pin1.0, Taster an Pin1.13
//----------------------------------------------------------------------
// Hardware  : XMC4500
// Takt      : 120 MHz
// Sprache   : ARM C++
// Datum     : heute
// Version   : 1
// Autor     : ich
//---------------------------------------------------------------------- 
#include <stddef.h>
#include <stdlib.h>
#include "hardware.h"
#include "xmc_gpio.h"
 
void initApplication()
{
	// u.a. nötig für waitMs(..) und waitUs(..)
	SysTick_Config(SystemCoreClock/100);
 
	// Konfiguriere Pin1.0 als Ausgang 
	PORT1->IOCR0 |= (XMC_GPIO_MODE_OUTPUT_PUSH_PULL<<0);	
	// Konfiguriere Pin1.13 als Eingang ohne PullUp
	PORT1->IOCR12 |= (XMC_GPIO_MODE_INPUT_INVERTED_PULL_UP<<1*8); 
 
}
int main(void)
{
	SystemInit();
	initApplication();
	do{
 
		// WENN Taster an Pin1.13 gedrückt DANN
		if ( PORT1->IN & BIT13 )
		{
			//  LED an Pin1.0 einschalten
			PORT1->OUT |= BIT0;
		}
		else // SONST
		{
			//  LED an Pin1.0 ausschalten 
			PORT1->OUT &= ~BIT0;
		}
 
	} while (true);
	return 0;
}
extern "C" void SysTick_Handler(void)
{
	// Application SysTick
}

Die Infineons Low Level Treiber (XMC Lib) anwenden

Aus der Treiberbibliothek stehen für diese Verarbeitungsaufgabe von digitalen Eingaben unter anderem folgende Funktionen zur Verfügung:

  • XMC_GPIO_SetMode(PORT, PinNummer, MODE);
  • XMC_GPIO_GetInput (PORT, PinNummer);

Die entsprechende Lösung sieht dann wie folgt aus:

//---------------------------------------------------------------------------
// Titel     : Beispiel intelligenter Lichtschalter 1d mit SiSy XMC (XMC Lib)
//---------------------------------------------------------------------------
// Funktion  : ein Taster schaltet eine LED an
// Schaltung : LED an Pin1.0, Taster an Pin1.13
//----------------------------------------------------------------------
// Hardware  : XMC4500
// Takt      : 120 MHz
// Sprache   : ARM C++
// Datum     : heute
// Version   : 1
// Autor     : ich
//---------------------------------------------------------------------- 
#include <stddef.h>
#include <stdlib.h>
#include "hardware.h"
#include "xmc_gpio.h"
 
void initApplication()
{
	// u.a. nötig für waitMs(..) und waitUs(..)
	SysTick_Config(SystemCoreClock/100);
 
	// Konfiguriere Pin1.0 als Ausgang 
	// PORT1->IOCR0 |= (XMC_GPIO_MODE_OUTPUT_PUSH_PULL<<0);
	XMC_GPIO_SetMode(XMC_GPIO_PORT1, 0, XMC_GPIO_MODE_OUTPUT_PUSH_PULL );
 
	// Konfiguriere Pin1.13 als Eingang ohne PullUp
	// PORT1->IOCR12 |= (XMC_GPIO_MODE_INPUT_INVERTED_PULL_UP<<1*8); 
	XMC_GPIO_SetMode(XMC_GPIO_PORT1, 13, XMC_GPIO_MODE_INPUT_INVERTED_PULL_UP);
}
 
int main(void)
{
	SystemInit();
	initApplication();
	do{
 
		// WENN Taster an Pin1.13 (PORT1->IN & BIT13) gedrückt DANN
		if ( XMC_GPIO_GetInput(XMC_GPIO_PORT1, 13) )
		{
			//  LED an Pin1.0 einschalten (PORT1->OUT |= BIT0;)
                        XMC_GPIO_SetOutputHigh(XMC_GPIO_PORT1, 0);
		}
		else // SONST
		{
			//  LED an Pin1.0 ausschalten (PORT1->OUT &= ~BIT0;)
                        XMC_GPIO_SetOutputLow(XMC_GPIO_PORT1, 0);
		}
 
	} while (true);
	return 0;
}
extern "C" void SysTick_Handler(void)
{
	// Application SysTick
}

Wohltuend ist es schon nicht mehr mit den Schiebeoperationen die Bits an die richtige Stelle schubsen zu müssen ;-).

Nächstes Thema

einfache_ein-_und_ausgaben_mit_dem_xmc.txt · Zuletzt geändert: 2017/04/10 18:08 von huwaldt