【兆易GD32H759I-EVAL】GD32H7 SysTick 延时
[复制链接]
Cortex-M7中的SysTick是一个重要的系统定时器,它在Cortex-M7内核中扮演着关键角色。
SysTick 校准值固定为 1000 , SysTick 时 钟 源 可 选 择 为 CK_SYS或 CK_SYS/2 。 通 过 对 SYST_RVR寄存器进行配置,从而为系统提供1ms时基。当SysTick时钟源为CK_SYS (CK_SYS=a MHz)时,SYST_RVR寄存器值设置为(a*1000-1)。当SysTick时钟源为 CK_SYS/2时,SYST_RVR寄存器值设置为(a/2*1000-1)。
SysTick定时器配置1ms时基的步骤:
- 选择SysTick时钟源:
- 如果选择CK_SYS作为时钟源,那么SysTick的计数频率将等于系统时钟频率。
- 如果选择CK_SYS/2作为时钟源,那么SysTick的计数频率将是系统时钟频率的一半。
- 计算SYST_RVR寄存器的值:
- 当使用CK_SYS作为时钟源时(假设CK_SYS = a MHz),SysTick每计数一次需要的时间为1/a微秒。为了获得1ms(即1000微秒)的时基,SysTick需要计数a * 1000次。但是,由于SysTick是向下递减的计数器,我们需要将计数次数减1作为重载值,所以SYST_RVR的值应设置为a * 1000 - 1。
- 当使用CK_SYS/2作为时钟源时,SysTick每计数一次需要的时间为2/a微秒。为了获得1ms的时基,SysTick需要计数a/2 * 1000次。同样地,SYST_RVR的值应设置为a/2 * 1000 - 1。
- 配置SYST_RVR寄存器:
- 使用合适的值配置SYST_RVR寄存器。这通常涉及将计算出的值写入该寄存器。
- 启用SysTick中断和定时器:
- 配置SysTick控制寄存器(SYST_CTRL)以启用SysTick中断(如果需要的话)并启动定时器。
- 编写SysTick中断服务程序:
- 编写一个中断服务程序来处理SysTick中断。这个中断服务程序将在每个1ms的时间间隔内被调用。
实例代码
#include "./SYSTEM/delay/delay.h"
static uint16_t g_fac_us = 0; /* us延时倍乘数 */
/**
* [url=home.php?mod=space&uid=159083]@brief[/url] 初始化延迟函数
* @param sysclk: 系统时钟频率, 即CPU频率(HCLK),单位 Mhz
* @retval 无
*/
void delay_init(uint16_t sysclk)
{
SysTick->CTRL |= (1 << 2); /* SYSTICK使用系统时钟源,频率为HCLK */
g_fac_us = sysclk ; /* 不论是否使用OS,g_fac_us都需要使用,作为1us的基础时基 */
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; /* 开启SYSTICK */
SysTick->LOAD = 0XFFFFFF; /* 注意systick计数器24位,所以这里设置最大重装载值 */
}
/**
* @brief 延时nus
* @note 无论是否使用OS, 都是用时钟摘取法来做us延时
* @param nus: 要延时的us数.
* @note nus取值范围: 0 ~ (2^32 / g_fac_us) (g_fac_us一般等于系统主频, 自行套入计算)
* @retval 无
*/
void delay_us(uint32_t nus)
{
uint32_t ticks;
uint32_t told, tnow, tcnt = 0;
uint32_t reload;
reload = SysTick->LOAD; /* LOAD的值 */
ticks = nus * g_fac_us; /* 需要的节拍数 */
told = SysTick->VAL; /* 刚进入时的计数器值 */
while (1)
{
tnow = SysTick->VAL;
if (tnow != told)
{
if (tnow < told)
{
tcnt += told - tnow; /* 这里注意一下SYSTICK是一个递减的计数器就可以了. */
}
else
{
tcnt += reload - tnow + told;
}
told = tnow;
if (tcnt >= ticks)
{
break; /* 时间超过/等于要延迟的时间,则退出. */
}
}
}
}
/**
* @brief 延时nms
* @param nms: 要延时的ms数 (0< nms <= (2^32 / g_fac_us / 1000))(g_fac_us一般等于系统主频, 自行套入计算)
* @retval 无
*/
void delay_ms(uint16_t nms)
{
delay_us((uint32_t)(nms * 1000)); /* 普通方式延时 */
}
|