SysTick系统滴答定时器(STM32F4xx系列)

  1. 定时器概念
    1.1 定时器的含义
    1.2片上外设的定时器
    1.3定时/延时原理
  2. 系统滴答定时器
    2.1 为什么需要系统滴答定时器
    2.2 系统滴答定时器概述
    2.3 系统滴答定时器框架
    2.4 系统滴答定时器相关寄存器
  3. 系统滴答定时器程序设计
    3.1 查询方式
    3.2 中断方式

  本章学习SysTick系统滴答定时器,在学习一个内容之前,我们要学会对于一个学习内容提出疑问,带着疑问去学习引导自己一步步的深入。
首先,对于系统滴答定时器的几个问题如下:
1.定时器是什么?
2.定时器的作用是什么?
3.有哪些定时器?
4.系统滴答定时器又是什么?

针对以上的问题,来进入以下学习。

定时器概述

定时器的含义

  定时器顾名思义是用来做定时延时功能的,而通过定时器,我们还需要引出计数器的概念,在我们使用定时器的同时,通常少不了计数器的作用,这些都是他们的基础功能。

片上外设的定时器

在之前我们学习的过程中,我们通常了解到的都是写属于片上外设的定时器,而它们又区分于基本定时器、通用定时器、高级定时器
基本定时器: 主要的功能有定时、延时和触发D/A转换(不常用),相当一部分单片机都没有(TIM6/7)。
通用定时器: 包含了基本定时器的所有功能,除此之外还包含了捕获输入比较输出的功能。
捕获输入:红外接收,按键时长等
比较输出:电机转速、呼吸灯、红外发射等
高级定时器: 包含了通用定时器的所有功能,另外还有死区操作,刹车功能等。
计数器:
看门狗: 检测程序是否跑飞、复位。
RTC: 实时时钟、日历、闹钟等。
在这里不对作为片上外设的这些定时器进行讲解。

定时/延时原理

  首先对于定时器如何去用,我们需要知道使用定时器进行定时延时需要哪些东西。
  我们想要使用定时器,肯定需要去设定一个我们需要定时的时间,而这个时间又要需要一个时钟源来提供一个时钟频率来作为基准时钟,例如:一个芯片内核主频84MHz,而一个计数周期就是1/84us。但我们使用定时器肯定不只是为了定时这么点时间的,所有这就需要一个设定一个计数的次数,来得到更多的定时时间,而这里就引出了重装载值这一概念来放置计数次数的,那么这里就要再引出计数器来实现从一个初始值每过一个基准时钟的时间记一次数,从而达到重装载值要求计数次数的时间。
然而,对于计数器,不同的定时器支持的计数方向也有不同,有的以递减形式,有的以递增形式,还有中心对齐形式。
SysTick系统滴答定时器(STM32F4xx系列)_第1张图片

系统滴答定时器

从上面的内容我们可以知道,单片机中有许多定时器片上外设,那我们又为什么要用系统滴答定时器呢?

为什么需要系统滴答定时器

我们知道,单片机上有基本定时器、通用定时器、高级定时器这些定时器,但这些定时器又都属于片上外设,不同的芯片上所使用的定时器又不一定相同,所以当考虑到移植问题,系统滴答定时器的作用就来了。

系统滴答定时器概述

  SysTick定时器被捆绑在NVIC(内核中的中断控制器)中,用于产生SysTick异常。在以前,操作系统还有所有使用了时基的系统,都必须一个硬件定时器来产生需要的“滴答”中断,作为整个系统的时基。滴答中断对操作系统尤其重要。例如,操作系统可以为多个任务许以不同数目的时间片,确保没有一个任务能霸占系统;或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。
  固定时间内某个任务调用CPU,不会让一个任务独占。速度非常快的情况下,人感受不出来。
  Systick定时器属于内核级模块。
  要查看它的相关说明需要查看内核级的手册。
系统滴答定时器的本质: 就一个定时器,只不过这个定时器在核心里面(只有一个作用:定时)

系统滴答定时器框架

计数方向: 递减
重装载值: 24位
时钟源: 外部参考时钟和内核时钟,外部参考时钟需要通过系统时钟分频而来(具体可参考时钟树)
外部时钟: 84M/8=10.5MHz 最长计数时长:大概1597ms
内核时钟: 84MHz 最长计数时长:大概199ms
SysTick系统滴答定时器(STM32F4xx系列)_第2张图片

系统滴答定时器相关寄存器

SysTick系统滴答定时器(STM32F4xx系列)_第3张图片

SysTick系统滴答定时器(STM32F4xx系列)_第4张图片
SysTick系统滴答定时器(STM32F4xx系列)_第5张图片
SysTick系统滴答定时器(STM32F4xx系列)_第6张图片
SysTick系统滴答定时器(STM32F4xx系列)_第7张图片

系统滴答定时器程序设计

查询方式

配置流程:

  1. 选择时钟源
  2. 配置重装载值
  3. 清零当前值
  4. 使能定时器
  5. 判断标志位
/*
函 数 名:Systick_ms
函数功能:系统滴答定时器毫秒级延时
返 回 值:无
形    参:u32 ms
备    注:
查询式 -- 毫秒级延时
84MHz-8分频-10.5MHz-1/10500ms
在延时完成后,关闭定时器,防止主函数中因其他语句导致延时不准确
*/
void Systick_ms(u32 ms)
{
	SysTick->CTRL &= ~(1<<2);			//选择外部参考时钟
	
	SysTick->VAL  &= ~(1<<0);			//计数器当前值清零										//系统滴答定时器初始化
	SysTick->LOAD  = 10500*ms-1;				//重装载值
	
	SysTick->CTRL |= (1<<0);						//系统滴答定时器使能
	
	while(!(SysTick->CTRL & (1<<16)));	//等待计时完成
	
	SysTick->VAL  &= ~(1<<0);						//计数器当前值清零
	
	SysTick->CTRL &= ~(1<<0);						//关闭系统滴答定时器
}
中断方式

同时还可以选择配置控制与状态寄存器第一位产生延时中断

//时间片任务参数
u32 time1[2] = {0,1000};
u32 time2[2] = {0,500};
/*
函 数 名:Systick_interrupt
函数功能:系统滴答定时器初始化
返 回 值:__STATIC_INLINE uint32_t
形    参:u32 arr -- 重装载值
备    注:
可参考系统内核文件中的函数
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
中断方式 -- 毫秒级
对于该种延时,相关外设的操作需要让入中断服务函数中
该种延时所能延时的时间并不会很长(重装载值只有24位)
*/
__STATIC_INLINE uint32_t Systick_interrupt(u32 arr)
{
	if ((arr - 1UL) > SysTick_LOAD_RELOAD_Msk)
  {
    return (1UL);                                                   /* Reload value impossible */
  }
	Systick_Config();							//系统滴答定时器初始化
	SysTick->CTRL |= (1<<2);			//选择内核参考时钟
	SysTick->CTRL |=  (1<<1);			//使能中断
	SysTick->VAL  &= ~(1<<0);			//清零
	
	NVIC_SetPriority(SysTick_IRQn,NVIC_EncodePriority(7-5,0,2));
	
	SysTick->LOAD  =  arr-1;			//选择延时1s的重装载值
	SysTick->CTRL |=  (1<<0);			//系统滴答定时器使能	
	
	return (0UL);
}

/*
函 数 名:Sys_config
函数功能:系统滴答定时器初始化
返 回 值:无
形    参:
备    注:
中断方式 -- 选择内核时钟(利用内核系统文件当中自带的函数)

*/
void Sys_config(void)
{
	if(Systick_interrupt(84000))  //定时1ms -- 判断重装载值是否超过范围
	{
		while(1);
	}
}

/*
函 数 名:SysTick_Handler
函数功能:系统滴答定时器中断服务函数
返 回 值:无
形    参:无
备    注:
*/
u32 stime = 0;			//计时标志
void SysTick_Handler(void)
{
	stime++;
	time1[0]++;
	time2[0]++;
}

/*
函 数 名:Sys_inter_ms
函数功能:系统滴答定时器延时函数
返 回 值:无
形    参:u32 mtime
备    注:
中断延时函数
该种延时是通过设置一个全局变量,
通过系统文件中的定时器初始化函数来进行初始化,设置计数一次定时时间
在中断服务中让计时标志自增
再通过该延时函数定义一个中间变量记录进入该函数的起始时间
再等待全局变量的计时标志的变化和起始时间的差值来进行延时
该种延时还能够提高延时的上限
*/
void Sys_inter_ms(u32 mtime)
{
	u32 temp = 0;
	temp = stime;
	
	while((stime-temp)<=mtime);
	
}

//  if(time2[0]>=time2[1])		//时间片任务
//			{
//				LED3_TOGGLE;
//				time2[0] = 0;
//			}

你可能感兴趣的:(Crotex-M4笔记,stm32,单片机,arm)