Probleme mit stm32f4 Discovery

Gast #3672171
Lesenswert?

Also langsam kriege ich die Kriese…
Ich habe jetz seit ungefähr einem halben Jahr das STM32F4-Discovery hier 
rumliegen und es bis jetzt noch nicht geschafft ein halbwegs 
anspruchsvolleres Programm dafür zu schreiben. Ich geb zwar zu, dass ich 
mich auch mit ner ganzen Menge anderer Dinge beschäftigt habe, aber 
trotzdem würde ich endlich mal weiterkomen. Meine Probleme liegen zum 
einen darin, dass das mein erster größerer Controller ist(vorher nur 
Arduino und Attiny) und zum anderen, dass ich in Dokumentationen 
ersticke. Ich habe mir mal dass programming manual durchgelesen, aber 
das hat mir nur sehr begrenzt weitergeholfen(nur Asm und hauptsöchlich 
Interrupts). Ab und zu werfe ich auch mal einen Blick ins Reference 
Manual, aber die 1700 Seiten schrecken mich irgendwie ab. Und die 
Periphal Library enthält erstens keine richtige Doku zu den Befehlen(hab 
sowas jedenfalls noch nicht gefunden) und zweitens keinen Beispiele für 
so richtig grundlegende Dinge(und wenn nur mit irgendetwas anderem 
vermischt).
Ich wäre euch wirklich sehr dankbar, wenn ihr mir irgendwie Tipps geben 
könntet, wie ich das besser lernen kann.
Vielleicht hilft auch ein ARM Cortex M4 Grundlagen tutorial weiter?
Gibt es irgendeine ausführliche Beschreibung der PeriphLib?
Gast #3672179
Lesenswert?

Hmm einfach ins kalte Wasser springen und ausprobieren. In der STM 
Firmware-Lib sind auch Beispiele drin. Ausprobieren, freuen und Stück 
für Stück nachvollziehen in Verbindung mit Ref. Manual, wenn du hinter 
die Firmware Lib schauen möchtest und wissen willst, wie es genau 
funktioniert.

http://www.diller-technologies.de/stm32.html

http://mikrocontroller.bplaced.net/wordpress/?page_id=744
#3672430
Lesenswert?

Moin und jein. Es gibt einfach zu viele Möglichkeiten, als dass man mit 
einem allumfassenden Tutorial was reißen könnte. Wenn du das durch 
hättest, hättest du den Anfang wieder vergessen. Learning by doing ist 
meiner Meinung nach auch die beste Methode. Ich kann dir nur ans Herz 
legen, von den Beispielprojekten, sehr gut eignen sich meiner Meinung 
nach die von Uwe (bplaced Link oben). Die sind direkt lauffähig und 
explizit für das STM32F4DISCO und es gibt zu sehr vielen Themen 
Beispiele. Wenn du dann deine eigene Projekte damit machst, wirst du 
hier und da eine etwas andere Funktionalität brauchen und den Code 
anfangen abzuwandeln. Das machst du mit Hilfe der Periph Lib und dem 
Reference Manual. Dann folgt Debugging mit Hilfe eines Blicks in die 
Peripherie Register (ist alles so eingestellt, wie ich es haben wollte) 
und dann irgendwann läufts :)

Übrigens gibt es für die Periph Lib meiner Meinung nach deswegen keine 
Doku, weil der Aufbau und die Beschreibung der Bits/Register in der 
Library selbst steckt. In Kombination mit dem Reference Manual kommt man 
eigentlich gut klar. Wenn man was etwas von Grund auf implementieren 
will, schaut man erst in die entsprechende .h der Periph Lib, schaut was 
die Init Funktion braucht und das dafür nötige Init Struct und dann 
welche anderen Funktionen noch nötig sind. Welche Einstellungen im Init 
Struct etc. dann was bewirken geht meist aus deren Namen schon hervor, 
ansonsten schaut man halt ins RefMan. Damit man mit dem Konzept klar 
kommt, welches sich nach einer gewissen Nutzung, jedenfalls meiner 
Meinung nach, als echt gut herausstellt, hangelt man sich am besten an 
Tutorials/Beispielen entlang.

