GD32系列总结 - systick介绍及使用

GD32系列总结 - systick介绍及使用

写在前面

从本文开始,后面的基本都会基于STM32和CubeMX使用的角度来介绍,搞了很久还是没搞到GD32的开发板,想着花钱去买一个,还不如用手上现成的STM32,基本上无差,关于CubeMX的使用,主要是基于LL库,可能也会有HAL库的使用。

SysTick

什么是SysTick

引用一段《Cortex-M3权威指南(中文).pdf》中关于SysTick定时器的一段话

SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)。在以前,大多操作系统需要一个硬件定时器来产生操作系统需要的滴答中断,作为整个系统的时基。例如,为多个任务许以不同数目的时间片,确保没有一个任务能霸占系统;或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。
Cortex‐M3处理器内部包含了一个简单的定时器。因为所有的CM3芯片都带有这个定时器,软件在不同 CM3器件间的移植工作得以化简。该定时器的时钟源可以是内部时钟(FCLK,CM3上的*运行时钟),或者是外部时钟( CM3处理器上的STCLK信号)。不过,STCLK的具体来源则由芯片设计者决定,因此不同产品之间的时钟频率可能会大不相同,你需要检视芯片的器件手册来决定选择什么作为时钟源。

这段话将SysTick已经介绍的很详细了,其实总结下来就是:

  1. 一个24位定时器,只能向下计数
  2. 嵌入系统内核之中,所有Cortex-M3内核均有该定时器,因此考虑到代码可移植性,大家多选其作为系统滴答定时器,用来产生系统时间
  3. 其定时器时钟源需用户配置,那么在移植时需要考虑不同的工程对SysTick定时器始终的配置

SysTick寄存器

一共有4个相关寄存器:

SysTick控制及状态寄存器(地址:0xE000_E010):
GD32系列总结 - systick介绍及使用
SysTick重装载数值寄存器(地址:0xE000_E014):
GD32系列总结 - systick介绍及使用
SysTick当前数值寄存器(地址:0xE000_E018):
GD32系列总结 - systick介绍及使用
SysTick校准数值寄存器(地址:0xE000_E01C)
GD32系列总结 - systick介绍及使用
其中,校准数值寄存器一般没有使用,大致意思就是如果读SKEW位为0,则可以将TENMS的值直接写入重装载寄存器,以此可以不用计算,直接产生10ms的滴答中断,但是具体怎么使用我也还没搞明白,我手上的芯片返回的SKEN位一直是1,而TENMS寄存器却定义的是9KHz时钟下的10ms计数值,无论我配置的时钟是72M还是9M,还希望有研究的朋友可以评论告诉我一下。
除去校准数值寄存器,还有三个寄存器,结合上面的描述,总结一下SysTick寄存器使用步骤:

  1. 选择时钟源,如果选择外部时钟,注意配置的SysTick定时器时钟源频率。
  2. 设置重装载值
  3. 使能INT和定时器

CubeMX配置

不需要任何配置

代码示例

时钟初始化

LL_Init1msTick(72000000);/*参数位SYSTICK时钟频率*/

注意:LL库的初始化不会默认开启中断,需手动使能中断

__STATIC_INLINE void LL_InitTick(uint32_t HCLKFrequency, uint32_t Ticks)
{
  /* Configure the SysTick to have interrupt in 1ms time base */
  SysTick->LOAD  = (uint32_t)((HCLKFrequency / Ticks) - 1UL);  /* set reload register */
  SysTick->VAL   = 0UL;                                       /* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_ENABLE_Msk |                    /* Enable the Systick Timer */
                   /*这一行需要手动加*/
                   SysTick_CTRL_TICKINT_Msk;                    /* Enable the Systick Timer INT*/
}

然后就可以在中断立马调用系统函数了

void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */

  /* USER CODE BEGIN SysTick_IRQn 1 */
  Task_1msNotification();
  /* USER CODE END SysTick_IRQn 1 */
}
上一篇:python数据模型


下一篇:LeetCode 49. 二叉树的右视图