STM32滴答定时器与UCOS时钟系统,以及心跳和延时函数的实现.

2023-11-17

   Systick就是一个定时器而已,只是它放在了NVIC中,主要的目的是为了给操作系统提供一个硬件上的中断(号称滴答中断)。滴答中断?这里来简单地解释一下。操作系统进行运转的时候,也会有“心跳”。它会根据“心跳”的节拍来工作,把整个时间段分成很多小小的时间片,每个任务每次只能运行一个“时间片”的时间长度就得退出给别的任务运行,这样可以确保任何一个任务都不会霸占整个系统不放。或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。 只要不把它在SysTick控制及状态寄存器中的使能位清除,就永不停息。

     知道systick在系统中的地位后,我们来了解systick的实现。这里只是举例说明systick的使用。它有四个寄存器,笔者把它列出来:

    SysTick->CTRL,        --控制和状态寄存器

    SysTick->LOAD,        --重装载寄存器

    SysTick->VAL,          --当前值寄存器

   SysTick->CALIB,        --校准值寄存器    

库里SysTick相关的函数我们能找到两个

一个在msic.h中

 

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;
        }
}

 

一个在core_m3.h中


 

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 */
}

我们一般只需要后一个就可以了

 

需要的操作在SysTick_Handler()(库版本不同可能是SysTickHandler)中添加就好了,意思每到加载到SysTick中的值减到0时就执行SysTick();

 

SystemInit();

    这个函数可以让主频运行到72M。可以把它作为systick的时钟源。

    接着开始配置systick,实际上配置systick的严格过程如下:

    1、调用SysTick_CounterCmd()       --失能SysTick计数器

    2、调用SysTick_ITConfig()          --失能SysTick中断

    3、调用SysTick_CLKSourceConfig()  --设置SysTick时钟源。

    4、调用SysTick_SetReload()         --设置SysTick重装载值。

    5、调用SysTick_ITConfig()          --使能SysTick中断

    6、调用SysTick_CounterCmd()       --开启SysTick计数器                                                      

    这里大家一定要注意,必须使得当前寄存器的值VAL等于0!

    SysTick->VAL  = (0x00);只有当VAL值为0时,计数器自动重载RELOAD。

接下来就可以直接调用Delay();函数进行延迟了。延迟函数的实现中,要注意的是,全局变量TimingDelay必须使用volatile,否则可能会被编译器优化。(以上的过程 在库函数SysTick_Config() 里已经配置稍做了解即可);

 

时钟的选择 在库文件 system_stm32f10x.c 里面

static void SetSysClock(void);

#ifdef SYSCLK_FREQ_HSE
  static void SetSysClockToHSE(void);
#elif defined SYSCLK_FREQ_24MHz
  static void SetSysClockTo24(void);
#elif defined SYSCLK_FREQ_36MHz
  static void SetSysClockTo36(void);
#elif defined SYSCLK_FREQ_48MHz
  static void SetSysClockTo48(void);
#elif defined SYSCLK_FREQ_56MHz
  static void SetSysClockTo56(void);  
#elif defined SYSCLK_FREQ_72MHz
  static void SetSysClockTo72(void);
#endif

以上 引用参考https://blog.csdn.net/yx_l128125/article/details/7884423

SetSysClock() 函数在SystemInit() 里面被调用 

SystemInit() 在startup_stm32f10x_hd.s 启动文件中的Reset_Handler调用(有的启动文件里面没有需要在main里面自己调用)

 

Systick作为操作系统的心跳:

UCOS 系统的os_cfg.h文件中 #define OS_TICKS_PER_SEC           100u   /* Set the number of ticks in one second                        */

定义了 每秒心跳(中断的次数);  100次.  假设是72MH的频率 , 在这里ucos给systick 的reload值应该为720000.

100次中断耗时1s.

心跳()时间片)原理为 SysTick_Handler() 中断函数. 里面增加 OSIntEnter() (OSIntNesting++),然后调用OSTimeTick() ucos的时钟服务程序,

最后OSIntExit() 任务调度一次.   

OSTimeTick()的功能: 为OSTime+1 以及为所有等待任务控制块的OSTCBDly-1 (如果-1为0 由后面的OSIntExit启动调度)

OSTimeDly()与OSTimeDlyHMSM();

