资料齐全的超声波测距学习板
超声波测距学习板,可应用于汽车倒车、建筑施工工地以及一些工业现场的位置监控,也可用于如液位、井深、管道长度的测量等场合。测量精度1cm,测量时与被测物体无直接接触,能够清晰稳定地显示测量结果。
超声波测距原理:
超声波发生器的内部结构有两个压电晶片和一个共振板,当它的两极外加上固有振荡频率的脉冲电压时压电晶片会发生共振并产生超声波。如果共振板接收到超声波时,也会迫使压电晶片产生振动,反过来将机械能转换为电信号,成为超声波接收器。
在超声波测距电路中,发射端连续输出一系列脉冲方波,然后判断接收端,实现超声测距一般有以下两种方法:
① 读取输出端脉冲电压的平均值,该电压 (其幅值基本固定 )与距离成正比,测量电压即可测得距离;
② 测量输出脉冲的宽度,即发射超声波与接收超声波的时间间隔 t,故被测距离为 S=1/2vt。
我们的产品采用第二种方案。由于超声波的传播速度和温度有关,如果温度变化不大,则可认为声速基本不变 。如果测距精度要求很高,则应通过温度补偿的方法加以校正。超声波测距适用于高精度的中长距离测量。因为超声波在标准空气中的传播速度为331.45米/秒,由单片机负责计时,单片机使用12M晶振,所以此系统的测量精度理论上可以达到毫米级。
超声波测距的算法设计:
超声波在空气中传播速度为每秒钟340米(15℃时)。X2是声波返回的时刻,X1是声波发声的时刻,X2-X1得出的是一个时间差的绝对值,假定X2-X1=0.01S,则有(340×0.01S)/2=1.7。这就是根据超声波从发出到遇到反射物后返回的时间换算后得到的1.7米距离。
产品1:超声波测距成品学习板 成品每套129元
产品性能特点:
我们的超声波测距成品学习板大小为90*75*10毫米,板上自带:超声波收发传感器、接收放大电路、四位LED数码显示、四位按键(四个按钮和蜂鸣器属于功能预留,程序中无定义),电源部分自带整流、滤波、稳压电路,允许交流7~15V或者直流9~16V输入,经过实际测试,测量范围可达0.27~3.5米,测量精度为1厘米。因为我们能提供完整的源程序,客户不但可以学习超声波测距的知识,还可以直接将这项技术用于产品开发,是不可多得的资料。
单片机系统及显示电路:
超声波学习板采用STC89C52单片机,晶振为12M,单片机用P1.0口输出超声波换能器所需的40K方波信号,利用外中断口0监测超声波接收电路输出的返回信号,显示电路采用简单的4位共阳LED数码管,段码用74HC245D,位码用PNP三极管9012驱动. 主要由单片机系统及显示电路、超声波发射电路和超声波检测接收电路三部分组成。采用STC89C52来实现对CX20106A红外接收芯片和TCT40-10系列超声波转换模块的控制。单片机通过P1.0引脚经反相器来控制超声波的发送,然后单片机不停的检测INT0引脚,当INT0引脚的电平由高电平变为低电平时就认为超声波已经返回。计数器所计的数据就是超声波所经历的时间,通过换算就可以得到传感器与障碍物之间的距离。
答疑解惑:
1、为什么你们选40KHZ的超声波传感器?
因为超声波在空气中传播时衰减很大,衰减的程度与频率成正比,但是频率越高则分辨力也会越高,所以短距离测量时一般选频率高的传感器(100KHZ以上),长距离测距只能选频率低的传感器。
2、为什么你们的最小检测距离为27厘米?
为了防止超声波发射传感器发出超声波沿电路板或者外壳直接进入超声波接收传感器内引起误判断,所以程序要求超声波发射若干时间后必须停止若干时间,这个时间大约是超声波在空气中传播20多厘米的时间,这段时间内是不接受信号的,主要就是为了躲开直接传导的信号避免引起误判断。
3、电路板上的四个按钮和蜂鸣器有啥作用?
这是为后续开发应用所预留的,例如你可以在程序中定义为开关功能,按下一个按键,电路板开始测距、按下另一个按键电路板停止测距,或者定义为多档距离报警设定,当检测到低于设定距离时,驱动蜂鸣器报警。其实我们的电路板您也可以加以改进,例如用1602的液晶模块代替数码管显示、增加语音电路实现语音播报探测距离等等。
4、为什么我的板不管前面有无遮挡物总是显示27呢?
这是因为标有T字样的超声波接收头没有收到正确的回波信息导致工作异常引起的,我们发现接收头比较娇嫩,轻微的磕碰就会导致内部器件错位影响正常工作,但是你只要稍稍旋转或者上下拨动一下接收头,很多情况就会排除故障又能正常工作了。
超声波测距板配套12V 1A直流稳压电源 10元一个
超声波专用发射接收头 6元一对 (标有T字样的是发射头,标有R字样的是接收头)
点击这里可以看到超声波测距学习板的PDF原理图 以下是附带的详细使用资料截图:
以下是部分汇编源程序,购买我们产品后我们可以通过电子邮件将完整的单片机汇编语言源程序和烧写文件发送给客户。
;///////////////////////////////////////////////////////
; USE BY :超声波测距器
; IC :AT89C51
; TEL :
; OSCCAL :XT (12M)
; display :共阳LED显示
;///////////////////////////////////////////////////////
;测距范围7CM-11M,堆栈在4FH以上,20H用于标志
;显示缓冲单元在40H-43H,使用内存44H、45H、46H用于计算距离
;
VOUT EQU P1.0 ; 红外脉冲输出端口
speak equ p1.1
;********************************************
;* 中断入口程序 *
;********************************************
;
ORG 0000H
LJMP START
ORG 0003H
LJMP PINT0
ORG 000BH
reti
ORG 0013H
RETI
ORG 001BH
LJMP INTT1
ORG 0023H
RETI
ORG 002BH
RETI
;
;********************************************
;* 主 程 序 *
;********************************************
;
START: MOV SP,#4FH
MOV R0,#40H ;40H-43H为显示数据存放单元(40H为最高位)
MOV R7,#0BH
CLEARDISP: MOV @R0,#00H
INC R0
DJNZ R7,CLEARDISP
MOV 20H,#00H
MOV TMOD,#11H ;T1为 T0为16位定时器
MOV TH0,#00H ;65毫秒初值
MOV TL0,#00H
MOV TH1,#00H
MOV TL1,#00H
MOV P0,#0FFH
MOV P1,#0FFH
MOV P2,#0FFH
MOV P3,#0FFH
MOV R4,#04H ;超声波肪冲个数控制(为赋值的一半)
SETB PX0
SETB ET1
SETB EA
SETB TR1 ;开启测距定时器
start1: LCALL DISPLAY
JNB 00H,START1 ;收到反射信号时标志位为1
CLR EA
LCALL WORK ;计算距离子程序
clr EA
MOV R2,#32h;#64H ;测量间隔控制(约4*100=400MS)
LOOP: LCALL DISPLAY
DJNZ R2,LOOP
CLR 00H
setb et0
mov th0,00h
mov tl0,00h
SETB TR1 ;重新开启测距定时器
SETB EA
SJMP Start1
;
;****************************************************
;* 中断程序* *
;****************************************************
;T1中断,发超声波用 ;T1中断,65毫秒中断一次
INTT1: CLR EA
CLR TR0
clr ex0
MOV TH0,#00H
MOV TL0,#00H
MOV TH1,#00H
MOV TL1,#00H
SETB ET0
SETB EA
SETB TR0 ;启动计数器T0,用以计
intt11:
CPL VOUT ;40KHZ
nop
nop
nop
nop
nop
nop
nop
nop
nop
DJNZ R4,intt11
;超声波发送完毕,
MOV R4,#04H
lcall delay_250 ;延时,避开发射的直达声波信号
SETB EX0 ;开启接收回波中断
RETIOUT: RETI
;外中断0,收到回波时进入
PINT0: nop
jb p3.2,pint0_exit
CLR TR0 ;关计数器
CLR EA ;
CLR EX0 ;
MOV 44H,TL0 ;将计数值移入处理单元
MOV 45H,TH0 ;
mov th0,#00h
mov tl0,#00h
jnb p3.2,$
SETB 00H ;接收成功标志
pint0_exit:
RETI
;
;****************************************************
;* 显示程序 *
;****************************************************
; 40H为最高位,43H为最低位,先扫描高位
DISPLAY: MOV R1,#40H;G
MOV R5,#7fH;G
PLAY: MOV A,R5
MOV P0,#0FFH
MOV P2,A
MOV A,@R1
MOV DPTR,#TAB
MOVC A,@A+DPTR
MOV P0,A
LCALL DL1MS
INC R1
MOV A,R5
JNB ACC.4,ENDOUT;G
RR A
MOV R5,A
AJMP PLAY
ENDOUT: MOV P2,#0FFH
MOV P0,#0FFH
RET
;
TAB: DB 18h, 7Bh, 2Ch, 29h, 4Bh, 89h, 88h, 3Bh, 08h, 09h,0ffh
;共阳段码表 "0" "1" "2" "3" "4" "5""6" "7" "8" "9" "不亮""A""-"
;
;****************************************************
;* 延时程序 *
;****************************************************
;
DL1MS:
push 06h
push 07h
MOV R6,#14H
DL1: MOV R7,#19H
DL2: DJNZ R7,DL2
DJNZ R6,DL1
pop 07h
pop 06h
RET
;
;****************************************************
;* 距离计算程序 (=计数值*17/1000cm) *
;****************************************************
;
work: PUSH ACC
PUSH PSW
PUSH B
MOV PSW, #18h
MOV R3, 45H
MOV R2, 44H
MOV R1, #00D
MOV R0, #17D
LCALL MUL2BY2
MOV R3, #03H
MOV R2, #0E8H
LCALL DIV4BY2
LCALL DIV4BY2
MOV 40H, R4
MOV A,40H
JNZ JJ0
MOV 40H,#0AH ;最高位为零,不点亮
JJ0: MOV A, R0
MOV R4, A
MOV A, R1
MOV R5, A
MOV R3, #00D
MOV R2, #100D
LCALL DIV4BY2
MOV 41H, R4
MOV A,41H
JNZ JJ1
MOV A,40H ;次高位为0,先看最高位是否为不亮
SUBB A,#0AH
JNZ JJ1
MOV 41H,#0AH ;最高位不亮,次高位也不亮
JJ1: MOV A, R0
MOV R4, A
MOV A, R1
MOV R5, A
MOV R3, #00D
MOV R2, #10D
LCALL DIV4BY2
MOV 42H, R4
MOV A,42H
JNZ JJ2
MOV A,41H ;次次高位为0,先看次高位是否为不亮
SUBB A,#0AH
JNZ JJ2
MOV 42H,#0AH ;次高位不亮,次次高位也不亮
JJ2: MOV 43H, R0
POP B
POP PSW
POP ACC
RET
;
;****************************************************
;* 两字节无符号数乘法程序 *
;****************************************************
; R7R6R5R4 <= R3R2 * R1R0
超声波测距学习板全部元件清单:
AT_ISP DC3-10 座子
STC_ISP 3 芯单排针
C6 330P
C7 104
C8 104
C9 473
C10 3.3UF/25V
C11 104
C15 470UF/25V
C16 470UF/25V
C17 3.3UF/25V
C19 3.3UF/25V
C20 20P
C25 20P
D1 (电源指示灯) φ3 LED(红色)
D2 206 桥堆
DS1 0.5 寸数码管
DS2 0.5 寸数码管
DS3 0.5 寸数码管
DS4 0.5 寸数码管
J3( POWER) 电源插座
J4 CX20106
LS1 [TX(F)] 超声波发射管
LS4 [RX(S)] 超声波接收管
LS3(SPEAK) +5V 有源蜂鸣器
Q1 9012
Q2 9012
Q3 9012
Q4 9012
Q6 9012
R8 1K
R9 1K
R10 2K
R11 2K
R12 2K
R13 2K
R14 4.7
R15 200K
R16 220K
R17 1K
R18 1K
R19 1K
R20 1K
R25 1K
R26 1K
R28 1K
R29 1K
R30 1K
R31 2K
R32 10K
RL1 排阻A103
S1(K1) 12X12 按键
S2(K2) 12X12 按键
S3(K3) 12X12 按键
S4(K4) 12X12 按键
S10(RST) 6X6 按键
XT1 12MHZ
U7 7805
U5(AT89S51) IC-40P 座子
U6(74LS245) IC-20P 座子
U4(74LS04) IC-14P 座子
4 个数码管插座IC-40P 座子
超小型超声波测距头(配合单片机使用) 每个22元
这是一款体积很小,集成度较高的超声波测距模块,性能参数和国外的SRF05、SRF02等超声波测距模块类似。
技术参数:
1:工作电压:DC5V
2:静态电流:小于2mA
3:电平输出:0~5V
4:测量精度:0.3cm
5:感应角度:不大于15度
6:探测距离:10cm-300cm
引脚功能:
1、VCC 正电源脚:5V直流的正极,4.2~6V电压范围。
2、Trig 控制端:需要测距时外部电路提供一个高电平信号,一般由外部单片机的IO口控制。
3、Echo 接收端:测量到的距离数据会对应输出一个高电平,高电平的宽度和距离成正比。
4、OUT 开关量输出端:无意义,功能预留。
5、GND 电源地:接5V直流的负极。
这是模块的内部电路图,主要器件的型号出于保密都打磨掉了,但是依然可以看出,U2应该是40KH的振荡器,驱动超声波发射头发射信号,U1是单片机,P25低电平时U2获得电源发射信号,U3应该是输出整型电路,通过P00和单片机通讯。
模块的使用方法:单片机平时将Trig 控制端置低电平,需要测距时Trig 控制端置高电平,当Trig 控制端高电平大于10微秒时模块启动测距,这是单片机等待Echo 接收端变成高电平,一旦检测到高电平,就可以开定时器计时,当Echo 接收端变成低电平时就可以读定时器的值,测距距离(米)=(高电平时间(秒)*声速(340M/S))/2 例如测量到的时间为0.01秒,那么距离为1.7米。
我们的模块还提供全套测距程序:C51,PIC18F877,超声波LCD1602显示,超声波LCD12864显示,数码管显示,串口显示等,测距参考程序。
/*
SMC1602A(16*2)模拟口线接线方式
连接线图:
---------------------------------------------------
|LCM-----51 | LCM-----51 | LCM------51 |
--------------------------------------------------|
|DB0-----P1.0 | DB4-----P1.4 | RW-------P3.4 |
|DB1-----P1.1 | DB5-----P1.5 | RS-------P3.3 |
|DB2-----P1.2 | DB6-----P1.6 | E--------P3.5 |
|DB3-----P1.3 | DB7-----P1.7 | VLCD接1K电阻到GND|
---------------------------------------------------
接线:模块TRIG接 P3.7 ECH0 接P3.6
[注:stc89c52使用12M或11.0592M晶振,实测使用11.0592M]
=============================================================*/
#include <AT89x51.H> //器件配置文件
#include <intrins.h>
#define RX P3_6
#define TX P3_7
#define LCM_RW P2_3 //定义LCD引脚
#define LCM_RS P2_4
#define LCM_E P2_2
#define LCM_Data P1
#define Key_Data P3_3 //定义Keyboard引脚
#define Key_CLK P3_2
#define Busy 0x80 //用于检测LCM状态字中的Busy标识
void LCMInit(void);
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);
void Delay5Ms(void);
void Delay400Ms(void);
void Decode(unsigned char ScanCode);
void WriteDataLCM(unsigned char WDLCM);
void WriteCommandLCM(unsigned char WCLCM,BuysC);
unsigned char ReadDataLCM(void);
unsigned char ReadStatusLCM(void);
unsigned char code mcustudio[] ={"==Range Finder=="};
unsigned char code email[] = {"[email protected] "};
unsigned char code Cls[] = {" "};
unsigned char code ASCII[15] = {'0','1','2','3','4','5','6','7','8','9','.','-','M'};
static unsigned char DisNum = 0; //显示用指针
unsigned int time=0;
unsigned long S=0;
bit flag =0;
unsigned char disbuff[4] ={ 0,0,0,0,};
//写数据
void WriteDataLCM(unsigned char WDLCM)
{
ReadStatusLCM(); //检测忙
LCM_Data = WDLCM;
LCM_RS = 1;
LCM_RW = 0;
LCM_E = 0; //若晶振速度太高可以在这后加小的延时
LCM_E = 0; //延时
LCM_E = 1;
}
//写指令
void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测
{
if (BuysC) ReadStatusLCM(); //根据需要检测忙
LCM_Data = WCLCM;
LCM_RS = 0;
LCM_RW = 0;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
}
//读数据
unsigned char ReadDataLCM(void)
{
LCM_RS = 1;
LCM_RW = 1;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
return(LCM_Data);
}
//读状态
unsigned char ReadStatusLCM(void)
{
LCM_Data = 0xFF;
LCM_RS = 0;
LCM_RW = 1;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
while (LCM_Data & Busy); //检测忙信号
return(LCM_Data);
}
void LCMInit(void) //LCM初始化
{
LCM_Data = 0;
WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
WriteCommandLCM(0x08,1); //关闭显示
WriteCommandLCM(0x01,1); //显示清屏
WriteCommandLCM(0x06,1); // 显示光标移动设置
WriteCommandLCM(0x0F,1); // 显示开及光标设置
}
//按指定位置显示一个字符
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
X |= 0x80; //算出指令码
WriteCommandLCM(X, 1); //发命令字
WriteDataLCM(DData); //发数据
}
//按指定位置显示一串字符
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
{
unsigned char ListLength;
ListLength = 0;
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
while (DData[ListLength]>0x19) //若到达字串尾则退出
{
if (X <= 0xF) //X坐标应小于0xF
{
DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
ListLength++;
X++;
}
}
}
//5ms延时
void Delay5Ms(void)
{
unsigned int TempCyc = 5552;
while(TempCyc--);
}
//400ms延时
void Delay400Ms(void)
{
unsigned char TempCycA = 5;
unsigned int TempCycB;
while(TempCycA--)
{
TempCycB=7269;
while(TempCycB--);
};
}
/********************************************************/
void Conut(void)
{
time=TH0*256+TL0;
TH0=0;
TL0=0;
S=(time*1.8)/10; //算出来是MM
if((S>=7000)||flag==1) //超出测量范围显示“-”
{
flag=0;
DisplayOneChar(0, 1, ASCII[11]);
DisplayOneChar(1, 1, ASCII[10]); //显示点
DisplayOneChar(2, 1, ASCII[11]);
DisplayOneChar(3, 1, ASCII[11]);
DisplayOneChar(4, 1, ASCII[11]);
DisplayOneChar(5, 1, ASCII[12]); //显示M
}
else
{
disbuff[0]=S/1000;
disbuff[1]=S/100%10;
disbuff[2]=S/10%10;
disbuff[3]=S%10;
DisplayOneChar(0, 1, ASCII[disbuff[0]]);
DisplayOneChar(1, 1, ASCII[10]); //显示点
DisplayOneChar(2, 1, ASCII[disbuff[1]]);
DisplayOneChar(3, 1, ASCII[disbuff[2]]);
DisplayOneChar(4, 1, ASCII[disbuff[3]]);
DisplayOneChar(5, 1, ASCII[12]); //显示M
}
}
/********************************************************/
void zd0() interrupt 1 //T0中断用来计数器溢出,超过测距范围
{
flag=1; //中断溢出标志
RX=0;
}
/********************************************************/
void StartModule() //启动模块
{
TX=1; //启动一次模块
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
TX=0;
}
void Timer_Count(void)
{
TR0=1; //开启计数
while(RX); //当RX为1计数并等待
TR0=0; //关闭计数
Conut(); //计算
}
/********************************************************/
void delayms(unsigned int ms)
{
unsigned char i=100,j;
for(;ms;ms--)
{
while(--i)
{
j=10;
while(--j);
}
}
}
/*********************************************************/
void main(void)
{
unsigned int valA;
unsigned char TempCyc;
Delay400Ms(); //启动等待,等LCM讲入工作状态
LCMInit(); //LCM初始化
Delay5Ms(); //延时片刻(可不要)
DisplayListChar(0, 0, mcustudio);
DisplayListChar(0, 1, email);
ReadDataLCM();//测试用句无意义
for (TempCyc=0; TempCyc<10; TempCyc++)
Delay400Ms(); //延时
DisplayListChar(0, 1, Cls);
TMOD=0x01; //设T0为方式1,GATE=1;
TH0=0;
TL0=0;
ET0=1; //允许T0中断
EA=1; //开启总中断
while(1)
{
delayms(60);
RX=1;
StartModule();
for(valA=7510;valA>0;valA--)
{
if(RX==1)
{
Timer_Count();
}
}
}
}
一体化超声波移动报警探测器 每套40元
超声波移动探测器是一种新型的检测器件,它工作时向周围空间发射超声波信号,当周围空间出现移动的物体时,会引起超声波声场的扰动,从而触发探测器报警,输出下拉信号。
应用说明:
本产品主要的应用领域是汽车内部的报警检测,它可以实现车门被打开瞬间或者是小偷从打开的车窗中拿走物品时立即报警,一般汽车防盗报警器都配备振动传感器,振动传感器通常也是采用三极管集电极开路输出方式,所以我们的超声波移动探测器可以直接代替原车的振动传感器,甚至可以直接和原车的振动传感器并联,就能实现振动和超声波移动双检测(请有一定技术把握时操作)
本产品也可用于楼房、小区通道、商铺等无人值守的地方进行探测,和常用的红外检测技术相比,红外对环境要求很高,不能使用在室外或者空气流通大的场合,而超声波对环境的要求低很多适应性更强。本产品固定也很方便,配有的万向座可以方便地调节到任何角度。
性能参数:
A、工作电压:DC10~15V(内部有78L08稳压后供电)
B、输出方式:NPN三极管集电极开路输出,蓝线输出下拉信号
C、探测距离:0~5米(无法精确控制距离,只能改变检测灵敏度,可以通过背后的旋钮调节)
D、工作频率:40KHz
E、工作电流:15mA
F、产品体积:90*40*25毫米
G、输出引线:红线:电源正极;黑线:电源地;蓝线:输出线。
模块的输出线有两个白色的插头,请对照上左图插入插头,当模块接入12V的直流工作电压后,红蓝两只LED灯交替闪烁,说明超声波发送接收正常,当检测到周围有活动物体时,中间的绿色LED点亮0.5秒,并输出报警信号。
这种传感器采用三极管集电极开路输出的驱动模式,没有活动物体时蓝线输出接近电源电压的高电平,当传感器检测到信号时NPN三极管导通,三极管的集电极电压下拉到0.1V左右,通过一个470欧姆的保护电阻输出到蓝色的输出线上,这种结构可以和单片机系统直接接口,只要首先单片机将端口置1,当单片机检测到端口电平变低得时就能输出报警信号了。
;///////////////////////////////////////////////////////
; USE BY :超声波测距器
; IC :AT89C51
; TEL :
; OSCCAL :XT (12M)
; display :共阳LED显示
; Updata :2004/12/12
; NAME :ZHOUSS
;///////////////////////////////////////////////////////
;测距范围7CM-11M,堆栈在4FH以上,20H用于标志
;显示缓冲单元在40H-43H,使用内存44H、45H、46H用于计算距离
;
VOUT EQU P1.0 ; 红外脉冲输出端口
speak equ p1.1
;********************************************
;* 中断入口程序 *
;********************************************
;
ORG 0000H
LJMP START
ORG 0003H
LJMP PINT0
ORG 000BH
reti
ORG 0013H
RETI
ORG 001BH
LJMP INTT1
ORG 0023H
RETI
ORG 002BH
RETI
;
;********************************************
;* 主 程 序 *
;********************************************
;
START: MOV SP,#4FH
MOV R0,#40H ;40H-43H为显示数据存放单元(40H为最高位)
MOV R7,#0BH
CLEARDISP: MOV @R0,#00H
INC R0
DJNZ R7,CLEARDISP
MOV 20H,#00H
MOV TMOD,#11H ;T1为 T0为16位定时器
MOV TH0,#00H ;65毫秒初值
MOV TL0,#00H
MOV TH1,#00H
MOV TL1,#00H
MOV P0,#0FFH
MOV P1,#0FFH
MOV P2,#0FFH
MOV P3,#0FFH
MOV R4,#04H ;超声波肪冲个数控制(为赋值的一半)
SETB PX0
SETB ET1
SETB EA
SETB TR1 ;开启测距定时器
start1: LCALL DISPLAY
JNB 00H,START1 ;收到反射信号时标志位为1
CLR EA
LCALL WORK ;计算距离子程序
clr EA
MOV R2,#32h;#64H ;测量间隔控制(约4*100=400MS)
LOOP: LCALL DISPLAY
DJNZ R2,LOOP
CLR 00H
setb et0
mov th0,00h
mov tl0,00h
SETB TR1 ;重新开启测距定时器
SETB EA
SJMP Start1
;
;****************************************************
;* 中断程序* *
;****************************************************
;T1中断,发超声波用 ;T1中断,65毫秒中断一次
INTT1: CLR EA
CLR TR0
clr ex0
MOV TH0,#00H
MOV TL0,#00H
MOV TH1,#00H
MOV TL1,#00H
SETB ET0
SETB EA
SETB TR0 ;启动计数器T0,用以计
intt11:
CPL VOUT ;40KHZ
nop
nop
nop
nop
nop
nop
nop
nop
nop
DJNZ R4,intt11
;超声波发送完毕,
MOV R4,#04H
lcall delay_250 ;延时,避开发射的直达声波信号
SETB EX0 ;开启接收回波中断
RETIOUT: RETI
;外中断0,收到回波时进入
PINT0: nop
jb p3.2,pint0_exit
CLR TR0 ;关计数器
CLR EA ;
CLR EX0 ;
MOV 44H,TL0 ;将计数值移入处理单元
MOV 45H,TH0 ;
mov th0,#00h
mov tl0,#00h
jnb p3.2,$
SETB 00H ;接收成功标志
pint0_exit:
RETI
;
;****************************************************
;* 显示程序 *
;****************************************************
; 40H为最高位,43H为最低位,先扫描高位
DISPLAY: MOV R1,#40H;G
MOV R5,#7fH;G
PLAY: MOV A,R5
MOV P0,#0FFH
MOV P2,A
MOV A,@R1
MOV DPTR,#TAB
MOVC A,@A+DPTR
MOV P0,A
LCALL DL1MS
INC R1
MOV A,R5
JNB ACC.4,ENDOUT;G
RR A
MOV R5,A
AJMP PLAY
ENDOUT: MOV P2,#0FFH
MOV P0,#0FFH
RET
;
TAB: DB 18h, 7Bh, 2Ch, 29h, 4Bh, 89h, 88h, 3Bh, 08h, 09h,0ffh
;共阳段码表 "0" "1" "2" "3" "4" "5""6" "7" "8" "9" "不亮""A""-"
;
;****************************************************
;* 延时程序 *
;****************************************************
;
DL1MS:
push 06h
push 07h
MOV R6,#14H
DL1: MOV R7,#19H
DL2: DJNZ R7,DL2
DJNZ R6,DL1
pop 07h
pop 06h
RET
;
;****************************************************
;* 距离计算程序 (=计数值*17/1000cm) *
;****************************************************
;
work: PUSH ACC
PUSH PSW
PUSH B
MOV PSW, #18h
MOV R3, 45H
MOV R2, 44H
MOV R1, #00D
MOV R0, #17D
LCALL MUL2BY2
MOV R3, #03H
MOV R2, #0E8H
LCALL DIV4BY2
LCALL DIV4BY2
MOV 40H, R4
MOV A,40H
JNZ JJ0
MOV 40H,#0AH ;最高位为零,不点亮
JJ0: MOV A, R0
MOV R4, A
MOV A, R1
MOV R5, A
MOV R3, #00D
MOV R2, #100D
LCALL DIV4BY2
MOV 41H, R4
MOV A,41H
JNZ JJ1
MOV A,40H ;次高位为0,先看最高位是否为不亮
SUBB A,#0AH
JNZ JJ1
MOV 41H,#0AH ;最高位不亮,次高位也不亮
JJ1: MOV A, R0
MOV R4, A
MOV A, R1
MOV R5, A
MOV R3, #00D
MOV R2, #10D
LCALL DIV4BY2
MOV 42H, R4
MOV A,42H
JNZ JJ2
MOV A,41H ;次次高位为0,先看次高位是否为不亮
SUBB A,#0AH
JNZ JJ2
MOV 42H,#0AH ;次高位不亮,次次高位也不亮
JJ2: MOV 43H, R0
POP B
POP PSW
POP ACC
RET
;
;****************************************************
;* 两字节无符号数乘法程序 *
;****************************************************
; R7R6R5R4 <= R3R2 * R1R0
;
MUL2BY2: CLR A
MOV R7, A
MOV R6, A
MOV R5, A
MOV R4, A
MOV 46H, #10H
MULLOOP1: CLR C
MOV A, R4
RLC A
MOV R4, A
MOV A, R5
RLC A
MOV R5, A
MOV A, R6
RLC A
MOV R6, A
MOV A, R7
RLC A
MOV R7, A
MOV A, R0
RLC A
MOV R0, A
MOV A, R1
RLC A
MOV R1, A
JNC MULLOOP2
MOV A, R4
ADD A, R2
MOV R4, A
MOV A, R5
ADDC A, R3
MOV R5, A
MOV A, R6
ADDC A, #00H
MOV R6, A
MOV A, R7
ADDC A, #00H
MOV R7, A
MULLOOP2: DJNZ 46H, MULLOOP1
RET
;
;****************************************************
;* 四字节/两字节无符号数除法程序 *
;****************************************************
;R7R6R5R4/R3R2=R7R6R5R4(商)...R1R0(余数)
;
DIV4BY2: MOV 46H, #20H
MOV R0, #00H
MOV R1, #00H
DIVLOOP1: MOV A, R4
RLC A
MOV R4, A
MOV A, R5
RLC A
MOV R5, A
MOV A, R6
RLC A
MOV R6, A
MOV A, R7
RLC A
MOV R7, A
MOV A, R0
RLC A
MOV R0, A
MOV A, R1
RLC A
MOV R1, A
CLR C
MOV A, R0
SUBB A, R2
MOV B, A
MOV A, R1
SUBB A, R3
JC DIVLOOP2
MOV R0, B
MOV R1, A
DIVLOOP2: CPL C
DJNZ 46H, DIVLOOP1
MOV A, R4
RLC A
MOV R4, A
MOV A, R5
RLC A
MOV R5, A
MOV A, R6
RLC A
MOV R6, A
MOV A, R7
RLC A
MOV R7, A
RET
;
delay_250:
push psw
push 07h
mov r7,#0ffh
delay_250_1:
nop
nop
nop
nop
djnz r7,delay_250_1
pop 07h
pop psw
ret
;-----------------------
END