打印
[经验分享]

如何理解定时器

[复制链接]
2789|51
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
mickit|  楼主 | 2024-10-14 22:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
      好,回到定时器最初的功能,定时,先掏出手机,定时十分钟,然后等着它响,盯着时间、告诉我你看到了什么?对,跳动的秒数、分数。到这里恭喜你就理解了定时器最最核心的概念:计数。这个计数可不是你自己念的1、2、3,而是规律跳变的数字,也就是时基。因此定时器的定时功能依赖时间的变化、时间的变化依赖计数、计数依赖基本的时基。比如光传播约299792458米的时间或者铯原子震荡9192631770次就是一秒。

        所以简单总结一下:定时器的核心功能依托计数实现,具体表现就是计数器,那计数器有什么用呢,比如你想从七点半定时到七点三十一分,需要的计数值就是60,同理定时到七点三十二分所需的计数是120,所以计数器的值直接决定了我们需要的定时时间。所以知道计数器有多重要了吧。

        现在到了你定时的时间,手机想起了铃声,这就是我们熟悉的中断,虽然你现在可能在放音乐,那也会停掉去放铃声。当然不会像下面这么简单。

void 闹铃_handler(void)
{
  铃声.play();
}
        你得获取闹铃服务对象,AlarmManager alarmManager = (AlarmManager) getSystemService(Service.ALARM_SERVICE);然后设置一个时间、是否在睡眠模式下有效、绑定闹铃回调动作等等。

        至此最简单的定时应用你就学会了。如果你需要每天六点半起床怎么办,总不能每天设置一次闹钟吧,这之后你可以选择重复模式。就像以前的指针闹钟一样。


        其实倒不是闹钟有循环模式,只是时间走到12点它就循环从1点又开始了。这也是我以前好奇闹钟下午六七点也会响的原因。有没有发现一点很像的样子,比如你的uint8_t变量加到255再加加就变成了0,没错,定时器循环工作的秘密就在这。

        现在再次梳理一下:定时器依赖计数器达到我们所需的定时,定时满了溢出之后不停止就有了循环模式。有没有发现一个问题,如果任着闹钟自行运作的话,就只能每间隔12小时响一次,如果想6小时响一次怎么办呢?两种办法,一个是让闹钟一圈就转6个小时,不过也太麻烦了,还有就是响铃之后马上调成12点,不过也需要一直等着闹铃响。

        当然了上述的情况基本上是用不到的,我们还有更灵活的单片机定时器,单片机的定时器同样是依托计数器实现的,闹钟数60秒变0从1开始,计数器数到65536变0从1开始,至于为什么是这么大,16位二进制最大就是这么大,2^16,就好像为什么只有2、4、8、16、32和64位的处理器一样,同样的数到65536的时候溢出变成0,触发更新中断,这时候你定时的时间就到了,不关闭它它就一直这么重复定时,又双叒叕触发中断。

        欸,如果我不想定时这么久怎么办呢?计数器不让它计到那么大不就行了嘛,是的,计数器作为寄存器它允许你修改,可以让它计数到32768就变成0然后从1重新开始,这时候你定时的时间就是之前的一半了,同样它将重复的一次次产生中断告诉你你定时的时间到了。

        不过细想一下,计数器本来不就是一直在变的嘛,那红红火火恍恍惚惚中修改的貌似不是计数器值,而是限制计数器的值吧,是的,这玩意叫预装值,它限制了计数器所能数到的最大值,而更新中断一方面是告诉你定时的时间到了,另外还会把预装值生效,就比如上次你修改了最大计数是32768,那么在这次数到65536的时候就把32768装载上了,所以接下来这次只需要数到32768就会变成0,然后再把预装放进去。这样你就可以随时随地想定时多久就定时多久。


        不过有没有发现一个问题,即使你最大预装65536,可是时间还是不够怎么办?比如时基是1ms,那你最大才能定时65.536s,我想定时五分钟怎么办,这里引入另一个东西,叫预分频器,什么意思呢,就是把时基给它放慢,跟预装值一样,可设定0~65535,也就是可以放慢1~65536倍,比如你想要五分钟,那我直接把时基放慢10倍,就是把预分频器设置成9,这样最大计时就可以达到655.35s了,你想要的五分钟就是300s,预装载设置成30000-1=29999不就行了嘛。这样一来可定时范围瞬间放大65536倍。

        值得注意的是,如果为什么预装值要下一次生效,比如现在计数器已经数到200了,你想要它数到100就从0开始,这时候显然就是错误的了,所以要按照上一次值就行比较,然后等下一次从头开始的时候再按照新修改的值,就像播放视频的时候把源文件删掉一样,要不播放器自己备份一份,要不直接文件加锁不给删。回到定时器,既然现在的预装还在生效、用户设置的新预装也有,所以这就有了影子寄存器的概念,我们直接修改的预分频和预装值都有影子寄存器,在计时器溢出更新的时候他们的值复制进影子寄存器起效,因此计数器与之比较的影子寄存器,也就是上一次的预装值或者预分频值。

        现在还差点什么呢?我们一直强调的时基,也就是定义时间的基准。比如1us的脉冲信号作为时基的话(也就是1MHz时钟),所能定时的最小值就是1us,最大值就是65536*65536us,看到这里大家应该发现了,定时器定时的精度取决于时基,输入时钟频率越高,定时器精度越高。不过相应的定时的时间也就变短了。所以还是却决于时钟输入和寄存器位数。不过当前的数值也满足绝大多数的应用了。愣是想用51做纳秒中断它也做不到对吧。

        到目前为止我们已经知道了定时器的基本构造,就差怎么利用它了,说明书就是参考手册,不过在看参考手册之前在来了解一下STM32给留出的开关,作为一个定时器,最基本的开关得有吧,也就是使能,啪,扳上去定时器就开始跑,啪,扳下来定时器就停了,定时一次时间到了就关掉定时器的控制开关叫单脉冲模式,啪、扳上去,定时时间到了就关上了。啪、扳下来,定时时间到了还会继续下一次计时,不会关了定时器。还有开关控制是否使能中断、是否触发DMA等等。除此外还有寄存器用于显示更新状态。


        简化一下定时器,就是上图了。实际上肯定会复杂很多。对比一下就发现了,似乎跟洗衣机面板很像,电源输入进来、设置好漂洗时间、设置好漂洗强度、是否甩干、多次清洗、完成提示音等等,最后按下开始按键,等待计时时间计数,完成后发出提示音提醒。

        实际上包括计数器、预分频等这些数值和中断使能、计数器使能这些开关及更新标志位全部被封装在一个叫寄存器的东西,比如控制计数器使能的控制寄存器CR(Control register),甚至位不够用分成CR1和CR2两部分控制寄存器。所以这时候就不是啪的一下按开关来打开定时器了,而是写寄存器的值,它的某一位的0或者1表示打开还是关闭定时器。所以我们就可以写这个寄存器的值来打开定时器、使能中断等等,又或者读取状态寄存器SR(Status register)的某个位是0还是1判断有没有发生更新中断。

        至于为什么要绑定在一起成为寄存器控制,就像结构体一样,把类似属性的东西放置在一起比较方便管理。又或者仪表盘的状态指示和功能控制也是集中放置在一起的。反正就是一堆开关、变量和状态、留给用户去使用。

        想要找到这些开关或者称之为寄存器,需要知道他们的地址,然后通过地址来定位并读写它们就完成了对定时器的使用。  

使用特权

评论回复
沙发
chenqianqian| | 2024-10-16 21:52 | 只看该作者
定时器这个概念应该很好理解吧

使用特权

评论回复
板凳
macpherson| | 2024-11-9 07:16 | 只看该作者
预分频器(Prescaler)用于减慢时钟频率,以便定时器可以产生更长的时间间隔。预分频器的分频系数可以是固定的或可编程的。

使用特权

评论回复
地板
macpherson| | 2024-11-9 07:35 | 只看该作者
如果需要使用定时器中断,需要正确配置和使能中断系统。这包括设置中断优先级、中断允许位等。

使用特权

评论回复
5
febgxu| | 2024-11-9 08:00 | 只看该作者
根据功能和应用场景的不同,单片机定时器可以分为基本定时器、通用定时器和高级定时器。
不同型号的单片机可能具有不同数量和类型的定时器。

使用特权

评论回复
6
everyrobin| | 2024-11-9 11:06 | 只看该作者
编写中断服务程序时,注意避免长时间占用中断,以免影响其他中断的正常响应。

使用特权

评论回复
7
hearstnorman323| | 2024-11-9 12:00 | 只看该作者
定时器通过晶振提供能量,并经过时钟电路的分频处理来产生一定频率的时钟信号。
这个时钟信号会驱动定时器内部的计数器不断递增。
当计数器的值达到预设的溢出值时,会产生一个中断信号,通知CPU进行处理。

