简介
“定时器/计数器”说的是一个东西,因为它既能计时也能计数。是存在于单片机内部的一个独立的硬件部分,依赖晶振产生固定的时间间隔,产生了一定量的固定时间间隔后会引发定时器中断从而将其产生的时间信息传送给由CPU执行的主程序中。
相关寄存器
TMOD寄存器:决定定时器/计数器的工作方式,C51单片机中一共有两个16位定时器/计数器,分别为T1,T0。
位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
符号 | T1 | T1 | T1 | T1 | T0 | T0 | T0 | T0 |
GATE | C/T | M1 | M0 | GATE | C/T | M1 | M0 |
GATE | C/T |
门控制位 | 定时器/计数器 |
0:仅受TCON的TR位控制。 1:由TR和外部中断一起控制。 | 0:定时器。1:计数器 |
M1 | M0 | 控制方式 |
0 | 0 | 方式0,为13位定时器/计数器 |
0 | 1 | 方式1,为16位定时器/计数器 |
1 | 0 | 方式2,8位初值自动重装的8位定时器/计数器 |
1 | 1 | 方式3,仅适用于T0,分成两个8位计数器,T1停止计数 |
TCON寄存器:控制启动、关闭、标志其溢出和中断情况
位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
符号 | TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | IE0 | IT0 |
TF | TR |
溢出标志位 | 运行控制位 |
溢出时该位自动置1。中断执行时硬件清0或软件清0 | 置1开始计时,清0停止计 |
TF0和TR0对应定时器0 | TF1和TR1对应定时器1。 |
IE | IT |
外部中断请求标志 | 外部中断触发方式选择位 |
IE0与IT0对应外部中断0 | IE1与IT1对应外部中断1 |
中断具体见——C51单片机学习笔记之中断系统
原理图
代码部分
实现一个秒表
/*数码管部分*/
#include <REGX52.H>
#include "delay.h"
sbit U3=P2^0;
sbit U4=P2^1;
unsigned char DX[]={0x3F,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7F,0x6F,0X40};//¶ÎÑ¡
char dx(unsigned int x)
{
unsigned char y;
y=DX[x];
return y;
}
void wx(unsigned char locaton)
{
switch(locaton)
{
case 1:P0=0xfe;break;
case 2:P0=0xfd;break;
case 3:P0=0xfb;break;
case 4:P0=0xf7;break;
case 5:P0=0xef;break;
case 6:P0=0xdf;break;
case 7:P0=0xbf;break;
case 8:P0=0x7f;break;
}
}
void print(unsigned char x,y)
{
U3=1;
P0=dx(x);
U3=0;
U4=1;
wx(y);
U4=0;
delay();
P0=0x00;
}
#ifndef __DigitalTube_h__
#define __DigitalTube_h__
void print(unsigned char x,y);
char dx(unsigned int x);
void wx(unsigned char locaton);
#endif
/*按键部分*/
#include <REGX52.H>
void delay1()
{
unsigned int i;
for(i=0;i<30000;i++);
}
unsigned char MatrixKey()
{
unsigned char KeyNumber;
P1=0xFF;
P1_0=0;
if(P1_4==0)
{
delay1();
while(P1_4==0);
delay1();
KeyNumber=1;
}
if(P1_5==0)
{
delay1();
while(P1_4==0);
delay1();
KeyNumber=2;
}
if(P1_6==0)
{
delay1();
while(P1_4==0);
delay1();
KeyNumber=3;
}
return KeyNumber;
}
#ifndef __MatrixKey_H__
#define __MatrixKey_H__
unsigned char MatrixKey();
#endif
/*延时部分*/
#include <REGX52.H>
#include "intrins.h"
void delay()
{
unsigned int i;
for(i=0;i<200;i++);
}
#ifndef __delay_h__
#define __delay_h__
void delay();
#endif
/*中断部分*/
#include <REGX52.H>
#include "delay.h"
#include "DigitalTube.h"
unsigned int time=0,num=0,num2=0,num3=0;
void InitTimer0()//中断初始化
{
TMOD=0X01;
TH0=(65535-50000)/256;//高八位
TL0=(65535-50000)%256; //低八位
EA=1;//中断打开
ET0=1;//定时器中断打开
TR0=1;//定时器打开
}
void delay1()
{
unsigned int i;
for(i=0;i<30000;i++);
}
void show()
{
while(1)
{
print(num3/10,1);
print(num3%10,2);
print(10,3);
P0=0x00;
print(num2/10,4);
print(num2%10,5);
print(10,6);
print(num/10,7);
print(num%10,8);
P1=0xFF;
P1_0=0;
if(P1_4==0)
{
delay1();
while(P1_4==0);
delay1();
num++;
}
if(P1_5==0)
{
delay1();
while(P1_4==0);
delay1();
num2++;
}
if(P1_6==0)
{
delay1();
while(P1_4==0);
delay1();
num3++;
}
}
}
void exter1() interrupt 1
{
TH0 = (65535-50000)/256;
TL0 = (65535-50000)%256;
time++;
if(time==20)
{
time=0;
num++;
}
if(num==60)
{
num=0;
num2++;
}
if(num2==60)
{
num2=0;
num3++;
}
if(num3==24)
{
num3=0;
}
}
#ifndef __Time_h__
#define __Time_h__
void show();
void InitTimer0();
void MatrixKey();
#endif
/*主函数*/
#include <REGX52.H>
#include "DigitalTube.h"
#include "Time.h"
main()
{
InitTimer0();
while(1)
{
show();
}
}
结论
这一章重点就是理解定时器/计数器的寄存器,能够配置寄存器。代码实现秒表的原理是——中断时间是50毫秒,累计20次就是1秒,每累计20次就置0。