Forum: Mikrocontroller und Digitale Elektronik STM32: Erster Schritt, LED Blinklicht


von Andre (Gast)


Lesenswert?

Hi,

ich benutze Coocox IDE und ein STM32 Discoveryboard mit einem 
STM2L152R8T6, an dem auf PB7 eine LED angeschlossen ist.

Ich habe einen Compiler heruntergeladen und die Treiber für STLink. Ich 
kann (so schaut es zumindest aus) mit Coocox flashen und erasen.

Mein Programm wird auch übersetzt, aber an der LED tut sich nichts.

Ich habe die HSI enabled und dem Systemclock zugewiesen. Anschließend 
aktiviere ich die Clocks für Port A-D.

Es sind bestimmt Anfängerfehler, aber für Hilfe wäre ich dankbar :).
1
#define STM32L1XX_MD STM32L152x6xx
2
#include "stm32l1xx.h"
3
4
int main(void)
5
{
6
  volatile uint32_t dly;
7
8
  RCC->CR = 0x01;
9
  RCC->CFGR = 0x01;
10
  RCC->AHBENR = 0x0F;
11
12
  GPIOB->MODER = 0x55555555;
13
  GPIOB->OTYPER = 0x00;
14
  GPIOB->OSPEEDR = 0x00;
15
  GPIOB->PUPDR = 0x00;
16
  GPIOB->ODR = 0xFF;
17
18
    while(1)
19
    {
20
      for(dly = 0; dly < 3000000; dly++);
21
      GPIOB->ODR = 0x00;
22
      for(dly = 0; dly < 3000000; dly++);
23
      GPIOB->ODR = 0xFF;
24
    }
25
}

von Jim M. (turboj)


Lesenswert?

Zuviele magische Zahlen in Deinem Code. Da gibt es sicher Header Defines 
für.

Schau mal im Debugger nach ob Du die Werte in den GPIOB Registern auch 
wieder auslesen kannst. Eventuell fehlt noch irgendwo ein Enable Bit.

von Ochs vorm Berg (Gast)


Lesenswert?

Andre schrieb:
> ich benutze Coocox IDE und ein STM32 Discoveryboard mit einem
> STM2L152R8T6, an dem auf PB7 eine LED angeschlossen ist.

Es wurden keine mit deiner Suchanfrage - STM2L152R8T6 - 
übereinstimmenden Dokumente gefunden.

von Andre (Gast)


Lesenswert?

Ist doch klar, dass ich den STM32L152R8T6 meinte :).

