STM32--系统滴答SysTick

一、SysTick是什么?

Systick定时器是一个24bit的倒计时(向下计数)定时器,功能就是实现简单的延时。
SysTick 是一种系统定时器,通常在嵌入式系统中使用。它是 ARM Cortex-M 处理器的一个特殊定时器,用于提供系统级的定时服务。SysTick 可以用于生成定时中断,以便执行特定的任务或进行系统级的时间跟踪。
例如:计数初值为100,经过一个时钟周期后,计数值减一,即99,98,97……1,0;计数至0后,又重新开始从100开始倒计数至0。​ 可以借此做精准延时。

二、SysTick框架图

因为SysTick是属于内核的一部分,其被捆绑在NVIC中,用于产生SYSTICK异常。
在这里插入图片描述

三、SysTick组成

​ SysTick包含四个寄存器,都是24位的寄存器,分别是:
(1) SysTick->CTRL

SysTick控制及状态寄存器 (-- 0xE000 E010

在这里插入图片描述

(2) SysTick->LOAD

SysTick重装载寄存器 – 0xE000 E014
在这里插入图片描述

(3) SysTick->VAL

SysTick当前值寄存器 – 0xE000 E018
在这里插入图片描述

(4) SysTick->CALIB

SysTick校准值寄存器 – 0xE000 E01C
在这里插入图片描述

四、SysTick时钟知识点

(1)首先明白频率(Hz)与时间(S)的转换。
●1Hz代表每秒周期震动1次, 60Hz代表每秒周期震动60次。假如滴答时钟的频率是72MHZ,72MHz表示每秒钟有72,000,000个时钟周期。那让滴答时钟计1次,时间过去了1/72μs,也就是一个时钟周期为1/72000000 s =1/72 us。
●定时1us,就需要72个时钟周期。
●定时1s,就需要72000个时钟周期。
(2)为什么需要装载预期值-1?
答:装载值就是装载的时钟周期个数。SysTick 定时器的计数是从 LOAD 装载值寄存器的值递减到零的,所以如果你希望实现 n 个时钟周期的延时,你需要将 LOAD 寄存器设置为 n - 1。如系统时钟频率为72MHz,经过8分频后,频率为9MHz。即1s震动9000 000个周期。所以装载值为8999 000,计数器从8999000减到0,总共经过 9000000 个时钟周期,则正好为1s的时间,即实现定时1s。
(3)
(3)时钟源选择—库函数( SysTick_CLKSourceConfig(时钟源)):

#define SysTick_CLKSource_HCLK_Div8    ((uint32_t)0xFFFFFFFB)   //经过8分频的外部时钟
#define SysTick_CLKSource_HCLK         ((uint32_t)0x00000004)   //内部时钟
#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \
                                       ((SOURCE) == SysTick_CLKSource_HCLK_Div8))
                                       
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)   //时钟源选择库函数
{
  /* Check the parameters */
  assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));
  if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
  {
    SysTick->CTRL |= SysTick_CLKSource_HCLK;
  }
  else
  {
    SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;
  }
}

时钟源选择—寄存器

SysTick->CTRL &=~(1<<2); //选择外部时钟,必须清零默认是1内核时钟
SysTick->CTRL |=(1<<2); //选择内核时钟。

在这里插入图片描述

(4)重装载值—库函数( SysTick_Config(装载值))
SysTick_Config(72000) ;滴答定时器的参数是72000即计数72000。使用这个函数不需要预期值-1。直接设为预期值即可。(因为我们使用72M的时钟频率,即1s计数72M=72000000次,那1ms计数72000次,所以计数值为72000)

static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{ 
  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /* Reload value impossible */
                                                               
  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;      /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority for Cortex-M0 System Interrupts */
  SysTick->VAL   = 0;                                          /* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | 
                   SysTick_CTRL_TICKINT_Msk   | 
                   SysTick_CTRL_ENABLE_Msk;                    /* Enable SysTick IRQ and SysTick Timer */
  return (0);                                                  /* Function successful */
}

(4)延时范围
●如系统时钟频率为72MHz,经过8分频后为9MHz。1s的时钟周期个数为9000 000,1ms的时钟周期个数为9000,1us的时钟周期个数为9。
●VAL寄存器以及LOAD寄存器都是24位的,它的最大值是1111 1111 1111 1111 1111 1111,转化乘十进制后是16777215。即装载的最大十周周期个数为16777215。
级别的定时器,一次最大定时时长为:16777215 / 9000000 s。
毫秒级别的定时器,一次最大的定时时长16777215/9000 ms,也就是1864.135毫秒,由于对于毫秒只能取整,也就是1864毫秒。
微秒级别的定时器,一次最大定时时长是16777215/9=1864135 us。
这就是Systick定时器循环一次所能达到的最大定时时长。也就是装载值的最大范围。当然也可以通过循环嵌套来实现更长时间的定时。

五、SysTick两种功能

(1)延时功能:
只需要定时器工作一个周期,也就是从重装载值减到0的一个过程,执行一次后需要关闭定时器,不然它还会不停的从重装载值减到0然后又从重装载值减到0无限循环。
伪代码:

实现系统的us延时(参数)
{
   1.选择时钟 建议选择经过8分频后的外部时钟
   2.写入重装载值,设为预期值-13.清空计数器
   4。打开计数器
   5.等待时间到达,等待标志位置1
   6.关闭计数器
   7.清空计数器
}

具体代码:

//  uint32_t SystemCoreClock         = SYSCLK_FREQ_72MHz;        /*!< System Clock Frequency (Core Clock) */
void delay_init()
{
 
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);	 // 1.选择外部时钟  HCLK/8 
	s_fac_num=SystemCoreClock/8;				    //选择的经过8分频的外部时钟,所以要将系统时钟72Mhz/8。此时频率为9MHz。1s震动9 000 000 次。
	us_fac_num=Clock_Div8_after/1000000;            //1us 震动9次。1s=1000 000 us.
	ms_fac_num=(u16)fac_us*1000;					//1个ms需要的systick时钟数 。
}	

void delay_us(u32 nus)
{		
	u32 temp;	    	 
	SysTick->LOAD=nus*us_fac_num; 					//2.写入装载值  		 
	SysTick->VAL=0x00;        					//3.清空计数器(当前值)这里大家一定要注意,必须使得当前寄存器的值VAL等于0! SysTick->VAL  = (0x00);只有当VAL值为0时,计数器自动重载RELOAD。下面同理。
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;	//4.打开计数器,开始倒数,使能  
	do
	{
		temp=SysTick->CTRL;
	}while((temp&0x01)&&!(temp&(1<<16)));		//5.等待时间到达   
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;	//6.关闭计数器
	SysTick->VAL =0X00;      				    //7.清空计数器(当前值) 
}
void delay_ms(u16 nms)
{	 		  	  
	u32 temp;		   
	SysTick->LOAD=(u32)nms*ms_fac_num;				//时间加载(SysTick->LOAD为24bit)
	SysTick->VAL =0x00;							//清空计数器(当前值)
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;	//开始倒数  
	do
	{
		temp=SysTick->CTRL;
	}while((temp&0x01)&&!(temp&(1<<16)));		//等待时间到达   
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;	//关闭计数器
	SysTick->VAL =0X00;       					//清空计数器	  	    
} 

(2)中断功能:
利用中断,一定时间进一次中断,以此来实现一个时间片轮询的操作方式。这时候,就需要定时器一直计数了,所以不能计数完成后就关闭计数器了。

实现功能:每过1ms发送一次123456。

伪代码:

系统滴答的初始化代码
{
   1.选择外部滴答的时钟源
   2.配置系统滴答的重装载值,设为预期值-13.当前值清零--清空计数器
   4.打开中断使能 
   5.配置NVIC控制器
   6.开启定时器   
}
中断服务函数
{
	1.检测标志与清除标志;
	2.执行操作。
}

具体代码:

#include "SysTick.h"
u16 SysTick_us;
u16 SysTick_ms;
/*******************************
函数名:SysTick_Init
函数功能:初始化系统滴答,选择外部时钟
函数形参:u32 sysclk 系统时钟72(MHZ)
函数返回值:void
备注:开启1ms中断
********************************/
void SysTick_Init(u32 sysclk) //72HZ
{	
	SysTick->CTRL &=~(1<<2); //1.选择外部时钟,必须清零。默认是1,为内核时钟。
	SysTick_s=SystemCoreClock/8;           //9000 000     1s  //外部时钟8分频
	SysTick_us=SysTick_s/1000 000;           //9     1us  
	SysTick_ms=SysTick_s/1000;            //9 000  1ms
	
	SysTick->LOAD = SysTick_ms;//2.重装载值9000
	SysTick->VAL=0;    //3.清空计数器,清标志位
	SysTick->CTRL |=1<<1;   //4.使能中断 SysTick倒数计数到0时产生SysTick异常(中断)请求 */

/*-----------------------配置NVIC---------------------------------------------*/
	NVIC_InitTypeDef NVIC_InitStructure; //结构体重命名
	NVIC_InitStructure.NVIC_IRQChannel = SysTick_IRQn;  //选择通道(要中断的对象)
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //设置抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //设置响应优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //通道使能
	NVIC_Init(&NVIC_InitStructure);  //根据以上参数初始化NVIC寄存器	
	
	//NVIC_SetPriority(SysTick_IRQn,NVIC_EncodePriority(7-2,1,2));  // 5.配置NVIC控制器
	//NVIC_EnableIRQ(SysTick_IRQn);    
	SysTick->CTRL |=1<<0;   //6.使能定时器
}

