Forum: Mikrocontroller und Digitale Elektronik STM32F103C8, einfacher LED Blinkerei


von GG (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen! Bislang habe ich eigentlich nur uCs á la 328p 
programmiert... und taste mich gerade vorsichtig an einen ARM M3 heran. 
Ich habe mir ein Board und einen Programmer zugelegt (siehe Anhang). 
Nachdem ich mit CooCox diverse Probleme hatte und noch immer habe, bin 
ich auf EmBitz umgestiegen. Hier funktioniert soweit scheinbar alles 
einwandfrei. Zum flashen nutze ich CoFlash von ST (funktioniert wohl 
auch einwandfrei). Nun wollte ich einfach mal eine LED zum blinken 
bringen... doch nun verhält sich der Code recht seltsam und ich weiß 
nicht wieso?!

#include "stm32f10x.h"

int main(void)
{
  unsigned long c = 0;

  SystemInit();

  GPIO_InitTypeDef  GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

    while(1)
    {
      GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET);
      for(c=0;c<100000;c++);

      GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET);
      for(c=0;c<100000;c++);
    }
}

Wenn man die for-Schleifen wie oben gezeigt bis 100000 zählen läßt, ist 
die LED aus! Zählen sie nur bis 1000, leuchtet die LED minimal. Bei 100 
mit etwa 50% Intensität. Bei 10 und 1 hell!

Wieso? Sollte sie nicht immer langsamer blinken, desto größer die Grenze 
gewählt wird? Und noch mal... es blinkt NICHTS! Es verhält sich ehr wir 
ein DAC... ???

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Welche Optimierungsstufe hast du eingestellt?
Ein halbwegs schlauer Compiler optimiert dir die Schleifen einfach raus, 
weil sie am Programmverlauf an sich nichts, sondern nur die 
Programmdauer ändern. Und das primäre Ziel ist eine möglichst kurze 
Programmausführungszeit bei geringem Speicherbedarf.

von GG (Gast)


Lesenswert?

Bullseye!!! :D

Die Optimierung Stand auf Stufe 2. Bei -O0 läuft alles wie gewünscht! 
Perfekt! ... DANKE!

von PascalFan (Gast)


Lesenswert?

ordne es anders an:

    while(1)
    {

      for(c=0;c<100000;c++) GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET);

      for(c=0;c<100000;c++) GPIO_WriteBit(GPIOC, GPIO_Pin_13, 
Bit_RESET);

    }

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

GG schrieb:
> Bullseye!!! :D
Naja, blind geworfen... ;-)

> Die Optimierung Stand auf Stufe 2. Bei -O0 läuft alles wie gewünscht!
Es ist übrigens eine gute Idee, hin- und wieder mal die 
Optimierungsstrategie umzuschalten und zu schauen, ob das Design noch 
"läuft". Sonst erlebt man evtl. beim nächsten Update mit einer neuen 
Compilerversion eine unliebsame Überraschung.

von GG (Gast)


Lesenswert?

Ok, wird gemacht. Dennoch verstehe ich nicht, was da "optimiert" wurde. 
Selbst wenn dem Compiler die for-Schleifen unsinnig erscheinen und er 
diese einfach entfernt hat, hätte die LED unabhängig vom eingestellten 
Wert immer gleich "leuchten" müssen... ???

von 2cents (Gast)


Lesenswert?

ersetze
unsigned long c = 0;
durch
volatile unsigned long c = 0;

dann sollte es mit voller Optimierung auch wieder laufen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

2cents schrieb:
> dann sollte es mit voller Optimierung auch wieder laufen.
Dann sollte man zumindest das c vorher noch zur globalen Variablen 
machen. Denn c ist innerhalb der main-Routine definiert, deshalb 
kann es sich gar nicht (z.B. durch einen Interrupt) von ausserhalb 
ändern. Das weiß der Compiler auch.

