【51入门系列】无法逃避的宿命----定时器

  • Cigoy
  • LV3工程师
  • |      2015-11-08 23:21:57
  • 浏览量 4120
  • 回复:25

本教程作者为云汉电子社区网友 ,回帖参与讨论、提问、分享,就能赢取超多丰厚奖励哦~  
也将随时和大家交流学习中的问题。(PS:本教程未经允许谢绝转载)

学教程,送奖励,活动说明详见:从〇开始学51系列

有了前面对于中断的理解

很多外设,就能够轻松驾驭了

今次咱聊聊有关定时器/计数器,下面简称T/C(Timer/Counter)

其实T/C51内部同属于一个电路模块

只不过计数器由外部事件驱动,接受的是外部脉冲

对外部脉冲进行计数

而定时器则是对51单片机自身产生的脉冲进行计数

无论是计数器还是定时器,计数或者定时达到一定数值

就会产生中断

看这个框图

【51入门系列】无法逃避的宿命----定时器

晶振的震荡频率经过12分频后,作为定时器的计数脉冲

如果是12MHz的晶振,不难推算

定时器的计数脉冲频率就是1Mhz

也就是说每1μs,定时器就会自己进行加1计数

值得一提的是,51单片机只能够进行加计数

而很多其他类型的单片机则可以进行加减计数

那么计数器呢

图中可以看出来

外部引脚T0/T1

【51入门系列】无法逃避的宿命----定时器

对应P3.4P3.5管脚所输入的信号

则作为计数器的计数脉冲

每一次有效信号到达

计数器就会自行加1计数

直至计数达到某一数值,产生中断

完成中断服务程序

So,定时器和计数器只是触发来源不同而已

那么究竟什么时候,T/C才会进中断呢?

咱就得给T/C的计数寄存器赋初值了

如果计数达到这个初值,便产生中断

最简单的理解就是杯子理论

51T/C比较简单,只能够加计数

所以,如果把一个杯子的容积看成T/C的计数大小

每一次计数都是向杯子里加水的话

那么杯子装满水后,继续加水便会溢出

也就是51产生中断的时刻

如果我们提前在被子里面倒上一些水,也就是赋初值

那么,就可以在我们需要的时间内出现中断

这种办法很容易被用来作为软件循环的时间基准

譬如定时1ms,然后在每xxms做一件什么事情

说高深点,也就是心跳啥的了

 

下面再来聊聊T/C的几种不同模式

一共有4种工作模式,以定时器0为例

直接上框图更加直观

先是工作模式0

【51入门系列】无法逃避的宿命----定时器

在工作模式0时,TL0的低5(D0-D4)TH0的全部8位构成了一个13位的寄存器

每次计数脉冲过来,这个13位的寄存器都会加1(如果有预设值的话,从预设值开始)

这个13位的寄存器自加满并溢出时

内核会把这个13位的寄存器清零,并且把TF0位置1,产生中断

如果我们需要继续使用定时器

那么在中断来临或者其他必要的时候

重新将TF0清零,且将TH0TL0进行赋初值

看看工作模式1

【51入门系列】无法逃避的宿命----定时器

模式1和模式0基本上完全一样

唯一的区别就是计数寄存器

模式013位,而模式1变成了TL0的全8位和TH0的全8位构成的16位计数寄存器

这么看来,模式1的计数/定时范围更大

再是工作模式2

【51入门系列】无法逃避的宿命----定时器

这个模式里面,可以自动装入预置数

不过牺牲了TH08位寄存器,将TH0作为保存预置数的寄存器

TL0作为计数寄存器,进行计数自加

显而易见,模式3虽然可以不需要手动赋初值

这种方式给编程带来了方便

但是计数范围就小了很多

适合作为一些通信的时间基准,譬如模式2可作为串口通信的波特率发生器

最后是工作模式3:

【51入门系列】无法逃避的宿命----定时器

要注意的是,T1/C1其实是没有工作模式3的,只有T0/C0才有

这种模式简单点理解,就是把T0/C0划为两个T/C

每个都是8位的计数寄存器

不过一个由TH0计数,一个由TL0计数

上面几张图很明显地可以看出各种模式之间的区别

简单总结一下:

工作方式0——13T/C工作模式,最多可计数213次方 次,:8192,;

工作方式1——16T/C工作模式,最多可计数216次方 次,:65536,;

工作方式2——8T/C工作模式,计算次数最多为2^8,256,;

工作方式3——8位定T/C工作模式 ,计算次数最多为2^8,256,;

 

51单片机设计了28位的特殊功能寄存器

用来控制T/C的工作状态

这两个特殊功能寄存器分别是

TMODTCON

都在特殊功能寄存器区

贴两个定时器中断寄存器,有前面中断的基础

应该是比较好理解的了

工作模式控制寄存器TMOD

【51入门系列】无法逃避的宿命----定时器

这个寄存器主要是用来设置T/C的工作模式和工作性质(是计数器还是定时器)

工作状态控制寄存器TCON

【51入门系列】无法逃避的宿命----定时器

其实TCON只有高4位是和T/C有关