void SysTick_Handler(void)
{
	if((SysTick->CTRL & 0x1 << 16))//检测标志位,也是清除标志位
	{
		printf("123456\r\n");
	}
}

六、附录:

上述函数中,为什么系统时钟要经过8分频?
在这里插入图片描述
答:因为在时钟树框图中,Cortex系统时钟需要系统时钟经过8分频。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/136954.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

7.运算符

目录 一.算数运算符 1、算术运算符 2、比较运算符 1、等号()用来判断数字、字符串和表达式是否相等。 2、安全等于运算符(<>) 3、不等于运算符(<>或者!) 4、小于或等于运算符(<) 5、小于运算符(<) 6、IS NULL(IS NULL)&#xff0c;IS NOT NULL 运算…

[MySQL] MySQL表的基础操作

文章目录 一、创建表 1、1 SQL语法 1、2 实例演示 二、查询表 三、修改表 3、1 修改表名字 3、2 新增列&#xff08;字段&#xff09; 3、3 修改列类型 3、4 修改列名 3、5 删除表 四、总结 &#x1f64b;‍♂️ 作者&#xff1a;Ggggggtm &#x1f64b;‍♂️ &#x1f440; 专…

【MySQL日志与备份篇】数据库备份与恢复

数据库备份与恢复 文章目录 数据库备份与恢复1. 物理备份与逻辑备份2. mysqldump实现逻辑备份2.1 备份一个数据库2.2 备份全部数据库2.3 备份部分数据库2.4 备份部分表2.5 备份单表的部分数据2.6 排除某些表的备份2.7 只备份结构或只备份数据2.8 备份中包含存储过程、函数、事件…

微信聊天,收到二维码图片就自动帮你提取出来的方法

10-3 如果你是二维码收集的重度用户&#xff0c;那我非常推荐你好好阅读本文&#xff0c;也许可以帮你解决你的问题&#xff0c;比如做网推的人&#xff0c;需要常年混迹在各种微信群&#xff0c;那如何在各个微信群中收集到群友分享出来的二维码&#xff0c;并且要立即保存出…

吃透 Spring 系列—MVC部分

目录 ◆ SpringMVC简介 - SpringMVC概述 - SpringMVC快速入门 - Controller中访问容器中的Bean - SpringMVC关键组件浅析 ◆ SpringMVC的请求处理 - 请求映射路径的配置 - 请求数据的接收 - Javaweb常用对象获取 - 请求静态资源 - 注解驱动 标签 ◆ SpringMV…

推荐系统笔记--Swing模型的原理

1--Swing模型的引入 在 Item CF 召回中&#xff0c;物品的相似度是基于其受众的交集来衡量的&#xff0c;但当受众的交集局限在一个小圈子时&#xff0c;就会误将两个不相似的物品定义为相似&#xff1b; Swing 模型引入用户的重合度来判断两个用户是否属于一个小圈子&#xff…

C++基础(2)——类和对象

目录 1. 类的引入&#xff1a; 2. 类的定义&#xff1a; 2.1类的定义以及基本结构&#xff1a; 2.2 类的访问限定符&#xff1a; 3. 类的声明与定义的分离&#xff1a; 4. 类的实例化&#xff1a; 5. 类的大小计算&#xff1a; 1. 类的引入&#xff1a; 在数据结构系列的…

使用openvc进行人脸检测:Haar级联分类器

1 人脸检测介绍 1.1 什么是人脸检测 人脸检测的目标是确定图像或视频中是否存在人脸。如果存在多个面&#xff0c;则每个面都被一个边界框包围&#xff0c;因此我们知道这些面的位置 人脸检测算法的主要目标是准确有效地确定图像或视频中人脸的存在和位置。这些算法分析数据…

