renzheshengui 发表于 2025-7-10 15:43

CW32F030C8T6: Systick定时器(滴答定时器)精解

CW32F030C8T6 Systick定时器概述
SysTick定时器可用作标准的下行计数器,是一个24位向下计数器,有自动重新装载能力

可屏蔽系统中断发生器。Cortex-M0+处理器内部包含了一个简单的定时器,所有基于M0+内核的控制器都带有SysTick定时器,这样就方便了程序在不同的器件之间的移植。

SysTick定时器可用于操作系统,提供系统必要的时钟节拍,为操作系统的任务调度提供一个有节奏的“心跳”。

SysTick定时器设定初值并使能之后,每经过1个系统时钟周期,计数值就减1,减到0时,SysTick计数器自动重新装载初值并继续计数,同时内部的COUNTFLAG标志位被置位,触发中断(前提开启中断)。



Systick寄存器配置



关键寄存器包括:

CTRL:控制寄存器

Bit 2: CLKSOURCE(时钟源选择,0=HCLK/8,1=内核时钟)
Bit 1: TICKINT(中断使能,1=计数到0时触发中断)
Bit 0: ENABLE(定时器使能)
LOAD:重载值寄存器

写入24位初始值,决定定时周期。
VAL:当前值寄存器

读取当前计数值,写入任意值会清零计数器。
CALIB:校准寄存器(通常无需修改)

InitTick函数
主要作用是初始化SysTick定时器,确保它能够在指定的频率(通过uwTickFreq定义)产生中断,并配置中断的优先级。



函数说明

__WEAK关键字表明这是一个弱定义函数,意味着如果在其他地方有同名的强定义函数,那么会优先使用强定义版本。这通常用于提供默认的实现,允许用户在需要时替换或扩展功能。
参数HclkFreq是系统时钟频率,单位是Hz(赫兹),用于计算SysTick的重载值。
SysTick_Config函数配置SysTick定时器,使其在每个uwTickFreq Hz频率下产生中断。uwTickFreq是你希望的SysTick中断频率,单位是Hz。
HclkFreq / (1000U / uwTickFreq)计算每次中断间隔对应的SysTick重载值。HclkFreq是48MHz,且希望每毫秒产生一次中断(即uwTickFreq=1000Hz),则计算结果为48。
如果SysTick_Config返回值大于0,表示配置失败(例如,因为请求的中断频率超过SysTick的最大支持频率),则函数直接返回,不继续执行后续配置。
这部分代码尝试设置SysTick中断(SysTick_IRQn)的优先级为TICK_INT_PRIORITY。__NVIC_PRIO_BITS定义了可以设置的优先级位数,如果TICK_INT_PRIORITY的值有效(即小于最大优先级数),则使用NVIC_SetPriority函数设置优先级。
如果TICK_INT_PRIORITY超出允许范围,则函数同样提前返回,不更改中断优先级。



案例一.实现100MS程序块
时钟与SysTick初始化

__IO uint32_t uwTick;
uint32_t uwTickPrio   = (1UL << __NVIC_PRIO_BITS); /* Invalid PRIO */
TickFreqTypeDef uwTickFreq = TICK_FREQ_DEFAULT;/* 1KHz */


RCC_HSI_Enable(RCC_HSIOSC_DIV2);       //启用HSI时钟,分频系数为2(输出24MHz)
InitTick(24000000);                  //基于24MHz时钟源初始化SysTick计时器


GPIO配置

CW_SYSCTRL->AHBEN_f.GPIOB = 1;         //使能GPIOB的AHB总线时钟
GPIO_InitTypeDef GPIO_InitStruct;      //定义GPIO初始化结构体
GPIO_InitStruct.Pins = GPIO_PIN_8 | GPIO_PIN_9;//选择PB8和PB9引脚
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;      //设置为推挽输出模式
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;         //设置输出速度为高速
GPIO_Init(CW_GPIOB, &GPIO_InitStruct); //应用配置到GPIOB
PB08_SETLOW();                         //初始化PB8为低电平
PB09_SETLOW();                         //初始化PB9为低电平


主循环逻辑

cnt = GetTick();                     //记录当前系统时间(单位:毫秒)
while (1)
{
    if ((GetTick() - cnt) > 100)       //检查是否达到100ms间隔
    {
      cnt = GetTick();               //更新计时基准
      PB08_TOG();                  //翻转PB8电平状态
      PB09_TOG();                  //翻转PB9电平状态
    }
}


SysTick中断处理函数

void SysTick_Handler(void)
{
    /* USER CODE BEGIN SysTick_IRQn */
    uwTick += uwTickFreq;            //递增系统时间计数器(需确保uwTickFreq已定义)
    /* USER CODE END SysTick_IRQn */
}


uwTick:全局变量,记录系统运行时间。
uwTickFreq:定义为每次中断的时间增量(如1毫秒)。
关键点说明
硬件依赖:移植时仔细核对GPIO端口。
实际行为:代码操作的是PB8/PB9。
重载值不得超过24位最大值(0xFFFFFF)。



————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/weixin_43260261/article/details/148925145

脑洞星球居民 发表于 2025-7-11 12:17

这篇文章对SysTick定时器的解释非常详细,对于嵌入式开发来说,理解定时器的工作机制是非常重要的。

穷得掉渣大侠 发表于 2025-7-11 16:13

这篇文章对SysTick定时器的讲解非常详细,特别是对于嵌入式系统的开发者来说,理解定时器的工作机制对于任务调度和时序控制至关重要。
页: [1]
查看完整版本: CW32F030C8T6: Systick定时器(滴答定时器)精解