Versuch es einfach mal anhand der Beispiele und berichte.

Liebe Grüße, Jan
Gast #3672538
Lesenswert?

Okay, ich werde mit den Beispielen von BPlaced.net probieren und 
berichte wie's läuft.
aber eine Frage habe ich noch: Läuft das bei allen ARM-Mikrocontrollern 
so, oder ẃie macht man das bei den anderen µC?
#3672550
Lesenswert?

Ich kenne mich, abgesehen von den STs, leider nur mit alten NXP ARM7s 
aus. Da habe ich direkt auf den Registern gearbeitet, was nicht wirklich 
angenehm war (Es ist meiner Meinung nach wie ein Bücherregal mit Büchern 
auf deren Rücken die ISBN Nummern statt dem Titel stehen: Nervig). Der 
Quellcode ist daher auch schnell unverständlich. Außer natürlich man 
steckt viel Zeit rein alles in defines etc. zu beschreiben, aber Zeit 
(bzw. Lust dazu ;) hat man ja meist nicht.

Wie die Libraries anderer Hersteller für ihre ARMs ist, weiß ich nicht. 
Die CMSIS gibt es aber quasi für jeden ARM und in der Grundstruktur 
sollte es daher schon zumindest ähnlich sein.

Wünsche dir viel Erfolg!
Gast #3672986
Lesenswert?

Also ich habe jetzt so ne Idee wofür die sein könnten, aber wo liegt der 
Unterschied zwischen den beiden?
1
  __IO uint16_t BSRRL;    /*!< GPIO port bit set/reset low register,  Address offset: 0x18      */
2
  __IO uint16_t BSRRH;    /*!< GPIO port bit set/reset high register, Address offset: 0x1A      */
 /stm32f4xx.h/
reagiert das eine nur wenn Low und das andere nur wenn High, oder 
andersrum? Was bedeutet das Address offset da am ende(zieht sich durch 
den ganzen Header)?
#3672990
Lesenswert?

stm32f4er schrieb:
> Also ich habe jetzt so ne Idee wofür die sein könnten, aber wo liegt der
> Unterschied zwischen den beiden?
>
1
  __IO uint16_t BSRRL;    /*!< GPIO port bit set/reset low register, 
2
> Address offset: 0x18      */
3
>   __IO uint16_t BSRRH;    /*!< GPIO port bit set/reset high register, 
4
> Address offset: 0x1A      */
 /stm32f4xx.h/
> reagiert das eine nur wenn Low und das andere nur wenn High, oder
> andersrum? Was bedeutet das Address offset da am ende(zieht sich durch
> den ganzen Header)?

Steht alles im Refernce Manual: 
http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00031020.pdf
#3673003
Lesenswert?

stm32f4er schrieb:
> Also ich habe jetzt so ne Idee wofür die sein könnten, aber wo
> liegt der
> Unterschied zwischen den beiden?  __IO uint16_t BSRRL;    /*!< GPIO port
> bit set/reset low register,  Address offset: 0x18      */
>   __IO uint16_t BSRRH;    /*!< GPIO port bit set/reset high register,
> Address offset: 0x1A      */ /stm32f4xx.h/
> reagiert das eine nur wenn Low und das andere nur wenn High, oder
> andersrum? Was bedeutet das Address offset da am ende(zieht sich durch
> den ganzen Header)?

Das ist ganz einfach
Also das BSRR-Register ist eigentlich ein 32Bit-Register.
Hier ist es in zwei 16Bit Register unterteilt worden.
BSRRL sind die untersten 16Bit von BSRR.
BSRRH sind die obersten 16Bit von BSRR.

