定时器/计数器 跟单片机CPU是相互独立的,定时、计数过程是自动完成的,不会占用CPU资源
是根据机器内部的时钟或者是外部的脉冲信号对寄存器中的数据加 1。
51单片机定时器有2组 (定时器/计时器),既可以定时、也可以计数 为定时器/计数器
可以增加单片机效率,简单重复的工作交给定时器、计数器,同事可以实现精确定时作用
为单片机提供定时信号的振荡源的周期(晶振周期或外加振荡 周期)。由晶振提供 一般12M 11.0952M 周期等于频率的倒数的。
2 个振荡周期为 1 个状态周期,用 S 表示。振荡周期又称 S 周 期或时钟周期。
1 个机器周期含 6 个状态周期,12 个振荡周期。
完成 1 条指令所占用的全部时间,它以机器周期为单位。
51 单片机相关周期的具体值为:
例如:外接晶振为 12MHz 时,51 单片机相关周期的具体值为:振荡周期=1/12us;状态周期=1/6us;机器周期=1us;指令周期=1~4us;一般机器周期使用的多
他有两组定时器/计数器、TMOD、TCON寄存器组成
他是来设置定时器/计数器的工作方式 低四位用于T0、高四位用于T1
GATE 是门空位,GATE=0 用于控制定时器启动是否受外部中断源信号影响
TMOD:
一般方式1、方式2 使用较多
使用 TR0、TR1,是否为1 启动定时器/计数器工作
GATA=1 时,要用软件使 TR0 或 TR1 为 1,同时外部中断引脚 INT0/1 也为高电平时,才能启动定时/计数器工作。即此时定时器的启动条件,加上了 INT0/1 引脚 为高电平这一条件
一般使用方式1、方式2,较多
计数为16位,分高八位,低8位
最高八位65536 第八位是你的初始值 计数多少ms
计数初值与计数个数的关系为:X=2 16 -N。
单片机使用的是12M外部晶振
机器周期 = 1/1m=1us,
1ms /1us =1000
初值= 65535 -1000 +1 ; 实际计数65536(2的16 次方溢出,后面+1)
64536=FC18H ,TH0=0xFC,TL0=0x18
自动重装初值的 8 位计数方式。工作方式 2 特别适合于用作较精确的脉冲信号发生器。
1、对TMOD寄存器配置,设置T0、T1的工作方式
TMOD |= 0x01 选择定时器0 方式1 工作,用或运算不干扰其他运算
2、根据所需时间,计算初值,并将其写入THO、TL0,TH1、TL1
3、使用中断,EA=1 开启定时器中断
4、TCON寄存器,是TR0或TR1 置位,启动定时/计数器计数
void time0_init(void) // 空类型函数(入参也为空)
{
TMOD|=0X01;//选择为定时器 0 模式,工作方式 1
TH0=0XFC; //给定时器赋初值,定时 1ms // 65535-1000+1 FC18H
TL0=0X18;
ET0=1;//打开定时器 0 中断允许
EA=1;//打开总中断
TR0=1;//打开定时器
}
// 定时服务 中断号1
void time0() interrupt 1 // 定时服务函数,定时0 中断号为1
{
static u16 i=0;
// 中断重新设置初值
TH0=0xFC; // 设置初值 定时1ms
TL0 = 0x18; // 以12M晶振 换算16进制
i++; // 进入一次计数一次
if(i ==1000) // 1s
{
i=0;
LED1=!LED1;
}
}
#include "reg52.h"
typedef unsigned char u8;
typedef unsigned int u16;
sbit LED1 = P2^0;
//void deplay_time(u16 time)
//{
// while(time--);
//}
void time0_init(void)
{
TMOD |=0x01; // 设置工作方式
TH0=0xFC; // 设置初值 定时1ms
TL0 = 0x18; // 以12M晶振 换算16进制
ET0 =1; // 使能
EA=1; // 总中断
TR0 =1; //定时器打开
}
// 定时1
//void time1_init(void)
//{
// TMOD |=0x10; // 设置工作方式1 高四位
// TH1=0xFC; // 设置初值 定时1ms
// TL1 = 0x18; // 以12M晶振 换算16进制
// ET1 =1; // 使能
// EA=1; // 总中断
// TR1 =1; //定时器打开
//}
void main()
{
time0_init();
while(1)
{
}
}
// 定时服务 中断号1
void time0() interrupt 1
{
static u16 i=0;
// 中断重新设置初值
TH0=0xFC; // 设置初值 定时1ms
TL0 = 0x18; // 以12M晶振 换算16进制
i++; // 进入一次计数一次
if(i ==1000) // 1s
{
i=0;
LED1=!LED1;
}
}