Skip to content

定时/计数器

  1. 51 单片机中有两个 16 位的定时计数器。
  2. 每个 16 位的定时计数器最大计算能力位:65536(2^16)
  3. 分类
    • 加计数器:计数初值 = 最大计数值 - 计数值。
    • 减计数器:计数初值 = 计数值。
  4. 工作模式
    • 定时模式
    • 计数模式
  5. 工作方式:方式 0 ~ 方式 3
    • 方式 0:13 位
    • 方式 1:16 位
    • 方式 2:8 位,自动载入初值
    • 方式 3:8 位

操作步骤

设置工作模式

  1. TMOD 寄存器结构图

    • GATE:门控信号。0-软件开启 1-硬件开启
    • C/~T:0-定时模式 1-计数模式
    • M1:M0:00、01、10、11 设置 4 种工作方式。
    • TMOD 不支持位寻址。
  2. TMOD 寄存器设置 T0 为软件开启,工作在计时模式,工作方式是方式1。

写入计数初值

  1. 计数初值较大,需要用两个 8 位寄存器存储。

  2. 借助 TH0、TL0、TH1、TL1 寄存器完成初值的存储。

开启

  1. 通过 TCON 寄存器的高 4 位完成软开启工作。

  2. TCON 寄存器结构图

    • TR0:T0 的软开关。0-关闭 1-开启
    • TF0:T0 的溢出标识位。0-正常 1-计数结束。
    • TR1/TF1 同上。

查询法

  1. 设计并开启一个软开启的计数器 T0,工作方式为方式1,计数值为 3000。

    c
    #include <STC12C5A60S2.H>
    
    void init(void) {
        TMOD = 0x05;
        TH0 = (65536 - 3000) / 256;
        TL0 = (65536 - 3000) % 256;
        TR0 = 1;
    }
    
    void main(void) {
        init();
    }
  2. 设计并开启一个软开启的计数器 T0,工作方式为方式1,计数值为 3。用计数器控制 LED 的亮灭。

    c
    #include <STC12C5A60S2.H>
    sbit LED = P1 ^ 0;
    
    void init(void) {
        LED = 1;
        TMOD = 0x05;
        TH0 = (65536 - 3) / 256;
        TL0 = (65536 - 3) % 256;
        TR0 = 1;
    }
    
    void main(void) {
        init();
        while (1) {
            if (TF0) {
                TR0 = TF0 = 0;
                TH0 = (65536 - 3) / 256;
                TL0 = (65536 - 3) % 256;
                LED = ~LED;
                TR0 = 1;
            }
        }
    }

定时计数器中断

  1. 触发条件:当定时计数器完成工作后回出发定时计数器中断。

  2. 中断处理子函数执行完后,CPU 自动将 TF0/TF1 自动清零。

  3. 开启中断 —— IE 寄存器

    • EA:中断总开关
    • ES:串型中断
    • ET1:定时计数器 1 中断开关
    • EX1:外部中断 1 开关
    • ET0:定时计数器 0 中断开关
    • EX0:外部中断 0 开关
  4. 中断处理子函数:文档

    c
    void timer0(void) interrupt 1 {
    	……
    }
  5. 例:通过定时计数器中断控制 LED 的亮灭。

    c
    #include <STC12C5A60S2.H>
    typedef unsigned int UI;
    typedef unsigned char UC;
    
    sbit LED = P1 ^ 0;
    
    void storageInitValue() {
        TR0 = 0;
        TH0 = (65536 - 50000) / 256;
        TL0 = (65536 - 50000) % 256;
        TR0 = 1;
    }
    
    // 初始化
    void init() {
        LED = 1;
        EA = 1;
        ET0 = 1;
        TMOD = 0x01;
        storageInitValue();
    }
    
    void main() {
        init();
        while(1);
    }
    
    // 定时计数器 0 中断处理子函数
    void testTime0() interrupt 1 {
        static UC count = 0;
        count = ++count % 10;
        if (count) storageInitValue();
        else LED = ~LED;
    }

时基

  1. 时基:时间基础。
  2. 时基值取决于时钟晶振的频率。
  3. 一个时基大小就是一个机器周期

总结

外部中断

  1. 开中断。IE 寄存器
  2. 设置中断请求信号类型。TCON 寄存器
  3. 中断处理子函数。关键字:interrupt

定时/计数器

  1. 设置工作模式。TMOD 寄存器
  2. 写入计数初值。TH0、TL0、TH1、TL1
  3. 启动。TCON 寄存器的高 4 位

定时/计数器中断

  1. 开中断。IE 寄存器
  2. 中断处理子函数。

基于 MIT 许可发布