当前位置: 首页 > article >正文

STM32-笔记11-手写带操作系统的延时函数

1、为什么带操作系统的延时函数,和笔记10上的延时函数不能使用同一种?

        因为笔记10的延时函数在每次调用的时候,会一直开关定时器,而在FreeRTOS操作系统中,SysTick定时器当作时基使用。

        时基是一个时间显示的基本单位。时基即时间基准,在电子线路中主要用来表示数字电路中的基准时钟。

        FreeRTOS的时基(Timebase)是指系统时钟的基础节拍,用于控制任务调度和定时功能。在FreeRTOS中,时基是通过系统时钟节拍(System Tick)来实现的。

2、分析滴答定时器的倒数情况

        流程如下:给滴答定时器一个重装载值:reload,当滴答定时器开始计时,从重装载值开始倒数(从16777215‌倒数到0),然后自动重载再倒数...... ,ticks是一共需要计多少数,获取刚进入while循环时计数器时VAL的值(tnow)和进入while循环时,当前VAL的值作为told,然后,不断的累加told和tnow的差值(tcnt),不断的判断tcnt是否大于等于ticks,当是的时候,证明已达到需要的数值,故可以退出循环。

差值tcnt有三种情况

情况1、

        第一次查询SysTick->VAL的值时told 和 第二次查询SysTick->VAL的值时tnow,正好在一次数数内。

情况2、

第一次查询SysTick->VAL的值时told 和 第二次查询SysTick->VAL的值时tnow,不在一次数数内。

情况3、

第一次查询SysTick->VAL的值时told 和 第二次查询SysTick->VAL的值时tnow,正好在同一个位置。(先不对其做出讨论,只把它当作条件)

流程图如下:

问题1:为什么直接给reload赋值SysTick->LOAD,SysTick->LOAD在赋值之前也没有手动赋值重装载值。原因是什么?

        回答:这里利用的是SysTick的自动重载功能,没有给SysTick->LOAD(重装载数值)手动赋值就会自动的重装载初始值,重装载初始值(SysTick是24位计数器)是2^24-1(数到0停止,不是数到1停止)。即从16777215‌倒数到‌0‌,所以这里直接给reload赋值SysTick->LOAD。

问题2:为什么在这里不需要手动开启SysTick的使能位(ENABLE)?

        回答:在这里确实没有显式地开启 SysTick 定时器的使能位。这是因为该函数的设计是基于一个前提:SysTick 定时器已经在系统的其他部分(如系统初始化或操作系统内核启动代码中)被配置并启用了。

注意:SysTick的LOAD寄存器在没有外界赋值的情况下会自动重载值。‌SysTick定时器是一个24位的自动重载递减计数器,当计数器从初始值(即LOAD寄存器的值)递减到0时,会自动重新装载这个初始值,并继续递减,形成一个循环。这个过程是由硬件自动完成的,不需要外界手动赋值‌

3、代码

实现的代码如下所示:

复制03-流水灯项目文件,在delay.c文件中重写delay_us();函数如下

void delay_us(uint32_t nus)
{
    uint32_t ticks;
    uint32_t tcnt = 0, told, tnow;
    uint32_t reload = SysTick->LOAD;                //重装载值
    
    ticks = nus * 72;                               //需要计的节拍数
    told = SysTick->VAL;                            //刚进入while循环时计数器的值
    
    while(1)
    {
        tnow = SysTick->VAL;
        if(tnow != told)
        {
            if(tnow < told)
                tcnt += told - tnow;
            else
                tcnt += reload - (tnow -told);
            
            told = tnow;                            //下次进入while循环时,当前VAL的值作为told
            
            if(tcnt >= ticks)                       //已计的数超过/等于需要计的数时,退出循环
                break;
        }
    }
}
 4、验证实现

先点击魔术棒

配置完记得点击确定

运行程序,连接好开发板

 

 对比两张图片的时间可以看出来,经历了0.5s也就是500ms

证明以上实验完成


http://www.kler.cn/a/455680.html

相关文章:

  • jetson 无显示器配置WIFI
  • Vue中接入萤石等直播视频(更新中ing)
  • JVM学习-内存结构(一)
  • 【Flutter_Web】Flutter编译Web第三篇(网络请求篇):dio如何改造方法,变成web之后数据如何处理
  • 深度学习中的并行策略概述:1 单GPU优化
  • 设计一个监控摄像头物联网IOT(webRTC、音视频、文件存储)
  • 笔记:使用python对飞书用户活跃度统计的一个尝试
  • Go Redis实现排行榜
  • 神经网络-ResNet
  • 【社区投稿】自动特征auto trait的扩散规则
  • Effective C++ 条款32:确定你的 public 继承塑模出 is-a 关系
  • Pytorch | 利用IE-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击
  • 如何在 Spring Boot 微服务中设置和管理多个数据库
  • 对外发PDF设置打开次数
  • Python机器学习笔记(十五、聚类算法的对比和评估)
  • 【JavaEE进阶】@RequestMapping注解
  • 《一文读懂BP神经网络:从原理到应用》
  • redis中,msyql数据库读写分离搭建
  • Gitlab17.7+Jenkins2.4.91实现Fastapi/Django项目持续发布版本详细操作(亲测可用)
  • C语言-结构体嵌套
  • 服务器数据恢复—Lustre分布式文件系统下服务器节点进水的数据恢复案例
  • 【网络工程师教程】六、网络互联与互联网
  • github codespaces推送镜像时unauthorized: access token has insufficient scopes 解决方法
  • 云服务器yum无法解析mirrorlist.centos.org
  • 网安瞭望台第17期:Rockstar 2FA 故障催生 FlowerStorm 钓鱼即服务扩张现象剖析
  • oracle基础:理解 Oracle SQL 中的 WHERE 后的 (+) 用法