STM32F407VET6 学习笔记3:内核定时器SystemTick(SysTick)初始化中断

今日继续学习使用嘉立创购买的 立创梁山派天空星,芯片是 STM32F407VET6

主要是在学习移植UC/OS III系统时,需要我掌握好内核定时器SystemTick,以掌控整个实时操作系统的节拍,但我之前并未过多研究单片机的内核定时器,因此同步学习一下

文章目的是理解内核定时器SystemTick初始化,并能够自己添加上SystemTick的中断功能

文章提供测试代码讲解、完整工程下载、测试效果图

【立创·天空星STM32F407VET6】入门手册:

【立创·天空星STM32F407VET6】入门手册 - 飞书云文档 (feishu.cn)

目录

系统定时器SysTick:

SysTick相关寄存器:

STK_CTRL 控制寄存器:

STK_LOAD 重载寄存器:

STK_VAL 当前值寄存器:

STK_CALRB 校准值寄存器:

SysTick相关函数:

SysTick定时周期计算方法:

配置系统时钟新增中断功能:

SysTick初始化:

SysTick中断服务函数:

测试效果图:

整体测试工程下载:

网上学习资料网址贴出:


系统定时器SysTick:

SysTick定时器可用作标准的下行计数器,是一个24位向下计数器,有自动重新装载能力,可屏蔽系统中断发生器。Cortex-M4处理器内部包含了一个简单的定时器,所有基于M4内核的控制器都带有SysTick定时器,这样就方便了程序在不同的器件之间的移植。SysTick定时器可用于操作系统,提供系统必要的时钟节拍,为操作系统的任务调度提供一个有节奏的“心跳”。正因为所有的M4内核的芯片都有Systick定时器,这在移植的时候不像普通定时器那样难以移植。

RCU 通过 AHB 时钟(HCLK)8 分频后作为 Cortex 系统定时器(SysTick)的外部时钟。通过对 SysTick 控制和状态寄存器的设置,可选择上述时钟或 AHB(HCLK)时钟作为 SysTick 时钟。

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

 

SysTick相关寄存器:

  • SysTick Control and Status Register (SysTick_CTRL): 用于控制SysTick定时器的启动、停止,选择时钟源,以及读取当前定时器的状态。

  • SysTick Reload Value Register (SysTick_LOAD): 设置定时器的重载值,即定时器从加载值递减到0所需的时钟周期数。

  • SysTick Current Value Register (SysTick_VAL): 读取或清除定时器的当前值。

  • SysTick Calibration Value Register (SysTick_CALIB): 提供一个校准值,用于实现与实际时钟频率无关的固定周期中断。

STK_CTRL 控制寄存器:

寄存器内有 4 个位具有意义

    第 0 位:ENABLE,Systick 使能位(0:关闭 Systick 功能;1:开启 Systick 功能)
    第 1 位:TICKINT,Systick 中断使能位(0:关闭 Systick 中断;1:开启 Systick 中断)
    第 2 位:CLK SOURCE,Systick 时钟源选择(0:使用 HCLK/8 作为 Systick 时钟;1:使用 HCLK 作为 Systick 时钟)
    第 16 位:COUNT FLAG,Systick 计数比较标志,当计数到0时,置1;定时器开始重新计数时(CLK_LOAD重新写入数值)自动清零。

 

STK_LOAD 重载寄存器:

Systick 是一个递减的定时器,当定时器递减至0 时,重载寄存器中的值就会被重装载,继续开始递减。STK_LOAD 重载寄存器是个24 位的寄存器最大计数0xFFFFFF。

STK_VAL 当前值寄存器:

24 位的寄存器,读取时返回当前倒计数的值,写它则使之清零,同时还会清除在 SysTick 控制及状态寄存器中的 COUNTFLAG 标志。

 

STK_CALRB 校准值寄存器:

用于存储或调整时钟的校准值。这在需要精确时间计数的应用中非常重要,例如实时操作系统(RTOS)或需要精确时间戳的应用。

SysTick相关函数:

SysTick定时器的使用主要有:

SysTick_Config()函数

     SysTick_Config()函数主要用来设置定时时间

void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)函数

     systick_clksource_set()函数用来选择SysTick时钟源

SysTick定时周期计算方法

通过对初始化函数的解读可以了解到SysTick 的 时钟源来自于HCLK(不分频)、频率168M:

	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); //Systick 时钟源频率168M

由此我们知道了SystemCoreClock =168 000 000

带入计算式:

SysTick_LOAD = (SystemCoreClock / TickRate) - 1

其中:

SysTick_LOAD 是SysTick的 计数寄存器重载值

TickRate 就是你希望的周期,如果是1000Hz(即1ms),就填1000即可

