Forum: Mikrocontroller und Digitale Elektronik STM32: Delay-Routine zu schnell


von Pete K. (pete77)


Lesenswert?

Hallo,

meine Delay-Routine ist zu schnell. Bei einer Eingabe von 10 Sekunden 
mit delay_us(10000000) ist schon nach 5 Sekunden schluss.
1
void delay_us(uint32_t time_us)
2
{
3
  SysTick->LOAD  = (72 * time_us)-1;
4
  SysTick->VAL   = 0;                                          // Load the SysTick Counter Value
5
  SysTick->CTRL  |= SysTick_CTRL_ENABLE_Msk;                   // Enable SysTick Timer
6
7
  do
8
  {
9
  } while ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG)==0);
10
  SysTick->CTRL  &= ~SysTick_CTRL_ENABLE_Msk;                  // Disable SysTick Timer
11
  SysTick->VAL   = 0;                                          // Load the SysTick Counter Value
12
}

Aufruf erfolgt mit:
1
  USART1_SendString("start_delay\n");
2
  delay_us(10000000); //10 Sekunden = 10000ms=1000000µs
3
  USART1_SendString("end_delay\n");

STM32F107RC mit 72Mhz. Kann vielleicht jemand helfen?

von (prx) A. K. (prx)


Lesenswert?

Auch wenn der Prozessor ein 32-Bitter ist, hat der Systick dennoch nur 
24 Bits. Das reicht für ca. 16 Mio Takte. Nicht für 720 Mio.

von Pete K. (pete77)


Lesenswert?

So, noch ein Versuch:
1
volatile uint16_t mult=25;
2
3
// **
4
void delay_init(void)
5
{
6
    RCC_ClocksTypeDef RCC_Clocks;
7
8
    RCC_GetClocksFreq(&RCC_Clocks);
9
    mult=RCC_Clocks.SYSCLK_Frequency/1000000;  
10
11
}
12
13
// **
14
void delay_us(uint32_t time_us)
15
{
16
17
18
  SysTick->LOAD  = (mult * time_us)-1;               // maximum 24 bit after multiplication
19
  SysTick->VAL   = 0;                                          // Load the SysTick Counter Value
20
  SysTick->CTRL  |= SysTick_CTRL_ENABLE_Msk;                   // Enable SysTick Timer
21
22
  do
23
  {
24
  } while ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG)==0);
25
  SysTick->CTRL  &= ~SysTick_CTRL_ENABLE_Msk;                  // Disable SysTick Timer
26
  SysTick->VAL   = 0;                                          // Load the SysTick Counter Value
27
}

Wenn ich das ganze in der main.c so aufrufe:
1
  
2
  delay_init();
3
        
4
  RCC_ClocksTypeDef RCC_Clocks;
5
  
6
  RCC_GetClocksFreq(&RCC_Clocks);
7
  
8
  sprintf(buffer,"SYSCLK: %i \n",RCC_Clocks.SYSCLK_Frequency/1000);
9
  USART1_SendString(buffer);  // hier ist die Ausgabe 25000, da ich einen 25Mhz externen Quarz verwende
10
11
  USART1_SendString("start_delay\n");
12
  delay_us(200000);  // 200ms
13
  delay_us(200000);  // 200ms
14
  delay_us(200000);  // 200ms
15
  delay_us(200000);  // 200ms
16
  delay_us(200000);  // 200ms
17
  USART1_SendString("end_delay\n");
bekomme ich eine Zeitspanne von 8 Sekunden zwischen start_delay und 
end_delay.
Die 200000*25 passen in 24 bit noch hinein.

von (prx) A. K. (prx)


Lesenswert?

Der Systick hat 2 alternative Taktquellen, siehe CLKSOURCE. Eine davon 
ist HCLK und die voreingestellte definiert der Integrator, bei den STM32 
ist das HCLK/8. Passt doch genau.

von Pete K. (pete77)


Lesenswert?

Ok, das passt dann ja, wenn man den LOAD Value noch einmal durch 8 
teilt.

Ich habe im Reference-Manual, bei Keil und im Datenblatt geschaut, aber 
die von Dir gegebene Info nicht gefunden.
Hast Du einen Tipp, welche Doku hier hilfreich sein könnte?

Besten Dank,
Pete

von (prx) A. K. (prx)


Lesenswert?

Pete K. schrieb:
> Hast Du einen Tipp, welche Doku hier hilfreich sein könnte?

Die STM32 Reference: "The RCC feeds the Cortex System Timer (SysTick) 
external clock with the AHB clock (HCLK) divided by 8."

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.