一、簡(jiǎn)介
SysTick —系統(tǒng)定時(shí)器是屬于 CM3 內(nèi)核中的一個(gè)外設(shè),內(nèi)嵌在 NVIC 中。系統(tǒng)定時(shí)器是一個(gè) 24bit 的向下遞減的計(jì)數(shù)器,計(jì)數(shù)器每計(jì)數(shù)一次的時(shí)間為 1/SYSCLK,一般我們?cè)O(shè)置系統(tǒng)時(shí)鐘 SYSCLK 等于 108M。當(dāng)重裝載數(shù)值寄存器的值遞減到 0 的時(shí)候,系統(tǒng)定時(shí)器就產(chǎn)生一次中斷,以此循環(huán)往復(fù)。
因?yàn)?SysTick 是屬于 CM3 內(nèi)核的外設(shè),所以所有基于 CM3 內(nèi)核的單片機(jī)都具有這個(gè)系統(tǒng)定時(shí)器,使得軟件在 CM3 單片機(jī)中可以很容易的移植。系統(tǒng)定時(shí)器一般用于操作系統(tǒng),用于產(chǎn)生時(shí)基,維持操作系統(tǒng)的心跳。
二、API說明
2.1 外設(shè)寄存器說明
SysTick寄存器列表如下表所示:
| 寄存器名稱 | 寄存器描述 |
|---|---|
| CTRL | 系統(tǒng)控制和狀態(tài)寄存器 |
| LOAD | 系統(tǒng)重載值寄存器 |
| VAL | 系統(tǒng)當(dāng)前值寄存器 |
| CALIB | 系統(tǒng)校準(zhǔn)寄存器 |
參考 core_cm3.h 文件中定義的結(jié)構(gòu)體類型 SysTick_Type
2.2 外設(shè)庫函數(shù)說明
以下 SYSTICK 接口位于 GD32F10x_Firmware_Library_V2.2.2\Firmware\GD32F10x_standard_peripheral\Include\gd32f10x_misc.h。
2.2.1 systick_clksource_set
| 功能 | 設(shè)置SysTick時(shí)鐘源 |
|---|---|
| 函數(shù)定義 | void systick_clksource_set(uint32_t systick_clksource) |
| 參數(shù) | systick_clksource:SysTick時(shí)鐘源 |
| 返回 | 無 |
systick_clksource: SysTick時(shí)鐘源,詳細(xì)列表如下:
| 值 | 含義 |
|---|---|
| SYSTICK_CLKSOURCE_HCLK | SysTick時(shí)鐘源為AHB時(shí)鐘 |
| SYSTICK_CLKSOURCE_HCLK_DIV8 | SysTick時(shí)鐘源為AHB時(shí)鐘的8分頻 |
三、中斷方式
3.1 systick.c
/*!
\file systick.c
\brief the systick configuration file
\version 2014-12-26, V1.0.0, firmware for GD32F10x
\version 2017-06-20, V2.0.0, firmware for GD32F10x
\version 2018-07-31, V2.1.0, firmware for GD32F10x
\version 2020-09-30, V2.2.0, firmware for GD32F10x
*/
/*
Copyright (c) 2020, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32f10x.h"
#include "systick.h"
volatile static uint32_t delay;
/*!
\brief configure systick
\param[in] none
\param[out] none
\retval none
*/
void systick_config(void)
{
/* setup systick timer for 1000Hz interrupts */
if (SysTick_Config(SystemCoreClock / 1000U)){
/* capture error */
while (1){
}
}
/* configure the systick handler priority */
NVIC_SetPriority(SysTick_IRQn, 0x00U);
}
/*!
\brief delay a time in milliseconds
\param[in] count: count in milliseconds
\param[out] none
\retval none
*/
void delay_1ms(uint32_t count)
{
delay = count;
while(0U != delay){
}
}
/*!
\brief delay decrement
\param[in] none
\param[out] none
\retval none
*/
void delay_decrement(void)
{
if (0U != delay){
delay--;
}
}
SysTick 初始化函數(shù)由用戶編寫,里面調(diào)用了 SysTick_Config() 這個(gè)固件庫函數(shù),通過設(shè)置該固件庫函數(shù)的形參,就決定了系統(tǒng)定時(shí)器經(jīng)過多少時(shí)間就產(chǎn)生一次中斷。
-
SysTick 中斷時(shí)間的計(jì)算
SysTick 定時(shí)器的計(jì)數(shù)器是向下遞減計(jì)數(shù)的,計(jì)數(shù)一次的時(shí)間,當(dāng)重裝載寄存器中的值
減到0的時(shí)候,產(chǎn)生中斷,可知中斷一次的時(shí)間
,其中
。 如果設(shè)置
為 108,那中斷一次的時(shí)間
。不過 1us 的中斷沒啥意義,整個(gè)程序的重心都花在進(jìn)出中斷上了,根本沒有時(shí)間處理其他的任務(wù)。
SysTick_Config(SystemCoreClock / 1000))
SysTick_Config() 的形我們配置為 ,從剛剛分析我們知道這個(gè)形參的值最終是寫到重裝載寄存器 LOAD 中的,從而可知我們現(xiàn)在把 SysTick 定時(shí)器中斷一次的時(shí)間
。
SysTick 定時(shí)時(shí)間的計(jì)算
當(dāng)設(shè)置好中斷時(shí)間后,我們可以設(shè)置一個(gè)變量 t,用來記錄進(jìn)入中斷的次數(shù),那么變量 t 乘以中斷的時(shí)間
就可以計(jì)算出需要定時(shí)的時(shí)間。
SysTick 定時(shí)函數(shù)
現(xiàn)在我們定義一個(gè)毫秒級(jí)別的延時(shí)函數(shù),形參為 count,當(dāng)用這個(gè)形參乘以中斷時(shí)間就得出我們需要的延時(shí)時(shí)間。
/*!
\brief delay a time in milliseconds
\param[in] count: count in milliseconds
\param[out] none
\retval none
*/
void delay_1ms(uint32_t count)
{
delay = count;
while(0U != delay){
}
}
函數(shù) delay_1ms() 中我們等待 delay 為 0,當(dāng) delay 為 0 的時(shí)候表示延時(shí)時(shí)間到。變量 delay 在中斷函數(shù)中遞減,即 SysTick 每進(jìn)一次中斷即 1ms 的時(shí)間 delay 遞減一次。
3.2 systick.h
/*!
\file systick.h
\brief the header file of systick
\version 2014-12-26, V1.0.0, firmware for GD32F10x
\version 2017-06-20, V2.0.0, firmware for GD32F10x
\version 2018-07-31, V2.1.0, firmware for GD32F10x
\version 2020-09-30, V2.2.0, firmware for GD32F10x
*/
/*
Copyright (c) 2020, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#ifndef SYSTICK_H
#define SYSTICK_H
#include <stdint.h>
/* configure systick */
void systick_config(void);
/* delay a time in milliseconds */
void delay_1ms(uint32_t count);
/* delay decrement */
void delay_decrement(void);
#endif /* SYSTICK_H */
3.3 gd32f10x_it.c
/*!
\file gd32f10x_it.c
\brief interrupt service routines
\version 2014-12-26, V1.0.0, firmware for GD32F10x
\version 2017-06-20, V2.0.0, firmware for GD32F10x
\version 2018-07-31, V2.1.0, firmware for GD32F10x
\version 2020-09-30, V2.2.0, firmware for GD32F10x
*/
/*
Copyright (c) 2020, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32f10x_it.h"
#include "systick.h"
/*!
\brief this function handles NMI exception
\param[in] none
\param[out] none
\retval none
*/
void NMI_Handler(void)
{
}
/*!
\brief this function handles HardFault exception
\param[in] none
\param[out] none
\retval none
*/
void HardFault_Handler(void)
{
/* if Hard Fault exception occurs, go to infinite loop */
while(1){
}
}
/*!
\brief this function handles MemManage exception
\param[in] none
\param[out] none
\retval none
*/
void MemManage_Handler(void)
{
/* if Memory Manage exception occurs, go to infinite loop */
while(1){
}
}
/*!
\brief this function handles BusFault exception
\param[in] none
\param[out] none
\retval none
*/
void BusFault_Handler(void)
{
/* if Bus Fault exception occurs, go to infinite loop */
while(1){
}
}
/*!
\brief this function handles UsageFault exception
\param[in] none
\param[out] none
\retval none
*/
void UsageFault_Handler(void)
{
/* if Usage Fault exception occurs, go to infinite loop */
while(1){
}
}
/*!
\brief this function handles SVC exception
\param[in] none
\param[out] none
\retval none
*/
void SVC_Handler(void)
{
}
/*!
\brief this function handles DebugMon exception
\param[in] none
\param[out] none
\retval none
*/
void DebugMon_Handler(void)
{
}
/*!
\brief this function handles PendSV exception
\param[in] none
\param[out] none
\retval none
*/
void PendSV_Handler(void)
{
}
/*!
\brief this function handles SysTick exception
\param[in] none
\param[out] none
\retval none
*/
void SysTick_Handler(void)
{
delay_decrement();
}
- SysTick 中斷服務(wù)函數(shù)
void SysTick_Handler(void)
{
delay_decrement();
}
中斷復(fù)位函數(shù)調(diào)用了另外一個(gè)函數(shù) delay_decrement(),原型如下:
void delay_decrement(void)
{
if (0U != delay){
delay--;
}
}
delay 的值等于延時(shí)函數(shù)中傳進(jìn)去的 count 的值,比如 count=1000,則延時(shí)的時(shí)間等于 1000*1ms=1s。
3.4 main.c
#include "gd32f10x.h"
#include "systick.h"
int main(void)
{
systick_config();//系統(tǒng)主頻108MHZ,采用外部晶振,由兩個(gè)宏決定(__SYSTEM_CLOCK_108M_PLL_HXTAL與HXTAL_VALUE)
LED_GPIO_Init();// LED燈模塊初始化
while(1)
{
LED_ON;
delay_1ms(500);
LED_OFF;
delay_1ms(500);
}
}
四、輪詢方式
直接方便,套路淺
4.1 systick.c
/*!
\file systick.c
\brief the systick configuration in polling mode
\version 2020-09-30, V1.0.0, firmware for GD32F10x
*/
/*
Copyright (c) 2020, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32f10x.h"
#include "systick.h"
volatile static float count_1us = 0;
volatile static float count_1ms = 0;
/*!
\brief configure systick
\param[in] none
\param[out] none
\retval none
*/
void systick_config(void)
{
/* systick clock source is from HCLK/8 內(nèi)部時(shí)鐘的108M/8分頻 */
systick_clksource_set(SYSTICK_CLKSOURCE_HCLK_DIV8);
count_1us = (float)SystemCoreClock/8000000;//延時(shí)1us需要的時(shí)鐘數(shù)量 108M/8M = 13.5
count_1ms = (float)count_1us * 1000;//延時(shí)1ms需要的時(shí)鐘數(shù)量 108M/8M *1000= 13500
}
/*!
\brief delay a time in microseconds in polling mode
\param[in] count: count in microseconds
\param[out] none
\retval none
*/
void delay_1us(uint32_t count)
{
uint32_t ctl;
/* reload the count value */
SysTick->LOAD = (uint32_t)(count * count_1us);
/* clear the current count value */
SysTick->VAL = 0x0000U;
/* enable the systick timer */
SysTick->CTRL = SysTick_CTRL_ENABLE_Msk;
/* wait for the COUNTFLAG flag set */
do{
ctl = SysTick->CTRL;
}while((ctl&SysTick_CTRL_ENABLE_Msk)&&!(ctl & SysTick_CTRL_COUNTFLAG_Msk));
/* disable the systick timer */
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
/* clear the current count value */
SysTick->VAL = 0x0000U;
}
/*!
\brief delay a time in milliseconds in polling mode
\param[in] count: count in milliseconds
\param[out] none
\retval none
*/
void delay_1ms(uint32_t count)
{
uint32_t ctl;
/* reload the count value */
SysTick->LOAD = (uint32_t)(count * count_1ms);
/* clear the current count value */
SysTick->VAL = 0x0000U;
/* enable the systick timer */
SysTick->CTRL = SysTick_CTRL_ENABLE_Msk;
/* wait for the COUNTFLAG flag set */
do{
ctl = SysTick->CTRL;
}while((ctl&SysTick_CTRL_ENABLE_Msk)&&!(ctl & SysTick_CTRL_COUNTFLAG_Msk));
/* disable the systick timer */
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
/* clear the current count value */
SysTick->VAL = 0x0000U;
}
GD32F103通過AHB時(shí)鐘(HCLK)即108MHz的8分頻后作為Cortex系統(tǒng)定時(shí)器(SysTick)的外部時(shí)鐘。

4.2 systick.h
/*!
\file systick.h
\brief the header file of systick
\version 2020-09-30, V1.0.0, firmware for GD32F10x
*/
/*
Copyright (c) 2020, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#ifndef SYSTICK_H
#define SYSTICK_H
#include <stdint.h>
/* configure systick */
void systick_config(void);
/* delay a time in milliseconds */
void delay_1ms(uint32_t count);
/* delay a time in microseconds */
void delay_1us(uint32_t count);
#endif /* SYSTICK_H */
4.3 main.c
#include "gd32f10x.h"
#include "systick.h"
int main(void)
{
systick_config();//系統(tǒng)主頻108MHZ,采用外部晶振,由兩個(gè)宏決定(__SYSTEM_CLOCK_108M_PLL_HXTAL與HXTAL_VALUE)
LED_GPIO_Init();// LED燈模塊初始化
while(1)
{
LED_ON;
delay_1ms(500);
LED_OFF;
delay_1us(500000);
}
}
? 由 Leung 寫于 2022 年 4 月 13 日
? 參考:14. GD32F103C8T6入門教程-Systick定時(shí)器
GD32精確延時(shí)和時(shí)間戳