Für was sind die Register gut?
Damit kann man atomar (also ohne die anderen Bits zu stören) einzelne 
Portbits setzen oder löschen.

Wenn du einen Wert in BSRRL schreibst, dann wird für jedes 1-Bit das 
entsprechente Portbit gsetzt. Dort wo ein Bit im BSRRL Null ist, tritt 
keine Änderung auf. Es dient also alleinig zum setzen von Bits.

Wenn du einen Wert in BSRRH schreibst, dann wird für jedes 1-Bit das 
entsprechente Portbit gelöscht. Dort wo ein Bit im BSRRH Null ist, 
tritt keine Änderung auf. Es dient also alleinig zum löschen von Bits.
#3673011
Lesenswert?

stm32f4er schrieb:
> Also ich finde da keine genaue Beschreibung zu BSRRx und Adress offset.
> Wäre schön, wenn du den(oder die) Auszug(Auszüge) hier posten könntest.

Seite 218. Weshalb auch immer wurde in den Registerdefinitionen das 
32bit-Register auf zwei 16bit-Register aufgeteilt. Der Address offset 
gibt an, an welcher Stelle im Speicher sich das Register relativ zur 
Basis-Adresse der Peripherieinheit befindet. Wie du siehst, stimmt die 
Angabe von Registerdefinition und Reference manual überein. BSSRL liegt 
an der Adresse des 32bit Registers aus dem Handbuch (0x18), BSSRH dann 
logischerweise 2bytes darüber (0x18+2=0x1A).
Gast #3673016
Lesenswert?

Also noch mal zum Verständnis: wenn ich den Befehl GPIOD->BSRRL = 0x1000 
ausführe, dann wird also das Bit an Port 4096 auf 1 gesetzt?

Detlef Kunz schrieb:
> Dort wo ein Bit im BSRRL Null ist, tritt
> keine Änderung auf.

Das verstehe ich allerdings nicht. Wenn ich ein Bit setze, muss doch da 
vorher Null gestanden haben?
Und was ist Adress offset?
Gast #3673026
Lesenswert?

> Seite 218.
Bei mir steht da weder was über BSRR, noch über Address offset, sondern 
über Clock-Out Capability.

Lukas K. schrieb:
> Der Address offset
> gibt an, an welcher Stelle im Speicher sich das Register relativ zur
> Basis-Adresse der Peripherieinheit befindet.
Okay, vielen Dank das habe ich jetzt verstanden.
#3673031
Lesenswert?

@ stm32f4er (Gast)

>Also noch mal zum Verständnis: wenn ich den Befehl GPIOD->BSRRL = 0x1000
>ausführe, dann wird also das Bit an Port 4096 auf 1 gesetzt?

Nein. PORT D15 wird auf 1 gesetzt.

>> Dort wo ein Bit im BSRRL Null ist, tritt
>> keine Änderung auf.

>Das verstehe ich allerdings nicht. Wenn ich ein Bit setze, muss doch da
>vorher Null gestanden haben?

Nein. Es kann auch vorher schon 1 sein.

>Und was ist Adress offset?

Eine Differenz zu Basisadresse.
#3673033
Lesenswert?

stm32f4er schrieb:
> Also noch mal zum Verständnis: wenn ich den Befehl GPIOD->BSRRL =
> 0x1000
> ausführe, dann wird also das Bit an Port 4096 auf 1 gesetzt?
>
> Detlef Kunz schrieb:
>> Dort wo ein Bit im BSRRL Null ist, tritt
>> keine Änderung auf.

GPIOD -> BSRRL = 0x1000;
im Parameter ist Bit13 gesetzt;
Ergebnis:  PD13 auf H setzen, alle anderen Portausgänge bleiben 
unverändert


GPIOD -> BSRRL = 0x1001;
im Parameter ist Bit13 und Bit0 gesetzt;
Ergebnis: PD13 und PD0 auf H setzen, alle anderen Portausgänge bleiben 
unverändert


GPIOD -> BSRRH = 0x0001;
im Parameter ist Bit0 gesetzt;
Ergebnis: PD0 auf L setzen, alle anderen Portausgänge bleiben 
unverändert
#3673035
Lesenswert?

Oder noch  einfacher:

BSRRL enthält 16 EIN-Schalter, einen für jeden Portausgang.
Betätigs Du einen dieser Schalter, dann wird der Ausgang eingeschaltet.

BSRRH enthält dementsprechend 16 AUS-Schalter.
Betätigs Du einen dieser Schalter, dann wird der Ausgang ausgeschaltet.
Gast #3673148
Lesenswert?

Und weiter geht die fragerei ;-)
1.)Wie kommt es, dass ich an den Ausgängen knapp 3V messe? Da müssten 
doch eigentlich 5V oder zumindest 3.3V rauskommen?
2.) Wieso schaltet folgende Zeile den Ausgang nicht auf HIGH?
GPIOD -> BSRRL = GPIO_Pin_0;
#3673156
Lesenswert?

>>1.)Wie kommt es, dass ich an den Ausgängen knapp 3V messe? Da müssten
>>doch eigentlich 5V oder zumindest 3.3V rauskommen?

Eigenartig, bei mir kommen 0V raus.

>>2.) Wieso schaltet folgende Zeile den Ausgang nicht auf HIGH?
>>GPIOD -> BSRRL = GPIO_Pin_0;

Vielleicht, weil die Zeile hier im Forum steht?
#3673158
Lesenswert?

@ stm32f4er (Gast)

>1.)Wie kommt es, dass ich an den Ausgängen knapp 3V messe?

Reicht das nicht?

>Da müssten
>doch eigentlich 5V oder

Nö, der STM32 kann nur 3,3V IO.

> zumindest 3.3V rauskommen?

Wieviel kommt denn GENAU raus? Was hängt an den IOs?

>2.) Wieso schaltet folgende Zeile den Ausgang nicht auf HIGH?
>GPIOD -> BSRRL = GPIO_Pin_0;

Wahrscheinlich ist dein IO-Pin nicht als Ausgang konfiguriert.
Gast #3673192
Lesenswert?

Jaja mit der geht es. Und so wieich es beschrieben hatte, geht es auch. 
Ich war nur zu dumm um GPIOD in GPIOA umzuwandeln. Benutzt man ein 
einziges Mal im gesamten Code Copy&Paste, hat man sofort nen Fehler ;-)
#3674543
Lesenswert?

Naja, IDR Register liest du. Es wirft dir für den ganzen Port die Daten 
entgegen. Wenn dich nur ein Pin daraus interessiert, musst du eben mit 
dem & auswählen, welcher das ist.
Auf das BSRRL/H Register schreibst du außerdem, daher der = Operator. 
Und da setzt du dann eben auch die Bits die du verändern willst.
Gast #3677440
Lesenswert?

Ich bin am verzweifeln. Ich habe hier zwei Programme: Das eine benutzt 
den User Button, um die LED's auf dem Board anzuschalten, und das andere 
den Button, um externe LEd's anzuschalten. Beide sehen für mich völlig 
identisch aus(naja, wenn man mal von den anderen Ports ausgeht usw.)
Hier der funktionierende Code:
1
#include "stm32f4xx_conf.h"
2
#include "stm32f4xx.h"
3
 
4
void init_app(void) {
5
  
6
  
7
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
8
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
9
  GPIO_InitTypeDef  pins;
10
  
11
  pins.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
12
  pins.GPIO_Mode = GPIO_Mode_OUT;
13
  pins.GPIO_OType = GPIO_OType_PP;
14
  pins.GPIO_Speed = GPIO_Speed_100MHz;
15
  pins.GPIO_PuPd = GPIO_PuPd_NOPULL;
16
  GPIO_Init(GPIOD, &pins);
17
 
18

19
  
20
  pins.GPIO_Pin   = GPIO_Pin_0;
21
  pins.GPIO_Mode  = GPIO_Mode_IN;
22
  pins.GPIO_OType = GPIO_OType_OD;
23
  pins.GPIO_Speed = GPIO_Speed_25MHz;
24
  pins.GPIO_PuPd  = GPIO_PuPd_DOWN;
25

26
  GPIO_Init(GPIOA, &pins);
27
}
28
 
