STM32学习笔记--系统滴答定时器

目录

一、什么是系统滴答定时器

二、如何配置系统滴答定时器

1、系统滴答定时器框图

2、3个寄存器控制SysTick时钟

3、程序思路

三、具体使用系统滴答定时器

需求1:延时

需求2:定时中断

定时器的本质:有规律的计数

            有规律:计数速度来自时钟频率

            计数  :定时器中可控计数器

定时器形成时间的原理:(时间)

            通过时钟源可知1s计数次数(计数频率)

            通过要定时的秒数 * 每秒计数的次数  来决定定时器中的计数器所需要计数的次数

一、什么是系统滴答定时器

        系统滴答定时器又称为内核级定时器

        作用:延时定时中断(给实时操作系统提供时钟节拍-->任务调度)

      系统滴答定时器是CM4核心内部集成的一个简单定时器硬件模块,SysTick系统滴答定时器属于NVIC一部分

注意:

        延时和定时中断的区别

延时:阻塞内核执行程序,等时间到了才能继续执行

  必须要CPU原地等待的情况

定时中断:通过定时器所定的时间,时间未到内核执行主程序;时间到了,内核执行执行紧急事件

  每隔多久要做什么事

二、如何配置系统滴答定时器

1、系统滴答定时器框图

系统滴答定时器是一个24bit递减定时器   24bit --->设置数数大小   0 - 16777215

时钟源的选择

系统内部时钟-HSI经过PLL锁相环得到系统时钟频率,再提供给内核(系统滴答定时器) 168MHZ

168MHZ == 168000000次/s == 168000次/ms == 168次/us

计数器的最大值;2^24 == 16777216

计时最大值:   16777216 / 168  == 99864us == 99ms

系统外部时钟---HSE经过PLL锁相环得到系统时钟频率,再经过8分频后提供给系统滴答定时器 21MHZ

21MHZ == 21000000次/s = 21000次/ms == 21次/us

计数器的最大值;2^24 == 16777216

计时最大值:   16777216 / 21  ==  798915us == 798ms

注意:一般情况下我们使用HSE经过PLL锁相环输出的频率来作为系统时钟,它可以用来驱动APB,DMA,Cortex等系统

2、3个寄存器控制SysTick时钟

3、程序思路

延时:

在时钟树里可以看到,对于Cortex时钟,是选用经过八分频的外部时钟源 21Mhz

计1μs:我们向计数器里放入21

计1ms:我们向计数器里放入21000
1ms(毫秒)=1μs(微秒)
配置滴答时钟步骤如下:

//注意:系统滴答不需要打开时钟

//1、时钟源选择           控制及状态寄存器的2号位    外部时钟 21M

//2、写入重载值           通过延时的时间写入重载值

//3、清空当前值寄存器     随便写一个值到当前值寄存器

//4、使能计数器           控制及状态寄存器的0号位

//5、等待计数器计数完成   控制及状态寄存器的16号位

//6、关闭定时器           控制及状态寄存器的0号位

中断定时:

系统滴答定时器中断初始化配置函数(触发定时中断的时间)

{

/*系统滴答定时器配置*/

//时钟源选择

//重载值寄存器

//当前值清零

//中断使能

/*NVIC控制器配置*/

//优先级分组

//计算编码值

//设置具体中断源

//使能计数器

}

系统滴答定时中断服务函数

{

//清除中断标志位

//紧急事件

}

为什么系统滴答定时器不使能NVIC响应通道?

因为系统滴答定时器属于内核的,而NVIC模块响应的是片上外设中断源的开关

三、具体使用系统滴答定时器

需求1:延时

/***************************************
*函数名			:SysTick_delay_ms
*函数功能		:系统滴答毫秒级延时函数
*函数参数		:u16 ms
*函数返回值	:无
*函数描述		:用21M时钟,21000/ms       
							最大延时毫秒数798ms
****************************************/
void SysTick_delay_ms(u16 ms)
{
	//时钟源选择
	SysTick->CTRL &= ~(1 << 2);
	//写入重装载值
	SysTick->LOAD = ms * 21000 - 1;
	//清空当前值 
	SysTick->VAL = 0xff;
	//使能计数器
	SysTick->CTRL |= 1 << 0;
	//等待计数完成
	while(!(SysTick->CTRL & (1 << 16)));
	//关闭计数器
	SysTick->CTRL &= ~(1 << 0);
	
	
}

需求2:定时中断

每301ms 切换LED1 状态

每522ms 切换LED2转态

每655ms 切换LED3转态

每900ms 切换LED4转态

主程序按键控制蜂鸣器开关

分析:

每1ms进一次定时中断,在定时中断里面计数,

计数变量到301的时候,改变LED1的状态

计数变量到522的时候,改变LED2的转态

.......

系统滴答毫秒级定时中断函数:



/***************************************
*函数名			:SysTick_delay_ms
*函数功能		:系统滴答毫秒级定时中断函数
*函数参数		:u16 ms
*函数返回值	:无
*函数描述		:用21M时钟,21000/ms       
							最大延时毫秒数798ms
****************************************/
void SysTick_interrupt_ms_init(u16 ms)
{
	/*系统滴答定时器控制器配置*/
	//时钟源选择
	SysTick->CTRL &= ~(1 << 2);
	//写入重装载值
	SysTick->LOAD = ms * 21000 - 1;
	//清空当前值 
	SysTick->VAL = 0xff;

	//中断使能
	SysTick->CTRL |= 1 << 1;
	
	/*NVIC控制器配置*/
	u32 pri = NVIC_EncodePriority (5, 1,2);//计算优先级编码值,设置抢占和响应的级别值
	NVIC_SetPriority(SysTick_IRQn, pri);//设置具体某个中断源的优先级
	
	//使能计数器
	SysTick->CTRL |= 1 << 0;
}

中断服务函数:

/*
函数名:SysTick_IRQHandler
函数功能:系统时钟中断服务函数
返回值:void
形参:void
函数说明:

*/
//用数组分别存放四个LED中断触发的次数
u16 Sys_cnt[5];
void SysTick_Handler(void)
{
	//清除中断标志位
	//SysTick->VAL = 0xff;
	SysTick->CTRL &= ~(1 << 16);
	//紧急事件
	Sys_cnt[1]++;
	Sys_cnt[2]++;
	Sys_cnt[3]++;
	Sys_cnt[4]++;
  if(Sys_cnt[1] == 301)
	{
		Sys_cnt[1] = 0;
		LED1_OVERTURN;
	}
	if(Sys_cnt[2] == 522)
	{
		Sys_cnt[2] = 0;
		LED2_OVERTURN;
	}
	if(Sys_cnt[3] == 655)
	{
		Sys_cnt[3] = 0;
		LED3_OVERTURN;
	}
	if(Sys_cnt[4] == 900)
	{
		Sys_cnt[4] = 0;
		LED4_OVERTURN;
	}

}

系统滴答定时器最主要的是实时操作系统提供时钟节拍-->任务调度,所以这些基本配置可以使用库函数,方法如下

调用系统库函数实现系统滴答1毫秒级中断

原型:

uint32_t SysTick_Config(uint32_t ticks)

二次封装:

SysTick_timer_ms(u8 timer)

{

SysTick_Config(168000*timer)

}

注意:

使用的时钟源是168MHZ

此函数相当于系统滴答定时器初始化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值