stm32 configuration summary using Systick tick counter

The system tick timer is a peripheral that exists in all m3 cores, but the number of other timers in m3 cores is different. Therefore, the system tick timer is generally used as the system time base, which is also convenient for the transplantation of RTOS in different chips.

1. Configure tick timer

On the graphic page of cubemx, you can easily find the entry of tick timer and configure it. You can directly select the tick timer.

At the same time, the tick timer is a counter that decreases downward. The time of each count is 1 / clock. For stm32f1, it is

The clock can be found in the graphical configuration as shown below, which is 72Mhz

Generally, we use SysTick timer and mainly use its four timers. I will also show their usage below

Register namedescribe
CTRLSysTick control and status register
LOADSysTick reload value register
VALSysTick current value register
CALIBSysTick calibration value register

2. Delay function in hal Library

Generally, we use hal library. The most commonly used delay function is hal_delay. This is provided by the official. It's very convenient to use. Let's see how it is used

First of all, open the method of tracing to the source by right clicking the function declaration

We can see that this function is a weakly defined function, so we can use it anywhere. Then we can see that it is actually used to judge Hal twice_ The time difference of gettick() is used to delay

We can look up this timestamp to see what it means

The results are as follows. You can see that there are three options, but this result is of little use to us

So the focus is still on HAL_GetTick() function. Let's check this function


Sure enough, there was a big harvest

But not only that, it is also in the interrupt function, so this delay actually depends on the interrupt, so it becomes particularly important to find out how the interrupt is carried out

By checking this time base related function, his purpose is to configure the interrupt once every 1ms (read and translate). To be honest, I haven't figured out how to calculate it here. If you know, you can comment and leave a message to me. Thank you very much!!!

This is obvious. Let's contact the above parameters:

typedef enum
{
  HAL_TICK_FREQ_10HZ         = 100U,
  HAL_TICK_FREQ_100HZ        = 10U,
  HAL_TICK_FREQ_1KHZ         = 1U,
  HAL_TICK_FREQ_DEFAULT      = HAL_TICK_FREQ_1KHZ
} HAL_TickFreqTypeDef;

The default is 1ms, that is, the time to stop counting to 1 is 1ms. Then we can modify this parameter to achieve the effect of modifying the delay function, and modify this parameter to achieve the effect

Finally, there is a very interesting experience in the whole process

In fact, the priority can also be found by viewing the interrupt table

In addition, some parameters are described as follows:

For example, there is a u after the end of the number, which means unsigned data. Correspondingly, there is l, which means long integer, and f, which means that the number is a floating point number

3. Use SysTick to implement us delay

The delay function is used in the punctual atomic routine. In fact, the notes have been written, which is easy to understand. There is no explanation here

#include "delay.h"


static u8  fac_us=0;							//Delay multiplier			   
static u16 fac_ms=0;							//MS delay multiplier, which represents the number of ms per beat under ucos
	
	
void delay_init()
{
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);	//Select external clock HCLK/8
	fac_us=SystemCoreClock/8000000;				                //1 / 8 of the system clock  
	fac_ms=(u16)fac_us*1000;					                    //Under non OS, it represents the number of systick clocks required for each ms   
}								    
		    								   
void delay_us(u32 nus)
{		
	u32 temp;	    	 
	SysTick->LOAD=nus*fac_us; 					     //Time loading	  		 
	SysTick->VAL=0x00;        					     //Clear counter
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //Start counting down	  
	do
	{
		temp=SysTick->CTRL;
	}while((temp&0x01)&&!(temp&(1<<16)));		//Waiting time arrives   
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;//Turn off counter
	SysTick->VAL =0X00;      					      //Clear counter	 
}

void delay_ms(u16 nms)
{	 		  	  
	u32 temp;		   
	SysTick->LOAD=(u32)nms*fac_ms;				    //Time loading (systick - > load is 24bit)
	SysTick->VAL =0x00;							          //Clear counter
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;	//Start counting down  
	do
	{
		temp=SysTick->CTRL;
	}while((temp&0x01)&&!(temp&(1<<16)));		  //Waiting time arrives   
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;	//Turn off counter
	SysTick->VAL =0X00;       					      //Clear counter	  	    
} 

Here, the related functions are transplanted to hal library, and I have written the related comments clearly

static uint8_t us = 0; //Define variables
static uint16_t ms = 0;

void delay_init(uint8_t Mhz)
{
	 HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK_DIV8); //8 frequency division, 9mhz

	us = Mhz/8; //9mhz divided by 9 is the time of 1us
	ms = (uint16_t)us*1000; //To avoid over value, you need to cast
}

void delay_ms(uint16_t num)
{
	uint32_t temp;
	SysTick->LOAD = (uint32_t)num*ms; //24 bit register, such time is 2^24/9000 ms, and the time is about 1.864s
	SysTick->VAL = 0; //Set the initial value to 0
	SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //Enable counter, or systick - > Ctrl = 0x01
	do
	{
		temp = SysTick->CTRL;
	}while((temp&0x01) &&!(temp&(1<<16))); //Cycle as long as it's not over

	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //Turn off counter
	SysTick->VAL = 0; //When the time comes, remember to empty the overflow
}

void delay_us(uint32_t num)
{
	uint32_t temp;
	SysTick->LOAD = num*us;
	SysTick->VAL = 0; //Set the initial value to 0
	SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //Enable counter, or systick - > Ctrl = 0x01
	do
	{
		temp = SysTick->CTRL;
	}while((temp&0x01) && !(temp&(1<<16))); //Cycle as long as it's not over

	SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //Turn off counter
	SysTick->VAL = 0; //When the time comes, remember to empty the overflow
}

4. Test delay effect

Write delay code and use logic analyzer to test. Here, 100ms delay is used once

Check the waveform effect collected by the logic analyzer as follows:

There is another way to write as follows, which is more convenient

#define fac_us 72 / / clock frequency, unit: MHZ

/*Microsecond delay function*/
void delay_us(uint32_t nus)
{
	uint32_t ticks;
	uint32_t told,tnow,tcnt=0;
	uint32_t reload=SysTick->LOAD;			//Value of LOAD
	ticks=nus*fac_us; 						//Number of beats required
	told=SysTick->VAL;        				//Counter value when entering
	while(1)
	{
		tnow=SysTick->VAL;
		if(tnow!=told)
		{
			if(tnow<told)tcnt+=told-tnow;	//Note that SYSTICK is a decrement counter
			else tcnt+=reload-tnow+told;
			told=tnow;
			if(tcnt>=ticks)break;			//If the time exceeds / equals the time to be delayed, exit
		}
	}
}
/*Millisecond delay function*/
void delay_ms(uint16_t nms)
{
	while(nms--)
	{
		delay_us(1000);
	}
}

Keywords: Single-Chip Microcomputer stm32 ARM

Added by swampone on Tue, 08 Mar 2022 17:37:48 +0200