这里我们顺便讲解一下定时器0的工作模式2,也就是使用“小试管”的方式,TMOD的初始化就为“TMOD=0x02;”。
我们知道工作模式2的最长溢出时间仅为256*(12/11059200)=0.000277秒=277微秒。
我们想实现间隔51ms的流水灯实验该怎么做,首先我们定义一个变量cnt用来记录每次的溢出次数,然后我们的定时时间为51微秒(因为最大定时只有278微秒),cnt记录的值等于1000的时候,证明时间已经过去了51ms,于是再去执行流水灯的任务。
我们已经知道工作模式2是不需要在溢出之后再填充初始值的,比如我们定时的时间为51微秒,那么计算出“距离溢出的刻度”就为47(实际计算出的是47.0016,所以定时为51微秒误差就不大)。
所以给TL0赋初值为256-47=209=0xD1。那么TH0也是给初值为0xD1,这是保证每次TL0溢出之后新的初始值是等于TH0的值的,所以定时器工作模式2又叫做8位自动重装载模式。相关概念还需读者再去另外学习这些理论知识。
#include <reg52.h> #include <function.h>//详见第六章第8讲 void main() { u8 i; u16 cnt; LED_Init(); //初始化LED硬件模块 TMOD = 0x02; //设置定时器0为工作模式2 TH0 = 0xD1; TL0 = 0xD1; //定时51us TR0 = 1; //启动定时器0 while(1) { if (TF0 == 1) //每隔51us就可以进入一次这个if语句 { TF0 = 0; //定时器0溢出后,清零中断标志 cnt++; //记录溢出次数 } if(cnt>=1000) //时间过去了51ms { cnt=0; P0=~(0x01<<i); i++; } if(i>=8)i=0; } }
大家对照上一讲的工作模式1的代码会发现,工作模式2在while循环中不再出现TH0和TL0的身影,TL0每次溢出之后,初值又变为TH0初始时候的值了,所以定时时间在while循环之前就已经决定好了。
大家可以尝试着把“if(cnt>1000)”里的1000改为10000就是间隔510ms的流水灯了。
往后我们做的题目定时时间一般最少都是要定时1毫秒以上,所以用工作模式1的机会会很多,而工作模式2在我们前期教程里会很少运用,等学到串口通信相关知识时我们再重拾这个知识点。
本文固定URL:https://www.dotcpp.com/course/376
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程