4位其实与外部中断相关

Reg51.h头文件中都定义了这些寄存器的位

可以直接寻址并赋值

十分方便

 

那么预设值该怎么计算呢?

预置数的计算公式:预置数=最大值-需要计数的次数;

举个栗子

我要1ms产生一个中断,假设外部晶振是12MHz,采用模式1

那么T/C1μs进行一次计数

T/C计数1000次,便是1ms

计数最大值就是216次方

那么 预置数 = 65536 – 1000 =64536

64536的十六进制便是 FC18

所以,将TH0 = FCTL0=18作为预设值

并使能中断,就能达到1ms产生中断的效果

来做个试验

#include 

sbit LED2 = P1^0;

        

void main()

{ 

 TMOD=0x01;//设置定时器0为工作方式1

 TH0=0xfc;//设置初值,计划1ms定时器溢出中断(我用的是11.0592Mhz晶振)

 TL0=0X66;

 EA=1;//开总中断

 ET0=1;//开定时器0中断

 TR0=1;//启动定时器0

 while(1)

 {}

}

 

void time0() interrupt 1

{

LED2 = ~LED2;

/*重新配置计数器*/

    TF0 = 0;

    TH0 = 0xfc;

    TL0 = 0x66; 

}

简单分析一下这个代码

T0工作在方式1,赋初值FC66

计数器自加溢出后产生中断

中断里面LED2(P1.0)发生电平翻转

产生一个周期2ms的方波

有图有真相

【51入门系列】无法逃避的宿命----定时器

上图中实测电平保持时间是1.0159ms,与预期的1ms 稍有差别

大约在20us左右

这是由多方面因素造成

一是测量仪器的精度和IO口翻转的延时

二是中断里面执行了数条语句,别忘了51执行语句也是us级别的哟

一条c语言语句被IDE编译后,可能等效于好几条汇编机器语言

不过话说回来,指望用单片机完成十分精确的定时

本身就是个不靠谱的想法

要求严格的时钟,还是用专用IC来实现吧

继续闪个灯

#include 

sbit LED = P1^0;

unsigned int Count=0; //定义一个无符号整型变量

        

void main()

{ 

 TMOD=0x01;//设置定时器0为工作方式1

 TH0=0xfc;	//定时1ms

 TL0=0X66;

 EA=1;//开总中断

 ET0=1;//开定时器0中断

 TR0=1;//启动定时器0

 while(1)

 {



  if(Count ==500) //如果有500次自加,也就是500ms

   {

    Count = 0;

    LED = ~LED; 	//LED取反

   }

 }

}

 

void time0() interrupt 1

{

 Count ++; //变量每1ms自加1

    TF0 = 0;

    TH0 = 0xfc;

    TL0 = 0x66;

}

上个GIF

【51入门系列】无法逃避的宿命----定时器

呃,绿灯被我玩坏了

换了个高冷的冰蓝LED

So,到这里

T/C的基本的操作就是这么些

 

嗯,还有奖品未送出

这里设计几个题目吧

1、  可以用定时器中断来完成按键的去抖吗?拿点证据出来

2、  可以用计数器来测量外部计数信号吗?拿点证据出来

3、  试试模式3

根据回帖,选出获奖的小伙伴哟



  • 0
  • 收藏
  • 举报
  • 分享
我来回复

登录后可评论,请 登录注册

所有回答 数量:20
771270048 2015-11-23
定时器是必须掌握的,感谢楼主分享
0   回复
举报
发布
Cigoy 2015-11-22
赞一个,好认真
0   回复
举报
发布
Cigoy 2015-11-22

不错哟

赞一个

0   回复
举报
发布
hlwhlw 2015-11-18

不是外部中断1,是定时器中断0~~~,后面的1是中断向量号

按键在没有稳定之前是在一直抖动的,而不是一直按下的。

我觉得在定时器中断0里面不用检测按键,而是10ms后再来检测。

我以前消抖就是这样检测的,你也可以实际测试一下看看效果。


0   回复
举报
发布
903 2015-11-18
楼主赞一个
0   回复
举报
发布
1192137406 2015-11-18

哈哈,这不是为了在实物上也可以应用上? 学习之必要嘛

不过哪里有错的请给我指点出来哈!谢过谢过!

0   回复
举报
发布
hlwhlw 2015-11-18
用proteus仿真是不用消抖的,因为proteus是把元器件都理想化了。
0   回复
举报
发布
hlwhlw 2015-11-18
没关系,定时器和中断确实容易混淆。
0   回复
举报
发布
1192137406 2015-11-17
不好意思。今天我发现了自己之前犯了好多错误。
0   回复
举报
发布
1192137406 2015-11-17
/*
用外部中断0响应定时器中断:
当有按键按下时,开启定时器中断,定时器的开启是为了按键消抖延时。

现象:每按一下按键,LED亮灭交替
注:这个方法只用来学习中断跟定时 ,并不适用于实际中,因为当外部中断进行时,会导致计时不准确.
*/
0   回复
举报
发布
查看更多
x
收藏成功!点击 我的收藏 查看收藏的全部帖子