当前位置:网站首页>Learning record: understand systick system timer and write delay function
Learning record: understand systick system timer and write delay function
2022-07-06 15:32:00 【Bitter tea seeds】
Catalog
One 、Sys Tick Calculation of timing time
3、 ... and 、Sys Tick Interrupt priority
Four 、 Write the delay function
SysTick Tied to NVIC in , It's a 24 position Timer for , And can only decrease .
(NVIC It is a vector interrupt controller , It also contains MPU Control register of 、SysTick Timer and debugging control .)
And in the 《STM32 Chinese Reference Manual 》 in , Yes SysTick The introduction of is just a simple sentence :SysTick The calibration value is fixed to 9000, When SysTick The clock is set to 9MHz(HCLK/8 The maximum of ), produce 1ms Time base .
One 、Sys Tick Calculation of timing time
Let the time of a cycle count be t ;
Clk from CTRL Register configuration , The frequency is 72M and 9M
misc.c The system clock
If you choose SysTick_CLKSource_HCLK for 72M;
Otherwise, it would be SysTick_CLKSource_HCLK_Div8 for 9M;
/**
* @brief Configures the SysTick clock source.
* @param SysTick_CLKSource: specifies the SysTick clock source.
* This parameter can be one of the following values:
* @arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source.
* @arg SysTick_CLKSource_HCLK: AHB clock selected as SysTick clock source.
* @retval None
*/
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
{
/* Check the parameters */
assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));
if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
{
SysTick->CTRL |= SysTick_CLKSource_HCLK;
}
else
{
SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;
}
}
misc.h The system clock
/** @defgroup SysTick_clock_source
* @{
*/
/*/8, That is, select the kernel clock 9M*/
#define SysTick_CLKSource_HCLK_Div8 ((uint32_t)0xFFFFFFFB)
/*72M*/
#define SysTick_CLKSource_HCLK ((uint32_t)0x00000004)
#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \
((SOURCE) == SysTick_CLKSource_HCLK_Div8))
t=RELOAD*(1/clk)
Clk( Clock interrupt )=72M when ,t=(72)×(1/72M)=1 us; //1 us Enter an interrupt NVIC
Clk( The clock )=72M when ,t=(72000)×(1/72M)=1 Ms; //1 ms Enter an interrupt NVIC
Convert units according to time :1 s=1000 ms=1000000 us=1000000000 ns
Two 、Sys Tick register
Sys Tick Register structure
core_cm3.h:
/** @addtogroup CMSIS_CM3_SysTick CMSIS CM3 SysTick
memory mapped structure for SysTick
@{
*/
typedef struct
{
__IO uint32_t CTRL; /*!< Offset: 0x00 SysTick Control and Status Register */
__IO uint32_t LOAD; /*!< Offset: 0x04 SysTick Reload Value Register */
__IO uint32_t VAL; /*!< Offset: 0x08 SysTick Current Value Register */
__I uint32_t CALIB; /*!< Offset: 0x0C SysTick Calibration Register */
} SysTick_Type;
Sys Tick Configure library functions
/**
* @brief Initialize and start the SysTick counter and its interrupt.
*
* @param ticks number of ticks between two interrupts
* @return 1 = failed, 0 = successful
*
* Initialise the system tick timer and its interrupt and start the
* system tick timer / counter in free running mode to generate
* periodical interrupts.
*/
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible reload The register of 24bit, The maximum value is 2^24*/
SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register To configure reload The initial value of the ,'-1' Because when configuring , One has been consumed systick cycle */
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts Configure interrupt priority as 1<<4-1=15, The priority is the lowest */
SysTick->VAL = 0; /* Load the SysTick Counter Value To configure counter The value of the counter */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer To configure systick The clock is 72M, To interrupt , Can make systick*/
return (0); /* Function successful */
}
NVIC_SetPriority function
static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
if(IRQn < 0) {
SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M3 System Interrupts */
else {
NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for device specific Interrupts */
}
3、 ... and 、Sys Tick Interrupt priority
1.STM32 Both the kernel and peripherals are used 4 Binary bits to indicate interrupt priority .
2. The grouping of interrupt priority is also applicable to the kernel and peripherals . When comparing , Just group and parse the four bits of the interrupt priority of the peripheral device of the kernel according to the interrupt priority of the peripheral device , That is to say, artificially divide preemptive priority and sub priority .
Four 、 Write the delay function
1. Write a delay function
bsp_SysTick.h The header file
#ifndef __SYSTICK_H
#define __SYSTICK_H
#include "stm32f10x.h"
void SysTick_Init(void);
void Delay_us(__IO u32 nTime);
#define Delay_ms(x) Delay_us(100*x) // Company ms
void SysTick_Delay_Us( __IO uint32_t us);
void SysTick_Delay_Ms( __IO uint32_t ms);
#endif
bsp_SysTick.c file
#include "bsp_SysTick.h"
#include "core_cm3.h"
#include "misc.h"
static __IO u32 TimingDelay;
/**
* @brief Start the system tick timer SysTick
* @param nothing
* @retval nothing
*/
void SysTick_Init(void)
{
/* SystemFrequency / 1000 1ms Break once
* SystemFrequency / 100000 10us Break once
* SystemFrequency / 1000000 1us Break once
*/
// if (SysTick_Config(SystemFrequency / 100000)) // ST3.0.0 Library version
if (SysTick_Config(SystemCoreClock / 100000)) // ST3.5.0 Library version
{
/* Capture error */
while (1);
}
}
/**
* @brief us Delay program ,10us For a unit
* @param
* @arg nTime: Delay_us( 1 ) Then the delay is 1 * 10us = 10us
* @retval nothing
*/
void Delay_us(__IO u32 nTime)
{
TimingDelay = nTime;
// Enable tick timer
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
while(TimingDelay != 0);
}
/**
* @brief Get the beat program
* @param nothing
* @retval nothing
* @attention stay SysTick Interrupt function SysTick_Handler() call
*/
void TimingDelay_Decrement(void)
{
if (TimingDelay != 0x00)
{
TimingDelay--;
}
}
#if 0
// This Firmware library functions stay core_cm3.h in
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
// reload The register is 24bit, The maximum value is 2^24
if (ticks > SysTick_LOAD_RELOAD_Msk) return (1);
// To configure reload The initial value of the register
SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;
// Configure interrupt priority as 1<<4-1 = 15, The priority is the lowest
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);
// To configure counter The value of the counter
SysTick->VAL = 0;
// To configure systick The clock is 72M
// To interrupt
// Can make systick
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk;
return (0);
}
#endif
// couter reduce 1 Time for be equal to 1/systick_clk
// When counter from reload The value of is reduced to 0 When , For a cycle , If interrupt is turned on, the interrupt service program is executed ,
// meanwhile CTRL Of countflag Position meeting position 1
// The time of this cycle is reload * (1/systick_clk)
void SysTick_Delay_Us( __IO uint32_t us)
{
uint32_t i;
SysTick_Config(SystemCoreClock/1000000);
for(i=0;i<us;i++)
{
// When the value of the counter decreases to 0 When ,CRTL Bit of register 16 I'll set 1
while( !((SysTick->CTRL)&(1<<16)) );
}
// close SysTick Timer
SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk;
}
void SysTick_Delay_Ms( __IO uint32_t ms)
{
uint32_t i;
SysTick_Config(SystemCoreClock/1000);
for(i=0;i<ms;i++)
{
// When the value of the counter decreases to 0 When ,CRTL Bit of register 16 I'll set 1
// Dangzhi 1 when , Reading this bit clears 0
while( !((SysTick->CTRL)&(1<<16)) );
}
// close SysTick Timer
SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk;
}
main.c
#include "stm32f10x.h"
#include "bsp_SysTick.h"
#include "bsp_led.h"
/*
* t : Timing time
* Ticks : How many clock cycles produce an interrupt
* f : clock frequency 72000000
* t = Ticks * 1/f = (72000000/100000) * (1/72000000) = 10us
*/
/**
* @brief The main function
* @param nothing
* @retval nothing
*/
int main(void)
{
/* LED Port initialization */
LED_GPIO_Config();
#if 0
/* To configure SysTick by 10us Break once */
SysTick_Init();
for(;;)
{
LED1( ON );
Delay_us(100000); // 100000 * 10us = 1000ms
//Delay_ms(100);
LED1( OFF );
LED0( ON );
Delay_us(100000); // 100000 * 10us = 1000ms
//Delay_ms(100);
LED0( OFF );
}
#else // Do not use interrupt , Use the method of query
for(;;)
{
LED1( ON );
SysTick_Delay_Ms( 1000 );
LED1( OFF );
LED0( ON );
SysTick_Delay_Ms( 1000 );
LED0( OFF );
}
#endif
}
Delay function library file
delay_init function
// Initialization delay function
// When using OS When , This function initializes OS The beat of the clock
//SYSTICK The clock is fixed to HCLK The clock
//SYSCLK: System clock frequency
void delay_init(u8 SYSCLK)
{
#if SYSTEM_SUPPORT_OS // If support is needed OS.
u32 reload;
#endif
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
//SysTick The frequency is HCLK
fac_us=SYSCLK; // Whether used or not OS,fac_us You need to use
#if SYSTEM_SUPPORT_OS // If support is needed OS.
reload=SYSCLK; // The number of counts per second Unit is K
reload*=1000000/delay_ostickspersec; // according to delay_ostickspersec Set the overflow time
//reload by 24 Bit register , Maximum :16777216, stay 72M Next , About us 0.233s about
fac_ms=1000/delay_ostickspersec; // representative OS The minimum unit that can delay
SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;// Turn on SYSTICK interrupt
SysTick->LOAD=reload; // Every time 1/OS_TICKS_PER_SEC Second break once
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; // Turn on SYSTICK
#else
#endif
}
SysTick->CTRL Bit definition of ( Structure pointer )
SysTick-> VAL The definition of
delay_us function
// Time delay nus
//nus To delay us Count .
//nus:0~190887435( The maximum value is 2^32/[email protected]_us=22.5)
void delay_us(u32 nus)
{
u32 ticks;
u32 told,tnow,tcnt=0;
u32 reload=SysTick->LOAD; //LOAD Value
ticks=nus*fac_us; // The number of beats needed
told=SysTick->VAL; // Counter value at the time of first entry
while(1)
{
tnow=SysTick->VAL;
if(tnow!=told)
{
if(tnow<told)tcnt+=told-tnow;// Note here SYSTICK It's just a decreasing counter .
else tcnt+=reload-tnow+told;
told=tnow;
if(tcnt>=ticks)break; // For more than / Equal to the time to delay , The exit .
}
};
}
// Time delay nus
//nus: To delay us Count .
//nus:0~190887435( The maximum value is 2^32/[email protected]_us=22.5)
void delay_us(u32 nus)
{
u32 ticks;
u32 told,tnow,tcnt=0;
u32 reload=SysTick->LOAD; //LOAD Value
ticks=nus*fac_us; // The number of beats needed
delay_osschedlock(); // prevent OS Dispatch , Prevent interruptions us Time delay
told=SysTick->VAL; // Counter value at the time of first entry
while(1)
{
tnow=SysTick->VAL;
if(tnow!=told)
{
if(tnow<told)tcnt+=told-tnow; // Be careful SYSTICK Is a decrement counter .
else tcnt+=reload-tnow+told;
told=tnow;
if(tcnt>=ticks)break; // For more than / Equal to the time to delay , The exit .
}
};
delay_osschedunlock(); // recovery OS Dispatch
}
delay_ms function
// Time delay nms
//nms: To delay ms Count
void delay_ms(u16 nms)
{
u32 i;
for(i=0;i<nms;i++) delay_us(1000);
}
// Time delay nms
//nms: To delay ms Count
//nms:0~65535
void delay_ms(u16 nms)
{
if(delay_osrunning&&delay_osintnesting==0)// If OS Already running , And not in interruption
{
if(nms>=fac_ms) // The delay time is longer than OS The minimum time period of
{
delay_ostimedly(nms/fac_ms); //OS Time delay
}
nms%=fac_ms; //OS It is no longer possible to provide such a small delay , Delay in the normal way
}
delay_us((u32)(nms*1000)); // Normal mode delay
}
边栏推荐
猜你喜欢
Knowledge that you need to know when changing to software testing
Mysql database (IV) transactions and functions
UCORE lab5 user process management experiment report
12306: mom, don't worry about me getting the ticket any more (1)
How to rename multiple folders and add unified new content to folder names
Crawler series (9): item+pipeline data storage
Flex --- detailed explanation of flex layout attributes
自动化测试中敏捷测试怎么做?
Future trend and planning of software testing industry
UCORE lab8 file system experiment report
随机推荐
全网最详细的postman接口测试教程,一篇文章满足你
STM32学习记录:输入捕获应用
自动化测试中敏捷测试怎么做?
LeetCode#62. Different paths
ucorelab4
STM32學習記錄:輸入捕獲應用
Preface to the foundations of Hilbert geometry
Es6--- two methods of capturing promise status as failed
C4D quick start tutorial - creating models
学习记录:USART—串口通讯
STM32学习记录:LED灯闪烁(寄存器版)
csapp shell lab
ucore lab5
Want to change jobs? Do you know the seven skills you need to master in the interview software test
Es6---es6 content details
LeetCode#53. Maximum subarray sum
UCORE Lab 1 system software startup process
Intensive learning notes: Sutton book Chapter III exercise explanation (ex17~ex29)
What is "test paper test" in software testing requirements analysis
51 lines of code, self-made TX to MySQL software!