51单片机定时器

转载自--简书点击打开链接
定时器/计数器

简介
首先,“定时器/计数器”说的是一个东西,因为它既能计时也能计数。其次,它与数码管不一样,不是独立出来的配件,而是存在于单片机内部的一个独立的硬件部分,依赖晶振产生固定的时间间隔,产生了一定量的固定时间间隔后会引发定时器中断(参见:《扯会儿单片机开发:中断》),从而将其产生的时间信息传送给由CPU执行的主程序中。
相关寄存器

  • TMOD
    TMOD为定时器/计数器工作方式寄存器,用于确定其工作方式和功能选择。
    字节地址:89H,不能位寻址,reg52.h中已定义,单片机复位时全部清零。
位序号76543210
位符号GATEC/TM1M0GATEC/TM1M0

你会发现,低四位和高四位格式是一样的,因为低四位(03)用于设置定时器0,高四位(47)用于设置定时器1。设置的内容都是GATE、C/T、M1、M0。

GATEC/TM1M0
门控制位计数器还是定时器工作方式
0:仅受TCON的TR位控制。1:由TR和外部中断一起控制。0:定时器。1:计数器见下表
M1M0工作方式
00方式0,为13位定时器/计数器
01方式1,为16位定时器/计数器
10方式2,8位初值自动重装的8位定时器/计数器
11方式3,仅适用于T0,分成两个8位计数器,T1停止计数
  • TCON
    TCON为定时器/计数器控制寄存器,用于控制其启动、停止,标志其溢出和中断情况。
    字节地址:88H,能位寻址,reg52.h中已定义,单片机复位时全部清零。
位序号76543210
位符号TF1TR1TF0TR0IE1IT1IE0IT0

高八位与其运行和溢出有关,第八位与外部中断有关。

高八位中:

TFTR
溢出标志位运行控制位
溢出时,由硬件置11:启动定时器

TF0和TR0对应定时器0,TF1和TR1对应定时器1。

低八位中:

IEIT
外部中断请求标志外部中断触发方式选择位

IE0与IT0对应外部中断0,IE1与IT1对应外部中断1。因为此例与这里无关,不作详细介绍,有兴趣请自查资料。

初值

  • 简介
    定时器的实质是,由机器频率向一个16位寄存器累加,累加满溢出时触发中断。为了产生一个我们想要的时间间隔,比如说1s,所以我们要在这个寄存器里设定一个初值,以至于让它在这个初值上累加可以产生一个1s的倍数。这样我们就得到了稳定的时间间隔。
    这个寄存器分为TH(高八位)和TL(低八位)。所以我们需要把计算好的初值分成两部分分别放入THTL

  • 过程
    首先,我们通过单片机的晶振频率得知其时钟周期,再尤其乘以12得到机器周期。每一个机器周期在寄存器内+1,直到加满溢出产生中断

  • 例子
    若单片机频率为12Mhz,其时钟周期就是1/12μs,机器周期为1μs,也就是每1μs寄存器+1。16位的寄存器加到溢出最多需要(2^16)-1=65535μs,溢出也需要一个机器周期,所以总共要65536μs。但这个值太别扭,和我们要的1s没什么关系。我们最好让它记50000μs产生一次中断,所以其初值就设为65536-50000=15536。但我们还要将这个值分别放在高八位和低八位,所以要将这个十进制数,转换为4位十六进制数再分开赋值。
    十进制计算法:TH = 15536/256; TL = 15536%256;,进制计算问题这里不细讨论。
    这样的话,每50ms就会产生一次中断。我们只要用程序判断其中断20次就记1s


代码

代码部分我分为两个部分,一个是自定义的关于数码管编码表的头文件7seg.h,另一个是主程序源代码文件main.c
本例要实现的是在12MHz的时钟频率下,每隔一秒数码管显示的数字加一。


结合我的前一篇中断的寄存器IE等看点击打开链接

  • 7seg.h
#ifndef __7SEG_H__
#define __7SEG_H__

