基于89C51单片机的超声波测距系统设计与制作

  • Post author:
  • Post category:其他



程序如下

main.c

/*********************************************************************/

/*              超声波测距数码管显示                                 */

/*********************************************************************/

/*  温度补偿                                                         */

/*  用定时器0计数测量超声波发送接收时间                              */

/*  用定时器1给ds18b20定时发收温度信号                               */

/*  用外部中断0接收超声波返回的第一个脉冲                            */

/*********************************************************************/

#include<reg52.H>

#include<intrins.h>

#include<wen.h>

#include<chao.h>

/*********************************************************************/

extern uint dis;

/*********************************************************************/

/***********************************/

/*        主函数


*/

/***********************************/

void main(void)

{





init();

//


display(1234);

//


delayms(100);



while(1)           //循环测量并显示



{



tran();        //发送超声波信号测距



display(dis);  //显示距离



delayms(100);

//


wen();


//显示温度



}

}

chao.c文件

#include<reg52.H>

#include<intrins.h>

#include<wen.h>

#include<chao.h>

/*********************************************************************/

uint dis;

uint H=100;

uint L=20;

uchar flag=0;


//中断标志

uchar high_time;   //时间高位

uchar low_time;


//时间低位

uchar i,s1num;

/***************************

数码管为共阴数码管

***************************/

#define seg P0   //数码管的数据口为P0口

sbit s3=P2^0;

sbit s0=P2^1;

sbit s1=P2^2;

sbit s2=P2^3;

sbit dp=P0^7;    //小数点

uchar shuzu[]={

0x3F, //”0″

0x06, //”1″

0x5B, //”2″

0x4F, //”3″

0x66, //”4″

0x6D, //”5″

0x7D, //”6″

0x07, //”7″

0x7F, //”8″

0x6F, //”9″

/*0x77, //”A”

0x7C, //”B”

0x39, //”C”

0x5E, //”D”

0x79, //”E”

0x71, //”F”

0x76, //”H”

0x38, //”L”

0x37, //”n”

0x3E, //”u”

0x73, //”P”

0x5C, //”o”

0x40, //”-” */

0x00, //熄灭

0x00  //自定义





};

/*********************************************************************/

/***********************************/

/*       初始化函数


*/

/***********************************/

void init(void)

{



TMOD=0x11;  //定时器0方式1用于计时



TH0=0;



TL0=0;



TH1=(65536-60000)/256;    //温度计时初值



TL1=(65536-60000)%256;



ET1=1;                           //开定时器1中断



TR1=1;                            //启动定时器1





EA=1;



IT0=1;  //下降沿有效

}

/***********************************/

/*       显示函数


*/

/***********************************/

void display(uint dat)

{



uchar i,j,k,l;  //分别为百十个位的缓存



dat=dat-70;



i=dat/1000;     //百位



j=dat/100%10;   //十位



k=dat/10%10;    //个位



l=dat%10;       //十分位

//


write_12864com(0x8b);

//


write_12864dat(table[i]);

//


delay_50us(1);



//


write_12864dat(table[j]);

//


delay_50us(1);

//


write_12864dat(table[k]);

//


delay_50us(1);

//


write_12864dat(table[10]);

//


delay_50us(1);

//


write_12864dat(table[l]);

//


delay_50us(1);



s3=1;



s2=0;



s1=1;



s0=1;



seg=~shuzu[i];

//


dp=0;



delayms(2);

//


dp=1;



s2=1;



s3=1;



s2=1;



s1=0;



s0=1;



seg=~shuzu[j];



delayms(2);



s1=1;



s3=1;



s2=1;



s1=1;



s0=0;



seg=~shuzu[k];



dp=0;



delayms(2);



dp=1;



s0=1;

s3=0;



s2=1;



s1=1;



s0=1;



seg=~shuzu[l];

//


dp=0;



delayms(2);

//


dp=1;



s3=1;

}

/***********************************/

/*       超声波测量函数


*/

/***********************************/

void tran(void)

{



uchar i;



float temp;



TH0=0;



TL0=0;    //清定时0



TR0=1;    //开定时0



flag=0;



for(i=8;i>0;i–)



{



csb=!csb;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;



nop;






}





csb=1;



delayms(50);



EX0=1;        //开中断

//


if(flag!=1)

//


{


//


dis=55;

//


}



if(flag==1)   //中断标志位置1,说明有回波



{             //以下为路程计算



temp=high_time*256+low_time;



temp=(temp/100.0)/2.0;



temp*=331.45+0.607*30;


//温度补偿V=331.45+0.607*T(温度)



//


temp*=350+0.607*(gett()/100.0);



temp=temp/10.0;



dis=temp;





flag=0;



}

}

/***********************************/

/*       中断函数


*/

/***********************************/

void TT() interrupt 0

{



float tmp;



TR0=0;     //关定时器0



ET0=0;     //关外部中断



flag=1;    //置位标志位



tmp=TH0*256+TL0;         //读取定时器的值

//


if((tmp>0)&&(tmp<30000)) //判断是否超出范围,此设置的范围为0到5米



if((tmp>0)&&(tmp<=60000))



{



high_time=TH0;       //把计时值放入缓冲



low_time=TL0;



}



else         //超出范围则重新测量



{



high_time=0;



low_time=0;



}

}