OSTimeDly(INT16U ticks)比较简单就是 任务控制块 状态改为等待 ,OSTCBCur->OSTCBDly赋值延迟心跳次数ticks.并任务调度.

OSTimeDlyHMSM(INT8U hours, INT8U minutes, INT8U seconds, INT16U ms)复杂了一点

小时分钟秒的延时简单的计算出对应的ticks 并调用OSTimeDly();毫秒级别的:

注意:最小延时时间为心跳 (1/OS_TICKS_PER_SEC);  

 ticks= OS_TICKS_PER_SEC * ((INT32U)ms + 500L / OS_TICKS_PER_SEC) / 1000L;

这里有个500L的取值.我们暂定为MINTIME变量吧. 

邵贝贝书里说:这里的500的取值 目的是为了(假设OS_TICKS_PER_SEC=100 最小心跳10ms) 延时4ms的时候不延时,5ms以上的时候才延时. 依次14ms延迟一个节拍 15ms两个节拍.

个人感觉怪怪的....

那么如果想单纯的引发一次任务调度.那么OSTimeDlyHMSM(0,0,0,5) 至少是5ms才行.

对于单位 10ms以内的精确延时还是要抛弃ucos的函数而自己写.

 

为了实现小于(1/OS_TICKS_PER_SEC)的延时函数. 

传统的做法是定义delay_us()函数.函数功能,对Systicks 定时器的reload 重装值赋值 需要延时的时间对应的数值.

程序较为简单,但是会影响ucos的心跳.不能在操作系统下使用;

 

为了能在操作系统下实现us级别的延时.

 

参考正点原子教程:可以定义一个delay_us()的延时函数

void delay_us(u32 nus)
{        
    u32 ticks;
    u32 told,tnow,tcnt=0;
    u32 reload=SysTick->LOAD;    //LOAD的值             
    ticks=nus*fac_us;             //需要的节拍数               fac_us=时钟频率/1000000(这里是72)
    tcnt=0;
    told=SysTick->VAL;            //刚进入时的计数器值
    while(1)
    {
        tnow=SysTick->VAL;    
        if(tnow!=told)
        {        
            if(tnow<told)tcnt+=told-tnow;//这里注意一下SYSTICK是一个递减的计数器就可以了.
            else tcnt+=reload-tnow+told;        
            told=tnow;
            if(tcnt>=ticks)break;//时间超过/等于要延迟的时间,则退出.
        }  
    };                                         
}

这段函数功能,就是不断的读取SysTick->VAL ; Systick定时器的计数值;并计算差值. 如果大于需要的ticks 啧延时结束

如果需要的ticks大于重装载值,  用systick递减的原理.判断如果取得计数值大于记录计数值,啧更新记录值,并对cnt计数加reload重装载值. 实现us延时

 

STM32库函数的封装默认的外部晶振是8MHZ 一切的频率设置都是以此为基础的.

操作寄存器的话需要自己 计算倍频和分频.并设置时钟的初始化.

 

 

 

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

STM32滴答定时器与UCOS时钟系统,以及心跳和延时函数的实现. 的相关文章

随机推荐

  • 本地主机连接阿里云数据库(自建数据库)排雷

    最近在阿里云上开了一台云主机 自己搭建了数据库作为数据库使用 正当我本地去连接云上mysql时 发现死活连接不上 我这边阿里云上安全组端口已经放开了 出方向和入方向都开了歪 但是依然连接不上 是不是数据库做了限制 此时的我恍然大悟 欻欻欻欻
  • 叉积的意义

    我们知道 向量的叉积可以帮助我们求出一个和已知两个向量构成的平面相互垂直的另一个向量 例如求法向量 而且一般来说 都是求三维空间的向量的叉积 下面我们要讨论的就是各种 为什么如此 考虑两个相互不平行的三维向量 它们的叉积 以行列式形式来表示
  • 用VRTK4.0如何实现与UI交互(保姆级别教程)

    1 导入Tilia UnityUI master包 点击下面的链接直接跳到这个界面studentutu Tilia UnityUI Tilia package for VRTK 4 featuring support for Unity U
  • Your python install is corrupted. Please fix the '/usr/bin/python' symlink.

    执行如下命令就ok了 sudo ln sf usr bin python2 7 usr bin python 如果还是不行 reinstall sudo apt get install reinstall python 参考地址 https
  • ‘open3d.open3d.geometry.PointCloud‘ object has no attribute ‘voxel_down_sample‘

    scene cloud open3d geometry PointCloud scene cloud points open3d utility Vector3dVector scene points scene cloud scene c
  • 第四讲 系统建模方法

    系统建模一般流程 实际系统的分析方法大致类似 但对于实际系统的模型实现方式则有多种 1 面向方程 图框 的因果建模 基于图框进行系统模型实现 的软件很多 如Simulink AMESim 应用于控制领域 等 2 面向对象 非因果 的物理建模
  • Ztree和eazyUi-tree的区别

    l 在页面中引入ztree相关的文件 1 1 使用简单json数据构造ztree 重点
  • 常用端口

    端口号码 层 名称 注释 1 tcpmux TCP 端口服务多路复用 5 rje 远程作业入口 7 echo Echo 服务 9 discard 用于连接测试的空服务 11 systat 用于列举连接了的端口的系统状态 13 daytime
  • 使用father打包发布前端工具库

    father库说明 GitHub https github com umijs father 升级迁移 教程使用father v1 版本较老 可参考下面的教程升级 father 4升级教程 安装 yarn add father 项目配置 0
  • WebStorm、Idea编辑器中右侧的SVN下拉,提交标志不见了呢?--已解决

    新打开的窗口 没有SVN的下拉标志如何把他弄出来呢 首先你得安装了小乌龟软件 然后来到编辑器中 选择 1 VCS Enable Version Control Integretion 2 选择Subversion 点击OK ok 完成
  • logback打印日志不显示具体的信息,显示问号

    目录 表象 原因 日志打印的Appender是使用的ch qos logback classic AsyncAppender 正确配置 表象 配置
  • java21天打卡Day13-正则表达式

    原来正则表达式是这样用的
  • 前端实现文件在线预览

    需求 一个览pdf word xls ppt等文件需要在线预览功能 介绍 使用 XDOC文档预览云服务文档地址 基于HTTP的REST方式调用 只需要传入URL 支持pdf docx xlsx pptx rtf jpg png mp4等多种
  • DINO-DETR论文学习记录

    摘要 我们介绍了DINO 带有改进的去噪器box的DETR 一种最先进的端到端对象检测器 DINO 通过使用对比方式进行去噪训练 混合查询选择方法进行锚点初始化以及用于框预测的ook forward twice方案 在性能和效率方面比以前的
  • 使用WIFI模块AT指令进行HTTP交互

    超文本传输协议 HTTP HyperText Transfer Protocol 是互联网上应用最为广泛的一种网络协议 所有的WWW文件都必须遵守这个标准 设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法 用户通过M0M1系
  • linux cd命令怎么用

    在Linux中 cd命令是用来改变当前工作目录的 具体使用方法如下 打开终端 输入cd命令 后面跟上要进入的目录的路径 例如 如果要进入home目录 可以输入cd home 按下回车键即可进入指定目录 如果要返回上一级目录 可以使用 cd
  • Arudio项目实战——003 TracKingTheCar(循迹小车)

    Arudio项目实战 003 TracKingTheCar 循迹小车 Cblock源码 Cblock转Arduino源代码 include
  • 信息学奥赛一本通C++语言——1111:不高兴的津津

    题目描述 津津上初中了 妈妈认为津津应该更加用功学习 所以津津除了上学之外 还要参加妈妈为她报名的各科复习班 另外每周妈妈还会送她去学习朗诵 舞蹈和钢琴 但是津津如果一天上课超过八个小时就会不高兴 而且上得越久就会越不高兴 假设津津不会因为
  • echart常用图表配置

    echart常用图表配置 柱状图 3D柱状图 效果 代码 排行榜柱状图 效果 代码 排行榜反转柱状图 效果 代码 柱状图 3D柱状图 效果 代码 import graphic from echarts const VALUE Array f
  • STM32滴答定时器与UCOS时钟系统,以及心跳和延时函数的实现.

    Systick就是一个定时器而已 只是它放在了NVIC中 主要的目的是为了给操作系统提供一个硬件上的中断 号称滴答中断 滴答中断 这里来简单地解释一下 操作系统进行运转的时候 也会有 心跳 它会根据 心跳 的节拍来工作 把整个时间段分成很多