10-Systick-Library (STM32F4)

-diese Library bindet den System-Counter ein. Der CPU-Systick wird auf 1us (bzw. 1ms) eingestellt und dann per Interrupt bearbeitet.

-in den Defines kann zwischen us und ms Auflösung umgestellt werden
(falls für die Pausen und Timer ein ms-Raster reicht)

-mit der Library können verschiedene Pausenfunktionen realisiert werden
(im us, ms, sek Raster)

-und zwei Software Timer können gestartet und zyklisch abgefragt werden.
(theoretisch können noch beliebig viele zusätzliche SW-Timer hinzugefügt werden)

-mit den Software-Countern kann eine Zeitspanne gemessen werden. Der Counter wird an einem Punkt bei 0 gestartet und kann dann irgendwann abgefragt werden, wieviel Zeit (in us,ms,sec) vergangen ist.

Voraussetzungen :

1
2
Benutzte Module der CooCox-IDE : keine
Benutzte Librarys : keine

Enumerationen :

1
2
3
4
5
6
7
typedef enum {
  TIMER_STOP =0,  // Timer stoppen und rücksetzen
  TIMER_START_us, // Timer starten im us-Mode
  TIMER_START_ms, // Timer starten im ms-Mode
  TIMER_START_s,  // Timer starten im s-Mode
  TIMER_CHECK     // Test ob Timer abgelaufen
}TIMER_STATUS_t;

.

1
2
3
4
typedef enum {
  TIMER_HOLD =0,  // Timer ist abgelaufen
  TIMER_RUN       // Timer läuft noch
}TIMER_CHECK_t;

.

1
2
3
4
5
6
7
typedef enum {
  COUNTER_STOP =0,  // Counter stoppen
  COUNTER_START_us, // Counter starten im us-Mode
  COUNTER_START_ms, // Counter starten im ms-Mode
  COUNTER_START_s,  // Counter starten im s-Mode
  COUNTER_CHECK     // Test wieviel Zeit vergangen
}COUNTER_STATUS_t;

Funktionen :

1
2
3
4
5
6
7
8
void UB_Systick_Init(void);                                            // zum init vom Systick
void UB_Systick_Pause_us(__IO uint32_t pause);                         // für eine Pause von x usek
void UB_Systick_Pause_ms(__IO uint32_t pause);                         // für eine Pause von x msek
void UB_Systick_Pause_s(__IO uint32_t pause);                          // für eine Pause von x sek
TIMER_CHECK_t UB_Systick_Timer1(TIMER_STATUS_t status, uint32_t wert); // zum starten und auslesen von Systick-Timer1
TIMER_CHECK_t UB_Systick_Timer2(TIMER_STATUS_t status, uint32_t wert); // zum starten und auslesen von Systick-Timer2
uint32_t UB_Systick_Counter1(COUNTER_STATUS_t status);                 // zum starten und auslesen von Systick-Counter1
uint32_t UB_Systick_Counter2(COUNTER_STATUS_t status);                 // zum starten und auslesen von Systick-Counter1

Beispiel :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//--------------------------------------------------------------
// File     : main.c
// Datum    : 22.02.2013
// Version  : 1.0
// Autor    : UB
// EMail    : mc-4u(@)t-online.de
// Web      : www.mikrocontroller-4u.de
// CPU      : STM32F4
// IDE      : CooCox CoIDE 1.7.0
// Module   : CMSIS_BOOT, M4_CMSIS_CORE
// Funktion : Demo der Systick-Library
// Hinweis  : Diese zwei Files muessen auf 8MHz stehen
//              "cmsis_boot/stm32f4xx.h"
//              "cmsis_boot/system_stm32f4xx.c"
//--------------------------------------------------------------
 
#include "main.h"
#include "stm32_ub_systick.h"
#include "stm32_ub_led.h"
 
int main(void)
{
  SystemInit(); // Quarz Einstellungen aktivieren
 
  UB_Systick_Init(); // init vom System-Counter
 
  UB_Led_Init(); // init der LEDs
 
  while(1)
  {
    // 200ms Pause (per Systick)
    UB_Systick_Pause_ms(200);
    // LED toggeln
    UB_Led_Toggle(LED_GREEN);
 
    // Test ob Systick-Timer1 abgelaufen ist
    if(UB_Systick_Timer1(TIMER_CHECK,0)==TIMER_HOLD) {
      // LED toggeln
      UB_Led_Toggle(LED_RED);
      // Timer wieder starten (mit 800 ms)
      UB_Systick_Timer1(TIMER_START_ms,800);
    }
  }
}

Hier die Library zum Download :

ub_stm32f4_systick_v104

Hier der komplette CooCox-Projektordner zum Download :

Demo_10_Systick

