51单片机定时器及其应用(2)(测量脉冲宽度)
上一篇文章讲了如何使用51单片机的定时器功能制作一个简易的数字钟,上次有一个GATE位没有涉及到,因此这次来介绍一下定时器的这个GATE位的应用,也就是测量脉冲宽度。先来介绍一下我们有什么“工具”,看一下定时器的TMOD寄存器:
这个GATE位,为了方便,这里以定时器1为例。手册说只有当定时器的外部引脚
I
N
T
1
ˉ
\bar{INT1}
INT1ˉ为高电平并且内部软件控制位TR1为1时才能打开定时器1,这正好能用于解决脉冲宽度测量这个难题。
将GATE置1,TR1置1,此时外部送来一个脉冲,在高电平器件就会开始计数,计数值在TH1和TL1寄存器里,当低电平到来时,关闭定时器,将最后的计数值减去初值,再乘以每秒计数间隔(51单片机每秒间隔为一个机器周期,1us左右),就可以得到脉冲宽度了。如果脉冲宽度过大,则每次计数值满了会产生溢出中断,此时只定义一个变量Count,每次溢出加1,并在中断服务程序中清0,就可以得到最终脉冲宽度为count×定时时间+TH1*256+TL1,单位为us。下面给出代码
#include <reg52.h>
sbit Wei_Select=P2^6;
sbit Duan_Select=P2^5;
sbit INT=P3^2;
char Display_Code[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
char Wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
long count=0;
long Pulse_Width=0;
unsigned int flag=0;
unsigned int Count_High=0;
unsigned int Count_Low=0;
unsigned int num=0;
unsigned int ge=0,shi=0,bai=0,qian=0,wan=0;
void delay_ms(unsigned int Xms)
{
unsigned int i=0,j=0;
for(i=Xms;i>0;i--)
for(j=110;j>0;j--);
}
void InitTimer0(void)
{
TMOD = 0x09;
TH0 = 0x14;
TL0 = 0x13;
EA = 1;
ET0 = 1;
EX0=0;
}
void Timer0()interrupt 1
{
TH0 = 0x14;
TL0 = 0x13;
count++;
}
void display(unsigned int position,unsigned int number)
{
Duan_Select=0;
Wei_Select=1;
P0=Wei[position-1];
Wei_Select=0;
Duan_Select=1;
P0=Display_Code[number];
delay_ms(2);
}
void Read_Count()
{
Count_Low=TL0;
Count_High=TH0;
num=Count_High*256+Count_Low;
}
void main()
{
InitTimer0();
while(1)
{
count=0;
flag=0;
while(INT==1);
TH0 = 0;
TL0 = 0;
TR0=1;
while(INT==0);
while(INT==1);
TR0=0;
Read_Count();
Pulse_Width=(count*65535+num)/1000;
ge=Pulse_Width%10;
shi=Pulse_Width/10%10;
bai=Pulse_Width/100%10;
qian=Pulse_Width/1000%10;
wan=Pulse_Width/10000%10;
while(flag!=200)
{
flag++;
display(8,ge);
display(7,shi);
display(6,bai);
display(5,qian);
display(4,wan);
}
}
}
测量范围为10ms到未知,只要你愿意等,能测量很宽的脉冲宽度,显示单位为ms。测量范围大的话,误差差不多为4ms左右。