29
int main(void) {
30
  SystemInit();
31
  init_app();
32
  while(1) {
33
    if (GPIOA->IDR & 0x0001) {
34
      GPIOD -> BSRRH = 0x1000 | 0x2000 | 0x4000 | 0x8000;
35
    }
36
    else {
37
      GPIOD -> BSRRL = 0x1000 | 0x2000 | 0x4000 | 0x8000;
38
    }
39
  }
40
  return 0;
41
}
Und hier der nicht funktionierende Code:
1
#include "stm32f4xx.h"
2
#include "stm32f4xx_conf.h"
3

4
void init_app(void);
5

6
int main(void){
7
  SystemInit();
8
  init_app();
9
  while(1){
10
     if(GPIOA -> IDR & 0x0001){
11
      GPIOC -> BSRRL = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
12
    }
13
    else{
14
      GPIOC -> BSRRH = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
15
    }
16
  return 0;
17
  }
18
}
19

20
void init_app(void){
21
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
22
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
23
  GPIO_InitTypeDef pins;
24
  pins.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
25
  pins.GPIO_Mode = GPIO_Mode_OUT;
26
  pins.GPIO_OType = GPIO_OType_PP;
27
  pins.GPIO_Speed = GPIO_Speed_100MHz;
28
  pins.GPIO_PuPd = GPIO_PuPd_NOPULL;
29
  GPIO_Init(GPIOC, &pins);
30

31
  
32
  pins.GPIO_Pin   = GPIO_Pin_0;
33
  pins.GPIO_Mode  = GPIO_Mode_IN;
34
  pins.GPIO_OType = GPIO_OType_OD;
35
  pins.GPIO_Speed = GPIO_Speed_25MHz;
36
  pins.GPIO_PuPd  = GPIO_PuPd_DOWN;
37
  GPIO_Init(GPIOA, &pins);
38
}
#3677518
Lesenswert?

Schau' mal in das Reference Manual/Datenblatt deines Prozessors. Da gibt 
es eine Tabelle "Alternate Functions". Vielleicht liegen auf deinen Pins 
schon andere Funktionen und du musst erst die Alternate Function korrekt 
als GPIO (etwa anstelle von SPI, RAM-Anbindung, I2C, Timer, ...) 
einstellen.

Sind die LEDs auch korrekt angeschlossen? Leuchtdioden glimmen nur bei 
Stromfluss in eine bestimmte Richtung.

Edit: Für Suchfaule auch hier wieder ein Link auf dem Silbertablett, mit 
einem Löffelchen Puderzucker obendrauf - 
http://kornakprotoblog.blogspot.de/2012/01/pinout-spreadsheet-for-stm32f4.html
Gast #3677532
Lesenswert?

Der funktionierende Code

    if (GPIOA->IDR & 0x0001) {
      GPIOD -> BSRRH = 0x1000 | 0x2000 | 0x4000 | 0x8000;

Der nicht funktionierende Code

     if(GPIOA -> IDR & 0x0001){
      GPIOC -> BSRRL = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;


Oben BSRRH, unten BSRRL. Könnte es daran liegen?
Gast #3677658
Lesenswert?

Stimmt, das war jetzt echt ein total be**** Fehler. Da hätte man auch 
selber drauf kommen können :(
Aber der gdb zeigte mir aber immer an, das Programm würde noch 
laufen('continue' beendete sich nicht, wie nach reset). Ist das normal?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren