prof. dr. otto parzhuber labor d204 stm32 einführung...

15
Prof. Dr. Otto Parzhuber Labor D204 STM32 Einführung D204 Version: 16.10.2018 Seite 1 - 15 File: STM32_Prakt_Einfuehrung_I.docx Einführung in die C-Programmierung mit STM32 Cortex Mikrocontroller Aufgabenstellung: Blinklicht und Taster mit dem stm32Nucleo und der OpenSTM32 Programmierumgebung Das Gerüst eines Blinklichts sieht folgendermaßen aus: /** \brief einfaches Blinklicht \author max muster */ int main(void) { Portbit auf Ausgang stellen; while(1){ Portbit setzen; Portbit löschen; } return 0; } Wenn an das entsprechende Portbit eine LED angeschlossen ist wird diese abwechselnd ein- und ausgeschaltet. Vorbereitungsfragen Weshalb muss Ihr Programm in einer Endlosschleife innerhalb von main() ablaufen? Wie viele Bits besitzen die Register des MikroControllers? Wie viele Bits besitzen die Ports des MikroControllers? Wie können Sie mit der Sprache C einzelne Bits in den Registern des Mikrocontrollers setzen und löschen? Sind die Portbits als Default Ein- oder Ausgänge? Begründung! Suchen Sie im Referenzmanual des Prozessors (stm32F072) die Bezeichnungen MODER, ODR und IDR. Was bedeuten sie? Welcher Datentyp verbirgt sich hinter dem Bezeichner GPIOA? Was bedeutet CMSIS und Cube-HAL? Für alle Verzeichnisse, Datei- und Projektnamen sind Umlaute, Sonderzeichen und Freizeichen tabu. Anstelle von \1. Versuch\Blödsinn.c können Sie z.B. \1_Versuch\Bloedsinn.c schreiben

Upload: lamkiet

Post on 10-Aug-2019

299 views

Category:

Documents


2 download

TRANSCRIPT

Prof. Dr. Otto Parzhuber

Labor D204

STM32 Einführung D204

Version: 16.10.2018 Seite 1 - 15

File: STM32_Prakt_Einfuehrung_I.docx

Einführung in die C-Programmierung mit STM32

Cortex Mikrocontroller

Aufgabenstellung:

Blinklicht und Taster mit dem stm32Nucleo und der

OpenSTM32 Programmierumgebung

Das Gerüst eines Blinklichts sieht folgendermaßen aus:

/**

\brief einfaches Blinklicht

\author max muster

*/

int main(void)

{

Portbit auf Ausgang stellen; while(1){ Portbit setzen; Portbit löschen; }

return 0;

}

Wenn an das entsprechende Portbit eine LED angeschlossen ist wird diese abwechselnd ein-

und ausgeschaltet.

Vorbereitungsfragen

Weshalb muss Ihr Programm in einer Endlosschleife innerhalb von main()

ablaufen?

Wie viele Bits besitzen die Register des MikroControllers?

Wie viele Bits besitzen die Ports des MikroControllers?

Wie können Sie mit der Sprache C einzelne Bits in den Registern des

Mikrocontrollers setzen und löschen?

Sind die Portbits als Default Ein- oder Ausgänge? Begründung!

Suchen Sie im Referenzmanual des Prozessors (stm32F072) die Bezeichnungen

MODER, ODR und IDR. Was bedeuten sie?

Welcher Datentyp verbirgt sich hinter dem Bezeichner GPIOA?

Was bedeutet CMSIS und Cube-HAL?

Für alle Verzeichnisse, Datei- und Projektnamen sind Umlaute,

Sonderzeichen und Freizeichen tabu.

Anstelle von \1. Versuch\Blödsinn.c können Sie z.B. \1_Versuch\Bloedsinn.c

schreiben

Prof. Dr. Otto Parzhuber

Labor D204

STM32 Einführung D204

Version: 16.10.2018 Seite 2 - 15

File: STM32_Prakt_Einfuehrung_I.docx

Kurzeinführung in die OpenStm32 IDE

Starten Sie die OpenStm32 IDE, falls bereits ein Projekt geöffnet ist, schließen Sie es mit

File->Close.

Da mit Sicherheit bereits Studierende anderer Praktikumsgruppen mit der

Programmierumgebung vor Ihnen gearbeitet haben ist es wichtig den Workspace

umzuschalten:

Unter Other… geben Sie nun ein Verzeichnis für Ihre Praktikumsgruppe ein, z.B.

Z:\mfb5g_pa1\workspace.

Zuvor müssen Sie sich natürlich mit dem Netzlaufwerk verbinden, in dem obigen Beispiel mit

dem Netzlaufwerk \\192.168.10.113\homes\mfb5g_pa1

Für ein lokales Laufwerk ist das Vorgehen natürlich identisch, aber in jedem Fall müssen Sie

zu jedem Beginn des Praktikums den Vorgang Switch Workspace durchführen.

Prof. Dr. Otto Parzhuber

Labor D204

STM32 Einführung D204

Version: 16.10.2018 Seite 3 - 15

File: STM32_Prakt_Einfuehrung_I.docx

Erstellen Sie ein neues Projekt mit File->New-> C Project. Der Name des Projekts bleibt

Ihnen überlassen, z.B. blinken wie im Beispiel:

Dieser Schritt ist sehr wichtig. Es muss als Board das NUCLEO-F072RB eingestellt sein.

Mit den Drop-Down Menüs finden sie es sicher problemlos.

Prof. Dr. Otto Parzhuber

Labor D204

STM32 Einführung D204

Version: 16.10.2018 Seite 4 - 15

File: STM32_Prakt_Einfuehrung_I.docx

Mit diesen wenigen Schritten haben Sie ein lauffähiges Gerüst für ein C-Programm für den

gewählten Prozessor und dem Nucleo-Board:

Prof. Dr. Otto Parzhuber

Labor D204

STM32 Einführung D204

Version: 16.10.2018 Seite 5 - 15

File: STM32_Prakt_Einfuehrung_I.docx

Unter dem Ordner src ist das Gerüst für die main-Funktion abgelegt. Für das Projekt wurden

mehrere weitere Verzeichnisse angelegt. Wichtig ist aber für unser erstes Projekt nur der

Ordner CMSIS.

CMSIS: CMSIS bedeutet Cortex Mikrocontroller Software Interface Standard und ermöglicht den

Zugriff auf die Peripheriemodule der unterschiedlichen Cortex Derivate von NXP, Atmel, TI

etc. mit einheitlichen Funktionen.

Mit dem Modul CMSIS core wird der für das Booten des Mikrocontrollers benötigte Code in

das Projekt eingefügt. Dazu gehören:

die Definition der Datentypen für den Zugriff auf die Peripherie,

der sogenannte Startup Code und die

vollständige (typspezifische) Interrupt Vektor Tabelle.

Programmieraufgabe I :

Erweitern Sie Datei main.c für die Erzeugung

eines Blinklichts. Verwenden Sie die Struktur

GPIOA und die Register MODER und ODR.

An welchem Port und welchem Pin ist die

LED angeschlossen?

Stellen Sie mit einer einfachen Wartefunktion

(for Schleife…) eine für das Auge sichtbare

Blinkfrequenz ein.

Sie müssen in der main-Funktion einmalig

den Takt für den GPIO-Port einschalten. Dies

geschieht mit der folgenden Anweisung: /* GPIOA Takt einschalten */ RCC->AHBENR |= (1<<17);

Das Referenzmanual liefert die Erklärung für diese ominösen 17 Bits um die Sie die „1“

verschieben müssen:

Prof. Dr. Otto Parzhuber

Labor D204

STM32 Einführung D204

Version: 16.10.2018 Seite 6 - 15

File: STM32_Prakt_Einfuehrung_I.docx

Alle GPIOs sind nach dem Reset als Eingang konfiguriert (warum?) und müssen zunächst

einmalig auf Ausgang gestellt werden. Vervollständigen Sie dazu die folgende Codezeile:

GPIOA->MODER |= (0b01 << . . . ); // Pin auf Ausgang

Die Antwort finden Sie im Referenzmanual auf Seite 157.

In einer Endlosschleife können Sie nun die LED abwechselnd ein- und ausschalten:

GPIOA->ODR ^= (1 << . . .); /* oder */ GPIOA->ODR |= (1 << . . .); GPIOA->ODR &= ~(1 << . . .);

Um welche Bitoperation handelt es sich bei der ersten Anweisung?

Um das Blinklicht für das Auge sichtbar zu machen benutzen Sie am einfachsten eine for-

Schleife, die einfach durch inkrementieren einer Variable Zeit „verbrät“.

Interessant ist es auch ohne Verwendung einer Warteschleife mit einem Logicanalyser die

Zeit zwischen ein- und ausschalten der LED zu betrachten. Ist die Zeit für das Einschalten

gleich lang wie die fürs ausschalten? Begründung.

Prof. Dr. Otto Parzhuber

Labor D204

STM32 Einführung D204

Version: 16.10.2018 Seite 7 - 15

File: STM32_Prakt_Einfuehrung_I.docx

Programmieraufgabe II :

Achtung: Kein neues Verzeichnis anlegen,

sondern das bereits bestehende Projekt

kopieren

Am Ende nicht vergessen das (alte) kopierte Projekt wieder zu schließen.

Erweitern Sie das

Programm aus der ersten

Programmieraufgabe. Das

Blinklicht soll nur bei

Betätigen des blauen

Tasters auf der Platine

aktiviert sein.

Verwenden Sie die

Struktur GPIOC und das

Register IDR.

Wie in der Programmieraufgabe I müssen Sie zuerst den Takt für den betreffenden GPIO-

Port einschalten. Welcher Port ist das und an welchen Pin ist der Taster angeschlossen?

Ein Gerüst für die Lösung zeigt der folgende Codeschnippsel:

taster = GPIO. . . ->IDR & (1 << . . . . );

if ( taster == . . . . ){ . . . blinke mit einer sichtbaren Frequenz . . . }

Welche zwei Werte kann die Variable taster annehmen? Welchen Datentyp können Sie

verwenden?

Prof. Dr. Otto Parzhuber

Labor D204

STM32 Einführung D204

Version: 16.10.2018 Seite 8 - 15

File: STM32_Prakt_Einfuehrung_I.docx

Programmieraufgabe III : ---- externe Interrupts und Einstieg in die Cube-HAL----

Achtung: Wie bei Aufgabe II ist es am einfachsten wenn Sie das bestehende Projekt

kopieren

Das Blinklicht soll nun

durch Betätigen des blauen

Tasters ein- und wieder

ausgeschaltet werden

können.

Der Pin soll als externer

Interrupteingang verwendet

werden

Bei der Projekterstellung

muss die Bibliothek Cube-HAL eingebunden sein.

Der prinzipielle Aufbau für die Verwendung der Cube-HAL ist immer gleich.

Vervollständigen Sie den folgenden Code:

. . . . . . int main(void) {

GPIO_InitTypeDef G; //Variablen deklarieren, meist Datentyp struct HAL_Init(); //Initialisierung für die Cube-HAL Library __HAL_RCC_GPIOA_CLK_ENABLE(); //Takt einschalten hier Beispiel GPIOA /* ---- LED PA5 einstellen ---- */ G.Pin = . . . . . . . . ; G.Mode = GPIO_MODE_OUTPUT_PP; G.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &G); /* ---- Taster PC13 einstellen ---- */ . . . . . . . . . . . . . . ; // Takt einschalten /* ---- Taster PC13 einstellen ---- */ G.Pin = . . . . . . . . ; G.Mode = GPIO_MODE_IT_FALLING; //1) G.Pull = GPIO_PULLUP; HAL_GPIO_Init( . . . . . , . . . .); /* ---- Interrupt einschalten ---- */ HAL_NVIC_EnableIRQ(. . . . . . . . ); //2)

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, . . . . . . ); //3)

Prof. Dr. Otto Parzhuber

Labor D204

STM32 Einführung D204

Version: 16.10.2018 Seite 9 - 15

File: STM32_Prakt_Einfuehrung_I.docx

while (1) { if (blinken_flag == true) { HAL_GPIO_TogglePin(. . . . . . ., . . . . . . ); HAL_Delay(50); //4) }

}

1) Ein Interrupt soll bei einer fallenden Flanke ausgelöst werden, was müssen Sie hier

einstellen? Welchen der folgenden Bezeichner verwenden Sie? GPIO_MODE_INPUT /*!< Input Floating Mode */ GPIO_MODE_OUTPUT_PP /*!< Output Push Pull Mode */ GPIO_MODE_OUTPUT_OD /*!< Output Open Drain Mode */ GPIO_MODE_AF_PP /*!< Alternate Function Push Pull Mode */ GPIO_MODE_AF_OD /*!< Alternate Function Open Drain Mode*/ GPIO_MODE_ANALOG /*!< Analog Mode */ GPIO_MODE_IT_RISING /*!< ExtInterrupt Mode with Rising edge trigger detection */ GPIO_MODE_IT_FALLING /*!< Ext Interrupt Mode with Falling edge trigger detection*/ GPIO_MODE_IT_RISING_FALLING /*!< External Interrupt Mode with Rising/Falling edge trigger detection */

2) Welchen Interruptvektor müssen Sie hier einsetzen? Die Lösung finden Sie in der Datei

startup_stm32f072xb.s. Die folgenden drei Möglichkeiten stehen zur Auswahl: EXTI0_1_IRQHandler /* EXTI Line 0 and 1 */ EXTI2_3_IRQHandler /* EXTI Line 2 and 3 */ EXTI4_15_IRQHandler /* EXTI Line 4 to 15 */

3) PA5 soll nun zuerst gelöscht werden. Tragen Sie den nötigen Bezeichner ein.

4) Die Funktion HAL_Delay wartet x Millisekunden.

Eine Möglichkeit für die Interruptfunktion sieht so aus:

//Interrupt Serviceroutine void EXTI4_15_IRQHandler(void) { HAL_GPIO_EXTI_IRQHandler(. . . . . . .); //1) if (blinken_flag == true) blinken_flag = . . . . ; //2) else blinken_flag = . . . .; }

1)

Hier müssen Sie den passenden Pin eintragen

2)

Vervollständigen Sie den Code.

Hinweis: für den Datentyp Boolean gibt es den Header stdbool.h.

Prof. Dr. Otto Parzhuber

Labor D204

STM32 Einführung D204

Version: 16.10.2018 Seite 10 - 15

File: STM32_Prakt_Einfuehrung_I.docx

Programmieraufgabe IV : Textausgabe über das LCD-Keypad

Achtung: Wie bei Aufgabe II ist es am einfachsten wenn Sie das bestehende Projekt

kopieren

Wir benützen eine Bibliothek bestehend aus den

beiden Dateien1 lcd.c und lcd.h

Diese beiden Dateien müssen Sie wie im

nebenstehenden Bild gezeigt in ihr Projekt

einfügen.

Um die gewohnte Funktion printf(….)

verwenden zu können muss nur noch in der Datei

syscalls.c (siehe rechts) ein Funktionsaufruf aus der lcd.c hinzugefügt

werden. Suchen Sie die (leere) Funktionsdefinition __io_putchar(int ch)

und fügen den unten gezeigten Funktionsaufruf hinzu:

/* * für die lcdbibliothek und printf */ int __io_putchar(int ch){ lcd_putchar(ch); }

Mit diesen kleinen Anpassungen können Sie nun beliebige Texte und

formatierte Zahlen auf dem LCD-Keypad ausgeben:

printf("Hallo %3d %3x \r\n", i, i);

Sie können die üblichen

Formatierungsparameter

verwenden, z.B. :

%s für Strings

%d für Dezimalzahlen

%x für Hexadezimalzahlen

%f für Gleitkommazahlen ist nicht

implementiert

1 Basiert auf der avr lib von Fleury

Prof. Dr. Otto Parzhuber

Labor D204

STM32 Einführung D204

Version: 16.10.2018 Seite 11 - 15

File: STM32_Prakt_Einfuehrung_I.docx

Anschluss des Boards:

Das Bild zeigt den Anschluss des Boards. Der linke Teil der Platine ist der Debugger und

rechts mit den Stiftleisten das Target-Board. Das Board wird über die USB-Schnittstelle des

Debuggers mit Strom versorgt, es wird also kein extra Stromanschluss benötigt.

