Using SysTick to implement delay in STM32 projects (STM32_06)

One, SysTick

Sys-system, Tick-tick, the system tick-tick is a very vivid representation that it is a system metronome. SysTick is a 24-bit countdown timer integrated in the Cortex core. When it reaches 0, it will automatically reload the initial value from the RELOAD register. As long as its enable bit in the SysTick Control and Status Register is not cleared, it will never stop.

SysTick-like action.

SysTick mainly has the following functions:

1. Generate the clock beat of the operating system;

When an RTOS processes tasks in a parallel architecture, the crash of a single task does not involve the entire system. In this way, users may design their own applications based on RTOS for reliability reasons. In this way, the meaning of SYSTICK's existence is to provide the necessary clock beats and provide a rhythmic "heartbeat" for RTOS task scheduling.

2. It is convenient for program porting between different processors

Because all CM3 chips have this timer, software migration between different CM3 devices is simplified.

3. Measure time as an alarm

Can be used as an alarm clock to start a specific task. It acts as an alarm and is used to measure time. It should be noted that when the processor is halted (halt) during debugging, the SysTick timer will also be suspended.

Second, the project configuration

This project is based on https://blog.csdn.net/fanxp66/article/details/80227611 , and replaces the delay in the program with SysTick to achieve precise delay.

1. Copy the "misc.h" header file in the library function library to the \Lib\inc folder of the project, and copy the "misc.c" program file to the \Lib\src folder;

2. Add the "misc.c" file to the "Lib" group of the project;

3. Create a new "Public" folder under the project folder, and add the "Public" group to the project;

4. Create a new "SysTick.h" file and a "SysTick.c" file, and add the "SysTick.c" file to the "Public" group of the project;

5. Modify the project configuration and add the path "\Public" to "Include Paths" of "C/C++".

3. Programming

In this program, SysTick is used for precise 1-second timing. The initial system clock is 72MHz, and 9MHz obtained after SYSCLK/8 frequency division is selected as the input timing clock of SysTick. When the count value is set to 9000000, 1-second timing is realized.

When using SysTick, there are two types of query mode and interrupt mode. When using the query mode, first select the clock source for SysTick, set the count value and start counting, and then query the count completion status bit. When the status bit is 1, it means the count is completed; use interrupt In the method, the interrupt service routine should be set for the 15th exception. The query method is used here.

SysTick programming uses the following registers:

CTRL SysTick Control and Status Register

LOAD SysTick reload value register

VAL SysTick current value register

CALIB SysTick Calibration Value Register

Defined in the "core_cm3.h" file:

typedef struct

{

  __IO uint32_t CTRL; /*Address offset: 0x00 SysTick Control and Status Register*/

  __IO uint32_t LOAD; /*Address offset: 0x04 SysTick load count value register*/

  __IO uint32_t VAL; /*Address offset: 0x08 SysTick current count value register*/

  __I uint32_t CALIB; /*Address offset: 0x0C SysTick calibration value register*/

} SysTick_Type;

#define SysTick   ((SysTick_Type *)SysTick_BASE)   /*SysTick 配置结构体  */

    Later, you can operate the SysTick register through the SysTick structure pointer.

1. SysTick programming steps.

① Set the clock source for SysTick

In the library function file of STM32, there are "misc.h" header files and "misc.c" program files that define the corresponding macros and library functions.

In the "misc.h" header file there is a definition:

#define SysTick_CLKSource_HCLK_Div8    ((uint32_t)0xFFFFFFFB)

#define SysTick_CLKSource_HCLK         ((uint32_t)0x00000004)

Define functions in the "misc.c" program file

void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)

{

  assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));

  if (SysTick_CLKSource == SysTick_CLKSource_HCLK)

  {

    SysTick->CTRL |= SysTick_CLKSource_HCLK; /*Set bit 2 of CTRL register to 1*/

  }

  else

  {

    SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8; /*Set bit 2 of CTRL register to 0*/

  }

}

In this program, the system clock divided by 8 is used, so the calling function is as follows:

SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);

② Set the count value for the SysTick load count value register;

③ Set the current count value register of SysTick to 0;

④ 通过对SysTick的CTRL寄存器的位0置位使能SysTick定时器。

2、编程实现

在程序中,为了方便使用,定义了"SysTick.h"头文件和"SysTick.c"程序文件(这两个文件已经在前面“项目配置”部分创建)。

"SysTick.h"头文件内容如下:

#ifndef __SysTick__H

#define __SysTick__H

#include "stm32f10x.h"

void SysTick_Init(u8 SYSCLK);

void delay_us(u32 nus);

void delay_ms(u16 nms);

"SysTick.c"程序文件内容如下:

#include "SysTick.h"

#include "misc.h"

u8 fac_us = 0;

u16 fac_ms = 0;

 

void SysTick_Init(u8 SYSCLK)

{

     SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);

     fac_us = SYSCLK / 8;

     fac_ms = (u16)fac_us*1000;

}

 

void delay_us(u32 nus)

{

     u32 temp;

     SysTick->LOAD = nus * fac_us;

     SysTick->VAL = 0;

     SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;

     do{

         temp = SysTick->CTRL;

     }while((temp&0x01)&&(!(temp&(1<<16))));

     SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;

     SysTick->VAL = 0;

}

void delay_ms(u16 nms)

{

     u32 temp;

     SysTick->LOAD = nms * fac_ms;

     SysTick->VAL = 0;

     SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;

     do{

         temp = SysTick->CTRL;

     }while((temp&0x01)&&(!(temp&(1<<16))));

     SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;

     SysTick->VAL = 0;

}

3、在主函数中使用定时

#include "stm32f10x.h"

#include "stm32f10x_rcc.h"

#include "led.h"

#include "SysTick.h"

 

int main()

{

     u32 i,j;

     //共阳数码管'0'-'9'显示码

     u32 LED[10] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

     LED_Init();

     SysTick_Init(72);  //系统时钟72MHz

     while(1)

     {

         for(i=0;i<10;i++)

         {

              //根据LED[n]数组的值决定数码管各个段位的显示

              for(j=0; j<8; j++)

                   if( ~(LED[i]) & 0x1<<j )

                       PCout(j) = 0;

                   else

                       PCout(j) = 1;

              delay_ms(1000);

         }

     }

}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326306496&siteId=291194637