使用定时器/计数器中断,需要将满足以下的条件。
1)中断总允许打开 EA = 1;
2)中断源允许打开 ET0 = 1或者 ET1= 1;
3)设置定时器计/计数器的工作方式(设置TMOD)
4)装载定时器,设置计数器的初始计算值。
5)开启定时器(TCON中的TR0 = 1或者TR1 = 1)
6)中断服务函数
通过前面一些中断文章的学习,相信除了上面的第4点外,使用定时器/计数器已经没什么难度了。
装载定时器,前面的定时器章节可以知道,定时器/计数器有4种方式。它们分别是13位手动装载(方式0)、16位手动装载(方式1)、8位自动重装(方式2)、8位手动装载(方式3)。根据定时器/计数器的位数需要TH0(1)与TL0(1)组成定时器/计数器的位数。
输入的时钟脉冲是由晶体振荡器的输出12分频后得到的,所以定时器是对机器周期的计数器,每一个机器周期+1,也就是说TH0(1)与TL0(1)组成定时器/计数器的位数的值,在每个机器周期+1,当该值溢出时,产生定时器/计数器中断。
下面以方式1与方式2,进行定时,点亮LED。
方式1
/****************************************
Header:
File Name: main.c
Author: adam
Date: 2020年9月19日
******************************************/
#include "reg52.h"
#include "stdio.h"
typedef unsigned char uchar;
typedef unsigned int uint;
uint countms = 0;
void DelayMs(uint ms);
void main(){
EA = 1; //总中断允许
ET0 = 1; //定时器T0中断允许
TMOD = 0x01; //设置为模式1,定时器模式:C/T=0;不启动外部INT0控制开始定时:GATE=0,
//定时1ms,机器周期1us,1000个机器周期1ms
//16位定时器溢出条件:满值65535(#FFFF)+1溢出,因此定时1ms需要(65535+1-1000);
//将该值分给两个寄存器,每个可以装256个数。
TH0 = (65536-1000)/256; //装载初值TH
TL0 = (65536-1000)%256; //装载初值TL
TR0 =1; //启动定时器TR0
while(1)
{
DelayMs(1000);
P0=~P0;
}
}
void DelayMs(uint ms)
{
while(countms<ms); //等待需要的ms;
countms=0;
}
void Timer0(void) interrupt 1
{
//重新装初值
TH0 = (65535-1000)/256;
TL0 = (65535-1000)%256;
countms++; //每ms,countms++
}
方式2
/****************************************
Header:
File Name: main.c
Author: adam
Date: 2020年9月19日
******************************************/
#include "reg52.h"
#include "stdio.h"
typedef unsigned char uchar;
typedef unsigned int uint;
uint countus = 0;
uint countms = 0;
void DelayMs(uint ms);
void main(){
EA = 1; //总中断允许
ET0 = 1; //定时器T0中断允许
TMOD = 0x02; //设置为模式2,定时器模式:C/T=0;不启动外部INT0控制开始定时:GATE=0,
//由于方式只有8位,最大定时只能到0.256us,因此先定时100us,然后通过100us定时ms。
TH0 = 256-100; //装载值TH,自动重装
TL0 = 256-100; //装载值TL,溢出产生中断。
TR0 =1; //启动定时器TR0
while(1)
{
DelayMs(100);
P0=~P0;
}
}
void DelayUs(uint us){
while(countus<us);
countus=0;
}
void DelayMs(uint ms)
{
while(countms<ms){
DelayUs(10);
countms++;
}
countms=0;
}
void Timer0(void) interrupt 1
{
countus++; //每ms,countms++
}
注:在上述的两个例子中,中断分别是1ms与100us。不建议使用定时器设置中断更小的时间。
虽然定时器可以设置定1us就可以产生中断,但是1us仅仅为一个机器周期,当中断响应后,进入中断服务函数。仅仅一条简单的语句执行可能要四个机器周期,再加上保护现场与恢复现场,将会占用较长的机器周期,使得定时不准确。
当GATE =1,定时器/计数器受到INT0/INT1电平的影响,INT0/INT1=1启动计数,INT0/INT1=0停止计数。当GATE =1,单片机上电后,P0~P3初值均为高电平,因此不需要外接高电平启动定时器/计数器。一般INT0/INT1采用以下的电路,按下按钮为低电平,定时器/计数器停止计数。
透析之眼 提了一个问题
阅读后有疑问,可以关注公众号,参与讨论哦
参与讨论
---------------------------------------------------------
如果觉得文章还不错,那就扫码关注吧!