Prof. Dr. Otto Parzhuber

Labor D204

STM32 Einführung D204

Version: 16.10.2018 Seite 12 - 15

File: STM32_Prakt_Einfuehrung_I.docx

Schaltplan des LCD-Keypad-Shield

Prof. Dr. Otto Parzhuber

Labor D204

STM32 Einführung D204

Version: 16.10.2018 Seite 13 - 15

File: STM32_Prakt_Einfuehrung_I.docx

GNU ARM Toolchain:

Im Praktikum wird die frei verfügbare GNU ARM Toolchain verwendet. Für eine genauere

Beschreibung des Compilers steht eine sehr lesenswerte Website zur Verfügung:

http://www.bravegnu.org/gnu-eprog/

Einfaches Beispiel:

Die Größe der Text und Datensegmente interessiert Sie spätestens bei einer Meldung des

Linkers wie memory overflow. Die Bezeichnung der Segmente lautet:

bss: in dieses Segment werden static und globale Variablen abgespeichert

data: hier werden initialisierte Daten abgespeichert

text: hier kommt der Code rein

Für die detaillierte Speicheraufteilung ist es interessant die map- Datei in dem

Unterverzeichnis (Projektverzeichnis)/debug/bin anzusehen!

Prof. Dr. Otto Parzhuber

Labor D204

STM32 Einführung D204

Version: 16.10.2018 Seite 14 - 15

File: STM32_Prakt_Einfuehrung_I.docx

Die folgende Tabelle zeigt die Speicheraufteilung für den Mikrocontroller.

Load and Runtime Location

Load Location

Runtime Location

Der Heap wächst von der ersten freien Adresse im Datenspeicher aufwärts.

Der StackPointer wächst von der höchsten Adresse abwärts. Der C Programmierer

muss sich nicht darum kümmern.

Aber:

Je größer der Stack eingestellt wird, umso kleiner wird der Heap.

Diese Eigenschaft ist für den C Programmierer bei größeren Programmen mit vielen

Variablen äußerst wichtig!!!!!

Flash

vectors

.text

.rodata

0x0000 0000

(512 KB)

Im Segment .data

werden lokale Variablen

abgelegt

.data

0x0007 FFFF

Nix, kein Speicher implementiert

RAM

Im Segment .bss werden

static und globale

Variablen abgelegt

.data

.bss

0x1000 0000

Initialer StackPointer ->

Heap

Stack

(32 KB)

0x1000 7FFF

Prof. Dr. Otto Parzhuber

Labor D204

STM32 Einführung D204

Version: 16.10.2018 Seite 15 - 15

File: STM32_Prakt_Einfuehrung_I.docx

Musterlösung:

// Musterlösung 1. Termin #include "stm32f0xx.h" #include "stm32f0xx_nucleo.h" int main(void) { uint32_t i; RCC->AHBENR |= (1<<17); // GPIOA Takt einschalten GPIOA->MODER |= (0b01 <<10); // Ausgang GPIOA.5 for(;;) // oder while(1) { GPIOA->ODR |= (1<<5); // logisch 1 for (i=0;i<1E5;i++); // Strichpunkt nicht vergessen!! GPIOA->ODR &= ~(1<<5); // logisch 0 for (i=0;i<1E5;i++); // Strichpunkt nicht vergessen!! } }

Oder kürzer mit der Exclusiv-Oder (XOR oder Antivalenz) Verknüpfung:

for(;;) // oder while(1) { GPIOA->ODR ^= (1<<5); // abwechselnd logisch 1 und 0 for (i=0;i<1E5;i++); // Strichpunkt nicht vergessen!! }

Mit dem Taster:

uint32_t taster; RCC->AHBENR |= (1<<17); // GPIOA Takt einschalten RCC->AHBENR |= (1<<19); // GPIOC Takt einschalten RCC->APB1ENR |= (1<<4); // Timer 6 GPIOA->MODER |= (0b01 <<10); // Ausgang GPIOA.5 for(;;){ taster = GPIOC->IDR & (1<<13); if ( taster == 0){ GPIOA->ODR ^= (1<<5); //delay_ms(500); delay(); } }