使用特权

评论回复
8
averyleigh| | 2024-11-9 12:36 | 只看该作者
当定时器接收到时钟信号后,其内部的计数器开始计数。计数器每接收到一个时钟脉冲,其计数值就增加1。这个计数过程是连续的,直到计数值达到预设的阈值为止。

使用特权

评论回复
9
mollylawrence| | 2024-11-9 13:07 | 只看该作者
定时器内部有一个计数器,它会根据时钟源频率递增或递减。当计数器的值达到某个预设值时,定时器可以触发事件,如中断。

使用特权

评论回复
10
minzisc| | 2024-11-9 17:16 | 只看该作者
不同的时钟源和分频系数会影响定时器的定时精度和范围。

使用特权

评论回复
11
sesefadou| | 2024-11-9 19:57 | 只看该作者
在定时器开始工作之前,需要对其进行初始化。这包括设置定时器的计数初值、工作模式等参数。计数初值决定了定时器从哪个值开始计数,而工作模式则决定了定时器的工作方式(如定时模式、计数模式等)。

使用特权

评论回复
12
qiufengsd| | 2024-11-9 20:33 | 只看该作者
选择合适的时钟源以满足定时器的精度和稳定性要求。外部晶体振荡器通常提供更高的精度和稳定性。

使用特权

评论回复
13
biechedan| | 2024-11-9 21:52 | 只看该作者
中断信号可以通知CPU进行相应的处理,如更新计数器值、执行定时任务等。

使用特权

评论回复
14
updownq| | 2024-11-9 23:03 | 只看该作者
在使用外部信号控制定时器的启动和停止时,需要注意信号的稳定性和可靠性。
外部信号的干扰或不稳定可能导致定时器工作异常或产生误操作。

使用特权

评论回复
15
earlmax| | 2024-11-10 09:56 | 只看该作者
当定时器计数达到设定值时,可以产生中断,CPU响应中断后可以执行特定的中断服务程序。

使用特权

评论回复
16
mnynt121| | 2024-11-10 10:21 | 只看该作者
定时器的功耗与效率需要在满足应用需求的前提下,尽量降低定时器的功耗,如选择低功耗模式、减少不必要的中断等,同时也要关注定时器的效率以及资源占用情况,避免影响其他任务的执行。

使用特权

评论回复
17
iyoum| | 2024-11-10 11:08 | 只看该作者
定时器的分辨率受到时钟源频率和预分频器的影响。确保定时器的分辨率满足应用需求。

使用特权

评论回复
18
robincotton| | 2024-11-10 15:13 | 只看该作者
当定时器溢出时,需要及时处理溢出标志位,并重新加载计数器的初值,以便定时器能够继续正常工作。

使用特权

评论回复
19
backlugin| | 2024-11-10 17:16 | 只看该作者
在实际应用中,需要结合实际需求对定时器进行调试和优化。
通过调整定时器的参数和配置,可以实现更精确和可靠的定时功能。

使用特权

评论回复
20
dspmana| | 2024-11-10 17:39 | 只看该作者
在使用定时器之前,需要根据需求配置定时器的模式、预分频值、计数初值等。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

78

主题

1328

帖子

1

粉丝