1. Systick Introduction
Systick is just a timer, but it is placed in NVIC. Its main purpose is to provide a hardware interrupt (called tick interrupt) to the operating system . Tick interrupt? Here is a brief explanation. When the operating system is running, it will also have a "heartbeat". It will work according to the beat of the "heartbeat", dividing the entire time period into many small time slices. Each task can only run for the length of a "time slice" at a time and must exit to let other tasks run. This ensures that no task will occupy the entire system. Or a certain time range of each timer cycle is given to a specific task, etc., and the various timing functions provided by the operating system are all related to this tick timer. Therefore, a timer is needed to generate periodic interrupts, and it is best not to allow user programs to access its registers at will to maintain the rhythm of the operating system's "heartbeat". As long as its enable bit in the SysTick control and status register is not cleared, it will never stop.
After knowing the position of systick in the system, let's learn about the implementation of systick. Here is just an example to illustrate the use of systick. It has four registers, which I list below:
SysTick->CTRL, --control and status register
SysTick->LOAD, --Reload register
SysTick->VAL, --current value register
SysTick->CALIB, --calibration value register
The following figure has their respective descriptions: The following figure reference address: http://blog.csdn .NET /marike1314/article/details/5673684
2. Systick programming
Now we want to use the Systick timer to make a precise delay function, such as making the LED flash once with a delay of exactly 1 second.
Idea: Use the Systick timer as a down counter. After setting the initial value and enabling it, it will decrement the counter every 1 system clock cycle. When the count reaches 0, the SysTick counter automatically reloads the initial value and continues counting, triggering an interrupt at the same time.
Then each time the counter is reduced to 0, the time that has passed is: system clock cycle * counter initial value. We use 72M as the system clock, so the time it takes for the counter to be reduced by 1 each time is 1/72M. If the initial value of the counter is 72000, then each time the counter is reduced to 0, the time that has passed is (1/72M)*72000= 0.001, that is, 1ms. (Simple understanding: using a clock frequency of 72M, that is, 1s counts 72M=72000000 times, then 1ms counts 72000 times, so the count value is 72000)
First, we need a 72M systick system clock, so just use the following clock!
SystemInit();
This function can make the main frequency run to 72M. It can be used as the clock source of systick.
Then start configuring systick. In fact, the strict process of configuring systick is as follows:
1. Call SysTick_CounterCmd() -- disable SysTick counter
2. Call SysTick_ITConfig() -- disable SysTick interrupt
3. Call SysTick_CLKSourceConfig() -- set the SysTick clock source.
4. Call SysTick_SetReload() -- sets the SysTick reload value.
5. Call SysTick_ITConfig() -- Enable SysTick interrupt
6. Call SysTick_CounterCmd() -- turn on the SysTick counter
Here everyone must pay attention that the current register value VAL must be equal to 0!
SysTick->VAL = (0x00); The counter is automatically reloaded RELOAD only when the VAL value is 0.
Next, you can directly call the Delay() function to delay. In the implementation of the delay function, it should be noted that the global variable TimingDelay must use volatile, otherwise it may be optimized by the compiler.
Let's do some program analysis:
(1) System clock configuration
First, we configured the system clock and the SetSysClock(void) function used 72M as the system clock;
In order to see the code clearly, I chose to take a screenshot:
(2) Let’s take a look at the main function first
int main(void)
{ unsigned char i=0;
unsigned char a[] = "abncdee";
SystemInit1(); //System initialization
if (SysTick_Config(72000)) //1ms response to an interrupt
{
/* Capture error */
while (1);
}
/*Analysis: Because the requirement is to send data to the intermediate computer every 500ms, it is placed in the while statement.
*Sending data + delay can achieve the effect equivalent to interruption;
*If one of the tasks in multi-tasking needs to be interrupted, call this task in the interrupt function;
*/
while (1)
{
//Test code: Test the timer function by delaying the test
GPIO_SetBits(GPIOC, GPIO_Pin_6); //V6
Delay(50);
GPIO_ResetBits(GPIOC, GPIO_Pin_6); //V6
Delay(50);
//Function 1 code: send data every 500ms
/*
UART2_TX485_Puts("123450");
Delay(500);
*/
//Function 2 code: The upper computer sends a specific instruction, and the middle computer performs the corresponding operation
// RS485_Test();
}
}
int main(void)
{ unsigned char i=0;
unsigned char a[] = "abncdee";
SystemInit1(); //System initialization
if (SysTick_Config(72000)) //1ms response to an interrupt
{
/* Capture error */
while (1);
}
/*Analysis: Because the requirement is to send data to the intermediate computer every 500ms, it is placed in the while statement.
*Sending data + delay can achieve the effect equivalent to interruption;
*If one of the tasks in multi-tasking needs to be interrupted, call this task in the interrupt function;
*/
while (1)
{
//Test code: Test the timer function by delaying the test
GPIO_SetBits(GPIOC, GPIO_Pin_6); //V6
Delay(50);
GPIO_ResetBits(GPIOC, GPIO_Pin_6); //V6
Delay(50);
//Function 1 code: send data every 500ms
/*
UART2_TX485_Puts("123450");
Delay(500);
*/
//Function 2 code: The upper computer sends a specific instruction, and the middle computer performs the corresponding operation
// RS485_Test();
}
}
(3) Configuration of the system tick timer - the protagonist appears:
In the main function: SysTick_Config(72000); the parameter of the tick timer is 72000, which means the count is 72000
(Because we use a clock frequency of 72M, that is, 1s counts 72M=72000000 times, then 1ms counts 72000 times, so the count value is 72000)
In the file Core_cm3.h
The specific implementation of the SysTick_Config function is as follows:
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if (ticks>SYSTICK_MAXCOUNT)
return (1); /* Reload value impossible */
SysTick->LOAD = (ticks & SYSTICK_MAXCOUNT) - 1; //systick reload value register /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts */
SysTick->VAL = (0x00); //systick current value register
/* Load the SysTick Counter Value */
SysTick->CTRL = (1 << SYSTICK_CLKSOURCE) | (1< } static __INLINE uint32_t SysTick_Config(uint32_t ticks) { if (ticks>SYSTICK_MAXCOUNT) return (1); /* Reload value impossible */ SysTick->LOAD = (ticks & SYSTICK_MAXCOUNT) - 1; //systick reload value register /* set reload register */ NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts */ SysTick->VAL = (0x00); //systick current value register /* Load the SysTick Counter Value */ SysTick->CTRL = (1 << SYSTICK_CLKSOURCE) | (1< } Let's take a look at this code: SysTick->CTRL = (1 << SYSTICK_CLKSOURCE) | (1< Let's take a look at the stm32f10x_it.h file: Find the tick timer interrupt function: SysTickHandler() void SysTickHandler(void) { TimingDelay_Decrement(); } From the above, we know that an interrupt occurs every 1ms through the loaded count value 72000. In the interrupt function, a function TimingDelay_Decrement() is called; ----- that is, this function is called every 1ms when an interrupt occurs; Let's take a look at what TimingDelay_Decrement(); is doing. /***************************************************************** *Function name: TimingDelay_Decrement *Function description: This function is called in an interrupt, that is, no interrupt occurs, this function is called, in this function * The variable TimingDelay is equivalent to a subtraction counter * *Input parameters: None *Return value: None *Other Notes: None *Current version: v1.0 *Author: Liang Yinxuan *Completion date: August 3, 2012 *Modification date Version number Modifier Modification content *----------------------------------------------------------------- * ******************************************************************/ void TimingDelay_Decrement(void) { if (TimingDelay != 0x00) { TimingDelay--; } } We looked at the definition of TimingDelay and saw which other functions call this variable, as follows: /***************************************************************** * Global variables ******************************************************************/ static __IO uint32_t TimingDelay=0; /***************************************************************** *Function name: Delay *Function description: Use the system clock counter to decrement to achieve the delay function * *Input parameter: nTime: the number of milliseconds required to delay *Return value: None *Other Notes: None *Current version: v1.0 *Author: Liang Yinxuan *Completion date: August 3, 2012 *Modification date Version number Modifier Modification content *----------------------------------------------------------------- * ******************************************************************/ void Delay(__IO uint32_t nTime) //When delay is called, nTime=500 { TimingDelay = nTime; while(TimingDelay != 0); } /***************************************************************** *Function name: TimingDelay_Decrement *Function description: This function is called in an interrupt, that is, no interrupt occurs, this function is called, in this function * The variable TimingDelay is equivalent to a subtraction counter * *Input parameters: None *Return value: None *Other Notes: None *Current version: v1.0 *Author: Liang Yinxuan *Completion date: August 3, 2012 *Modification date Version number Modifier Modification content *----------------------------------------------------------------- * ******************************************************************/ void TimingDelay_Decrement(void) { if (TimingDelay != 0x00) { TimingDelay--; } } We looked at the definition of TimingDelay and saw which other functions call this variable, as follows: /***************************************************************** * Global variables ******************************************************************/ static __IO uint32_t TimingDelay=0; /***************************************************************** *Function name: Delay *Function description: Use the system clock counter to decrement to achieve the delay function * *Input parameter: nTime: the number of milliseconds required to delay *Return value: None *Other Notes: None *Current version: v1.0 *Author: Liang Yinxuan *Completion date: August 3, 2012 *Modification date Version number Modifier Modification content *----------------------------------------------------------------- * ******************************************************************/ void Delay(__IO uint32_t nTime) //When delay is called, nTime=500 { TimingDelay = nTime; while(TimingDelay != 0); } Through the above functions, we know that when calling Delay(500), nTime=500; then in the Delay() function, TimingDelay =nTime; (that is, TimingDelay=500 is its initial value), and then the function of TimingDelay_Decrement(void) is to decrement TimingDelay- -; every millisecond until it reaches 0; this plays a role of delay; Now the Delay(1) we created is 1 millisecond delay, and Delay(1000) is 1 second. Let's draw a picture to facilitate the understanding of the relationship between these functions: Let's return to the main function main() and look at these statements: while (1) { //Test code: Test the timer function by delaying the test GPIO_SetBits(GPIOC, GPIO_Pin_6); //V6 Delay(500); GPIO_ResetBits(GPIOC, GPIO_Pin_6); //V6 Delay(500); //Function 1 code: send data every 500ms /* UART2_TX485_Puts("123450"); Delay(500); */ //Function 2 code: The upper computer sends a specific instruction, and the middle computer performs the corresponding operation // RS485_Test(); } while (1) { //Test code: Test the timer function by delaying the test GPIO_SetBits(GPIOC, GPIO_Pin_6); //V6 Delay(500); GPIO_ResetBits(GPIOC, GPIO_Pin_6); //V6 Delay(500); //Function 1 code: send data every 500ms /* UART2_TX485_Puts("123450"); Delay(500); */ //Function 2 code: The upper computer sends a specific instruction, and the middle computer performs the corresponding operation // RS485_Test(); } After analyzing the system timer above, we know that Delay(500); means a delay of 500ms; then the LED flashes every 500ms; The above explanation about the application of system tick timer is basically completed! Regarding the source code package compiled by SysTick, (in fact, if you are careful, you will find that the above code contains 485 communication code, It's just temporarily blocked, which will be discussed in the next section) I put it in my resources: http://download.csdn.net/detail/yx_l128125/4511622 Let’s take a look at the reference material to get a deeper understanding of the blog I wrote above: The Definitive Guide to Cortex-M3 《Cortex-M3 Technical Reference Manual》 Q: What is the SYSTick timer? SysTick is a 24-bit countdown timer. When it reaches 0, it will automatically reload the initial value of the timer from the RELOAD register. As long as the enable bit in the SysTick control and status register is not cleared, it will never stop. Q: Why do we need to set the SysTick timer? (1) Generate the clock beat of the operating system The SysTick timer is bundled in the NVIC and is used to generate the SYSTICK exception (exception number: 15). In the past, most operating systems required a hardware timer to generate the tick interrupt required by the operating system as the time base of the entire system. Therefore, a timer is needed to generate periodic interrupts, and it is best not to allow user programs to access its registers at will to maintain the rhythm of the operating system's "heartbeat". (2) Facilitates program porting between different processors. The Cortex-M3 processor contains a simple timer. Because all CM3 chips have this timer, software migration between different CM3 devices is simplified. The clock source of this timer can be an internal clock (FCLK, the free-running clock on CM3) or an external clock (STCLK signal on CM3 processors). However, the specific source of STCLK is determined by the chip designer, so the clock frequency between different products may be very different. You need to check the device manual of the chip to decide what to choose as the clock source. The SysTick timer can generate an interrupt, and CM3 has a special exception type for it, and it has a place in the vector table. It makes it much easier to port the operating system and other system software between CM3 devices, because it is handled the same in all CM3 products. (3) As an alarm to measure time. In addition to serving the operating system, the SysTick timer can also be used for other purposes: as an alarm, for measuring time, etc. It should be noted that when the processor is halted during debugging, the SysTick timer will also be suspended. Q: How does Systick work? First, set the counter clock source, CTRL->CLKSOURCE (control register). Set the reload value (RELOAD register), clear the count register VAL (CURRENT in the figure below). Set CTRL->ENABLE to start timing. If it is an interrupt, then Systick interrupt is enabled and processed in the interrupt routine. If the query mode is used, then the COUNTFLAG flag bit of the control register is continuously read to determine whether the timing has reached zero. Or, one of the following methods can be used: When the SysTick timer counts from 1 to 0, it will set the COUNTFLAG bit; the following method can clear it: 1. Read the SysTick Control and Status Register (STCSR) 2. Write any data to the SysTick Current Value Register (STCVR) The counter is automatically reloaded with RELOAD only when the VAL value is 0. Q: How to use SysTicks as system clock? The biggest mission of SysTick is to generate exception requests regularly as the system time base. The OS needs this "tick" to promote task and time management. To enable SysTick exceptions, set STCSR.TICKINT. In addition, if the vector table is relocated to SRAM, it is also necessary to create a vector for the SysTick exception and provide the entry address of its service routine.
Previous article:STM32 Introduction - General Timer Configuration
Next article:Three methods of STM32 delay function - it is best to master the third one
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Huawei's Strategic Department Director Gai Gang: The cumulative installed base of open source Euler operating system exceeds 10 million sets
- Download from the Internet--ARM Getting Started Notes
- Learn ARM development(22)
- Learn ARM development(21)
- Learn ARM development(20)
- Learn ARM development(19)
- Learn ARM development(14)
- Learn ARM development(15)
- Analysis of the application of several common contact parts in high-voltage connectors of new energy vehicles
- Wiring harness durability test and contact voltage drop test method
- Common delay and interrupt problems and solutions for various microcontrollers
- Q&A about connectivity: Wi-Fi opens up new virtual worlds
- Forth on the Raspberry Pi Pico
- Summary: lb8820265 DIY Bluetooth somatosensory controller journey (updated)
- Looking to buy Freescale's 9S12HY64 development board
- Why does the capacity of laptop batteries decrease as they are used?
- CC2640R2F Single Carrier Code
- Pre-registration for the prize live broadcast | PI helps to provide high reliability and high efficiency industrial measurement solutions
- ADAS functions
- 【Contactless facial recognition access control system】+Unboxing