Differences

This shows you the differences between two versions of the page.

Link to this comparison view

einfache_ein-_und_ausgaben_mit_dem_arm [2018/12/20 12:32]
einfache_ein-_und_ausgaben_mit_dem_arm [2019/02/04 14:10] (current)
Line 1: Line 1:
 +====== Einfache Ein- und Ausgaben mit dem ARM ======
 +Mit der zweiten Übung tasten wir uns im wahrsten Sinne des Wortes an die eigentliche Aufgabe eines jeden Controllers. 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 solange, wie man mit der EVA nichts Praktisches anfängt //​*grins*//​. Es soll der blaue Taster auf dem STM32F4 Discovery ausgewertet werden. Und da der Taster blau ist, auch zünftig die blaue 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 [[http://​www.st.com/​internet/​com/​TECHNICAL_RESOURCES/​TECHNICAL_LITERATURE/​USER_MANUAL/​DM00039084.pdf|STM32F4 Discovery]]. In der folgenden vereinfachten Darstellung ist das Wesentliche zusammengefasst.
 +
 +>​{{:​armlichtschalter1.jpg?​700|}}
 +
 +Die blaue LED hängt überraschenderweise //immer noch// an D15 und der Taster ist //diesmal// an A0 angeschlossen. Die tatsächliche Tasterlogik ist hier etwas vereinfacht als Umschalter abgebildet. ​ RCC liefert wieder über AHB1 den Takt. Wir merken schon, als Erstes müssen wir immer dafür sorgen, das jedes Gerät, welches wir benutzen wollen, seinen Takt bekommt. Es ist also Folgendes zu tun, um die Aufgabe zu erfüllen:
 +
 +  - über den AHB1 Bus den GPIO Port A mit Takt versorgen
 +  - das Bit 0 des GPIO Port A als Eingang ohne PullUp konfigurieren
 +  - über den AHB1 Bus den GPIO Port D mit Takt versorgen
 +  - das Bit 15 des GPIO Port D als Ausgang konfigurieren
 +  - das Bit 0 von GPIO Port A einlesen
 +  - wenn der Taster gedrückt ist, das Bit 15 des GPIO Port D
 +    * 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 STM32F4-Discovery.
 +
 +>>​{{:​neueeva.jpg?​700|}}
 +
 +Erstellen Sie die Programmkopfdokumentation. Übersetzen und Übertragen Sie das noch leere Programm auf den Controller, um die Verbindung zu testen.
 +
 +>>><​code cpp>
 +//​----------------------------------------------------------------------
 +// Titel     : Beispiel intelligenter Lichtschalter 1 mit SiSy STM32
 +//​----------------------------------------------------------------------
 +// Funktion ​ : der blaue Taster schaltet die blaue LED an
 +// Schaltung : blaue LED an GPIO Port D15, Taster an A0
 +//​----------------------------------------------------------------------
 +// Hardware ​ : STM32F4 Discovery
 +// Takt      : 168 MHz
 +// Sprache ​  : ARM C++
 +// Datum     : heute
 +// Version ​  : 1
 +// Autor     : ich
 +//​---------------------------------------------------------------------- ​
 +</​code>​
 +
 +===== Lösungsansatz =====
 +Rekapitulieren wir noch mal das Blockbild von oben. Man erkennt, dass der RCC-Unit (Reset & Clock Control ) mitgeteilt werden muss, dass GPIOD und GPIOA über den AHB1 mit Takt versorgt werden müssen. Wie bereits im Beispiel //​HalloARM//,​ benutzen wir dafür die Funktion //​RCC_AHB1PeriphClockCmd//​ aus den STM32F4-Peripherie-Treibern. ​
 +
 +>>><​code cpp>
 +// GPIOD Takt einschalten ​
 +RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,​ ENABLE);
 +// GPIOA Takt einschalten ​
 +RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,​ ENABLE);
 +</​code>​
 +
 +Damit sind die GPIO Ports A und D bereit initialisiert zu werden. Es sind nach dem bekannten Muster ​
 +  - Takt einschalten
 +  - Initialisierungsstruktur anlegen
 +  - Struktur mit Standardwerten füllen
 +  - Anwendungsspezifische Anpassungen vornehmen
 +  - Gerät initialisieren
 +
 +als Nächstes die Initialisierungsstrukturen für die beiden Ports vorzubereiten. Dazu können zwei Instanzen der Struktur angelegt werden oder nur eine, um diese dann wieder zu verwenden. Wir entscheiden uns für die Wiederverwendung einer Struktur. ​
 +
 +>>><​code>​
 +GPIO_InitTypeDef ​ GPIO_InitStructure;​
 +GPIO_StructInit (&​GPIO_InitStructure);​
 +</​code>​
 +
 +Jetzt kümmern wir uns um den Ausgang für die LED, PortD Bit15. Dieser muss im Output Mode als Gegentaktstufe,​ also Push-Pull arbeiten und benötigt kein PullUp oder PullDown. Die Geschwindigkeit des Ports ist uns bei dieser Anwendung eigentlich recht egal. Strom müssen wir jetzt nicht sparen, also belassen wir es bei den 100 MHz.
 +
 +>>><​code cpp>
 +GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_15;​
 +GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;​
 +GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;​
 +GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;​
 +GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;​
 +GPIO_Init(GPIOD,​ &​GPIO_InitStructure);​
 +</​code>​
 +
 +Kümmern wir uns jetzt um den Eingang für den Taster, Port A Bit0. Der blaue Taster auf dem STM32F4 hat eine kleine Treiberstufe,​ die zwischen High und Low umschaltet. Ist der Taster nicht gedrückt, zieht die Treiberstufe die Pin A.0  auf Low. Wird der Taster gedrückt, wird Pin A.0 gegen High geschaltet. Der Taster ist also Hihg-Aktiv und benötigt weder einen PullUp noch ein PullDown.
 +
 +>>><​code cpp>
 +GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
 +GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;​
 +GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;​
 +GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;​
 +GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;​
 +GPIO_Init(GPIOA,​ &​GPIO_InitStructure);​
 +</​code>​
 +
 +Das Einlesen eines Port-Pin erfolgt mit der Funktion //​GPIO_ReadInputDataBit//​ aus den STM32F4 Peripherietreibern. Die Funktion erwartet den Port und das Bit als Parameter und liefert mit 0 oder 1 den aktuellen Status des Port-Pins als Rückgabewert. Das können wir recht nett auswerten.
 +
 +>>><​code cpp>
 +if (GPIO_ReadInputDataBit(GPIOA,​ GPIO_Pin_0)==1)
 +</​code>​
 +
 +Entsprechend der Auswerung können wir mit den bereits bekannten Funktionen //​GPIO_SetBit//​ und //​GPIO_ResetBit//​ die LED einschalten:​
 +
 +>>><​code cpp>
 +GPIO_SetBits(GPIOD,​GPIO_Pin_15);​
 +</​code>​
 +
 +oder ausschalten:​
 +
 +>>><​code cpp>
 +GPIO_ResetBits(GPIOD,​GPIO_Pin_15);​
 +</​code>​
 +
 +
 +===== Entwurf =====
 +Zuerst wieder der Entwurf in Form von Kommentaren:​
 +
 +>>><​code c>
 +//​----------------------------------------------------------------------
 +// Titel     : ENTWURF intelligenter Lichtschalter 1 in SiSy STM32
 +//​----------------------------------------------------------------------
 +// Funktion ​ : blaue Taste schaltet blaue LED an
 +// Schaltung : Taste an PA0 LED an PD15
 +//​----------------------------------------------------------------------
 +// Hardware ​ : STM32F4 Discovery
 +// Takt      : 168 MHz
 +// Sprache ​  : ARM C
 +// Datum     : 29.08.2012
 +// Version ​  : ENTWURF
 +// Autor     : Alexander Huwaldt
 +//​----------------------------------------------------------------------
 +#include <​stddef.h>​
 +#include <​stdlib.h>​
 +#include "​hardware.h"​
 +
 +void initApplication()
 +{
 + SysTick_Config(SystemCoreClock/​100);​
 +
 + // GPIOD Takt einschalten
 + // Konfiguriere PD15 als Ausgang
 + // GPIOA Takt einschalten
 + // Konfiguriere PA0 als Eingang
 +
 +}
 +
 +int main(void)
 +{
 + SystemInit();​
 + initApplication();​
 + do{
 + // WENN Taster an A0 gedrückt DANN
 + //  LED an D15 einschalten
 + // SONST
 + //  LED an D15 ausschalten ​
 +
 + } while (true);
 + return 0;
 +}
 + 
 +extern "​C"​ void SysTick_Handler(void)
 +{
 + // hier nichts tun
 +}
 +</​code>​
 +
 +===== Realisierung =====
 +Nachdem wir den Entwurf in Ruhe rekapituliert haben, kann es an die Umsetzung gehen. 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.
 +
 +>>><​code c>
 +//​----------------------------------------------------------------------
 +// Titel     : Beispiel intelligenter Lichtschalter 1 in SiSy STM32
 +//​----------------------------------------------------------------------
 +// Funktion ​ : blaue Taste schaltet blaue LED an
 +// Schaltung : Taste an PA0 LED an PD15
 +//​----------------------------------------------------------------------
 +// Hardware ​ : STM32F4 Discovery
 +// Takt      : 168 MHz
 +// Sprache ​  : ARM C++
 +// Datum     : 29.08.2012
 +// Version ​  : 1
 +// Autor     : Alexander Huwaldt
 +//​----------------------------------------------------------------------
 +#include <​stddef.h>​
 +#include <​stdlib.h>​
 +#include "​hardware.h"​
 +
 +void initApplication()
 +{
 + SysTick_Config(SystemCoreClock/​100);​
 + // weitere Initialisierungen durchführen
 +
 + // GPIOD Takt einschalten
 + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,​ ENABLE);
 + // GPIOA Takt einschalten
 + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,​ ENABLE);
 +
 + GPIO_InitTypeDef ​ GPIO_InitStructure;​
 + GPIO_StructInit (&​GPIO_InitStructure);​
 +
 + // Konfiguriere PD15
 + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;​
 + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;​
 + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;​
 + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;​
 + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;​
 + GPIO_Init(GPIOD,​ &​GPIO_InitStructure);​
 +
 + //  Konfiguriere PA0
 + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
 + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;​
 + GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;​
 + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;​
 + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;​
 + GPIO_Init(GPIOA,​ &​GPIO_InitStructure);​
 +
 +}
 +
 +int main(void)
 +{
 + SystemInit();​
 + initApplication();​
 + do{
 + if ( GPIO_ReadInputDataBit(GPIOA,​ GPIO_Pin_0) == 1 )
 + {
 + GPIO_SetBits(GPIOD,​GPIO_Pin_15);​
 + }
 + else
 + {
 + GPIO_ResetBits(GPIOD,​GPIO_Pin_15);​
 + }
 + } while (true);
 + return 0;
 +}
 + 
 +extern "​C"​ void SysTick_Handler(void)
 +{
 + // Application SysTick
 +}
 +</​code>​
 +
 +===== Test =====
 +Übersetzen Sie das Programm. Korrigieren Sie ggf. Schreibfehler. Übertragen Sie das lauffähige Programm in den Programmspeicher des Controllers. ​
 +  - Kompiliern
 +  - Linken
 +  - Brennen
 +
 +>>>​{{:​tasterblaueled.jpg?​500|}}
 +
 +Die blaue LED auf dem STM32F4 Discovery leuchtet jetzt immer solange, wie der blaue Taster gedrückt ist. 
 +
 +====== Videozusammenfassung ======
 +An dieser Stelle wieder eine kurze Zusammenfassung. Wirklich Neues ist fett hervorgehoben:​
 +
 +**Initialisierungssequenz für Geräte:**
 +  - Takt einschalten,​ RCC_xxxClockCmd
 +  - Initialisierungsstruktur anlegen, xxx_InitTypDef initStruct
 +  - Struktur mit Standardwerten füllen, xxx_StructInit (&​initStruct)
 +  - Anwendungsspezifische Anpassungen vornehmen, initStruc.xxx_Mode = wert
 +  - Gerät initialisieren,​ xxx_Init(xxx,​ &​initStructure)
 +
 +**Initialisierungsstruktur für Digitalports:​** //​GPIO_InitTypeDef initStruct;//​
 +  * initStruct.GPIO_Pin =  GPIO_Pin_0..15;​
 +  * initStruct.GPIO_Mode = GPIO_Mode_OUT|**IN**|AF;​
 +  * initStruct.GPIO_OType = GPIO_OType_PP|OD;​
 +  * initStruct.GPIO_Speed = GPIO_Speed_2..100MHz;​
 +  * initStruct.GPIO_PuPd = GPIO_PuPd_NOPULL|UP|DOWN;​
 +
 +**wichtige Funktionen für Digitalports:​**
 +  * RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOx,​ ENABLE|DISABLE);​
 +  * GPIO_StructInit (&​initStruct);​
 +  * GPIO_Init(GPIOx,​ &​initStruct);​
 +  * **GPIO_ReadInputDataBit(GPIOx,​ GPIO_Pin_x)**
 +  * GPIO_SetBits(GPIOx,​GPIO_Pin_x);​
 +  * GPIO_ResetBits(GPIOx,​GPIO_Pin_x);​
 +
 +
 +Und hier diesen Abschnitt dann auch als Videozusammenfassung.
 +
 +>>><​html><​iframe width="​640"​ height="​400"​ src="​https://​www.youtube.com/​embed/​HVHzasneQeo"​ frameborder="​0"​ allowfullscreen></​iframe></​html>​
 +
 +====== Nächstes Thema ======
 +  * [[SystemTickC|Der SystemTick in C]]