Die entsprechenden Defines muss ich erstmal finden, das war bis jetzt ja 
schon unübersichtlich genug :(.

von ui (Gast)


Lesenswert?

Und du glaubst echt das
- jemand der alle konstanten im kopf hat bock hat deine durchzugehen
- jemand der nicht die konstanten im kopf hat bock hat im Datenblatt 
nach allen konstanten zu suchen.

Ach ja, nur beim instruktionen zählen ist mir aufgefallen:
es müssten 5 instruktionen zur konfiguration von GBOIOB_x als ausgang 
sein, OHNE den wert zu setzen. Damit fehlt wahrscheinlich 1.

von Andre (Gast)


Lesenswert?

Ich sehe aber nur 4 passende Register.
Input/Output, Speed, Type, Pullup/down

Dann gibts noch Data Out/In. Lock, Alternate Funktion benutze ich nicht, 
kann laut Datenblatt alles auf 0 bleiben.

von pegel (Gast)


Lesenswert?

Willst du wirklich auf Registerebene arbeiten?
Wenn schon die aller simpelste Funktion nicht nicht klappt, was soll das 
am Ende bringen?

von Ochs vorm Berg (Gast)


Lesenswert?

pegel schrieb:
> was soll das am Ende bringen?

Jeder ist seines eigenen Glückes Schmied.

Irgendwann wird er es schon checken.

Vor allem auch dass CooCox nicht das Glückseeligmachende ist.

von derjaeger (Gast)


Lesenswert?

Was du da machst hat für dich der Hersteller ST bereits gemacht, du 
musst das Rad nicht neu erfinden indem du auf Registerebene arbeitest.


Hier:
http://www.st.com/en/embedded-software/stsw-stm32077.html

Diese Bibliothek in dein Projekt einbinden und die Funktionen verwenden

Diese Bibliothek übernimmt die ganze Registerarbeit für dich verpackt in 
C-Funktionen und Strukturen die du nur noch aufrufen musst.

Dann hast du solche Funktionen wie:


RCC_AHB1(RCC_GPIOA,ENABLE); // Clock aktivieren
// ...

GPIO_Struct.Pin = 5
GPIO_Struct.Speed = 100 // MHz
GPIO_Struct.Type = Output
// ...
// ...
GPIO_Init(GPIOA, Strukturvariable mit allen Einstellungen);


Das was du machst , mit Registern zu arbeiten, ist bei der AVR-Plattform 
noch in Ordnung. Aber bei STM32 wirst du besonders als Anfänger 
untergehen, einfach weil es sehr kompliziert ist und sehr viel 
Datenblattkenntnisse erfordert.

von derjaeger (Gast)


Lesenswert?

Die StdPeriph hat noch vieles weitere Nützliche, was du besonders 
brauchen wirst, um schnell eine LED zum blinken zu bringen:

>83 examples for 24 different peripherals

Es sind bereits ganze Beispiele vorprogrammiert: Wie schalte ich einen 
Ausgang, wie lese ich einen Eingang, SPI-Bus, I2C-Bus, UART, DMA, ....

Damit befassen (und gute Englischkenntnisse haben) und von dort kopieren 
und  an deine Situation anpassen (richtigen Pin, ..)

>Template project for 3 different IDEs

Hier kriegst du bereits vorgefertigte leere Projekte, die alles 
initialisiert haben, wenn du in deine main gelangst.

Damit hast du:  Richtig konfigurierten Clock inkl. aktivierten Quarz, 
initialisierte Interruptvektoren, "sauberen" RAM (alles mit Nullen 
vorinitialisiert!)

Also bitte die Templates verbwenden, denn bei einem STM32 
Mikrocontroller musst du sehr viel erst vorkonfigurieren, bevor du was 
in der main anstellen kannst.

von grundschüler (Gast)


Lesenswert?

Andre schrieb:
> Ich sehe aber nur 4 passende Register.

Irgendwas scheint aber trotzdem falsch zu sein. Schon um die Fehlersuche 
zu erleichtern würde ich mal den Coide-examplecode mit
   RCC_Configuration();
 und
   GPIO_Configuration();
nehmen.

  RCC->CR = 0x01;
  RCC->CFGR = 0x01;
  RCC->AHBENR = 0x0F;

Ich hab sowas noch nie selbst gemacht. in der Stm-Funktion sind aber 
Warteschleifen drin. Vielleicht haben die doch einen Sinn?

von derjaeger (Gast)


Lesenswert?

Vielleicht ist eine alternative Funktion des Pins aktiviert

von Nop (Gast)


Lesenswert?

Die Delays mit der Warteschleife werden evtl. nicht funktionieren, weil 
die Dummyvariable zwar volatile deklariert ist, dies aber 
funktionslokal. Evtl. optimiert das der Compiler trotz volatile weg. 
Deklarier die lieber als globale Variable.

Mal abgesehen davon, daß man so ein Delay eh über den Systick machen 
würde mit Systemzeit, aber für den ersten Schnellschuß ist ein 
provisorisches Delay ja OK.

Merkwürdig finde ich, daß bei Dir der Init dermaßen einfach ist. Also 
bei den Oszillatoren etwa gehört noch ne Warteschleife dahinter, daß der 
auch wirklich losgegangen ist (RCC_CR abfragen). Das Reference Manual 
enthält oftmals interessante Hinweise, was man wie machen soll.

Bei den Clocks kann's noch sein, daß außer AHB auch noch APB geclockt 
werden muß, das kommt aber auf den Chip an (Datenblatt nachschlagen).

Ich finde den Hinweis auf die HAL mit "nimmt einem alles ab" übrigens 
nicht produktiv. Wenn ein Anfänger sich schon die Mühe macht, den Chip 
wirklich verstehen zu wollen, dann finde ich das positiv bemerkenswert. 
Ist etwas steiniger, ja, aber der Lerneffekt ist weitaus größer, als 
wenn man in der HAL bloß lernt, welche Funktionen man aufrufen soll.

von Ochs vorm Berg (Gast)


Lesenswert?

Nop schrieb:
> Ich finde den Hinweis auf die HAL mit "nimmt einem alles ab" übrigens
> nicht produktiv.

Wer schreibt hier was von HAL? Kein Schwein.

Es wurde nur berechtigterweise "gemeint" doch die SPL und deren
Set-Funktionen zu verwenden.

Ich hoffe du kennst den Unterschied zwischen HAL und SPL?

von derjaeger (Gast)


Lesenswert?

>Ich finde den Hinweis auf die HAL mit "nimmt einem alles ab" übrigens
>nicht produktiv. Wenn ein Anfänger sich schon die Mühe macht, den Chip
>wirklich verstehen zu wollen, dann finde ich das positiv bemerkenswert.

Ist nicht HAL, sondern stdperiph. Und warum soll diese Bibliothek nicht 
lernfördernd sein? Sie ist open-source und dokumentiert und arbeitet 
auch mit Registern, aber mit vielen Defines.

Man kann jederzeit da reinschauen in die Funktionsimplementierung und 
sehen welche Register in welcher Reihenfolge ansteuert werden und sich 
davon insperieren lassen.

Das was der Threadersteller oben gemacht hat, kann er morgen nicht mehr 
nachvollziehen, weil da Bits gesetzt werden, aber die Zugehörigkeit der 
Bits nicht aus dem Code hervorgeht. Wenn er diesen Weg weitergeht, wird 
irgendwann alles zusammenbrechen weil die Komplexität zu groß geworden 
ist.



>Merkwürdig finde ich, daß bei Dir der Init dermaßen einfach ist.

Wenn der Threadersteller ein IDE-Template verwendet hat, kann es sein, 
dass vielleicht vorher etwas schon initialisiert wurde.

Wenn nicht, dann kann es so überhaupt nicht funktionieren. Wo ist z.B. 
die PLL-Konfig (richtigen Multiplikator setzen), Quarzaktivierung?

von Sebastian S. (amateur)


Lesenswert?

Ich kenne den STM32 nicht, aber so weit mir bekannt, kann man bei 
solchen Teilen, mit den Defaults, keine LED beeindrucken.
Üblicherweise sind alle Pins - Reset-Modus - Eingänge und somit sollte 
man zumindest den Gewünschten Port explizit davon überzeugen ein Ausgang 
zu werden.

von derjaeger (Gast)


Lesenswert?

Noch eine kleine Randbemerkung zum Anfangspost:

Die Bibliothek von ST verwenden für die Ausgangspins die folgenden 
Register anstelle von ODR:

->BSRR (Ausgang auf HIGH setzen)
->BRR  (Ausgang auf GND)

Das könnte der folgende Grund sein, da man weniger Instruktionen 
braucht:

but you have to read the ODR register, OR (|) or AND(&) (modify) it with 
a mask and then write it back to the ODR register. This means that at 
the assembly language level, at least three instructions are used to 
set/clear an I/O which can significantly slow down toggling speed. A 
better way would be to use the BSRR register  and the BRR registers for 
setting and clearing pins. They enable 'atomic' access that allows the 
I/O pin to be clear/set in as short a time as possible.

von grundschüler (Gast)


Lesenswert?

Sebastian S. schrieb:
> Port explizit davon überzeugen ein Ausgang

Das hat er wohl:
 GPIOB->MODER = 0x55555555;

von Nop (Gast)


Lesenswert?

derjaeger schrieb:

> Ist nicht HAL, sondern stdperiph.

Spielt keine Rolle.

> Und warum soll diese Bibliothek nicht
> lernfördernd sein? Sie ist open-source und dokumentiert und arbeitet
> auch mit Registern, aber mit vielen Defines.

Weil hier genau schon wieder sowas kam:

"Diese Bibliothek übernimmt die ganze Registerarbeit für dich verpackt 
in
C-Funktionen und Strukturen die du nur noch aufrufen musst."

Auf gut deutsch: man muß sich nicht mit der Hardware befassen, machen 
alles ganz tolle vorgefertigte Funktionen, damit man auch ja nichts über 
den Chip lernen muß. Großartig, und die Konsequenz ist, daß man dann 
blöd dasteht, wenn man einen nicht-ST-Chip bearbeiten soll/will. Oder 
wenn die rottige ST-Software mal wieder nicht das tut, was sie soll.

> Das was der Threadersteller oben gemacht hat, kann er morgen nicht mehr
> nachvollziehen, weil da Bits gesetzt werden, aber die Zugehörigkeit der
> Bits nicht aus dem Code hervorgeht.

Ja klar, das sollte man mit vernünftigen Bitmasken-Defines machen.

> Wenn nicht, dann kann es so überhaupt nicht funktionieren. Wo ist z.B.
> die PLL-Konfig (richtigen Multiplikator setzen), Quarzaktivierung?

Braucht man nicht. Der TE schrieb doch, daß er auf HSI geht, also kein 
Quartz nötig. Sicher hat man dann nur 16 MHz (je nach Chip) und nicht 
den vollen Rums, aber um eine LED blinken zu lassen, langt der HSI auch 
ohne PLL.

von Andre (Gast)


Lesenswert?

Ich habe bisher nur mit 8bittern mit AVR/PIC gearbeitet. Auf dem ersten 
Blick sieht das Datenblatt des STM32 etwas komplexer aber definitiv 
nicht komplizierter aus.

Wo es die Bitmasken Defines gibt ist mir auch noch ein Rätsel. Warum es 
Hersteller wie ST nicht hinbekommen eine übersichtliche Software wie 
Microchip/Atmel zu erstellen ist mir ein Rätsel. Das hat auch mMn nichts 
mit Anfängertum etc. zu tun, sondern mit Benutzerfreundlichkeit. Die ST 
Homepage ist ja nun übertroffen unübersichtlich. Nimm hier eine IDE, 
hier hast du 1000 Bibliotheken, irgendwo gibts auch noch hier ein Paket 
zu finden mit 1000 Programmen.

von jaeger (Gast)


Lesenswert?

>Warum es
>Hersteller wie ST nicht hinbekommen eine übersichtliche Software wie
>Microchip/Atmel zu erstellen ist mir ein Rätsel.

Welche Software? Die IDE? Was hat denn die IDE mit der richtigen 
Programmierung des ARM zu tun?


>Wo es die Bitmasken Defines gibt ist mir auch noch ein Rätsel.

Entschuldige, DU hast doch die Headerdatei eingebunden. Mal reinschauen?


>/*******************  Bit definition for GPIO_MODER register  >*****************/
>#define GPIO_MODER_MODER0          ((uint32_t)0x00000003)
>#define GPIO_MODER_MODER0_0        ((uint32_t)0x00000001)
>#define GPIO_MODER_MODER0_1        ((uint32_t)0x00000002)
>#define GPIO_MODER_MODER1          ((uint32_t)0x0000000C)
>#define GPIO_MODER_MODER1_0        ((uint32_t)0x00000004)


>/*******************  Bit definition for GPIO_OTYPER register  >****************/
>#define GPIO_OTYPER_OT_0           ((uint32_t)0x00000001)
>#define GPIO_OTYPER_OT_1           ((uint32_t)0x00000002)
>#define GPIO_OTYPER_OT_2           ((uint32_t)0x00000004)
>#define GPIO_OTYPER_OT_3           ((uint32_t)0x00000008)
>#define GPIO_OTYPER_OT_4           ((uint32_t)0x00000010)

von Ochs vorm Berg (Gast)


Lesenswert?

Andre schrieb:
> Das hat auch mMn nichts mit Anfängertum etc. zu tun

Doch genau das ist es. Du hast dich noch nicht ausreichend
zurechtgefunden, das "was ist wo" fehlt dir noch.

von Christopher J. (christopher_j23)


Lesenswert?

Andre schrieb:
> RCC->CR = 0x01;

Das ist meiner Meinung nach wirklich sehr unleserlich. Viel besser wäre
1
RCC->CR = RCC_CR_HSION;

Die Bitmasken sind standardisiert nach dem Schema 
PERIPHERIE_REGISTER_FELDBEZEICHNER und entsprechen 1:1 den Abkürzungen 
im Reference Manual.

Andre schrieb:
> RCC->AHBENR = 0x0F;

Auch hier wäre mMn RCC-> AHBENR |= RCC_AHBENR_GPIOBEN; deutlich besser. 
Man sollte auch aufpassen wegen "|=" und "=" und wo sinnvoll, verodern 
statt einen fixen Wert zuzuweisen.

Die HSI-Konfiguration würde ich erstmal komplett weglassen, da der L1 ja 
ab Reset mit 2 MHz MSI läuft.

Warum es bei dir nicht funktioniert kann ich nicht sagen. Es ist gut 
möglich, dass Coocox hinter deinem Rücken schon irgendeine 
Taktkonfiguration vorgenommen hat, wobei ich mir nicht erklären kann 
warum das einen Unterschied machen sollte (abgesehen von der Frequenz 
mit der die LED flackert). Wenn man von einer Taktquelle auf eine andere 
umschaltet sollte man jedenfalls das jeweilige "Ready-Bit" abfragen, da 
es jeweils ein paar Takte dauern kann bis HSI, HSE, PLL und Co 
eingeschwungen sind.

Wenn du dich auf Registerebene mit den STM32 beschäftigen willst und den 
Frustfaktor möglichst gering halten willst, dann würde ich dir die 
STM32-Snippets empfehlen ( 
http://www.st.com/en/embedded-software/stm32snippets.html ), die gibt es 
für die F0 und L0 Serie und sind auf das F072-Discovery bzw. 
L053-Discovery Board zugeschnitten. Letzteres gibt es derzeit in der 
Bucht für ~13€ inkl. Versand 
http://www.ebay.de/itm/Discovery-kit-for-STM32L0-series-with-STM32L053C8-MCU-1-Stuck-/311934443991?hash=item48a0bde1d7:g:8tQAAOSwGrFZiWcP
Bei den "Snippets" wird im Prinzip die komplette Peripherie abgedeckt 
und es gibt zu allem Beispielcode woran man sich orientieren kann. Dazu 
dann noch das Reference-Manual und in relativ kurzer Zeit weißt du was 
die Welt im innersten zusammen hält.

Als IDE würde ich dann für den Einstieg SW4STM32 nehmen. Coocox ist ein 
totes Pferd, bei dem aktuelle Controller-Familien schon nicht mehr 
unterstützt werden und es mehr als zweifelhaft ist ob sich das jemals 
ändern wird. Das gleiche gilt für die so oft gepriesene StdPeriphLib. 
Die L4-Serie wird zum Beispiel nicht unterstützt, was eine Portierung 
von L0 oder L1 sehr schwierig gestalten dürfte.

von Nop (Gast)


Lesenswert?

Grundsätzlich sollte man sich auch überlegen, inwieweit man sich 
überhaupt an eine IDE binden will. Zum Flashen oder gelegentlichen 
graphischen Debuggen ist das sicherlich nützlich, aber den eigentlichen 
Build mache ich lieber mit Scripten.

von Andre (Gast)


Lesenswert?

Mit der SW4STM32 geht es auf Anhieb, auch mit Registern. So habe ich mir 
das vorgestellt - IDE installieren, neues Projekt und ich kann mich auf 
das Programmieren konzentrieren.

von pegel (Gast)


Lesenswert?

Und das hat auch so fantastische Funktionen wie Auto Ergänzung.
Strg + Leertaste

Oder Anzeige der Werte und Funktionen.
mit der Maus drüber oder markieren und F3

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.