利用51单片机做的超声波测距仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- LCD_RS BIT P1.0 //LCD1602引脚定义
- LCD_RW BIT P1.1
- LCD_EN BIT P1.2
- LCD_DATA EQU P0 //数据并行口
-
- key1 BIT P1.3 //设置
- key2 BIT P1.4 //减1
- key3 BIT P1.5 //加1
- ECHO BIT P3.6 //回波信号端
- TRIG BIT P3.7 //触发信号端
-
- LED BIT P2.0 //
- BEE BIT P2.1
- water_in BIT P2.2
- water_out BIT P2.3
- TIME_FULL BIT 20H
- START_FLAG BIT 21H
- TX EQU 40H //定时器用
- S_HH EQU 41H //距离上限高8位
- S_HL EQU 42H //距离上限低8位
- S_LH EQU 43H //距离下限高8位
- S_LL EQU 44H //距离下限低8位
- S_H EQU 45H //距离高8位
- S_L EQU 46H //距离低8位
-
- SET_FLAG EQU 47H //设置按键按下标志 1设置上限 2设置下限
- ORG 0000H
- LJMP MAIN
- ORG 000BH //定时器0入口
- LJMP TIME0
- ORG 001BH
- LJMP TIME1
- ORG 0030H
- MAIN:
- CLR TRIG
- CLR TIME_FULL
- MOV SP,#52H //预置堆栈地址
- MOV R0,#40H
- MOV A,#0
- CLR_ADD: //把40H-5FH的内容清零
- MOV @R0,A
- INC R0
- CJNE R0,#60H,CLR_ADD
-
- MOV S_HH,#1
- MOV S_HL,#00H ;上限=S_HH*256+S_HL
- MOV S_LH,#0
- MOV S_LL,#00H
-
- MOV S_H,#1
- MOV S_L,#0
- MOV SET_FLAG,#0
- CLR START_FLAG
- LCALL LCD1602_INIT //1602初始化
- LCALL DELAY2
-
- MOV A,#80H
- LCALL WRITE_1602COM
- MOV DPTR,#CODE_PRINT1
- LCALL PRINT //格式:"Now S: "
-
- MOV A,#0C0H
- LCALL WRITE_1602COM
- MOV DPTR,#CODE_PRINT2
- LCALL PRINT //格式:"Set H L "
-
-
- MOV TMOD,#11H //初始化定时器
- MOV TH0,#0; //用于检测超时
- MOV TL0,#0;
- MOV TH1,#(65536-50000)/256 //50MS 触发
- MOV TL1,#(65536-50000)MOD 256
- SETB EA
- SETB ET0
- SETB ET1 //开启中断
- SETB TR1
- LCALL DISPLAY1
-
-
-
- //主循环
- LOOP:
- LCALL KEYBOARD //调用按键
-
- MOV A,#0
- CJNE A,SET_FLAG,LOOP1
- SETB TR1
- LOOP7:
- JB ECHO,LOOP2
- SETB START_FLAG
- SJMP LOOP7
- LOOP2:
- JNB START_FLAG,LOOP3 //为0表示不正常的值 不更新
- CLR START_FLAG
- SETB TR0
- LOOP6:
- JNB ECHO,LOOP4
- JB TIME_FULL,LOOP5 //超出范围
- SJMP LOOP6
- LOOP4:
- CLR TR0
- LCALL COUNT
- LCALL DISPLAY2 //显示距离
- LCALL FUNTION //判断范围
- SJMP LOOP3
- LOOP5:
- CLR TIME_FULL
- CLR TR0
- MOV TH0,#0;
- MOV TL0,#0;
-
- MOV A,#89H
- LCALL WRITE_1602COM
- MOV DPTR,#CODE_PRINT3
- LCALL PRINT //格式:"Err"
- CLR LED
- CLR BEE //超时 仅报警
- LOOP3:
-
-
- SJMP LOOP
- LOOP1:
- CLR TR1 //按键设置的时候禁止测量
- CLR TR0
- LCALL DISPLAY1 //有按键时在屏幕上更新上下限的值
- LJMP LOOP
-
-
- FUNTION:
- CLR C
- MOV A,S_H //实际值减去下限
- SUBB A,S_LH
- MOV B,A
- JNC FUN0 //为0跳转继续判断 为1说明低于下限
- FUN1:
- CLR water_in //注水 开灯 报警
- CLR LED
- CLR BEE
- SJMP FUN
- FUN0:
- MOV A,S_L
- SUBB A,S_LL
- JNC FUN2 //低8位是否有借位
- MOV A,B
- CJNE A,#1,FUN1 //有借位B为1说明测量值大于下限 判断上限
- FUN2: //实际值和上限相比较
- CLR C
- MOV A,S_HH
- SUBB A,S_H
- MOV B,A
- JNC FUN3
- FUN4:
- CLR water_out
- CLR LED
- CLR BEE
- SJMP FUN
- FUN3:
- MOV A,S_HL
- SUBB A,S_L
- JNC FUN5 //
- MOV A,B
- CJNE A,#1,FUN4
- FUN5:
- SETB water_in
- SETB water_out
- SETB LED
- SETB BEE
- FUN:
- RET
-
- COUNT: //计算距离 cm=us/58
- MOV R1,TH0
- MOV R0,TL0
- MOV S_L,#0
- MOV S_H,#0
- MOV TH0,#0
- MOV TL0,#0
- _D1:
- CLR C //循环被除数减去除数的次数就是这个商
- MOV A, R0
- SUBB A, #3AH
- MOV R0, A
- MOV A, R1
- SUBB A, #0
- MOV R1, A
- JC _D2
- INC S_L
- MOV A,S_L
- CJNE A,#0,_D1
- INC S_H
- SJMP _D1
- _D2:
- RET
- //显示数字函数
-
- DISPLAY1:
- //显示上下限
- MOV A,#0C5H
- LCALL WRITE_1602COM
- MOV A,#' '
- LCALL WRITE_1602DAT
-
- MOV A,SET_FLAG
- CJNE A,#1,DIS1
- MOV A,#0C5H
- LCALL WRITE_1602COM
- MOV A,#'*'
- LCALL WRITE_1602DAT
- SJMP DIS2
- DIS1:
- CJNE A,#2,DIS2
- MOV A,#0CBH
- LCALL WRITE_1602COM
- MOV A,#'*'
- LCALL WRITE_1602DAT
- DIS2:
- MOV R6,S_HH
- MOV R7,S_HL
- LCALL HB2 //2字节16进制数转换为3字节压缩BCD码
- MOV A,#0C6H
- MOV B,R4
- LCALL DIS_1WEI
- MOV A,R5
- LCALL DIS_2WEI
-
-
- MOV R6,S_LH
- MOV R7,S_LL
- LCALL HB2 //2字节16进制数转换为3字节压缩BCD码
- MOV A,#0CCH
- MOV B,R4
- LCALL DIS_1WEI
- MOV A,R5
- LCALL DIS_2WEI
- RET
- DISPLAY2:
- //显示距离
- MOV R6,S_H
- MOV R7,S_L
- LCALL HB2 //2字节16进制数转换为3字节压缩BCD码
- MOV A,#089H
- MOV B,R4
- LCALL DIS_1WEI
- MOV A,R5
- LCALL DIS_2WEI
- RET
-
- //按键函数
- KEYBOARD:
- JB KEY1,K06 //设置
- LCALL DELAY2
- JB KEY1,K06
- INC SET_FLAG
- MOV A,SET_FLAG
- CJNE A,#3,K07 //为3退出设置状态
- MOV SET_FLAG,#0
-
- MOV A,#0CBH
- LCALL WRITE_1602COM
- MOV A,#' ' //把*号去掉
- LCALL WRITE_1602DAT
- K07:
- JNB KEY1,$
- LJMP K00
- K06:
- MOV A,SET_FLAG
- CJNE A,#0,K060
- SJMP K00
- K060:
- JB KEY2,K04 //加
- LCALL DELAY2
- JB KEY2,K04
- CJNE A,#1,K061 //按下设置键第一次上限 第二次下限
- INC S_HL //上限加 不能高于500即可
- MOV A,S_HL
- CJNE A,#0F5H,K063 //最大值为1F4(500),所以得先判断是否到最大值
- MOV A,S_HH
- CJNE A,#1,K063 //不相等表示没到500 继续设置
- DEC S_HL
- SJMP K05
- K063:
- MOV A,S_HL
- CJNE A,#0,K05
- INC S_HH //进位
- SJMP K05
- K061:
- MOV A,S_LL //下限加 不能高于上限且判断进位
- CJNE A,S_HL,K062
- MOV A,S_LH
- CJNE A,S_HH,K062 //下限不能超过上限 可以相等
- SJMP K05
- K062:
- INC S_LL
- MOV A,S_LL
- CJNE A,#0,K05
- INC S_LH
- K05:
- JNB KEY2,$
- SJMP K00
- K04:
- JB KEY3,K00
- LCALL DELAY1
- JB KEY3,K00
- MOV A,SET_FLAG
- CJNE A,#1,K040
- MOV A,S_HL //上限减 不能低于下限 且还得判断借位
- CJNE A,S_LL,K041 //相等再判断高8位 不相等直接减
- MOV A,S_HH
- CJNE A,S_LH,K041 //相等不做任何操作 ,不相等直接减
- K042:
- JNB KEY3,$
- SJMP K00
- K041:
- DEC S_HL
- MOV A,S_HL
- CJNE A,#255,K042 //判断是否借位 否直接退出
- DEC S_HH
- SJMP K042
- K040: //下限减
- MOV A,S_LL
- CJNE A,#0,K043
- MOV A,S_LH
- CJNE A,#0,K043
- SJMP K042 //下限为0不做任何操作
- K043:
- DEC S_LL
- MOV A,S_LL
- CJNE A,#255,K042 //判断是否有借位
- DEC S_LH
- SJMP K042
- K00:
- RET
-
-
- //LCD1602初始化函数
- LCD1602_INIT:
- MOV A,#38H
- LCALL WRITE_1602COM
- MOV A,#0CH
- LCALL WRITE_1602COM
- MOV A,#06H
- LCALL WRITE_1602COM
- MOV A,#01H
- LCALL WRITE_1602COM
- RET
-
- WRITE_1602COM: //写命令
- CLR LCD_RS
- CLR LCD_RW
- MOV P0,A
- LCALL DELAY1
- SETB LCD_EN
- LCALL DELAY1
- CLR LCD_EN
- RET
- WRITE_1602DAT: //写数据
- SETB LCD_RS
- CLR LCD_RW
- MOV P0,A
- LCALL DELAY1
- SETB LCD_EN
- LCALL DELAY1
- CLR LCD_EN
- RET
-
-
- //1602显示字符串函数
- PRINT:
- MOV R0,#0
- PRINT01:
- MOV A,R0
- MOVC A,@A+DPTR
- CJNE A,#0,PRINT00
- RET
- PRINT00:
- LCALL WRITE_1602DAT
- INC R0
- SJMP PRINT01
-
- //1602显示3位整数
- DIS_3WEI:
- MOV R0,A
- MOV B,#100
- DIV AB
- CJNE A,#0,W1
- MOV A,#' '
- SJMP W2
- W1:
- ADD A,#30H
- W2:
- LCALL WRITE_1602DAT
- MOV A,B
- MOV B,#10
- DIV AB
- CJNE A,#0,W3
- CJNE R0,#100,W5
- SJMP W3
- W5:
- MOV A,#' '
- SJMP W4
- W3:
- ADD A,#30H
- W4:
- LCALL WRITE_1602DAT
- MOV A,B
- ADD A,#30H
- LCALL WRITE_1602DAT
- RET
-
- //1602显示2位整数
- DIS_2WEI:
- MOV B,#16
- DIV AB
- ADD A,#30H
- LCALL WRITE_1602DAT
- MOV A,B
- ADD A,#30H
- LCALL WRITE_1602DAT
- RET
-
- //1602显示1位整数
- DIS_1WEI: ;A是地址 B放数据
- LCALL WRITE_1602COM
- MOV A,B
- ADD A,#30H
- LCALL WRITE_1602DAT
- RET
-
- DELAY1: ;延时1
- MOV 30H,#20
- DJNZ 30H,$
- RET
-
- DELAY2: ;延时2
- MOV 30H,#50
- DELAY20:
- MOV 31H,#50
- DJNZ 31H,$
- DJNZ 30H,DELAY20
- RET
-
- ;//定时器0中断函数
- TIME0:
- PUSH PSW
- PUSH ACC
-
- SETB TIME_FULL
- POP ACC
- POP PSW
- RETI
-
-
- TIME1:
- PUSH PSW
- PUSH ACC
- MOV TH1,#(65536-50000)/256; //50MS
- MOV TL1,#(65536-50000)MOD 256;
- INC TX
- MOV A,TX
- CJNE A,#8,TIME10 //400MS测量一次
- MOV TX,#0
- SETB TRIG
- LCALL DELAY1
- CLR TRIG
- TIME10:
- POP ACC
- POP PSW
- RETI
-
- ; 功能:双字节十六进制整数转换成双字节BCD码整数
- ; 入口条件:待转换的双字节十六进制整数在R6、R7中。
- ; 出口信息:转换后的三字节BCD码整数在R3、R4、R5中。
- HB2:
- CLR A ;BCD码初始化
- MOV R3,A
- MOV R4,A
- MOV R5,A
- MOV R2,#10H ;转换双字节十六进制整数
- HB3:
- MOV A,R7 ;从高端移出待转换数的一位到CY中
- RLC A
- MOV R7,A
- MOV A,R6
- RLC A
- MOV R6,A
- MOV A,R5 ;BCD码带进位自身相加,相当于乘2
- ADDC A,R5
- DA A ;十进制调整
- MOV R5,A
- MOV A,R4
- ADDC A,R4
- DA A
- MOV R4,A
- MOV A,R3
- ADDC A,R3
- MOV R3,A ;双字节十六进制数的万位数不超过6,不用调整
- DJNZ R2,HB3 ;处理完16bit
- RET
-
- CODE_PRINT1:
- DB " Now S: cm",0
- CODE_PRINT2:
- DB "Set H L ",0
- CODE_PRINT3:
- DB "Err",0
- END
复制代码
仿真如上图所示,有需要欢迎下载。全部资料51hei下载地址:
仿真.zip
(24.09 KB, 下载次数: 112)
51超声波测距 汇编语言.zip
(37.92 KB, 下载次数: 92)
|