|
A /****************************************************************
Title: 超声波测距系统
Mcu: AT89S51 Oscillator: 12M
Designer: linqiuxiong Date: 2010.2.12
Email:taking@vip.qq.com
Directions: 经实践表明该系统的测距范围在0.21m-2m时,误差不超0.5cm;
大于2m时,最大误差不超过1.5cm;因发射功率不足,本系统的稳定测量范
围是0.21m-4m。
*****************************************************************/
#include<reg51.h> /*头文件*/
#include<intrins.h>
#define uchar unsigned char /*缩定义*/
#define uint unsigned int
#define nop() _nop_() /*定义空操作指令*/
#define sled_dm_port P0 /*定义数码管段码控制端口*/
#define sled_wm_port P1 /*定义数码管位码控制端口*/
sbit vout=P1^6; /*声明40KHz脉冲信号输出口*/
sbit fm=P1^7; /*声明蜂鸣器使能引脚*/
void delay_1ms(uchar x); /*1MS为单位的延时程序 */
void display(); /*显示子程序*/
uchar code num_table[13]=
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff,0x7f};
/* 0 1 2 3 4 5 6 7 8 9 - 消隐 .*/
/*定义数码管显示字符跟数字的对应数组关系*/
uchar data sled_lighten_table[]={0xf7,0xfb,0xfd,0xfe};
/*定义每次扫描时需点亮的数码管*/
uchar dis_buff[4]={0xff,0xff,0xff,0xff}; /*定义段码缓冲数组*/
uint time,distance; /*定义接收时间与距离变量*/
bit rec_flag; /*定义接收成功标志位*/
uchar k,j,wm; /*定义脉冲个数与位选控制变量*/
/*主程序*/
void main()
{
uint i;
TMOD=0x21; /*T1为8位自动重装模式*/
TH0=0x00; /*65ms计数初值*/
TL0=0x00;
TH1=0xf2; /*12us计数初值*/
TL1=0xf2;
PX0=1; /*外部中断0定义为高优先级中断源*/
PT1=1; /*定时器1定义为高优先级中断 */
ET0=1; /*T0溢出中断允许*/
EA=1; /*开中断*/
TR0=1; /*启动T0定时器*/
while(1)
{
dis_buff[2]=num_table[distance/100];
dis_buff[1]=num_table[distance%100/10];
dis_buff[0]=num_table[distance%10];
display();
if(rec_flag)
{
rec_flag=0;
for(i=400;i>0;i--) /*测量间隔控制(约4*100=400MS)*/
display();
EA=1;
TR0=1;
}
}
}
/*显示子程序*/
void display()
{
sled_wm_port=0xff; /*显示消影*/
if(wm==3)
sled_dm_port=0xff;
if(wm==2)
{
if(dis_buff[2]==0xc0) /*若第2位数码管为0则不显示*/
sled_dm_port=0xff;
else
sled_dm_port=dis_buff[2];
}
else
sled_dm_port=dis_buff[wm];
sled_wm_port=sled_lighten_table[wm];
wm++;
if(wm==4)
wm=0;
delay_1ms(1);
}
/*定时器T0中断程序*/
void TIMER0() interrupt 1
{
EA=0;
TH0=0x00;
TL0=0x00;
ET1=1;
EA=1;
TR1=1;
TR0=1;
}
/*定时器T1中断程序*/
void TIMER1() interrupt 3
{
vout=!vout;
k++;
if(k>=4) /*超声波脉冲个数控制(为赋值的一半)*/
{
k=0;
TR1=0;
ET1=0;
for(j=200;j>0;j--); /*1ms延时避开盲区*/
for(j=200;j>0;j--);
for(j=200;j>0;j--);
EX0=1; /*开启外部中断0*/
}
}
/*外部中断0程序*/
void PINT0() interrupt 0
{
TR0=0;
TR1=0;
ET1=0;
EA=0;
EX0=0; /*禁止外部中断0中断 */
rec_flag=1; /*接收成功标志位置1*/
time=TH0;
time=time*256+TL0;
time=time-120; /*补偿软件或硬件带来的误差*/
distance=time*0.017;
}
/*1MS为单位的延时程序*/
void delay_1ms(uchar x)
{
uchar i;
while(x--)
for(i=0;i<100;i++);
} |
|