|
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++);
} |
|