超声波测距 + 行人检测系统电路原理图如下:
Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)
元件清单:
单片机源程序如下:
- #include "reg52.h"
- #include "18b20.h"
- #include "delay.h"
- #include "math.h"
- #include "stdio.h"
- #include "lcd.h"
- bit ReadTemFlag=0; //定义读时间标志
- bit ViewTemFlag=0; //定义读时间标志
- bit PeopleFlag=0;//定义行人标志
- uint time=0;
- uchar DisdisData[];
- sbit War1=P3^2;
- sbit Beep=P3^7;
- sbit War=P1;
- sbit IRIG=P2^0;//超声波接口
- sbit ECHO=P2^1;//超声波接口
- void TIMInit()
- {
- TMOD|=0x11; //定时计数0、1,工作方式为1,即16位定时
- TH0=0x00;
- TL0=0x00;
- ET0=1; //定时计数器中断0允许位
- ET1=1; //定时计数器中断1允许位
- TR1=1; //开放定时计数器中断1
- EA=1; //总开关开启
- }
- void main()
- {
- int temp;
- float temperature;
- char displaytemp[16]; //定义显示区域临时存储数组
- float s,a;
- DS18b20Init(); //温度初始化
- LCD1602Init(); //LCD初始化
- LCD1602Char(); //写入自定义字符
- while(1)
- {
- if(ReadTemFlag==1)
- {
- ReadTemFlag=0;
- temp=DS18b20sj();
- if(temp<0)
- {
- temp=temp-1;
- temp=~temp;
- temperature=(float)temp*0.0625;
- sprintf(displaytemp,"-TEMP % 7.3f",temperature);// 把温度值放入displaytemp
- }
- else
- {
- temperature=(float)temp*0.0625;
- sprintf(displaytemp,"TEMP % 7.3f",temperature);//把温度值放入displaytemp
- }
- }
-
- if(ViewTemFlag==1)
- {
- ViewTemFlag=0;
- War1=0;//行人检测灯灭
- Beep=0;//蜂鸣器关闭
- War=0xff;//关闭所有指示灯
- LCD1602WriteChar(13,1,0x01); //点亮温度右上角的一个小点
- LCD1602WriteChar(14,1,'C'); //显示温度单位
- LCD1602WriteChar(15,1,' '); //空格
- LCD1602SWritetring(0,1,displaytemp); //第二行显示温度
- }
- IRIG=1;
- Delayus(3); //延时10us
- while(!ECHO);//当ECHO为0时等待
- TR0=1;
- while(ECHO);//等待ECHO为低电平
- TR0=0;
- time=TH0*256+TL0;//*256是左移八位的意思,计数为16位,这是算出的总时间,但要乘以12/11.0592
- TH0=0; //清零
- TL0=0; //清零
- temperature=(int)temperature;//取整数有利于数据稳定
- a=(331.5+0.607*temperature);//声速与温度的函数关系
- /* s=time*a/2 ;time的单位是s,a的单位是m/s,如果time的单位是us,a的单位仍旧是m/s,s的单位是cm
- 那么s*10^-2=time*10^-6*a/2
- 化成s=time*10^-4*a/2=time*a/20000 和 S=(time*a/200)/100是一样的 */
- s=(time*a*(12/11.0592))/20000; //单位为厘米 ,这里原先s的单位是米,time的单位是us
- sprintf(DisdisData,"Dis= % 7.3f cm",s);
- LCD1602SWritetring(0,0,DisdisData); //在液晶屏显示出来
- if(PeopleFlag==1)
- {
- PeopleFlag=0;
- if(s>200)
- {
- Beep=1;
- War=0xff;
- }
- else if(s>150)
- {
- War=0xfe;
- LCD1602SWritetring(0,1,"Waring1:<200CM R");//距离小于200cm大于150cm,准备随时停车
- Beep=0;
- Delayms(255);
- Delayms(255);
- Delayms(255);
- Delayms(255);
- Delayms(255);
- Beep=1;
- }
- else if(s>100)
- {
- War=0xf0;
- LCD1602SWritetring(0,1,"Waring2:<150CM L");//距离小于150cm大于100cm,减速慢行
- Beep=0;
- Delayms(255);
- Delayms(255);
- Delayms(255);
- Delayms(255);
- Delayms(255);
- Beep=1;
- }
- else if(s>40)
- {
- War=0x90;
- LCD1602SWritetring(0,1,"Waring3:<100CM A");//距离小于100cm大于40cm,警戒区
- Beep=0;
- Delayms(255);
- Delayms(255);
- Delayms(255);
- Delayms(255);
- Delayms(255);
- Beep=1;
- }
- else if(s>20)
- {
- War=0x00;
- LCD1602SWritetring(0,1,"Waring4:<40CM S");//距离小于40cm,停止
- Beep=0;
- Delayms(255);
- Delayms(255);
- Delayms(255);
- Delayms(255);
- Delayms(255);
- Beep=1;
- }
- else if(s<20)
- {
- War=0xff;
- LCD1602SWritetring(0,1,"Waring3:<20CM L");//距离小于20cm,危险紧停
- Beep=0;
- Delayms(255);
- Delayms(255);
- Delayms(255);
- Delayms(255);
- Delayms(255);
- Beep=1;
- }
- }
- }
- }
- //定时器0中断服务程序
- void Timer0_isr(void) interrupt 1
- {
- ECHO=0;
- }
- //定时器1中断服务程序
- void Timer1_isr(void) interrupt 3
- {
- static unsigned int num;
- static unsigned int num1;
- TH1=(65536-2000)/256; //重新赋值 2ms
- TL1=(65536-2000)%256;
-
- num++;
- if(num==300)
- {
- num=0;
- num1++;
- ReadTemFlag=1; //读标志位置1
- if(num1==30)
- {
- num1=0;
- ViewTemFlag=1; //显示标志位置1
- PeopleFlag=0;
- }
- }
- }
- void exter0(void) interrupt 2
- {
- //由于热释电是当有人时为高电平,因此当有人进入时是一个上升沿,而中断跳沿触发默认为下降沿,因此在程序中取反后几位上升沿
- //有行人时将PeopleFlag置位,并开启行人指示灯,蜂鸣器长鸣,开启所有指示灯进行提示
- if(!INT1)
- {
- LCD1602SWritetring(0,1,"Waring:People D");//Danger即刻停止,危险
- War1=0; //行人指示灯亮
- Beep=0; //蜂鸣器长鸣
- War=0x00;//开启所有指示灯
- PeopleFlag=1;
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
多功能超声波测距.zip
(457.61 KB, 下载次数: 49)
|