11 Antworten auf 10-Systick-Library (STM32F4)

  1. Tom sagt:

    Ich teste gerade deine Systick Library.
    Folgendes Problem habe ich festgestellt. Kommentiere ich bei mir SystemInit() aus, sind die Signalverläufe am Oszi wie erwartet, d.h. die Pausenzeiten werden perfekt eingehalten. Mache ich vorab das SystemInit() sind alle Pausenzeiten um den Faktor 10 zu kurz (daraus resultierende Frequenzen zu hoch). Irgend eine Idee an was das liegen kann?
    “cmsis_boot/stm32f4xx.h”
    “cmsis_boot/system_stm32f4xx.c” –> sind eventuell diese Files eine Fehlerquelle?

    • admin_ub sagt:

      was ist den für ein Systemclock eingestellt ? In den beiden Files muss die Angabe vom angeschlossenen externen Quarz stimmen. Wo hast du den die Files her ? Vergleich sie mal mit denen aus meinem Projekt…die sind an das Discovery-Board angepasst.

  2. Thomas55 sagt:

    Danke für diese Arbeit. Das hat mir sehr geholfen.

  3. Jackob sagt:

    Guten Abend,
    Erstmals vielen Dank für die tolle Librarys .
    Ich versuche seit 3 Stunden ohne Erfolg das untere Programm im Lauf zu bringen. Mit dem Library 10 hat eine Kollision entstanden sowie mit dem Code unteren lässt sich die externe Interrupt ganz gut funktionieren aber die LEDs lassen sich durcheinander togglen und manchmal gar nicht. das passiert nur wenn ich systick mit dem externe Interrupt in einem Code integriere.

    ich wäre sehr Dankbar wenn jemaden mir hilft den Fehler zu erkennen.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    
    #include "stm32_ub_uart.h"
    #include "stm32_ub_string.h"
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
     
     
    //===========================================================
    void init_externe_Intr(){
     
      GPIO_InitTypeDef GPIO_InitStructure;
      EXTI_InitTypeDef EXTI_InitStructure;
      NVIC_InitTypeDef NVIC_InitStructure;
     
      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD |  RCC_AHB1Periph_GPIOC , ENABLE);
     
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
      GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
      GPIO_Init(GPIOD, &GPIO_InitStructure);
     
      // Enable SYSCFG clock
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
     
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
      GPIO_Init(GPIOC, &GPIO_InitStructure);
     
      SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource0);
     
      EXTI_InitStructure.EXTI_Line = EXTI_Line0;
      EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
      EXTI_InitStructure.EXTI_Trigger =  EXTI_Trigger_Rising_Falling;
      EXTI_InitStructure.EXTI_LineCmd = ENABLE;
      EXTI_Init(&EXTI_InitStructure);
     
     
      NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
      NVIC_Init(&NVIC_InitStructure);
    }
     
    BitAction wert;
     
    //=======================================================================
    int main(void)
    {
    SysTick_Config(SystemCoreClock/100);
    init_externe_Intr();
    SystemInit(); 
    UB_Uart_Init();
     
     
     while(1)
      {
     
     
     if (TIM_GetCounter(TIM6) == 25)
     GPIO_ToggleBits(GPIOD,GPIO_Pin_15);
     if (TIM_GetCounter(TIM6) == 50)
     GPIO_ToggleBits(GPIOD,GPIO_Pin_14);
     
     if (TIM_GetCounter(TIM6) == 100)
     GPIO_ToggleBits(GPIOD,GPIO_Pin_13);
     if (TIM_GetCounter(TIM6) == 200)
     GPIO_ToggleBits(GPIOD,GPIO_Pin_12);
      }
    }
    //===================================================================================================
    void SysTick_Handler(void)
    {
    //leer
     
    }
    //===================================================================================================
    void EXTI0_IRQHandler(void){
     
     
    wert= GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_0);
    sprintf(STRING_BUF,"%d",wert);
    UB_Uart_SendString(COM3, STRING_BUF, LFCR);
     
    }

  4. Cortex-Einsteiger sagt:

    Du benutzt Timer 6 um die Leds zu toggeln, dabei wird Timer 6 nirgendwo eingerichtet.
    Zusätzlich schreibst du von der Sys-Tick Library (10) aber die Lib wird nicht benutzt sondern deine eigene Implementierung.

  5. sakis sagt:

    your libraries are best found.thanks a lot

  6. Charlie sagt:

    Hallo,
    danke für die Libs.
    Die sind sehr Hilfreich. Ich habe aber ein kleines Verständnisproblem, welches du denke ich leicht beantworten kannst.
    Wenn ich das hier aufrufe, dann funktioniert soweit alles.

    UB_Systick_Counter1(COUNTER_START_us)

    diese Funktion geht hier rein:

    else if(status==COUNTER_START_s) {
    // Counter1 im s-Mode starten
    Systick_C1.faktor=1000*1000;
    Systick_C1.wert=0;
    }

    und der startet auch. Aber wie? Das sind alles deine Variablen die du deklariert hast. Ich finde den Bezug von dieser Funktion zum STM32F4 nicht. Wo ist die Schnittstelle?

    Danke dir im Voraus
    Charlie

    • admin_ub sagt:

      was meinst du mit “schnittstelle” ?
      Die variablen sind “global” und werden in der Systick-ISR
      (die jede ms aufgerufen wird) incrementiert.

      • Charlie sagt:

        Hallo,
        könntenst du mir villeicht sagen, wo genua, an welcher Stelle die variable Systick_C1.wert incrementiert wird.?
        Ich glaube, ich habe die Interruptroutine in stm23f4 nicht so ganz verstanden.?
        danke dir
        Gruß
        Charlie

        • admin_ub sagt:

          nochmal langsam :
          die ISR vom Systick hat den Namen “Systick_Handler”
          und wird jede Millisekunde aufgerufen :

          //--------------------------------------------------------------
          // Systic-Interrupt
          //--------------------------------------------------------------
          void SysTick_Handler(void)
          {
            // Tick für Counter1
            if(Systick_C1.faktor != 0x00) {
              Systick_C1.wert++;
            }
          }
          

          • Charlie sagt:

            Hallo,
            ouch.. !
            Beim debugen kam der routine aber nie da rein:)

            ok, ich bei es einfach übersehen.
            Besten Dank, du hast mir den Tag gerettet.

            viele grüße
            Charlie


Wie hat Dir dieser Artikel gefallen?

1 Stern2 Sterne3 Sterne4 Sterne5 Sterne (Noch keine Bewertungen)
Loading...

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert