概括
硬件定时器很精确,软件定时器无论如何都有延迟,主要用在不需要精确定时的地方,而且软件定时比较浪费单片机资源。
梳理
讲到定时器,大家多多少少都会接触到硬件定时器,但是由于有时候资源的限制,又难免会出现使用软件定时器的情况,但是讲定时器需要从硬件定时器开始讲,软件定时器是在其基础之上延伸出来的。
硬件定时器
1.一般硬件定时器集成在CPU的内部,有的可以使用外置的硬件定时器芯片,可以人为通过编程来设置硬件定时器的工作频率,硬件定时器一旦设定好了工作频率,只要上电,那么硬件定时器就会周期性的给CPU输出一个中断信 ,称这个中断信 为时钟中断,linux内核已经实现好了时钟中断对应的服务程序,这个服务程序也称之为时钟中断服务函数,既然硬件定时器周期性的给CPU产生时钟中断,那么对应的中断服务程序就会被内核周期性的调用;
2.硬件延时利用定时器/计数器芯片,或用微控制器内部的定时器/计数器,实际上,它就是对晶振的分频(分频系数可编程设置),得到一个精确的低频的周期信 ,用这个周期信 (比如10ms)去触发中断,每10ms调用一次定时中断服务程序。在定时中断服务程序中加入计数变量,就可以得到任意的定时了。在10ms没有到时,微控制器可以运行其它程序,10ms到时再自动进去中断服务程序以处理定时任务,不会像软件延时阻塞了。
软件定时器
软件定时器是在硬件定时器基础之上出来的定时器,可以由一个硬件定时器模拟出成千上万个软件定时器,这样程序在需要使用较多定时器的时候就不会受限于硬件资源的不足,这是软件定时器的一个优点,即数量不受限制。但由于软件定时器是通过程序实现的,其运行和维护都需要耗费一定的CPU资源,同时精度也相对硬件定时器要差一些。
实现方法
典型的实现方法是:通过一个硬件定时器产生固定的时钟节拍,每次硬件定时器中断到,就对一个全局的时间标记加一,每个软件定时器都保存着到期时间,程序需要定期扫描所有运行中的软件定时器,将各个到期时间与全局时钟标记做比较,以判断对应软件定时器是否到期,到期则执行相应的回调函数,并关闭该定时器。
注意
因为是在内核态中进行的中断服务,我们定义全局变量需要使用volatile,前面的博客也有讲到他的用法,明确有三种情况,否则造成定时器失败。如:
定一个我们需要的回调函数:argv,argc为其参数:
一旦开始运行,whiole_cnt将不停地加一,而每个软件定时器都记录着一个到期时间,只要whiole_cnt大于该到期时间,就代表定时器到期了。
上面的代码都能理解,这时如果我们需要一个定时,需要确定哪些东西呢/p>
这是单个软件定时器的基本情况,如果需要多个,可以这样:
定义两个定时器数组:
如上只是一个框架,我们需要先对他初始化,以免影响到后期使用,
初始化函数:
TIME[i].state有三种状态:
TIME[i].mode有两种状态:
初始化完,实际上还没有真正的定时器出现,下一步做的就是,封装结构体,构造单独的定时器:
根据定义的NUM值,分别初始化,初始化后就可以跑了,如:想要定时一个500ms的软件定时器,且此时定时器中断的时间为10ms,则需要50个中断即可:
Time是回调函数指针:
argv,argc为其参数
初始化完成后,我们需要一直扫描软件定时器,主要的原因就是跟定时器中断的变量作比较,判断是否定时时间到!被扫描的函数是这样的:
我们在主函数中定义一个while(1),一直扫描,方可达到效果。
主函数main.c
别忘记了回调函数!
总结
不管哪种模式,定时器到期后,都将执行回调函数,以下是该函数的定义,参数指针argv为void指针类型,便于传入不同类型的参数。
文章知识点与官方知识档案匹配,可进一步学习相关知识算法技能树首页概览34041 人正在系统学习中
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!