Forum: Mikrocontroller und Digitale Elektronik delay(ms) funktioniert nicht


von ratloser_stm_user (Gast)


Lesenswert?

Da ich noch ein ziemlicher Anfänger mit dem STM32F4 Discovery bin, 
probiere ich im Moment eine Delay Funktion aus, die solange in einer 
Schleife nichts tut, bis ein counter unter 0 ist. Dieser wird im 
SysTickHandler() runtergezählt.
folgendes Problem: Diese Schleife wird irgendwie endlos ausgefürt, 
jedenfalls gehen die LED's nich wieder an.
Hier der Quellcode:
1
#include "stm32f4xx_conf.h"
2
#include <stdio.h>
3
#include <stddef.h>
4
#include <stdlib.h>
5
#include "stm32f4xx.h"
6
7
signed int counter = 100;
8
9
//delay funktion abhängig von SysTick_Config
10
void delay(signed int ms){
11
  counter = ms;  
12
  while(counter > 0){
13
    
14
  }
15
  counter = ms;
16
}
17
18
void initApplication()
19
{
20
  SysTick_Config(SystemCoreClock/1000);
21
  // GPIOD Periph clock enable
22
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
23
  GPIO_InitTypeDef  GPIO_InitStructure;
24
  // Konfigurire PD12,13,14,15 als Ausgang
25
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
26
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
27
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
28
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
29
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
30
  GPIO_Init(GPIOD, &GPIO_InitStructure);
31
}
32
 
33
int main(void) {
34
  SystemInit();
35
  initApplication();
36
  while(1) {
37
      GPIO_ResetBits(GPIOD,GPIO_Pin_15);
38
      GPIO_ResetBits(GPIOD,GPIO_Pin_14);
39
      GPIO_ResetBits(GPIOD,GPIO_Pin_13);
40
      GPIO_ResetBits(GPIOD,GPIO_Pin_12);
41
      delay(100);
42
      GPIO_SetBits(GPIOD,GPIO_Pin_15);
43
      GPIO_SetBits(GPIOD,GPIO_Pin_14);
44
      GPIO_SetBits(GPIOD,GPIO_Pin_13);
45
      GPIO_SetBits(GPIOD,GPIO_Pin_12);
46
      delay(100);
47
  }
48
  return 0;
49
}
50
void SysTick_Handler(void) {
51
  --counter;
52
}
Ich wäre euch sehr dankbar, wenn ihr eine Lösung für dieses Problem 
hättet.

PS: OS ist Ubuntu 13.10 mit arm-none-eabi und st-link
    Beide Programme sind in der Kommandozeile zuhause, also sthet mir 
keine IDE zur Verfügung.

von Peter II (Gast)


Lesenswert?

machen mal die Variabel volatile, sonst wird sie wegoptimiert.

volatile signed int counter = 100;

von Mike (Gast)


Lesenswert?

Volatile ?

von holger (Gast)


Lesenswert?

>Ich wäre euch sehr dankbar, wenn ihr eine Lösung für dieses Problem
>hättet.

Ein Counter der negativ wird ist Quatsch. Es reicht ihn auf
Null zu zählen.
1
volatile uint32_t counter;
2
3
//delay funktion abhängig von SysTick_Config
4
void delay(uint32_t ms)
5
{
6
  counter = ms;  
7
  while(counter);
8
}
9
10
void SysTick_Handler(void)
11
{
12
  if(counter) counter--;
13
}

Und schon ist der Drops gelutscht;)

von holger (Gast)


Lesenswert?

Einen Nachteil hat die Geschichte allerdings.
Wenn der Systick Interrupt kurz bevor steht
und man ein delay(1); macht wird das delay
keine ganze Millisekunde dauern. Das Teil kann auch sofort
zurückkommen;)

von ratloser_stm_user (Gast)


Lesenswert?

Vielen Dank. Jetzt funktioniert das ganze prima.

holger schrieb:
> Einen Nachteil hat die Geschichte allerdings.
> Wenn der Systick Interrupt kurz bevor steht
> und man ein delay(1); macht wird das delay
> keine ganze Millisekunde dauern. Das Teil kann auch sofort
> zurückkommen;)

Das dürfte doch kein Problem mehr sein, wenn ich die SysTickClock auf
1
 SysTick_Config(SystemCoreClock/1000 - 1);
 seze, oder?

(nicht mehr) ratloser_stm_user

PS: was macht volatile eigentlich genau?? Ich weiß nur, dass auf die 
Varablen anders zugegriffen wird, um sie aktuell zu halten.
Und vor allem warum und was optimieren die Funktionen?

von Ingo (Gast)


Lesenswert?

Ich würde in deiner Delay Funktion einfach nochmal ne ms drauf 
addieren...

von Dr. Sommer (Gast)


Lesenswert?

Besser so
1
//delay funktion abhängig von SysTick_Config
2
void delay(uint32_t ms) {
3
   counter = ms;
4
   while(counter) __WFI ();
5
}
Zum Heizleistung einzusparen.

von ratloser_stm_user (Gast)


Lesenswert?

Dr. Sommer schrieb:
> __WFI ();

Was ist das denn??

von ratloser_stm_user (Gast)


Lesenswert?

ratloser_stm_user schrieb:
> PS: was macht volatile eigentlich genau?? Ich weiß nur, dass auf die
> Varablen anders zugegriffen wird, um sie aktuell zu halten.
> Und vor allem warum und was optimieren die Funktionen?
Kann mir hierauf jmd einen Link oder eine Antwort geben?

von N.G. (Gast)


Lesenswert?

Schau ins FAQ hier
Der Abschnitt heißt: was hat es mit volatile auf sich?
Sry, dass ich den link grad net da hab

von Dr. Sommer (Gast)


Lesenswert?

ratloser_stm_user schrieb:
> Dr. Sommer schrieb:
>> __WFI ();
>
> Was ist das denn??
Wait For Interrupt. Legt den Core schlafen bis ein Interrupt - wie der 
SysTick Interrupt - kommt. So muss er nicht mit 168 MHz nichts tun. 
Reduziert den Stromverbrauch um Größenordnungen...
Siehe S. 683 im ARM v7-M Architecture Reference Manual.

von ratloser_stm_user (Gast)


Lesenswert?

N.G. schrieb:
> Schau ins FAQ hier

Jo vielen Dank, jetz hab ichs verstanden.

Dr. Sommer schrieb:
> Wait For Interrupt. Legt den Core schlafen bis ein Interrupt

also im rinzip nicts anderes als wenn ichs net hinschreibe, nur dass der 
Prozessor schläft(also nichts verbraucht).
1.)Aber wenn er den Prozessor nur zu irgendeinem Interrupt hochfährt, 
kann das doch irgendein X-beliebiger sein, oder?
2.)Wenn der Prozessor aus dem Interrupt rausgeht, wird im Ablauf normal 
fortgefahren?

von Dr. Sommer (Gast)


Lesenswert?

ratloser_stm_user schrieb:
> also im rinzip nicts anderes als wenn ichs net hinschreibe, nur dass der
> Prozessor schläft(also nichts verbraucht).
Ja.
> 1.)Aber wenn er den Prozessor nur zu irgendeinem Interrupt hochfährt,
> kann das doch irgendein X-beliebiger sein, oder?
Ja, er wacht bei allen Interrupts auf. Wenn kein Interrupt-Handler 
definiert ist wird er wie ohne Verwendung von __WFI() auch abstürzen 
(einer der Error-Handler wird aufgerufen).
> 2.)Wenn der Prozessor aus dem Interrupt rausgeht, wird im Ablauf normal
> fortgefahren?
Wenn alle Interrupts abgehandelt sind kehrt __WFI() zurück; in diesem 
Fall wird es direkt wieder aufgerufen wegen der Schleife bzw.

von ratloser_stm_user (Gast)


Lesenswert?

Dr. Sommer schrieb:
> ratloser_stm_user schrieb:
>> also im rinzip nicts anderes als wenn ichs net hinschreibe, nur dass der
>> Prozessor schläft(also nichts verbraucht).
> Ja.
>> 1.)Aber wenn er den Prozessor nur zu irgendeinem Interrupt hochfährt,
>> kann das doch irgendein X-beliebiger sein, oder?
> Ja, er wacht bei allen Interrupts auf. Wenn kein Interrupt-Handler
> definiert ist wird er wie ohne Verwendung von __WFI() auch abstürzen
> (einer der Error-Handler wird aufgerufen).
>> 2.)Wenn der Prozessor aus dem Interrupt rausgeht, wird im Ablauf normal
>> fortgefahren?
> Wenn alle Interrupts abgehandelt sind kehrt __WFI() zurück; in diesem
> Fall wird es direkt wieder aufgerufen wegen der Schleife bzw.

Das heißt, dass ich ihn lieber nicht benutze, nur um ein paar mA zu 
sparen...
Nicht dass ich dann beim nächsten Interrupt hier die nächste Frage 
stelle.

von Dr. Sommer (Gast)


Lesenswert?

ratloser_stm_user schrieb:
>>> 2.)Wenn der Prozessor aus dem Interrupt rausgeht, wird im Ablauf normal
>>> fortgefahren?
>> Wenn alle Interrupts abgehandelt sind kehrt __WFI() zurück; in diesem
>> Fall wird es direkt wieder aufgerufen wegen der Schleife bzw.
>
> Das heißt, dass ich ihn lieber nicht benutze, nur um ein paar mA zu
> sparen...
Was warum nicht?! Es ist funktional kein Unterschied zu ohne Nutzung 
von __WFI() da, es braucht nur weniger Strom und vermeidet das sehr 
intensive Tun von nichts.
> Nicht dass ich dann beim nächsten Interrupt hier die nächste Frage
> stelle.
Wieso das? Du verwendest alle Interrupts einfach ganz normal wie immer.

von ratloser_stm_user (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Wieso das? Du verwendest alle Interrupts einfach ganz normal wie immer.

jaja, Denkfehler.

Vielen Dank für alle Antworten

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.