1. 51-microcontroler

51-microcontroler-第四话-Timer

一.写在前面

stc89c51有两个定时/计数器,今天主要测试它的定时功能。使用定时器来进行时间计算要比使用循环来的更精准一些。

这里我使用的晶振为12MHz,至于为什么使用12MHz的晶振,原因是stc89c51的机器周期是12个时钟周期,选用12MHz晶振后单片机执行一个机器周期的时间刚好是1us。而定时器的工作原理就是每过一个机器周期就自动加一直到溢出。

stc89c51的定时器为16位,下图给出的是定时/计数器相关的寄存器TCON

此寄存器可以按位寻址,就是说你可以这样赋值TR1 = 1(开启定时器1);对于那些不能按位寻址的寄存器比如TMOD就不能这样赋值了。

TF1:定时器/计数器T1溢出标志。T1被允许计数以后,从初值开始加1计数。当最高位产生溢出时由硬件置‘1’TF1,向CPU发送中断请求,一直保持到CPU响应中断时,由硬件自动清零,当不执行中断时,也可以通过查询的方式对TF1标志位进行软件清零

TR1:定时器T1的运行控制位。由软件置位和清零。当GATE(TMOD.7)=0,TR1=1时就运行T1开始计数,TR1=0时禁止T1计数。当GATE(TMOD.7)=1,TR1=1且INTI外部输入高电平时,才允许T1计数

TF0:同TF1拥有两种清零方式。

本次测试只使用TCON的高四位,低四位为中断使用,下一次在测试。

还有一个寄存器TMOD需要使用

对于TMOD的模式选择

•模式 1(M1=0,M0=1),是THn和TLn组成了一个16位的定时器,计数范围是0~65535,溢出后,只要不对THn和TLn重新赋值,则从0开始计数。(最常用的一种定时模式)

•模式 2 (M1=1,M0=0),是8位自动重装载模式,只有TLn做加1计数,计数范围0~255,THn的值并不发生变化,而是保持原值,TLn溢出后,TFn就直接置1了,并且THn原先的值直接赋给TLn,然后TLn从新赋值的这个数字开始计数。 (常用于串口通信)

二.具体使用方法

本次在P0^0口接上一个LED灯希望LED灯能够1s亮,1s灭。

/* Main.c file generated by New Project wizard
 *
 * Created:   周一 6月 17 2019
 * Processor: AT89C51
 * Compiler:  Keil for 8051

单片机时钟周期为12MHz
12/12MHz = 1us
 */

#include <reg51.h>
#include <stdio.h>

//初始化LED灯,和计数器counter
int counter = 0;
sbit LED = P0^0;

void main(void)
 { 
    // Write your code here
    TMOD = 0x01;//定时器工作在模式1
    
    //设置定时器初始值(每次定时50ms)
    TH0 = (65536 - 50000) / 256;
    TL0 = (65536 - 50000) % 256;
    TR0 = 1;//开启定时器

    
    
    while (1){
        if(TF0 == 1){//定时器溢出
            //对定时器重新初始化
            TF0 = 0;
            TH0 = (65536 - 50000) / 256;
            TL0 = (65536 - 50000) % 256;
            //counter计数
            counter++;
            if(counter == 20){//计数满1s
                LED = ~LED;
                counter = 0;
            }
        }
    }
 }

说明:由于定时器是16位的所以当计数到65536时就会溢出,单片机会置TF0 = 1作为溢出标志。

因为我们希望一次溢出为50ms所以要对它设置初始值即(65536 - 50000) 为该十六位寄存器的初始值,

但是我们不能直接对该十六位寄存器赋值,只能通过高位TH0和低位TL0进行赋值

此时就会有初始值的求模运算结果赋值给TH0;求余运算结果赋值给TL0。