带温度补偿的超声波测距仪电路原理图如下:
Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)
元器件清单
带温度补偿的超声波测距仪
序号 元件名称 型号与规格 单位 数量
1 电阻 1KΩ 只 6
R19 10k 只 1
R3 200K 只 1
R4 20Ω 只 1
R7~R12 R14 R17 R18 R20 470Ω 只 10
2 排针 排 1
3 电解电容 C3 3.3μF 只 1
C4 1μF 只 1
C7 10μF 只 1
4 电瓷电容 C1 0.24μF 只 1
C2 330 pF 只 1
C5 C6 30 pF 只 1
5 晶振 Y1 12MHz 只 1
6 三级管 VT1~VT4 9012 只 4
7 温度传感器 DX18320 块 1
8 单片机 AT89S52 块 1
9 红外线接收芯片 CX20106A 块 1
10 按钮 S1~S3 只 3
11 发光二级管 VD1 只 1
12 数码管 4位 只 1
13 超声波发射 LS1 只 1
14 超声波接收 LS2 只 1
单片机源程序如下:
- #include<reg52.h>
- #define uint unsigned int
- #define uchar unsigned char
- #define ulong unsigned long
- sbit we0=P2^0; // 数码管位定义
- sbit we1=P2^1; //
- sbit we2=P2^2; //
- sbit we3=P2^3;
- sbit fasong=P1^0; //超生波发送接口
- sbit jieshou=P3^2; //超声波接受接口
- sbit k1=P3^6; //开关键
- sbit k2=P3^7; //温度距离显示切换键
- sbit ds=P1^4; //温度传感数据接口
- uchar timers,mi,fenmi,limi,num2,num1,shi,ge,shifen,shengsu;
- bit flag,kaiflag,temflag; //定义各种标志位
- ulong t,s; //接收时间和距离
- uint temp,num;
- float n; //18b20读取数据时用
- uchar code table[]= //数码管显示编码(不带小数点and带)
- {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
- 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
- void init(); //声明初始化函数
- void delay100us() //超声波避盲区延时函数
- {
- uchar i,j;
- for(i=40;i>0;i--)
- for(j=248;j>0;j--);
- }
- void delay(uchar a) //短暂延时函数(用于18B20)
- {
- while(a>0)
- a--;
- }
- void shijian(uint x) //一毫秒延时函数
- {
- uint i,j;
- for(i=x;i>0;i--)
- for(j=110;j>0;j--);
- }
- void reset() //18B20复位
- {
- ds=0;
- delay(103);
- ds=1;
- delay(4);
- }
- void write(uchar date) //18B20写一字节数据
- {
- uchar temp,i;
- uint j;
- temp=date;
- for(i=0;i<8;i++)
- {
- temp=temp>>1;
- if(CY) //写1
- {
- ds=0;
- j++;j++;
- ds=1;
- delay(8);
- }
- else
- {
- ds=0;
- delay(8);
- ds=1;
- j++;j++;
- }
- }
- }
- uchar read() //18B20读一字节数据
- {
- uchar j,dat;
- for(j=0;j<8;j++)
- {
- ds=0;
- dat>>=1;
- ds=1;
- delay(1);
- if(ds)
- dat|=0x80;
- delay(8);
- }
- return(dat);
- }
- uint get() //从温度传感器获取数值
- {
- uchar gao,di;
- reset();
- shijian(1);
- write(0xcc);
- write(0x44);
- reset();
- shijian(1);
- write(0xcc);
- write(0xbe);
- di=read();
- gao=read();
- temp=gao<<8;
- temp=temp|di;
- n=temp*0.065+0.5;
- temp=n*10;
- return(temp);
- }
- void send() //超声波发送函数
- {
- uchar i;
- while(TF0==0)
- { we0=0;
- timers++;
- fasong=~fasong;
- for(i=12;i>0;i--); //40hz延时
- if(timers==4) //连续发送两个超声波脉冲
- break;
-
- }
- we0=1;
- timers=0; //将发送次数归零
- TH0=0X00; //定时器装初值
- TL0=0X32; //装0x32是因为发送时也占用了时间
- TR0=1; //打开计时器
- EX0=1; //打开外部中断等待接收返回声波
- delay100us(); //避盲延时
- delay100us();
- delay100us();
- // delay100us();
- // delay100us();
- }
- void keyscan() //键盘扫描
- {
- if(k1==0) //开关键按下
- {
- shijian(10);
- if(k1==0)
- kaiflag=~kaiflag; //开关标志位取反
- while(k1==0); //等待按键释放
- }
- if(k2==0) //k2按下
- {
- shijian(10);
- if(k2==0)
- temflag=~temflag; //温度距离标志位取反
- while(k2==0); //等待按键释放
- }
- }
- void temdisplay() //温度显示函数
- {
- num=get(); //读取当前温度值
- shi=num/100; //分离出十位值
- ge=num%100/10; //分离出个位值
- shifen=num%10; //分离出十分位值
- P0=table[shi]; //十位显示
- we1=0;
- we0=1;
- we2=1;
- we3=1;
- shijian(6);
- P0=table[ge+10]; //个位显示
- we1=1;
- we0=1;
- we2=0;
- we3=1;
- shijian(6);
- P0=table[shifen]; //十分位显示
- we3=0;
- we1=1;
- we0=1;
- we2=1;
- shijian(1);
- }
- void init() //初始化函数
- {
- TMOD=0x21; //定时器1为8位自动重装模式,
- //定时器0为十六位计数器
- TH0=0X00; //定时器0装初值
- TL0=0X32;
- TH1=0x00; //定时器装空值
- TL1=0x00;
- TR1=0; //关闭显示定时
- TR0=0; //关闭定时器0计时
- EA=1; //打开总中断
- ET0=1; //打开计时中断
- ET1=1; //打开定时器1中断
- EX0=1; //打开外部中断
- IT0=1; //外部中断选择下降沿触发
- P2=0xff;
- P0=0xff; //关闭数码管段选
- kaiflag=0; //开标志位置0
- temflag=0; //温度距离标志位置0
- }
- void main() //主函数
- {
- init(); //进行初始化
- while(1)
- {
- keyscan(); //键盘扫描
- if((kaiflag==1)&&(temflag==1))//如果打开并且选择测温
- {
- temdisplay(); //进行温度显示
- TR1=0; //将定时器都关闭
- TR0=0;
- EX0=0;
- }
- if((kaiflag==1)&&(temflag==0)) //如果打开并选择测距
- {
- send(); //发送脉冲
- num=get(); //读取温度值
- TR1=1; //打开测距显示中断
- }
- if(kaiflag==0) //如果处于关闭状态
- {
- TR1=0;
- TR0=0; //测距显示关闭
- init(); //进行初始化
- }
- }
- }
- /*******************对下面用到的中断的解释************
- 1.外部中断0用来接收返回的脉冲,当接收到以后进行中断处理,优先级最高;
- 2.定时器0用来计时,选择的是十六位定时模式;用来计算超声波脉冲
- 从发射到接受所用的时间。
- 3.定时器1用来作为测试距离的显示定时。每中断一次就扫描一位数码管
- *********************************************************/
- void IN0() interrupt 0 //超声波接收中断(外部)
- {
- TR0=0; //关闭设计时器
- EX0=0; //停止接收返回脉冲
- if(num<=50) //根据当前温度值来调整声速
- {
- shengsu=165;
- }
- else if(num<=100)
- {
- shengsu=169;
- }
- else if(num<=200)
- {
- shengsu=172;
- }
- else if(num<=300)
- {
- shengsu=175;
- }
- else if(num<=500)
- {
- shengsu=180;
- }
- t=TH0*256+TL0; //计算从发射到接收用时(单位us)
- s=t*shengsu/10000; //根据时间计算距离
- mi=s/100; //分离出米
- fenmi=s%100/10; //……分米
- limi=s%10; //……厘米
- EX0=1; //计算完毕允许接收下个脉冲
- }
- void timer0() interrupt 1
- {
- TR0=0;
- TH0=0;
- TL0=0;
- }
- void timer1() interrupt 3 //显示测距距离中断
- {
- TH1=0x00; //装初值
- TL1=0x00;
- num1++;
-
- if(num1==5) //如果经过1250us,显示一位
- {
-
- num1=0;
- shijian(2);
- num2++;
- if(num2==4)
- num2=0;
- }
-
- if(temflag==0)
- {
- if(num2==0)
- {
- P0=table[mi+10];
- we1=0;
- we0=1;
- we2=1;
- we3=1;
- }
- if(num2==2)
- {
- P0=table[fenmi];
- we1=1;
- we0=1;
- we2=0;
- we3=1;
- }
- if(num2==3)
- {
- P0=table[limi];
- we3=0;
- we1=1;
- we0=1;
- we2=1;
- }
- }
-
- }
复制代码
所有资料51hei提供下载:
Desktop.rar
(1.56 MB, 下载次数: 97)
|