单片机学习之定时器原理及应用
前言
一、快速上手
1.1 原理简述
1.2 定时时间
1.3 自定义定时时间
二、使用步骤
2.1 工作方式设置
2.2 定时器!启动!
2.3 清溢出
三、实例
总结
前言
51单片机的学习重点在于中断、定时器和串口,熟练掌握这几个知识点再加上一点模块化编程的思想就可以看懂大部分程序啦!
一、快速上手
首先我们记住一个值,12MHZ的晶振对应的机器周期是1微秒:
机器周期是1us!
机器周期是1us!!
机器周期是1us!!!
(重要的事情说三遍)
1.1 原理简述
定时器实际上就是每个机器周期自动加一的16位计数器,不过这十六位不是一个整体,是由两个八位的寄存器(分别叫TH0和TL0,我猜H是high,L是low的意思,希望能帮助你记忆)组合而成的。
你以为计数器长这样?
实际人家长这样
区别就在于加一的时候会优先把低八位的TL0加满,然后才会加高八位的TH0。
1.2 定时时间
明白了定时器基本原理我们就想知道,从定时器全为零(开始定时)到定时结束(全为1然后再加1的时候定时器才会反应过来自己溢出了哦),这个过程一共经理了65536个机器周期,也就是65536us,也就是65.536ms
那再让我们记住一个值,定时器默认定时65.536毫秒:
定时器默认定时65.536ms!
定时器默认定时65.536ms!!
定时器默认定时65.536ms!!!
1.3 自定义定时时间
由于我们在使用定时器时经常使用50ms或者100ms,所以我们经常需要自定义定时时间,细心一点的朋友可以发现他们一个小于默认的定时时间(50ms),一个大于默认的定时时间(100ms)
1.3.1 小于默认时间
还记得65.536ms的默认时间是怎么得到的么,是定时器从全为0(我们称之为初值)一直加到全为1然后再溢出一个的时间对吧。最终的结局肯定是定时器全部加满之后溢出则定时结束,这个我们无法改变,但我们却可以改变初值,这样从初值开始到加满溢出的时间不就减少了么!
初值的得到也很简单,就是小学加减法吧,如果我们定50ms,就是50000us,就是50000个机器周期,初值就等于:
所以我们只要把这个初值赋给定时器就好啦!
15536(十进制,我们日常使用的进制)转成我们熟悉的样子(二进制)就是
更形象一点就是
不过单片机编程最好给他转成16进制再赋值
TH0=0x3c;
TL0=0xb0;
当然你可能也会经常看到这么写的,他俩是一个意思,你觉得这样好用的话直接这么写就行,原理就不多赘述,用的时候改一下减数就好。
1.3.2 大于默认时间
大于默认时间我们可以使用循环来解决
我们需要注意的是我们需要一个清溢出的功能,因为如果没有这个功能,比如我们想让50ms循环两次得到100ms,但定时器50ms就溢出了,循环就没有意义了。
这里直接放伪代码太抽象了,我们下面结合实际例子来讲
二、使用步骤
2.1 工作方式设置
使用定时器就需要设置一些工作方式来通知CPU,管理这些方式的寄存器叫TMOD,它的格式长这样,每个位有0和1两种工作状态:
前面的四位和后面的四位是相同的,前面是定时器T1,后面是定时器T0(51单片机有两个定时器),我们上面都是以T0为例讲解的,但它们的原理是一样的。
上面讲的工作方式是工作方式1(详细原理我放在下面了,来源是普中的51单片机开发攻略),如果只使用定时器T0的话,固定代码就是这样的:
TMOD=0x01
只使用定时器T1的话,固定代码就是这样的:
TMOD=0x10
详细原理在这里。想学的明白一点可以自己花时间看看:
2.2 定时器!启动!
控制定时器的寄存器叫TCON,他的格式长这样:
这个寄存器比较特殊,他的每个位是可以单独控制的,所以我们不用向TMOD那样一下子给整个寄存器赋值,只需要给管理定时器打开/关断的TRO赋值就可以
TR0=1 //打开定时器
TRO=0 //关闭定时器
2.3 清溢出
还是上面的控制寄存器TCON,其中的TF0是溢出控制位,定时器溢出时他会自动置1,需要我们把它手动清0。
TF0=0
三、实例
我们可以用定时器来实现延时功能,比如实现一个流水灯:
#include <reg51.h>
unsigned char k=0;
unsigned char n=0x01;
void main() {
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256; // 设置50ms
TR0=1;
while(1)
{
unsigned char i; // 声明变量i
for(i=0;i<8;i++)
{
P2=~n; // 按位取反,不同设备的LED引脚可能不同
while(k<10) // 50ms循环10次
{
while(TF0==0); // 只要定时器没溢出,程序就会在这里一直打转
TH0=(65536-50000)/256;
TL0=(65536-50000)%256; // 重置初值
TF0=0; // 清溢出
k++;
}
k=0;
n=n<<1;
}
}
}
总结
参考文献:普中51单片机开发攻略
参考视频链接:【【51单片机入门教程】51单片机定时器工作原理及流水灯的实现,溢出、初值计算】https://www.bilibili.com/video/BV1k84y1v7q9?vd_source=5cce42e69288bd011ec197e4f4b8ae61