[Android]修改应用包名、名称、版本号、Icon以及环境判断和打包

1.修改包名 在Android Studio中更改项目的包名涉及几个步骤&#xff1a; 打开项目结构: 在Android Studio中&#xff0c;确保您处于Android视图模式&#xff08;在左侧面板顶部有一个下拉菜单可以选择&#xff09;。 重命名包名: 在项目视图中&#xff0c;找到您的包名&…

结构型设计模式07-享元模式

结构型设计模式07-享元模式 1、享元模式介绍 享元模式是一种结构型设计模式&#xff0c;旨在通过共享对象来减少内存使用和提高性能。它主要用于处理大量细粒度对象的情况&#xff0c;其中许多对象具有相似的属性和行为。 在享元模式中&#xff0c;对象分为两种类型&#xf…

互联网大厂招兵买马开发鸿蒙应用,移动开发的春天又来了?

日前&#xff0c;美团拟开发鸿蒙系统APP的多个相关岗位正招聘开发人员引发业内关注。事实上&#xff0c;鸿蒙开发者已经成为京东、WPS、凤凰新闻、微博等互联网大厂争相招聘的人才&#xff0c;且招聘岗位众多。也就是说&#xff0c;这些公司正在加快鸿蒙化开发&#xff0c;为鸿…

计算机毕业设计选题推荐-校园交流平台微信小程序/安卓APP-项目实战

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

录制GIF图,动态图

软件下载链接&#xff1a; https://www.cockos.com/licecap/ 参考链接&#xff1a; https://chat.xutongbao.top/

Linux学习第40天:Linux SPI 驱动实验(一):乾坤大挪移

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 主从工作方式完成数据交换&#xff0c;形象的说就是武侠中的乾坤大挪移。 本章实验的最终目的就是驱动 I.MX6UALPHA 开发板上的 ICM-20608 这个 SPI 接口的六轴传…

2023.11.13 hive数据仓库之分区表与分桶表操作,与复杂类型的运用

目录 0.hadoop hive的文档 1.一级分区表 2.一级分区表练习2 3.创建多级分区表 4.分区表操作 5.分桶表 6. 分桶表进行排序 7.分桶的原理 8.hive的复杂类型 9.array类型: 又叫数组类型,存储同类型的单数据的集合 10.struct类型: 又叫结构类型,可以存储不同类型单数据的集合…

【函数讲解】pygmo中的函数 fast_non_dominated_sorting() + 利用支配关系,学习一个SVM分类器,将解分为两类

这个函数是用来执行非支配排序的&#xff0c;可以分层构建Pareto&#xff0c;并返回每一层的解以及每个解支配其他解的索引、解被其他解支配的次数、解所在的非支配层级。这个函数对这些解进行非支配排序&#xff0c;并返回四个数组&#xff1a;ndf, dl, dc, 和 ndr。 ndf (Non…

CentOS7、CentOS8 如何修改ip信息(修改网络信息)(无图形界面)(亲测可用)

文章目录 CentOS 7方法一&#xff1a;使用 nmcli 命令方法二&#xff1a;编辑配置文件&#xff08;我的CentOS7是使用这种方法&#xff0c;亲测可用&#xff09; CentOS 8方法一&#xff1a;使用 nmcli 命令方法二&#xff1a;编辑配置文件 在 CentOS 系统中&#xff0c;如果你…

【论文精读】DMVSNet

今天读的是一篇发表在ICCV 2023上的文章&#xff0c;作者来自华中科技大学。 文章地址&#xff1a;点击前往 项目地址&#xff1a;Github 文章目录 Abstract1 Introduction2 Relative Work3 Motivation3.1 Estimated bias and interpolated bias3.2 One-sided V.S. Saddle-shap…

怎么做到高性能网络IO?

为什么要做高性能网络IO。主要是解决c10&#xff0c;c10M问题 最开始的时候我们走的内核协议栈&#xff0c;走内核协议栈其实性能比较低&#xff0c;因为我们之前介绍的时候需要拷贝两次 但是我们采用用户态协议栈可以少拷贝一次&#xff0c;可以大大提高效率&#xff0c; 步骤…

基于粒子群算法优化概率神经网络PNN的分类预测 - 附代码

基于粒子群算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于粒子群算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于粒子群优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络…