GG schrieb:
> Ok, wird gemacht. Dennoch verstehe ich nicht, was da "optimiert" wurde.
Ich sehe mir da immmer das erzeugte Compilat an. Man lernst mit solchen 
Dreizeilern seinen Compiler ganz gut kennen...

von GG (Gast)


Lesenswert?

2cents schrieb:
> ersetze
> unsigned long c = 0;
> durch
> volatile unsigned long c = 0;
>
> dann sollte es mit voller Optimierung auch wieder laufen.

ja, das funktioniert! :)

von Quatschkopf (Gast)


Lesenswert?

Als Delay-Funktion empfehle ich:
1
void Delay(__IO uint32_t nCount)
2
{
3
  while(nCount--)
4
  {
5
  }
6
}

von Jim M. (turboj)


Lesenswert?

Quatschkopf schrieb:
> Als Delay-Funktion empfehle ich:

Leider hat die AFAIK je nach Compiler Optimierungsstufe 
unterschiedliches Delay.

Für konstantes Delay muss man Hardware Timer oder Assembler bemühen.

von Nop (Gast)


Lesenswert?

Delay über Dummy-Operationen war schon vor 30 Jahren Unsinn.

Damals(tm) hatten DOS-Rechner tatsächlich einen Turbo-Knopf, mit dem man 
von 8MHz auf höhere Taktung gehen konnte, für Anwendungen. Weil viele 
Spieleprogrammierer genau diese Methode für die Warteroutinen genutzt 
haben.

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

Nop schrieb:
> Delay über Dummy-Operationen war schon vor 30 Jahren Unsinn.
>
> Damals(tm) hatten DOS-Rechner tatsächlich einen Turbo-Knopf, mit dem man
> von 8MHz auf höhere Taktung gehen konnte, für Anwendungen. Weil viele
> Spieleprogrammierer genau diese Methode für die Warteroutinen genutzt
> haben.


Jim M. schrieb:
>
> Für konstantes Delay muss man Hardware Timer oder Assembler bemühen.

was genau meinst Du mit "Hardware Timern"? Externe RTCs? Jeder 
Prozessortimer leitet sich von der Taktfrequenz ab, also ist Alles, was 
im Controller passiert, bei Änderung der Taktung beeinträchtigt. Das 
passiert aber zumindestens bei Embedded relativ selten, und wenn, 
funktioniert so ziemlich nichts mehr wie erwartet.

WENN schon ein busy waiting, kann man das beim Cortex M über den DWT 
cycle counter machen, dessen Stand abhängig vom Takt immer einen 
verlässlichen Wert liefert. Da die Taktfrequenz i.d. Regel aus dem RCC 
ausgelesen werden kann, ist sogar die Mathematik relativ einfach, das 
erforderliche Delta an Taktzyklen zu einem Delay auch bei sich ändernden 
Taktfrequenzen für ein "absolutes delay" dynamisch zu berechnen, aber 
wie gesagt sind dynamisch variable Taktungen ein eher akademisches 
Problem.

Was Alles natürlich nichts daran ändert, dass busy waiting nur in 
seltenen Fällen eine Berechtigung hat.

von Nico W. (nico_w)


Lesenswert?

Hat der Cortex M1 überhaupt nen DWT? Ist doch afaik erst in nem M3?!?

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

Nico W. schrieb:
> Hat der Cortex M1 überhaupt nen DWT? Ist doch afaik erst in nem M3?!?

guter Punkt, aber wie kommst Du darauf, dass der 32F103xx auf einem M1 
basiert? lt. ST Dokument RM0008 ist das ein M3?

von Nico W. (nico_w)


Lesenswert?

Ruediger A. schrieb:
> lt. ST Dokument RM0008 ist das ein M3?

Ja, da hast du auch wieder recht :)

Ich nutze bei meinem Projekt Assembler für ein kurzes Delay.

Ich nutze den DWT gerne dazu mein Projekt genauer zu betrachten wie 
lange die Funktionen brauchen.

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.