//共阳数码管的十六进制数编码表
unsigned char code hexForCommonAnode[] = {
    0x40, 0x79, 0x24, 0x30,
    0x19, 0x12, 0x02, 0x78,
    0x00, 0x10, 0x08, 0x03,
    0x46, 0x21, 0x06, 0x0e
};

//共阴数码管的十六进制数编码表
unsigned char code hexForCommonCathode[] = {
    0x3f, 0x06, 0x5b, 0x4f,
    0x66, 0x6d, 0x7d, 0x07,
    0x7f, 0x6f, 0x77, 0x7c,
    0x39, 0x5e, 0x79, 0x71
};

#endif
  • main.c
#include <reg52.h>
#include <7seg.h>    //包含自定义的编码表头文件

unsigned char THx = (65536-50000)/256;    //存储高八位寄存器初值的临时变量
unsigned char TLx = (65536-50000)%256;    //存储低八位寄存器初值的临时变量
unsigned char counter = 0;    //用于记录产生中断的次数
unsigned char digit = 0;      //用作编码表索引

//初始化函数:用于初始化各种参数
void init() {
    TMOD = 0x01;    //设置定时器0,GATE = 0, C/T = 0 , M1M0 = 01(方式1,16位定时器/计数器)

    //赋初值
    TH0 = THx;
    TL0 = TLx;

    EA = 1;    //中断总闸·开!
    ET0 = 1;  //定时器0中断·开!
    TR0 = 1;  //定时器0·运行!
}

//刷新函数:每调用一次就更新一次数码表的显示方式。
void refresh(){
    counter = 0;    //中断计数器清零
    P0 = hexForCommonAnode[digit];    //根据索引找编码表,将显示方式的二进制位丢给共阳数码管
    P2 = hexForCommonCathode[digit];  //根据索引找编码表,将显示方式的二进制位丢给共阴数码管
    P1 = digit;    //索引就是要显示的那个数字,可直接丢给BCD显示出来

    //数满后索引(数字)清零
    if(++digit >= 16)
        digit = 0;
}

//主函数
void main() {
    init();     //初始化
    refresh();  //先把0显示出来
    while(1);   //卡住
}

//定时器0的中断函数:由定时器中断自动调用,你只需要写好中断后要怎么处理就好
void timeInt_T0 () interrupt 1 {
    //每中断一次都要重新赋初值
    TH0 = THx;
    TL0 = TLx;

    //记够20次中断后,刷新显示
    if(++counter == 20)
        refresh();
}


作者:兔子泽
链接:https://www.jianshu.com/p/90ea43a7b4fd
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
C51单片机有两个定时器,分别为Timer 0和Timer 1。定时器的主要功能是计时和延时,可以用于控制程序执行的时间。 以下是C51单片机定时器的基本操作步骤: 1. 设置定时器模式:选择定时器工作模式,如定时器模式或计数器模式。 2. 设置定时器计数值:确定计数器的初始值,即计时的时间。 3. 启动定时器:启动定时器开始计时。 4. 等待定时器计时结束:等待定时器计时结束,即达到设定的计数值。 5. 停止定时器:停止定时器计时。 以下是一个简单的C51单片机定时器示例程序: ``` #include<reg52.h> #define uint unsigned int #define uchar unsigned char void timer0_init(); //定时器0初始化函数 void main() { timer0_init(); //调用定时器0初始化函数 while(1) { //程序执行任务 } } void timer0_init() { TMOD &= 0xF0; //设置定时器0为模式1 TH0 = 0x3C; //给定时器赋初值,定时1ms TL0 = 0xAF; ET0 = 1; //打开定时器0中断允许 EA = 1; //打开总中断允许 TR0 = 1; //启动定时器0 } void timer0() interrupt 1 using 1 { TH0 = 0x3C; //给定时器赋初值,定时1ms TL0 = 0xAF; //中断执行任务 } ``` 在上面的程序中,timer0_init()函数用于初始化定时器0,设置为模式1,计时1ms;timer0()函数是定时器0的中断处理函数,当定时器0计时结束后,会自动进入此函数进行中断处理。在这个函数中,可以编写相应的任务执行代码。在主函数中,通过while(1)循环不停地执行程序任务,而定时器0会在后台进行计时和中断处理。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值