基于STM32的软件定时器设计

发布者:心满愿望最新更新时间:2024-01-25 来源: elecfans关键字:STM32  软件定时器  操作系统 手机看文章 扫描二维码
随时随地手机看文章

1 什么是软件定时器

软件定时器是用程序模拟出来的定时器,可以由一个硬件定时器模拟出成千上万个软件定时器,这样程序在需要使用较多定时器的时候就不会受限于硬件资源的不足,这是软件定时器的一个优点,即数量不受限制。


但由于软件定时器是通过程序实现的,其运行和维护都需要耗费一定的CPU资源,同时精度也相对硬件定时器要差一些。


2 软件定时器的实现原理

在Linux,uC/OS,FreeRTOS等操作系统中,都带有软件定时器,原理大同小异。典型的实现方法是:通过一个硬件定时器产生固定的时钟节拍,每次硬件定时器中断到,就对一个全局的时间标记加一,每个软件定时器都保存着到期时间。

程序需要定期扫描所有运行中的软件定时器,将各个到期时间与全局时钟标记做比较,以判断对应软件定时器是否到期,到期则执行相应的回调函数,并关闭该定时器。

以上是单次定时器的实现,若要实现周期定时器,即到期后接着重新定时,只需要在执行完回调函数后,获取当前时间标记的值,加上延时时间作为下一次到期时间,继续运行软件定时器即可。

3 基于STM32的软件定时器

3.1 时钟节拍

软件定时器需要一个硬件时钟源作为基准,这个时钟源有一个固定的节拍(可以理解为秒针的每次滴答),用一个32位的全局变量tickCnt来记录这个节拍的变化:

wKgZomSij8aAWJbKAAAE_75qgLo355.png

每来一个节拍就对tickCnt加一(记录滴答了多少下):

wKgaomSij8aAA2FtAAAGD4Ah42A189.png

一旦开始运行,tickCnt将不停地加一,而每个软件定时器都记录着一个到期时间,只要tickCnt大于该到期时间,就代表定时器到期了。

3.2 数据结构

软件定时器的数据结构决定了其执行的性能和功能,一般可分为两种:数组结构和链表结构。什么意思呢?这是(多个)软件定时器在内存中的存储方式,可以用数组来存,也可以用链表来存。

两者的优劣之分就是两种数据结构的特性之分:数组方式的定时器查找较快,但数量固定,无法动态变化,数组大了容易浪费内存,数组小了又可能不够用,适用于定时事件明确且固定的系统。

链表方式的定时器数量可动态增减,易造成内存碎片(如果没有内存管理),查找的时间开销相对数组大,适用于通用性强的系统,Linux,uC/OS,FreeRTOS等操作系统用的都是链表式的软件定时器。

本文使用数组结构:

wKgaomSij8aAXtq1AAAEv-JgQ6w518.png

数组和链表是软件定时器整体的数据结构,当具体到单个定时器时,就涉及软件定时器结构体的定义,软件定时器所具有的功能与其结构体定义密切相关,以下是本文中软件定时器的结构体定义:

wKgaomSij8aAc6GnAAAOX2kTzro439.png

定时器的状态共有三种,默认是停止,启动后为运行,到期后为超时。

wKgZomSij8aANr40AAAIZoQATFs865.png

模式有两种:到期后就停止的是单次模式,到期后重新定时的是周期模式。

wKgZomSij8aASp4LAAAHdwO9ALw018.png

不管哪种模式,定时器到期后,都将执行回调函数,以下是该函数的定义,参数指针argv为void指针类型,便于传入不同类型的参数。

wKgaomSij8eAEvhaAAAFDezjkdQ630.png

上述结构体中的模式state和回调函数指针cb是可选的功能,如果系统不需要周期执行的定时器,或者不需要到期后自动执行某个函数,可删除此二者定义。

3.3 定时器操作

3.3.1 初始化

首先是软件定时器的初始化,对每个定时器结构体的成员赋初值,虽说static变量的初值为0,但个人觉得还是有必要保持初始化变量的习惯,避免出现一些奇奇怪怪的BUG。

wKgZomSij8eAS-TLAAAO-j0nr5s601.png

3.3.2 启动

启动一个软件定时器不仅要改变其状态为运行状态,同时还要告诉定时器什么时候到期(当前tickCnt值加上延时时间即为到期时间),单次定时还是周期定时,到期后执行哪个函数,函数的参数是什么,交代好这些就可以开跑了。

wKgZomSij8eAHLVEAAAZW8p-oNY011.png

上面函数中的assert_param()用于参数检查,类似于库函数assert()。

3.3.3 更新

本文中软件定时器有三种状态:停止,运行和超时,不同的状态做不同的事情。停止状态最简单,啥事都不做;运行状态需要不停地检查有没有到期,到期就执行回调函数并进入超时状态。

超时状态判断定时器的模式,如果是周期模式就更新到期时间,继续运行,如果是单次模式就停止定时器。这些操作都由一个更新函数来实现:

wKgaomSij8eAEPpsAAArBWPg1z8640.png

3.3.4 停止

如果定时器跑到一半,想把它停掉,就需要一个停止函数,操作很简单,改变目标定时器的状态为停止即可:

wKgaomSij8eANy3qAAAKAyP-vuk894.png

3.3.5 读状态

又如果想知道一个定时器是在跑着呢还是已经停下来?也很简单,返回它的状态:

wKgZomSij8eAaq2fAAAHOWlTvEc281.png

或许这看起来很怪,为什么要返回,而不是直接读?别忘了在前面3.2节中定义的定时器数组是个静态全局变量,该变量只能被当前源文件访问,当外部文件需要访问它的时候只能通过函数返回,这是一种简单的封装,保持程序的模块化。

3.4 测试

最后,当然是来验证一下我们的软件定时器有没达到预想的功能。
定义三个定时器:

定时器TMR_STRING_PRINT只执行一次,1s后在串口1打印一串字符;

定时器TMR_TWINKLING为周期定时器,周期为0.5s,每次到期都将取反LED0的状态,实现LED0的闪烁;

定时器TMR_DELAY_ON执行一次,3s后点亮LED1,跟第一个定时器不同的是,此定时器的回调函数是个空函数nop(),点亮LED1的操作通过主循环中判断定时器的状态来实现,这种方式在某些场合可能会用到。

wKgaomSij8eAEpR2AAAn7vUsbKs893.png

以下是测试结果,这是串口的打印:

wKgZomSij8eAQ8bIAAABY7_VEU0351.png

这是两个LED:

wKgZomSij8eACn4RAAPxmny0ovo217.png

请原谅我比较穷,LED1只能看电平输出了,如下图所示,输出为低电平,嗯,确实亮了 :

wKgaomSij8eAHUtyAAKjR3r3PWc409.png


关键字:STM32  软件定时器  操作系统 引用地址:基于STM32的软件定时器设计

上一篇:谈谈晶振的原理以及晶振和STM32的关系
下一篇:STM32中的SPI总线介绍

推荐阅读最新更新时间:2024-11-07 23:34

STM32串口通信中使用printf发送数据配置方法
STM32串口通信中使用printf发送数据配置方法(开发环境 Keil RVMDK) 标签: STM32 串口通信 printf方法 2011-06-29 23:29 在STM32串口通信程序中使用printf发送数据,非常的方便。可在刚开始使用的时候总是遇到问题,常见的是硬件访真时无法进入main主函数,其实只要简单的配置一下就可以了。 下面就说一下使用printf需要做哪些配置。 有两种配置方法: 一、对工程属性进行配置,详细步骤如下 1、首先要在你的main 文件中 包含“stdio.h” (标准输入输出头文件)。 2、在main文件中重定义函数 如下: // 发送数据 in
[单片机]
STM32窗口看门狗WWDG复位
STM32除了有一个独立看门狗外,还有一个窗口看门狗。窗口看门狗当然也能复位MCU,但是与独立看门狗复位不同。首先,窗口看门狗所需要的时钟源来自PCLK2,它时钟是经过PCLK2的4096分频后得到的,能够提供准确的计数。其次,复位的条件有要求:(1)当减计数器的值小于0x40,则产生复位;(2)当减计数值在窗口外被重新装载,则复位。接着,窗口看门狗的计数值与窗口值都只有7位,所以变化范围在0~127之间。还有,装载值一定要大于0x3F,否则就失去了看门狗的功能。 窗口看门狗,它的 窗口 可以有下图体现出来: 图中W 表示窗口值,当看门狗的减计数器不断递减,只有计数值到达窗口值与0x3F之间的时候 喂狗 ,才不会发生复位,
[单片机]
<font color='red'>STM32</font>窗口看门狗WWDG复位
STM32中的独立看门狗IWDG
一. 简述STM32中的看门狗系统 STM32F10xxx内置两个看门狗,一个是IWDG(独立看门狗),一个是WWDG(窗口看门狗),两个看 门狗设备(可用来检测和解决由软件错误引起的故障。 当计数器达到给定的超时值时,IWDG会产生系统复位。而WWDG会触发中断。这篇文章主要讲解一下IWDG。 二. 关于 独立看门狗IWDG 1. 独立看门狗(IWDG)由专用的低速时钟(LSI)驱动,即使主时钟发生故障它也仍然有效。IWDG最适合应用于那些需要看门狗作为一个在主程序之外,能够完全独立工作,并且对时间精度要求较低的场合。 2. IWDG主要性能 自由运行的递减计数器 时钟由独立的RC振荡器提供(可在
[单片机]
stm32 TFTLCD驱动原理(二)
FSMC简介: (1) 在大容量, 100 脚以上的 STM32F103 芯片都带有 FSMC 接口,硬石开发板 F1采用的主芯片为 STM32F103ZET6, 是带有 FSMC 接口的。 FSMC(灵活的静态存储器控制器),之所以称为灵活,是由于通过对特殊公的寄存器的设置, FSMC 能够根据不同个外部存储器列席,发出相应的数据/地址 /控制信号类型以匹配信号的速度,使得 STM32 系列微控制器不仅能够应用各种不同的外部静态存储器,而且能够在不增加外部器件的情况下同时扩展多种不同 类型的静态存储器, 满足系统设计对存储容量、产品体积以及成本的综合要求。 从上图中可以看到, STM32 的 FSMC 将外部设备分为
[单片机]
<font color='red'>stm32</font> TFTLCD驱动原理(二)
再造STM32---第一部分:如何正规的安装KEIL5?
本章内容所涉及的软件只供未出社会的学生使用,不得用于商业用途。个人或公司因商业用途导致的法律责任,后果自负。 获取本文所有安装包和注册机方式: 1、CSDN下载: https://download.csdn.net/download/qq_38351824/10943718 2、可以关注点赞并在下方评论,我给你邮箱发过去。 3、关注微信公众号下载: ① 关注微信公众号:Tech云 一、温馨提示: 1、 安装路径不能带中文,必须是英文路径 2、 安装目录不能跟 51 的 KEIL 或者 KEIL4 冲突,三者目录必须分开 3、 KEIL5 的安装比起 KEIL4 多了一个步骤,必须添加 MCU 库,不然没
[单片机]
再造STM32---第一部分:如何正规的安装KEIL5?
STM32 can配置PA11 PA12
code class= language-cpp /* Private variables ---------------------------------------------------------*/ uint16_t CAN_ID; uint8_t CAN_DATA0,CAN_DATA1,CAN_DATA2,CAN_DATA3,CAN_DATA4,CAN_DATA5,CAN_DATA6,CAN_DATA7; uint8_t CanFlag,Display; void CAN_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitSt
[单片机]
STM32物联网之TFTP文件传输
感言:专注物联网应用开发,分享物联网技术经验。 软件平台:IAR6.5 TCP/IP协议栈:LWIP1.4.1 硬件平台:STM32F103C8T6有线通信板 1、TCP/IP协议栈LWIP 1.1、LWIP认识 LWIP是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈,是Light Weight (轻型)IP协议,有无操作系统的支持都可以运行。LWIP提供三种API,分别是RAW API、LWIP API 、BSD API。其中RAW API把协议栈和应用程序放到一个进程里边,该接口基于函数回调技术来实现的,适合于无操作系统的场合运行,如单片机。本
[单片机]
STM32下uIP移植问题
就我个人认为在uIP的移植中除了驱动之处有以下几点需要注意: 1.uip_timer 时钟要加入到中断中去。 2.各种appcall实现。如在tcp_client_demo.c 有如下语句 if(uip_len 199) { ((u8*)uip_appdata) =0; } strcpy((char*)tcp_client_databuf,uip_appdata); 这样在处理数据长时都是以tcp_client_databuf 数组的长来处理,这样不灵活,client从网络中接收到的数据长本来就是用一个全局变量uip_len来存储的。
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved