详细SysTick定时器(+对寄存器段位的解释)

2023-11-13

1。       首先,systick定时器(嘀嗒定时器)隶属于CM4内核的一个外设,内嵌在NVIC中,所以一些函数在core_cm4.c中,系统定时器是一个24bit向下递减的计数器,计数器每次计数时间为1/SYSCLK。        (SYSCLK->系统时钟,通常设定为100MHZ。公式:f=100MHZ,则T=1/f=1/SYSCLK)。                                                          

当重装载数值寄存器的值减到0时,系统定时器就产生一次中断(这个中断需要配置并使能),以此循环往复

频率与周期对照表:(f与T)。 1Hz:1s        1Khz=1ms       1Mhz:1us        100Mhz:10ns                

 对原理图:首先对SysTick->CTRL的第16位置1后,使能LODA(LODA->装载),对SysTick->VAL进行赋值,(VAL当前数值,对应递减的数值,随着数字递减,数值在变化),之后可以选择不分频或者8分频,重装载计数器每1/SYSCLK计数一次,也就是1/100Mhz,10ns计数一次,计数100次就是1us。

2。SysTick定时器寄存器

定时器配置时,只需要配置前三个,最后一个校准寄存器不用配置。 

 

 位段16:计数标志位,意思是:读了该位,他自己清0,如果读过一次,并且他还是0,则该位变成1

 位段2:选择分频

 位段1:置1后,计数器计到0就产生请求,为0没啥作用,

位段0:使能位

段位:把内存分为很多段,每一段有一个段基址,当然段基址也是一个20位的内存地址。不过段寄存器仍然是16位的,它的内容代表了段基址的高16位,这个16位的地址后面再加上4个0就构成20位的段基址。

这个简单,意思是计数到0自己会重新装载数值再倒计时 

 可读可写位。读的时候,就是把寄存器当前倒计的数值进行读取

                        写的时候,意思只是把它置位写状态,这个不是设定数值的寄存器,写不进去实际数值,置写位后,还会清除COUNTFLAG的标志位。

SysTick->VAL寄存器的值每一个时钟周期就会递减1,当他递减到0时候, SysTick->LOAD的值将会进入SysTick->VAL中,并且SysTick->CTRL的COUNTFLAG位将会置1,如果还使能了中断,将还会进入中断。

延时原理就是通过设定SysTick->LOAD的值以及时钟周期的数值(通常设定为100MHz)来实现的

定时器的配置代码如下:(在core_cm4.h中)                                                                                                                                                                                     

__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
  if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); }    /* Reload value impossible */

  SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
  SysTick->VAL   = 0UL;                                             /* 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 (0UL);                                                     /* Function successful */
}

        对于SysTick_Config(uint32_t ticks);这个函数,要知道他已经将定时器配置为AHB(100MHZ) 时钟为 SysTick 定时器的时钟频率,并且使能了计数中断。也就是说,计数ticks(变量参数)次,就会产生一次SysTick中断。

        因此,我们就可以根据这个进行配置我们想要的ticks参数。例如:我们配置1ms的SysTick中断,我们可以调用SysTick_Config(uint32_t ticks);这个函数,首先,因为我们的计数周期为10ns(1/100MHZ),1ms/10ns=10*-3  /  10*-8=100000,也就是要递减10 0000次,也就是SysTick->VAL递减10 0000次,所以SysTick->LODA是10 0000,也可以说ticks参数必须是10 0000

SysTick_Config(SystemCoreClock/1000);    //设置SysTick定时器1ms中断一次

参数ticks=SystemCoreClock/1000(SystemCoreClock为系统时钟100Mhz,100Mhz/1000=10 0000)。也可以直接填10 0000.

3。利用SysTick定时器设计程序,运行计时器

        在此,我们定义一个全局变量volatile uint32_t sysTickUptime=0;在之后,每一次产生中断sysTickUptime++;(volatile修饰符表示sysTickUptime变量是一个易变的变量,它告诉编译器不要优化内容,直接读取变量内容)。

        SysTick定时器中断在文件stm32f4xx_it.c,它中不仅有SysTick定时器中断,其他所有中断都在其中。

         SysTick定时器中断代码如下:

extern unit32_t sysTickUptime;
void SysTick_Handler(void)
{
    sysTickUptime++;
}

        通过这段简单的代码可知:每1ms产生中断后sysTickUptime会进行加1。就是说,如果我们想知道一段代码运行了多长时间,可以在代码前面,后面分别读一下sysTickUptime的值:StartTime=sysTickUptime; 代码运行时间;EndTime=sysTickUptime;最终代码运行的时间为EndTime-StartTime(ms)

        但是,在32系统时钟中,都是以兆级别的,所以一个程序运行时间很短,一般以微妙级,所以毫秒对于一些代码,可能太大,不适合,不满足要求,所以也有微妙的计数器,以下是微妙级函数:

//延时初始化
void Delay_init(void)
{
    RCC_ClocksTypeDef clocks;
    //选择系统时钟HCLK作为Systick定时器的时钟,开Systick中断1ms一次
    SysTick_Config(SystemCoreClock/1000);
    RCC_GetClocksFreq(&clocks);//获取当前时钟
    usTicks = clocks.SYSCLK_Frequency/1000000;//100M/1M=100次 也就是计数100次为1us
}

//微妙计数器
uint32_t micros(void)
{
//register请求编译器尽可能的将变量存在CPU内部寄存器,而不是通过内存寻址访问。
    register uint32_t ms, cycle_cnt;
    do
    {
        ms = sysTickUptime;
        cycle_cnt = SysTick->VAL;//SysTick->VAL 的计数范围10 0000~0就是1ms,递减计数器
    }while (ms != sysTickUptime);
return (ms*1000)+ (usTicks * 1000 - cycle_cnt)/usTicks; 

}

        我们配置SysTick定时器的计数时钟为系统时钟,也就是100Mhz,也可以说SysTick->VAL每10ns递减1,1us也就是递减100次,1ms也就是10 0000次,其实我们也可以把上面的程序改为微妙级的中断,但是这样比较消耗资源,中断频率太高对程序运行也不太友好 。因此,我们可以进行毫秒中断微秒计时的方法。usTicks表示1微秒的计数次数,usTicks=100Mhz/1Mhz=100次,那么,在我们没进毫秒中断前进行循环读取sysTickUptime和SysTick->VAL的值(毫秒级别大嘛,没产生中断前可以读很多次),SysTick->VAL是从10 0000递减到0进行一次中断sysTickUptime才加1。

        所以在函数micros(void);在调用的时候,do{},while()里面的函数先进行一次执行,把两个值分别赋给ms,cycle_cnt,因为刚赋完,ms肯定=sysTickUptime,所以条件不满足,立即返回微妙计数值。等待sysTickUptime更新后,就再进入函数。就是说:do{},while()​​​​​​​里面的循环体只有在sysTickUptime更新时才执行两次,其他情况执行一次就返回了微妙计数。

4。​​​​​​​利用SysTick定时器设置精准延时

        上面我们写出了毫秒计数器millis();i和微妙计数器micros();也知道了怎么计算程序运行时间,其实延时函数就简单为:延时多长时间计多少次数。

//毫秒延时
void delay_ms(unit32_t nms)
{
    uint32_t mStart = 0;
    mStart = mills();//毫秒开始值
    while(mills()-mStart<nms)
    {}
}

