超声波测距

来源:互联网 发布:java ftp 坑 编辑:程序博客网 时间:2024/04/26 04:01

/*******************************************
**************超声波测距程序****************
*******说明:t0定时中断控制t2产生40khz的方波,
方波从p1.0口输出;由外部中断p3.3检测反射波;
t1用于发射到接收的计时**********************
*******张传兵制作于2009年8月14号***********
*******************************************/
#include<reg52.h>
#include<math.h> //用到sprt函数
#define uchar unsigned char
#define uint unsigned int

/*显示模块端口定义*/
sbit lcden=P1^3;
sbit lcdrs=P1^2;

bit display_flag; //显示标志位
bit cj_flag; //反射波测到标志
uchar stor_th1,stor_tl1;
uint distance[4];//距离缓冲区
uint pre_time;//用于特殊处理
uint dis;//距离

/*显示函数*/
void delay(uint x)
{
    uint i;
    for(i=x;i>0;i--);
}
void write_com(uchar com)
{
 lcdrs=0;
 lcden=1;
 delay(10);
 P0=com;
 delay(10);
 lcden=0;
 delay(10); 
}
void write_num(uchar num)
{
 lcdrs=1;
 lcden=1;
 delay(10);
 P0=num;
 delay(10);
 lcden=0;
 delay(10);  
}
void write_sfm(uchar add,uint time)
{
 uchar qian, bai,shi,ge;
 qian=time%10000/1000;
 bai=time%1000/100;
 shi=time%100/10;
 ge=time%10;
 write_com(0x80+add);
 write_num(qian+0x30);
 write_num(bai+0x30); 
 write_num(shi+0x30); 
 write_num(ge+0x30);     
}
void lcd_init(void)
{
 lcden=0;
 write_com(0x38);
 write_com(0x0c);
 write_com(0x06);
 write_com(0x01);
 write_com(0x80+0x01);
 write_num(0x20);
 write_num(0x20);
// write_sfm(0x06,real);
// write_sfm(0x46,set);
}
void init()
{
 EA=1;
 ET0=1; ET1=1;
 EX1=1;
     IT1=1;//外部中断1下降沿触发 
 TH1=0;
 TL1=0;//清定时
 TMOD=0x11;//定时0为16位
 TH0=(65536-1000)/256;
 TL0=(65536-1000)%256;
 TR0=1;

 T2MOD=0X02;/*t2产生40khz的方波*/
 T2CON=0X00;
 RCAP2H=(65536-75)/256;
 RCAP2L=(65536-75)%256;

 lcd_init();
}
void t0() interrupt 1 using 3
{
 static uint count1=1000;
 TH0=(65536-1000)/256;
 TL0=(65536-1000)%256;
 count1--;
 if(!count1) 
 {
  count1=1000;
  display_flag=1;   
 }
 if(count1%30==0)
 {
  TH1=0;//计数器清零
  TL1=0;
  EX1=1;//开接收反射波的外部中断1
  TR2=1;//产生40HZ的方波
  TR1=1;//记时开始 
 }
}
void t1() interrupt 3
{
 stor_th1=0x00;
 stor_tl1=0x00;
 distance[0]=0x01;
 distance[1]=0x00;
 distance[2]=0x00;
 distance[3]=0x00;
}
void int1() interrupt 2
{  
 TR1=0;//停止计数
 stor_th1=TH1;//存储时间值
 stor_tl1=TL1;
 TR2=0;//停止发送方波 
 EX1=0;
// TH1=0;//计数器清零
// TL1=0;
 cj_flag=1;//中断标志置位     
}
void main()
{
 uint time;
 init();
 while(1)
 {
  if(cj_flag)
  {
   time=(stor_tl1|(stor_th1<<8));
   if(time==15) //特殊情况处理 ,我也不知道为什么是这样的
    time=pre_time;
   else
    pre_time=time;
   distance[3]=distance[2];
   distance[2]=distance[1];
   distance[1]=distance[0];
   distance[0]=(uint)(time*0.17);
   dis=((distance[0]+distance[1]+distance[2]+distance[3])>>2); 
   dis=sqrt(dis-35)*sqrt(dis+35)-40;  
   cj_flag=0;
  }
  if(display_flag)
  {
  // write_com(0x01);
   write_sfm(0x40,distance[0]);
   write_sfm(0x46,distance[1]);
   write_sfm(0x4c,distance[2]);
   write_sfm(0x00,distance[3]);
   write_sfm(0x0c,time);    
   write_sfm(0x06,dis);
   display_flag=0;
  }
 }
}