Forum: Mikrocontroller und Digitale Elektronik STM32 Systicktimer wert in ms


von Marcel (Gast)


Lesenswert?

Hallo,

ich würde gerne eine Variable mit dem aktuellen Systicktimer Wert 
versehen, welchen ich über die UART versenden mag.

Irgendwie so:
1
int Ticker =0;
2
Ticker = SysTick;
3
4
5
printf("Laufzeit: %i", Ticker);

Sinn und Zweck, ich moechte gerne ueber die UART die Laufzeit des uC 
versenden, zu einem Sensormesswert.

am ende schaut das so aus:

Sample, Sampletime, Messwert1, Messwert2  ..

Habt ihr eine Idee?

Gruss
Marcel

von holger (Gast)


Lesenswert?

>Habt ihr eine Idee?

Beispiel aus der Standard Peripheral Lib ansehen?

von holger (Gast)


Lesenswert?

Übrigends ein 32 Bit Zähler läuft bei 1ms Takt nach ca. 50 Tagen über.

von Marcel (Gast)


Lesenswert?

Und was gibts da fuer moeglichkeiten, diesen vor einem ueberlauf zu 
schuetzen ?

davon abgesehen das dass geraet max. 2 std. lauft

von Verwirrter Anfänger (Gast)


Lesenswert?

Marcel schrieb:
> Und was gibts da fuer moeglichkeiten, diesen vor einem ueberlauf zu
> schuetzen ?
Du könntest dir einen eigenen Zähler bauen, der zaehlt wie oft der 
Systick übergelaufen ist. Du musst dann nur innerhalb von 50 Tagen 
zweimal den Systick abrufen.

von holger (Gast)


Lesenswert?

>> Und was gibts da fuer moeglichkeiten, diesen vor einem ueberlauf zu
>> schuetzen ?
>Du könntest dir einen eigenen Zähler bauen, der zaehlt wie oft der
>Systick übergelaufen ist. Du musst dann nur innerhalb von 50 Tagen
>zweimal den Systick abrufen.

Falsch. Der Systick selber hat nur 24Bit. Der wird benutzt
um einen 1ms Interrupt zu erzeugen. Dort zählst du eine
Variable im 1ms Takt hoch. Wenn 50 Tage zu wenig sind
zählt man halt wenn diese Variable 1000 erreicht hat eine
zweite Variable hoch und setzt die erste auf Null.

von Marcel (Gast)


Lesenswert?

ich hab jetzt folgendes gemacht.

in main eine

volatile int32_t mtime=0;

erstellt und im stm32f10x_it.c im Systick_handler eine funktion erstellt 
die mein mtime hochzaehlt :
1
void SysTick_Handler(void)
2
{
3
  TimValAdd();  
4
}
5
6
7
void TimValAdd(){
8
  
9
  mtime++;
10
  
11
  }

Nur wann passiert der Interrupt denn immer? bzw ist mtime in ms oder us 
?

Ich hab folgendes konfiguriert:
1
  /* Configure HCLK clock as SysTick clock source. */
2
  SysTick_CLKSourceConfig( SysTick_CLKSource_HCLK );
3
4
  /* set SysTick */
5
  SystemCoreClockUpdate();
6
  
7
  SysTick_Config(SystemCoreClock / 100);     /* Generate interrupt each 10 ms */


und meine Delay funktion:

1
 void Delay_us(uint32_t time_us) //Delay in usec
2
{
3
  SysTick->LOAD  = 72 * time_us-1;
4
  /* Load the SysTick Counter Value */
5
  SysTick->VAL   = 0;          
6
  /* Enable SysTick Timer */  
7
  SysTick->CTRL  |= SysTick_CTRL_ENABLE_Msk;                   
8
9
  do
10
  {
11
  } while ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG)==0);
12
  /* Disable SysTick Timer */
13
  SysTick->CTRL  &= ~SysTick_CTRL_ENABLE_Msk;                  
14
  /* Load the SysTick Counter Value */
15
  SysTick->VAL   = 0;                                          
16
}
17
18
19
void Delay(uint16_t time_ms) //Delay in msec
20
{
21
  while (time_ms>0)
22
  {
23
    Delay_us(1000);
24
    time_ms--;
25
  }
26
}

von Marcel (Gast)


Lesenswert?

Alle 10msec oder?

Viele Gruesse!

von holger (Gast)


Lesenswert?

>und meine Delay funktion:

Ersatzlos löschen. Was treibst du da?
Der Systick wird nicht angefasst. Der läuft einfach frei weiter.
Also Finger weg.

Dein Systick Interrupt kommt alle 10ms.

von Marcel (Gast)


Lesenswert?

Ja wie soll denn sonst die Delay funktion gemacht werden oder was meinst 
du bitte schoen mit nicht anfassen?

Meinst du etwa, das ich in den handler geschrieben hab ?

von Marcel (Gast)


Lesenswert?

ok ich hab das jetzt mal nach dem template example von der std. lib 
gemacht
1
void SysTick_Handler(void)
2
{
3
  TimValAdd();
4
  TimingDelay_Decrement();
5
  
6
}


und

in main
1
void Delay(__IO uint32_t nTime)
2
{ 
3
  TimingDelay = nTime;
4
5
  while(TimingDelay != 0);
6
}
7
8
/**
9
  * @brief  Decrements the TimingDelay variable.
10
  * @param  None
11
  * @retval None
12
  */
13
void TimingDelay_Decrement(void)
14
{
15
  if (TimingDelay != 0x00)
16
  { 
17
    TimingDelay--;
18
  }
19
}


dann hab ich ja Delay(wertinMs)

und meine Variable mtime die sich hochzaehlt alle 10msec

von holger (Gast)


Lesenswert?

>Meinst du etwa, das ich in den handler geschrieben hab ?

Du bastelst am Systick rum. Dann kommt der Interrupt
nicht mehr alle 10ms weil du den Systick manipulierst.

Und wieso ist mtime int? Können Zeiten negativ werden?
volatile int32_t mtime=0;

Was willst du eigentlich machen?

von Marcel (Gast)


Lesenswert?

ok, dann uint32_t sorry.

Aber im Example wurde doch auch eine Funktion in den Handler geschrieben 
(systick example fuer Delay funktionen)

Ich wollte urspruenglich einfach nur einen Wert in millisekunden 
ausgeben.

also

uint32_t timer =0;

while(1)
{

//printf ist Ausgabe per USART2
printf("Timer in MSec %i", timer);

}


wie bekomme ich dann >timer< alle 1msec oder 10msec  um eins erhoeht?

VG
Marcel

von Marcel (Gast)


Lesenswert?

oder soll ich dafuer extra einen Timer erstellen der mir nen Interrupt 
erzeugt?

von Verwirrter Anfänger (Gast)


Lesenswert?

Angenommen dein mtime hat eine Auflösung von 1ms, dann wäre die 
einfachste Lösung für einen delay:
1
void SysTick_Handler(void){
2
  TimValAdd();
3
}
4
5
void delayMs(uint32_t delay){
6
  uint32_t end = mtime+delay;
7
  while(mtime < end){
8
    // do nothing
9
  }
10
  return;
11
}

bzw. etwas modularer gehalten
1
void SysTick_Handler(void){
2
  TimValAdd();
3
}
4
5
uint32_t getMs(void){
6
  return mtime;
7
}
8
9
10
void delayMs(uint32_t delay){
11
  uint32_t end = getMs()+delay;
12
  while(getMs() < end){
13
    // do nothing
14
  }
15
  return;
16
}

Das ganze hat noch 2 Probleme:
- Ein Überlauf des Systick timers wird nicht beachtet, falls (mtime + 
end) > 2^32 ist hört die Funktion sofort auf
- Die Funktion ist nur auf 1mS genau. Ein delay(2) kann zwischen 1ms und 
2ms dauern.


Und um die Zeit ab einen beliebigen Start zu messen:
1
uint32_t start = getMs();
2
3
while(1){
4
  //printf ist Ausgabe per USART2
5
  printf("Timer in MSec %i", (getMs() - start));
6
}

von holger (Gast)


Lesenswert?

>Ich wollte urspruenglich einfach nur einen Wert in millisekunden
>ausgeben.

Dann stell den Systick auf 1ms.

>wie bekomme ich dann >timer< alle 1msec oder 10msec  um eins erhoeht?

Entscheide dich mal. Alle 1ms oder alle 10ms?
Du zählst im Systick Interrupt eine Variable hoch.
Deren Wert holst du dir dann in deinem Programm. Fertig.

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.