这部分初始化函数调用书写大致如下:

    uint32_t reload = SystemCoreClock / 1000 - 1; // 1ms中断频率  
    SysTick->LOAD = reload;  

配置系统时钟新增中断功能:

配置SysTick 定时器步骤大致如下:

1、设置时钟源

2、设置 SysTick_LOAD 重载值(需要中断就打开中断)

3、清零当前计数器值

4、打开SysTick 定时器

5、如果需要还可配置定时器的NVIC中断优先级

本文这部分实践内容主要是打开 SysTick中断,频率1ms

并借此中断服务函数与标志位组合达到每1s串口发送数据的程序效果:

 

SysTick初始化:

/**
 * This function will initial stm32 board.
 */
void board_init(void)
{
    /* NVIC Configuration */
#define NVIC_VTOR_MASK              0x3FFFFF80
#ifdef  VECT_TAB_RAM
    /* Set the Vector Table base location at 0x10000000 */
    SCB->VTOR  = (0x10000000 & NVIC_VTOR_MASK);
#else  /* VECT_TAB_FLASH  */
    /* Set the Vector Table base location at 0x08000000 */
    SCB->VTOR  = (0x08000000 & NVIC_VTOR_MASK);
#endif

	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); //Systick 时钟源频率168M
	
	  // 计算SysTick重装载值(SystemCoreClock为168MHz,希望SysTick中断频率为1ms(1000 Hz))
		//SysTick_LOAD = (SystemCoreClock / TickRate) - 1
    uint32_t reload = SystemCoreClock / 1000 - 1; // 1ms中断频率  
    SysTick->LOAD = reload;  

    // 清除SysTick当前值并启动SysTick,同时使能中断
    SysTick->VAL  = 0; // 清空当前值  
    SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;  

    /* 设置NVIC优先级分组 */  
    // 4位抢占优先级和0位子优先级  
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);   
    /* 设置SysTick中断的优先级 */  
    // 设置SysTick的抢占优先级为3(最低),没有子优先级(因为分组4没有子优先级位)  
    NVIC_SetPriority(SysTick_IRQn, 3); // 注意:优先级值根据分组设置可能有所不同 
		
}

SysTick中断服务函数:

首先我们要注释掉:#include "stm32f4xx_it.h" 文件中的 中断服务函数定义的代码:

然后在我们选定的位置编写中断服务函数:

我是选择在主函数下面编写了,这样可以更直白观察:这个函数里面包括了一个打印函数,用于串口测试:

其中的 i 与 m 只是定义的int类型的全局变量,计数测试用的:

//SysTick中断服务函数:
void SysTick_Handler(void)
{
    // 在这里处理SysTick中断  
    // 例如,可以更新一个时间戳,或者触发某个周期性任务  
    // 清除SysTick的中断标志位(如果需要的话,某些STM32库会自动处理)  
    SysTick->CTRL &= ~SysTick_CTRL_COUNTFLAG_Msk;
		i++;
			if(i==1000)
			{
				i=0;m++;
				UsartPrintf(USART1," %d seconds past \r\n",m);	//打印测试字符串
			}
    // ... 其他中断处理代码 ...  
}

测试效果图:

通过串口助手时间戳对比看出,确实是1s发送了一次串口数据:

整体测试工程下载:

https://download.csdn.net/download/qq_64257614/89336131

 

网上学习资料网址贴出:

STM32F407的系统定时器_stm32f407系统定时器-CSDN博客

 

 

  • 29
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
当然可以!下面是一个简单的示例代码,用于在STM32F407VET6上配置和使用定时器中断: 首先,需要包含相应的头文件: ```c #include "stm32f4xx.h" ``` 然后,需要进行一些初始化设置: ```c void TIM_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; // 使能定时器时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 配置定时器参数 TIM_TimeBaseStructure.TIM_Period = 1000 - 1; // 定时器周期为1ms TIM_TimeBaseStructure.TIM_Prescaler = 8400 - 1; // 定时器预分频为8400,即定时器时钟为10kHz TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); // 配置定时器中断 NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); // 使能定时器更新中断 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); // 启动定时器 TIM_Cmd(TIM2, ENABLE); } ``` 接下来,需要编写定时器中断处理函数: ```c void TIM2_IRQHandler(void) { if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { // 在这里编写定时器中断处理代码 // 清除中断标志位 TIM_ClearITPendingBit(TIM2, TIM_IT_Update); } } ``` 最后,在主函数中调用定时器配置函数即可: ```c int main(void) { // 初始化系统时钟等 // 配置定时器 TIM_Configuration(); while (1) { // 主循环代码 } } ``` 这是一个简单的定时器中断示例,你可以根据自己的需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NULL指向我

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值