前端开发入门到精通的在线学习网站

网站首页 > 资源文章 正文

51单片机-配置定时器 51单片机配置定时器步骤

qiguaw 2024-12-25 14:55:17 资源文章 27 ℃ 0 评论

配置寄存器

首先,让我们来先配置下定时器,如何配置定时器。定时器是要先把相关的符号先进行声明的,但由于#include <REGX52.H>当中已经帮我们声明好了,那么我们直接使用即可。

先把图放在这里方便观看!

⒈TMOD配置

〖内容?定时器/计数器工作模式寄存器TMOD〗

?

那么我们先创建一个子函数 void Timer0_Init() ? 对定时器进行初始化。

那么首先是TMOD的一个配置,定时器1我们先不管(高四位定时器全部给上0),只管低四位的一个定时器0的一个配置。

STC89C52 的 T0 和 T1 一共有四种工作模式:在这里我们选择最常用的工作模式1。

Ⅰ:工作模式①的话,我们只需要把 M1 = 0,M0 = 1 就是定时器模式①的配置了。

Ⅱ:C/T(取反):这个我们只需要给C/T(取反) = 0即可,SYSclk?系统时钟。

Ⅲ:GATE(门控端),GATE = 0,这里当中都是数字电路当中的一些基础逻辑门,TR0 = 1。

经过上述的TMOD配置,此时,TMOD = 0x01;// 0000 0001 (十六进制→二进制)

注→TMOD是不可位寻址:寄存器只能进行整体的进行赋值『十六进制0x』

⒉TCON配置

〖内容?定时器/计数器控制寄存器TCON〗

?TCON可位寻址,注→可位寻址可以为每一位寄存器单独赋值。

在这个我们主要针对 TF0 和 TR0,注:这里我们是单独赋值,用二进制(0/1)来。

Ⅰ: TF0中断溢出标志位,TF0 = 0 被允许计数以后,从处置开始计数+1,当最高位产生溢出的时候,由n硬件置"1"TF0 = 1的时候就会向CPU请求中断。

在程序当中我们先可以直接给TF0 = 0,因为一旦TF0 = 1的就会产生中断。

Ⅱ:TR0 就是计数系统会不会开启,TR0 = 1的时候就代表着开始计数。

那么我们就可以给 TR0 = 1 开始计数工作。

拓展→IE0和IT0就是用来控制外部中断引脚的,但是因为GATE门控端 = 0,那么我们就可以不用去配置这些东西。

?Ⅲ:我们还需要配置 TL0 和 TH0 这里我们也需要给它写好一个值。这个计数脉冲就是在12MHZ情况下,每隔1us进行+1,等加到最大值的时候 65535us,它才进行产生一个中断。TL0是低字节,TH0是高字节。它们都是计数系统,这两个字节总共可以存储0~65535。每隔1us加1,总共时间是65535us,这就相当于是65ms计满之后就计数不下去了(好比一个沙漏?的沙子已经放满了)

64535us离计数器溢出差值1000us=1ms,每隔1ms的时候产生中断。每一次中断之后再次的计一次数,每计数1000us的时候再做其它的事情。

注:定时器的工作单位方式是以微妙(us)为单位的。

那么在这里我们可以先定义一个1ms的时间,所以我们刚开始的时候就可以给64535离计数器计满(溢出)差值的时候就为1000个数(1ms),注:我们寄存器是⑧个比特位为一位的,⑧位的只能存的下256。而这个65535它是指的是两个⑧位的拼接在了一起,一句话:要分开来。

TH0 = 64535/256;把高8位拿出来了,TL0=64535%256;低8位拿出来了。这个可能理解起来会比较难点,但是其实这样就很好理解了,用画图的方法来演示下吧

?中断的配置

?为了方便观看把图放在这里

那么定时器的配置已经配置好了,接下来就是中断的配置了。

在这里我们只需要配置T0的那一条路线即可。这个配置就比上述容易许多了。

Ⅰ:ET0 = 1

Ⅱ:EA = 1

Ⅲ:PT0 = 0 『默认:即为zero』

void Timer0_Init(void)

那么上述的定时器初始化配置如下↓


那么以上void Timer0_Init() ? 对定时器初始化的函数就已经好了。我们只需要在源文件.c的 main() 函数当中进行初始化,上电的时候它实际上已经是开始工作的了。那么这样才能让它进行中断呢。

注:上述实际上是65536才到溢出,当然65535仅仅也知识多出了1微秒。

STC89C52中断资源

?interrupt0 表示的是外部中断。注:P3.2引脚可以使用。

interrupt1 表示(定时器中断0) 在这里我们使用的是定时器0的中断。

interrupt2 表示(外部中断1) 注:P3.3引脚可以使用。

interrupt3 表示(定时器中断1)

interrupt4 表示(串口中断)

我们此时还需要在main()函数后面再写一个子函数,这个子函数的作用就是代表"闹钟"响了之后跳转到这个子函数当中去执行最终的中断任务,指的就是void Timer0_Init(void)

注:interrupt是关键字。


上述代码总的意思实际上就是→执行main()函数当中的定时器初始化Timer0_Init(); 定时器初始化好之后。原本这个程序是在while(1);执行的时候就会跳转到 void Timer0_Routine(void) interrupt 1 这个中断子函数当中去执行完这个子函数完的时候就会回到while(1);依次往复这个过程。

注?在中断任务当中需要重新赋值定时器初始值,如果你赋值它为2ms的话,那么也只是第一次为1ms,等到第二次的时候到中断任务就会编程2ms。所以我们通常会把中断任务的赋初始值和定时器任务赋初始值都是一样的。

但是如果我们在while(1);死循环+个让一脚点灯,它既可以执行while(1)循环里面的点灯的程序又可以执行中断任务,这个就是为什么使用定时器是可以在一定情况下同时完成⒉项任务

实验很简单我们可以点个灯试一下或者调试看下是不是如上述所说。

流程图

?主程序(main)函数 --> 其它子函数 --> 中断来了定时

器溢出,中断请求 --> 跳转到中断的一个函数里面执行中断里面的任务 --> 中断执行完之后再返回原来断点的地方就是原来从哪里停的现在从哪里回来 --> 然后再继续执行主函数。

从上面的理解当中我们可以看出,这个程序当中在一定的程度上,可以同时完成两项任务。比如说:执行主程序其它子程序也在执行。就像是LED的流水灯上,既可以执行流水灯的扫描,其次按键也可以进行控制流水灯。好处是:大大的提高了运行效率,有兴趣可以了解一下中断的概念实际上是非常多的。

定时器点灯?间隔1s

程序代码如下所示↓

拓展:注如果g_Count不是用全局变量的话,而是局部变量的话,那么那个局部变量需要被static 进行修饰,其作用:延长生命周期,出了局部变量原来修饰变量的值不会被销毁,再次回到函数当中被修饰的变量依旧会保持原来的值的大小。

注:我们这里的 g_Count++ 是每次+1ms。所以当它不满足if()语句的判断条件的时候是还需要返回到while(1);语句当中去的。再次进入到中断执行中断任务。

TMOD问题

当然上述代码当中还是存在着缺陷的,那就是TMOD,在上述当中我们TMOD是不可谓寻址就是不能单个赋值初始值必须⑧位才行。在这里我们使用一个定时器是当然没有任何问题的,因为我们的定时器1更本就没有开始工作不会出现问题。

出问题是在于:同时使用⒉个定时器的时候,定时器1和定时器0的话。高位会被刷新!

当然,实际上TOMD = 0x11;也是可以使用两个定时器的。但是它的操作上有很大的区别↓

TMOD = TMOD&0xF0;

TMOD = TMOD|0x01;

这个是可以进行统一的处理,而也建议大家这样养成一个好的习惯。

TMOD = 0x11;

这种是单独进行处理。

所以,在使用TMOD的时候推荐用这种代码方式↓


注:TMOD默认为低电平。

TMOD低四位清0,高四位保持不变。 0000 0000 & 1111 0000 = 0000 0000

任何数1&1还是等于1,任何数&0还是等于0的。

TMOD最低为置1,高四位保持不变。 0000 0000 | 0000 0001 = 0000 0001

任何数或上一个0,就是等于自身的那个数。

那么这个与或赋值法就可以操作其中的几个位而不会影响其它的位。

STC-ISP-自动配置

在STC-ISP软件上可以直接配置定时器计算器的,如下图所示

?AUTR:可以删除因为已经是12T模式了。当然这里还是少了中断的配置我们需要加上的。

Ⅰ:ET0 = 1

Ⅱ:EA = 1

Ⅲ:PT0 = 0 『默认:即为zero』

TL1和TH1的配置都是可以的?

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表