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 name | describe |
---|---|
CTRL | SysTick control and status register |
LOAD | SysTick reload value register |
VAL | SysTick current value register |
CALIB | SysTick 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); } }