wen.c文件

#include <reg52.h>

#include <wen.h>

#include”chao.h”

/***********************************************************************************/

uchar8 dis1[6] = { 0, 0, 0, 0, 0, 0 }; //数据暂存

uchar8 code wendu[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};  //0到9的代码

uchar8 flag1,sig,temp1;


//flag用于判定是否有中断,sig判定温度符号

/***********************************************************************************/

/********************************/

/*         延时函数             */

/********************************/

void delay(int us)


//DELAY-11.0592MHZ 调用程序大约为24us,每次循环为16us

{




int s;



for(s=0;s<us;s++);

}

/********************************/

/*         毫秒延时             */

/********************************/

void delayms(int z)



{




int x,y;



for(x=z;x>0;x–)



for(y=125;y>0;y–);

}

/********************************/

/*         复位程序             */

/********************************/

unsigned char reset(void)

{




uchar8 presence;



DQ=0;


//拉低总线。当总线停留在低电平480us-960us ,总线上所以器件都将被复位



delay(30);


//保持低电平504us



DQ=1;


//释放总线,让其恢复高电平



delay(3);


//等待芯片应答信号



presence=DQ;


//获取应答信号



delay(25);


//延时以完成整个时序



return(presence);


//返回应答信号。有芯片应答返回0,否则返回1。

}

/********************************/

/*        写一位数据            */

/********************************/

void write_bit(char bitval)

{




DQ=0;


//拉低DQ总线,开始时序



if(bitval==1)  //如果写入的为1,则返回高电平



DQ=1;



delay(5);  //延时104us,以完成整个时序



DQ=1;



}

/********************************/

/*       写一字节数据           */

/********************************/

void write_byte(char val)

{




uchar8 i,commend;



for (i=0;i<8;i++)


//写入一个字节的数据,一个时序中写一次



{




commend=val>>i;


//右移i位



commend&=0x01;


//复制那位数据到temp



write_bit(commend);  //调用write_bit()



}



delay(5);


//延时104us以完成此次时序,之后再写下一数据

}

/********************************/

/*       读一位数据             */

/********************************/

unsigned char read_bit(void)

{




uchar8 i;



DQ=0;


//拉低DQ,开始读时序



DQ=1;


//释放DQ总线





for(i=0;i<3;i++);


//从时序开始延时15us

return(DQ);


//返回DQ值

}

/********************************/

/*     读一字节数据             */

/********************************/

unsigned char read_byte(void)

{




uchar8 i,value=0;



for(i=0;i<8;i++)



{






if(read_bit())  //读一字节数据,一个时序中读一次,并作移位处理



value|=0x01<<i;



delay(6);


//延时以完成此次读时序,之后再读下一数据



}



return(value);

}

/********************************/

/*     温度转化                 */

/********************************/

void tmconvert(void)

{




reset();


//复位



delay(1);



write_byte(0xcc);


//仅一个DS18b20 ,跳过ROM



write_byte(0x44);


//温度变换

}

/********************************/

/*     读取温度                 */

/********************************/

unsigned int gett()

{




uchar8 LSB=0,MSB=0;


//用于存储读取的温度



long temp;





reset();


//复位



write_byte(0xcc);


//写指令,跳过ROM,仅一个DS18b20



write_byte(0xbe);


//写指令,读暂存存储器



LSB = read_byte();


//读LSB



MSB = read_byte();


//读MSB



sig=(MSB>>4==0X0F);



if(sig)                   //判断符号位是否为负值,是负值了,转去处理

{





LSB=~LSB;                 //温度处理



MSB=~MSB;



LSB=LSB+1;



}



temp=MSB*256+LSB;


//十六进制转换为10进制



temp=temp*100/16;


//12位精度,最小分辨率为0.0625°C



return temp;


//获得0.01°C 的精度并返回

}

/********************************/

/*     温度处理                 */

/********************************/

void display1(unsigned int m)



{


uchar8 i;


//分离各数位



dis1[1] = m/10000;


//百位





dis1[2] = (m%10000)/1000;  //十位



dis1[3] = (m%1000)/100;


//个位



dis1[4] = (m%100)/10;


//小数第一位





dis1[5] = m%10;


//小数第二位



delayms(30);

//


write_12864com(0x9b);


//0x80+地址码,设置数据地址指针(显示 第一行:0-0fH,第二行:40-4fH;)




//


if(sig) write_12864dat(table[11]);


//如果sig=1,显示负号;否则显示正号

//


else write_12864dat(table[12]);

//


for(i=1; i<6; i++)

//


{




write_12864dat(table[dis1[i]]);


//显示温度



if(i==3) write_12864dat(table[10]);


//显示小数点



//


}

}

/********************************/

/*     温度显示函数             */

/********************************/

void wen(void)

{




char i;



if(flag1==1)


//是否有中断产生



{




flag1=0;


//中断标志位清零



tmconvert();


//开始温度转化



gett();


//读取温度



for(i=0;i<30;i++)



display(gett());


//显示温度



}

}

void timer0() interrupt 3


//定时器0 中断

{





TH1 =(65536-60000)/256;



TL1 =(65536-60000)%256;



flag1=1;

}

这是我们大三时候的课程设计,现在拿出来和大家分享,希望对各位朋友有帮助!



版权声明:本文为weiguishan原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。