51单片机学习----定时器/计数器

什么是定时器?什么是计数器?

定时器,字面意思就是定时的。手机的闹钟就是个定时器,定个每天早上7点的闹钟。

计数器,字面意思计时统计个数的,来一个就加一个,一直累加着。

其实定时器和计数器里面的内容是一样的,区别在于,定时器是在数内部的时钟,计数器是数外面的脉冲。

STC89C51RC单片机的定时器/计数器

定时器/计数器0

定时器/计数器1

定时器/计数器2

其实传统的51单片机就只有定时器/计数器0和定时器/计数器1这两个,STC的51单片机自己加了一个定时器/计数器2。

定时器/计数器的核心内容就是一个加法计数器,对脉冲进行计数,来一个脉冲计数器就加1.

用作定时的时候,单片机是在数自己的系统时钟脉冲;

用作计数的时候,单片机是在数从外面的脉冲,这个外面的脉冲通过计数器绑定的引脚传给单片机,

T0对应的引脚是P3.4,T1对应的引脚是P3.5;

是用来定时还是用来计数,可以通过设置定时器模式寄存器TMOD的C/T位来决定。

定时器/计数器0的工作模式

模式0:13位定时器/计数器

模式1:16位定时器/计数器

模式2:8位自动重装模式

模式3:两个8位定时器/计数器

定时器/计数器1的工作模式

模式0:13位定时器/计数器

模式1:16位定时器/计数器

模式2:8位自动重装模式

定时器/计数器0、定时器/计数器1相关的寄存器

定时器控制寄存器TCON

TF1:定时器/计数器T1溢出标志位。当T1被允许计数后,就开始不断+1计数,计数计到最大值的时候,TF1位的值就自动变成1了,这也叫做硬件置1。如果这个时候定时器中断被允许了,那就向CPU请求中断,当CPU响应了中断之后,TF1位的值就自动变成0了。

TR1:定时器T1的运行控制位。TR1位要由软件来置位或者清零。TR1相当于计数使能信号,但是这个计数使能信号有个前提:

当TMOD计数器的第7位那个GATE =0的时候,TR1 =1,开始计数,TR1=0,禁止计数;

当TMOD计数器的第7位那个GATE =1的时候,TR1 =1,然后INT1为高电平的时候才开始计数

TF0:跟TF 1的功能是一样的,用于定时器/计数器0;

TR0:跟TR1的功能是一样的,用于定时器/计数器0;

IE1、IT1、IE0、IT0主要用于外部中断,这里就不介绍,免得引起混乱。

定时器模式寄存器TMOD

BIT7、BIT6、BIT5、BIT4是控制定时器1的

GATE =0的时候,TR1 =1,开始计数,TR1=0,禁止计数;

GATE =0的时候,GATE =1的时候,TR1 =1,然后INT1为高电平的时候才开始计数

C/T = 1的时候用于计数功能,C/T = 0的时候用于定时功能;

BIT3、BIT2、BIT1、BIT0是控制定时器0的

定时器0的数据寄存器TH0、TL0

定时器1的数据寄存器TH1、TL1

定时器0和定时器1工作在模式1的模型

定时器0和定时器1定时功能的C语言实现

#include <STC89C5xRC.H>

#define FOSC    11059200L

/*把T_MS的值写进TH和TL寄存器,TH是高八位,TL是低八位
**65535 - FOSC/12/1000,算一下,到定时器溢出刚好1ms
*/
#define T_MS    (65535 - FOSC/12/1000)

unsigned int count0 = 0;
unsigned int count1 = 0;

void main()
{  
    //TMOD = 0x01;//定时器0工作在模式1,16位模式,GATE==0
    TMOD = 0x11; //定时器0和定时器1都工作在模式1,16位模式
    
    /*把倒计时1ms的值装进数据寄存器*/
    TH0 = T_MS / 256;
    TL0 = T_MS % 256;

    TH1 = T_MS / 256;
    TL1 = T_MS % 256;
    
    TR0 = 1; //定时器0开启计数
    TR1 = 1; //定时器1开启计数
    
    ET0 = 1; //定时器0中断使能
    ET1 = 1; //定时器1中断使能
    
    EA  = 1; //中断总开关使能
    
    while(1);
}

//定时器0的中断服务函数
void timer0_ISR() interrupt 1 
{
    
    TH0 = T_MS/256;  //装载高八位的数据
    TL0 = T_MS %256; //装载低8位的数据

    count0++; //每次中断+1
    if(count0 == 1000) //1000次就是1秒钟
    {
        count0 = 0;
        P00 = !P00; //P00挂个LED,就能看到1秒的闪烁
    }
}

//定时器1的中断服务函数
void timer1_ISR() interrupt 3 
{
    TH1 = T_MS/256; //装载高八位的数据
    TL1 = T_MS %256; //装载低8位的数据

    count1++;

    if(count1 == 500) //500ms
    {
        count1 = 0;
        P01 = !P01; //P01挂个LED就能看到500ms的闪烁
    }
    
}

定时器0和定时器1的模式1(16位定时器)是用的比较多的,其实我们都知道51单片机是8位的单片机,所谓的16位,也是两个8位的寄存器拼接起来的。

在模式1,定时器中断服务程序中都要把TH(TH0、TH1)寄存器和TL(TL0、TL1)寄存器的值重新写入一遍,这样有点麻烦。就像你定闹钟一样,闹钟响之后,你还得重新设置一下。我想定个每天7点的闹钟,只设置一次可不可以,当然是可以的。这个就涉及到定时器的自动重装模式

定时器0和定时器1的模式2(自动重载)

所谓自动重载就是,定时器溢出中断产生后,不用在中断服务程序中再次设定TH和TL的值;

当溢出产生时,将TH中存放的值自动的装入TL中,显然自动重载模式计数最大值只有8位了,因为只有一个寄存器来计数,8位最大值就是255,到256就溢出,所以最多也就0.28ms就溢出中断了

定时器0模式2自动重装C语言实现

#include <STC89C5xRC.H>

unsigned int count0 = 0;

sbit TEST_LED = P0^0;

void main()
{
    TMOD = 0x02; //定时器0工作在模式2,8位自动重载
    TL0 = TH0 = 0; //256*12/11059200 = 0.28ms
    
    TR0 = 1; //定时器0开启计数 
    ET0 = 1; //定时器0中断使能    
    EA  = 1; //中断总开关使能
    
    while(1);
}

void timer0_ISR() interrupt 1 
{
    count0++;
    if(count0 == 1000) //280ms的闪烁
    {
        count0 = 0;
        TEST_LED = !TEST_LED;
    }
    
}

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值