//微妙延时
void delay_us(uint32_t nus)
{
    uint32_t uStart =0;
    uStart = micros();
    while(micros()-uStart<nus)
    {}
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

详细SysTick定时器(+对寄存器段位的解释) 的相关文章

  • UNIX环境高级编程 学习笔记 第十五章 进程间通信

    进程间通信可通过传送打开的文件 也可以经由fork和exec函数来传送 还可以通过文件系统传送 IPC InterProcess Communication 进程间通信 是进程通信方式的统称 不同UNIX系统支持的IPC形式不同 虽然SUS
  • net::ERR_CONNECTION_REFUSED,Network Error

    net ERR CONNECTION REFUSED 项目部署服务器后报如图所示错误 但在本地调用后台RESRful接口数据没问题 最后发现是tomcat服务器没有开 开了后没有再次执行命令使后台运行 其实这个问题从两点能够发现 一是执行n
  • 解决Anaconda导入第三方包的各种问题

    1 win R win R 输入 HOMEPATH 然后找到 condarc 把里面的内容改为 ssl verify true show channel urls true channels http mirrors tuna tsingh

随机推荐

  • 点云数据做简单的平面的分割 三维场景中有平面,杯子,和其他物体 实现欧式聚类提取 对三维点云组成的场景进行分割

    点云分割是根据空间 几何和纹理等特征对点云进行划分 使得同一划分内的点云拥有相似的特征 点云的有效分割往往是许多应用的前提 例如逆向工作 CAD领域对零件的不同扫描表面进行分割 然后才能更好的进行空洞修复曲面重建 特征描述和提取 进而进行基
  • Qt 事件过滤器 - EventFilter

    事件过滤器 见名之意 就是将事件过滤一遍 将不需要的事件都清除掉 剩下需要的事件进行操作 可能讲得不是很透彻 那就看下图 就很明白了 原本事件应该直接发送给 组件对象 但是现在却先将事件发送给 过滤器对象 经过过滤的事件再发给 组件对象 如
  • xss level11

    Level11 1 2 毫无头绪 查看PHP源代码发现 是从头文件的referer获取的输入 3 用Burp抓包 修改头文件如下 4 再点击Proxy界面的forward 回到浏览器页面如下 5 点击即可 转载于 https www cnb
  • 走进强化学习

    一 什么是强化学习 强化学习是机器学习里面的一个分支 是一个智能体通过不断的与环境产生互动而不断改进它的行为 从而积累最大奖励的一个决策过程 智能体在完成某项任务时 首先通过动作A与周围环境进行交互 在动作A和环境的作用下 智能体会产生新的
  • CUDA 计算线程索引的一般公式

    第一种方法 CUDA thread index int blockId blockIdx z gridDim x gridDim y blockIdx y gridDim x blockIdx x int threadId blockId
  • Couldn‘t resolve host

    Centos6安装完并配置静态ip地址后 发现yum命令下载出现Couldn t resolve host ping www baidu com 出现域名解析错误 百度大部分答案是在 etc sysconfig network script
  • 用java求出1-1/2+1/3-1/4…..1/100的和

    public class sumPractice3 public static void main String args 需求 求出1 1 2 1 3 1 4 1 100的和 分子始终为1 double num 1 定义个变量用来存储计算
  • 三个基于WebRTC开源MCU框架的横向对比

    1 licode 官网地址 http lynckia com licode index html 官方demo地址 https chotis2 dit upm es Github地址 https github com lynckia lic
  • switch的用法

    switch语句 实际生活中 需要做出很多选择 大家都知道做选择可以使用if语句 但是如果选择太多 if语句使用起来就会很繁琐 这个时候就需要一个能将代码简化的语句 也就是我们今天的主角switch语句 switch语句是一个多分支选择语句
  • 【中等】【LeetCode刷题笔记(二十九)】之54.螺旋矩阵

    本文章由公号 开发小鸽 发布 欢迎关注 老规矩 妹妹镇楼 一 题目 一 题干 给定一个包含 m x n 个元素的矩阵 m 行 n 列 请按照顺时针螺旋顺序 返回矩阵中的所有元素 二 示例 示例 1 输入 1 2 3 4 5 6 7 8 9
  • 零基础如何使用IDEA启动前后端分离中的前端项目(Vue)?

    一 在IDEA中配置vue插件 点击File gt Settings gt Plugins gt 搜索vue js插件进行安装 下面的图中我已经安装好了 二 搭建node js环境 安装node js 可以去官网下载 安装过程就很简单 直接
  • 活动预告丨SMP十周年系列论坛第一期:社交机器人论坛开幕

    全国社会媒体处理大会十周年系列论坛 第一期 SMP2021社交机器人论坛 将于2021年11月13日 周六 上午线上举办 旨在探讨社交机器人领域的热点和前沿 探索构建更智能的社交机器人的学术研究和技术方案 人机对话系统是人工智能领域最具挑战
  • LocalDate、LocalDateTime互转String

    目录 1 LocalDate String互转 LocalDate转String String转LocalDate 2 LocalDateTime String互转 LocalDateTime转String String转LocalDate
  • c语言连点器脚本

    include
  • 数据分析学习之路——(五)用数据告诉你电影的市场趋势

    随着社会的多元化 越来越多的影视作品走入人们的生活中 但是近年来鲜有几部新制作的电影能俘获观众的心 到底是观众越来越挑剔 还是电影作品本身不够吸引力 如果你是有一个电影公司 你想制作一部电影作品 你有想过拍一部什么样的电影吗 你会选择一名什
  • 高级Bash脚本编程指南(24):时间/日期 命令

    高级Bash脚本编程指南 24 时间 日期 命令 成于坚持 败于止步 时间 日期和计时 date 直接调用date命令就会把日期和时间输出到 stdout上 这个命令有趣的地方在于它的格式化和分析选项上 root ubuntu resour
  • PAT乙级1016 部分A+B (15 分)

    1016 部分A B 15 分 一 问题描述 二 代码实现 include
  • solidity通用模式访问限制

    通用模式 访问限制 访问限制是智能合约的一种通用模式 但你不能限制任何人获取你的智能合约和交易的状态 当然 你可以通过加密来增加读取难度 但是如果你的智能合约需要读取该数据 指加密的数据 其他人也可以读取 你可以通过将合约状态设置为私有来限
  • Delphi程序使用资源的释放

    写出一个不会造成资源分配崩溃的Delphi应用程序的 关键是确保如果程序中分配了资源 即使当故障发生 程 序也应能释放占用的资源 文件 内存 WINDOWS资源和对象是一些必须时时加 以注意的需确保释放的资源 下面的事件控制代码例子中 先分
  • 详细SysTick定时器(+对寄存器段位的解释)

    1 首先 systick定时器 嘀嗒定时器 隶属于CM4内核的一个外设 内嵌在NVIC中 所以一些函数在core cm4 c中 系统定时器是一个24bit向下递减的计数器 计数器每次计数时间为1 SYSCLK SYSCLK gt 系统时钟