使用51单片机和CX20106A做超声波测距,余震时间如何设置?
大家好!我现在在做超声波测距,用的是非门 + CX20106A方案。发射部分用非门驱动,如下:
http://cache.amobbs.com/bbs_upload782111/files_12/ourdev_422391.gif
(原文件名:超声波发射电路原理图.gif)
我手上没有74ALS04或74LS04,所以用74HC04和HCF4069UBE代替。
超声波接收采用CX20106A,如下:
http://cache.amobbs.com/bbs_upload782111/files_12/ourdev_422392.jpg
(原文件名:接收电路 .jpg)
我用的CX20106A是拆机件。
用万用板搭好电路之后,在网上找到了一些参考汇编程序,我修改后可以通过串口发到PC显示超声波往返的时间:
;///////////////////////////////////////////////////////
; USEBY :超声波测距器
; IC :STC89C52
; OSCCAL:XT (12M)
;///////////////////////////////////////////////////////
;
T2CON EQU 0C8H
T2MOD EQU 0C9H
RCAP2L EQU 0CAH
RCAP2H EQU 0CBH
TH2 EQU 0CDH
TL2 EQU 0CCH
VOUT EQU P3.7 ;超声波输出端口
;********************************************
;* 中断入口程序 *
;********************************************
;
ORG 0000H ;复位
LJMPSTART
ORG 0003H ;外部中断0
LJMPPINT0
ORG 000BH ;T0溢出中断
RETI
ORG 0013H ;外部中断1
RETI
ORG 001BH ;T1溢出中断
LJMPINTT1
ORG 0023H ;串口中断
RETI
ORG 002BH ;T2EN端负跳变(52系列)
RETI
;
;********************************************
;* 主 程 序 *
;********************************************
;
START:MOV SP,#4FH
MOV SCON,#50H ;串口方式1工作,8位数据位,1位停止位,无奇偶校验,允许接收
MOV T2MOD,#00H ;DCEN = 0,向上计数
MOV RCAP2H,#0FEH;定时器T2置重装数,波特率:1200. (12MHz)
MOV RCAP2L,#0C8H
MOV TH2,#0FEH ;定时器T2置初值
MOV TL2,#0C8H
MOV T2CON,#34H ;T2工作方式:波特率发生器,同时启动Time2定时器
CLR TI
CLR 30H
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 ;超声波脉冲个数控制(为赋值的一半,即2个超声波)
SETB PX0
CLR IE0 ;外部中断0中断请求标志位。当主机响应中断转向该中断服务程序执行时,由内部硬件自动将IE0位清0
SETB IT0 ;当IT0 = 1时,则外部中断0(INT0 )端口由“1 ”→“0 ”下降沿跳变,激活中断请求标志位IE0,向主机请求中断处理
SETB ET1 ;允许T1中断
SETB EA
SETB TR1 ;开启测距定时器
;main主循环开始
start1:
JNB 30H,$ ;收到反射信号时标志位为1
CLR EA ;不让T1中断
MOV R2,#64H ;测量间隔控制(约5*100=500MS). 64H = 100
LOOP: LCALLDL1MS
LCALLDL1MS
LCALLDL1MS
LCALLDL1MS
LCALLDL1MS
DJNZ R2,LOOP
CLR 30H ;清除反射信号标志位
CLR ET0 ;关闭T0中断
MOV TH0,00H
MOV TL0,00H
SETB TR1 ;重新开启测距定时器
SETB EA
SJMP start1
;main主循环结束
;****************************************************
;* 中断程序 *
;****************************************************
;T1中断,发超声波用 ;T1中断,65毫秒中断一次
INTT1: CLR EA
CLR TR0
CLR EX0
MOV TH0,#00H
MOV TL0,#00H
MOV TH1,#00H
MOV TL1,#00H
SETB ET0 ;外部中断0中断请求标志位。当主机响应中断转向该中断服务程序执行时,由内部硬件自动将IE0位清0
SETB EA
SETB TR0 ;启动计数器T0,用以计算超声波传播时间
intt11:
CPL VOUT ;发射40KHZ超声波. 晶振:12MHz,1us
nop
nop
nop
nop
nop
nop
nop
nop
nop
DJNZ R4,intt11 ;2us
;超声波发送完毕
CLR IE0
MOV R4,#04H
LCALL DL1MS ;延时2ms,避开发射的直达声波信号,消除余震
LCALL DL1MS
SETB EX0 ;开启接收回波中断
RETIOUT: RETI
;外中断0,收到回波时进入
PINT0: nop
jb P3.2,pint0_exit
CLR TR0 ;关闭T0
CLR EA
CLR EX0
MOV SBUF,TH0
JNB TI,$
CLR TI
MOV SBUF,TL0
JNB TI,$
CLR TI
MOV TH0,#00H
MOV TL0,#00H
JNB p3.2,$
SETB 30H ;接收成功标志
pint0_exit:
RETI
;
;****************************************************
;* 延时程序 *
;****************************************************
;
DL1MS:
push 06H
push 07H
MOV R6,#14H ;14H = 20
DL1: MOV R7,#19H ;19H = 25
DL2: DJNZ R7,DL2 ;2us * 25 = 50
DJNZ R6,DL1 ;50us * 20 = 1000us
pop 07H
pop 06H
RET
;
;
DL100US:
push 06H
MOV R6,#32H ;32H = 50
DL3: DJNZ R7,DL3 ;2us * 50 = 100us
pop 07H
pop 06H
RET
;
END
在本论坛也找到了一些参考资料,说是在发射超声波后,为了消除余震,需要延时2ms,再打开外部中断0。我在以上程序中也这样做了,但发现无论距离远近,PC机显示的超声波往返时间居然都是2ms!我把余震延时时间设置为1ms,PC机显示的就是1ms,设置为3ms,PC机显示的就为3ms!
我把耳朵靠近超声波发射头,是可以听到嗒嗒的声音的,说明超声波已经有发射了。我把CX20106A拔下来,PC机就没有显示了,说明51的外部中断是好的,即CX20106A是有下降沿的。
麻烦看一下问题出在哪里?余震时间要如何设置?谢谢! 发射脉冲后,等待余震之后开中断。一般余震的大小跟你使用的探头有关,两个探头靠太近的话这个余震时间就比较长(因为接收头会收到发射头刚刚发出的脉冲),所以稍微增大两个探头之间的距离。
---以上针对收发分离的探头的应用。
如果是对收发同体的,那就没什么招了,跟探头的性能有关,一般盲距都在30厘米以上,盲距和探测具体成反比。 回benladn911 AVR猎手:我用的是收发分体的超声波头,开放式的非防水探头(就是铝外壳,探头表面有金属网,可以看到里面有一锥形的金属)。我刚用尺子测量两个探头之间的中心距离,是5CM。这种情况下的余震延时时间要怎么设置呢?
现在我的情况是:无论把余震延时时间设置为多少,一打开EX0,马上外部中断0就发生了,所以T0(超声波往返时间)读到的是余震延时时间。 你把发射和接受头中间加点东西阻隔一下看看 在你发出N个波峰的时候做一个很短的延时,延时结束后打开中断
程序我这里有可以给你的
不过看你的问题建议你检查一下你的接收电路
仿佛过于简单了啊,接收后面怎么的也得有放大吧?
加上施密特触发
可能你的接收点电压低于2.7V,单片机一直认为在中断状态了,素以你的延时一道,中断一开就又中断信号触发中断了 谢谢the5moon!以后多向您请教了。
CX20106A接收电路是有放大作用的,应该是可行的。
我没有示波器,无法看到波形。听说TA8141S比CX20106A性能好,明天准备重新搭个电路试试。 http://cache.amobbs.com/bbs_upload782111/files_12/ourdev_422961.jpg
(原文件名:1.jpg)
http://cache.amobbs.com/bbs_upload782111/files_12/ourdev_422962.jpg
实验板 (原文件名:2.jpg)
http://cache.amobbs.com/bbs_upload782111/files_12/ourdev_422963.jpg
电路原理 (原文件名:3.jpg)
http://cache.amobbs.com/bbs_upload782111/files_12/ourdev_422964.jpg
反射波形 (原文件名:4.jpg)
http://cache.amobbs.com/bbs_upload782111/files_12/ourdev_422965.jpg
放大后的波形 (原文件名:5.jpg)
http://cache.amobbs.com/bbs_upload782111/files_12/ourdev_422966.jpg
施密特整形后的波形 (原文件名:6.jpg) 谢谢the5moon提供这么宝贵的资料,波形图很直观,很详细,谢谢! 再请教个问题:超声波探头的两个引脚有没有正负之分的?在实际电路中要如何连接?我看到有一个引脚底部是有一个大黑点的。
谢谢! 超声波测距已经成功。感谢以上朋友的热心帮忙,谢谢!
要严格按照CX20106A的电路图和74LS04非门驱动来做,一般都可以成功的。
但现在的问题是:我的超声波测距波形中会有干扰,如下:
http://cache.amobbs.com/bbs_upload782111/files_12/ourdev_423282.PNG
(原文件名:csb.PNG)
不知如何去掉这些干扰?
谢谢! 我的毕业设计就是<超声波定位>,发射用的是555,接收用的CX20106A效果还是挺不错的,不过其中有几点要特别注意的地方 没遇到楼主说的问题 我不知道这些干扰是否与超声波探头有关。因为我买的探头是在电子市场5元一对买的,卖探头的大叔也提供不了任何技术参数。 呵呵
可能是没说明白
我做的时候是发一组波形,接受到的时候也是一组正弦波
然后通过放大,在施密特触发前用了简单的4148和一个电容(多大忘了)做滤波了
然后通过施密特整形,这样可以消除一部分微弱的干扰波。
测量时多发几组,算平均值。
楼主加油啊!~~~ 请问10楼的大哥,要注意些什么问题啊??我现在也在做超声波测距的,可是发现接收端在有接收到回波和没有的接收到得时候差别不大,中断分别不出来,只要我一接上断就有反应了,集啊!!!谢谢了!! 楼主大大,我也正在做超声测距,跟你采用的是一个方案。问两个弱弱的问题:你的问题“无论把余震延时时间设置为多少,一打开EX0,马上外部中断0就发生了,所以T0(超声波往返时间)读到的是余震延时时间。”是怎么解决的。还有发射器的正负极区分不,怎么区分呀! 大家好哈我想知道74LS04是怎样提高驱动能力的 想呀!告诉大家一下呀! D个 现在在做,帮助很大 mark 请问比较器LM331的IN-如何连接的? 我和你用的是一样的电路图,但是做出来一调试老出现差错,有时都接受不到波,这是我写的程序,用C语言编的,大家看一下:
#include<reg52.h>
unsigned char const dofly[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 显示段码值01234567
unsigned char code dian[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};//显示断码值带小数点
#define unchar unsigned char
#define unint unsigned int
unchar bai,shi,ge,mm,flag;
unint temp;
long int a,tt=0;
sbit fa=P1^0;
void display(unchar,unchar,unchar,unchar);
void delay(unsigned int cnt)
{
while(--cnt);
}
void main()
{
EA=1;//开总中断
ET0=1;//开定时器0中断允许位
TMOD=0x01;//设置定时器的工作方式为方式1
TH0=(65536-25)/256;//赋初值让其产生40KHz的方波
TL0=(65536-25)%256;
TR0=1;//启动定时器0
EX0=1;//外部中断0设置
IT0=1;
delay(100);
while(1)
{
if(flag==1)
{
a=tt;
temp=4143125*a/2000000;//temp右边的等式是12.5*a*331450/2/1000000的缩写
bai=temp/1000;
shi=temp%1000/100;
ge=temp%100/10;
mm=temp%10;
display(bai,shi,ge,mm);
while(1);
}
}
}
voidzhongduan() interrupt 0
{
flag=1;
EX0=0;
}
void timer0() interrupt 1
{
fa=!fa;
TH0=(65536-25)/256;
TL0=(65536-25)%256;
tt++;
}
void display(unchar bai,unchar shi,unchar ge,unchar mm)//显示子函数
{
P0=dofly;
P2=0;
delay(20);
P0=dofly;
P2=1;
delay(20);
P0=dian;
P2=2;
delay(20);
P0=dofly;
P2=3;
delay(20);
}
我用的是24MHz的晶振。 记号<font color="red"> mark 图片不错。 我以前在调试我那个超声波的时候也遇到过这样的问题,后来发现是中断标志位没有清零,所以延时时间一到,中断一使能就接收到中断信号。不知楼主是不是也因为同样的原因? LZ你好~我的毕业设计也是用04非门和CX20106A的超声波测距~~我现在的问题和你一样一发射就接受~加延迟也没用~距离一直显示000,我想问下你是怎么解决的~我怀疑问题出在硬件上~我是用面包板焊的~可能干扰会强些~我的QQ:65409098~希望你看到后能加下我~我想向你请教下,谢谢~ mark 顶一个 请问一下怎么确定障碍物是自己想测的,谢谢 我是新手,来学习学习 USEBY :超声波测距器
; IC :STC89C52
; OSCCAL:XT (12M)
超声波测距,用的是非门 + CX20106A方案。发射部分用非门驱动
mark. 把R1换成3K~4.7K 这个方案我搞过,我发现那个发射电路的发射功率太小了,达不到一米,而且抗干扰差,我把这个东西装在
小车上做壁障用,用PWM控制电机,结果:当调高电机速度到一定程度时,超声波测距会遇到误判,就是那个进中断的
的端口上的电平受干扰、不稳定。 用LZ的发射的图和程序试了下,有嗒嗒声,不过用示波器测到74LS04一脚上是37KHZ多一点的方波。 问一下,如果外部中断口测到的电压只有2.5伏左右能否触发中断? 您好,我现在也在做超声波测距,收发电路和楼主的一样。在接收电路中,当我将cx20106拔掉之后,cx20106的7管脚电平保持不变,当我将其插上之后,即使我将接收探头堵住,7管脚仍然有一系列的脉冲产生。请问这是什么原因?望高手解答!!! 并且7管脚的脉冲是不规则的,因为转换的距离在不停地变化,且差别很大!!! 我用集成运放和非门做过,效果不好。太近。说总显示0的问题就是发射的信号直接从某个地方进到接收电路里了或来自电源干扰。也可能是放大倍数太大引起的。我试过用两个电源分别作发射和接收。效果要好。电源的质量也有关系。电源的杂波被放大回答导致失效。
这个破玩意弄了半个学期。我的建议是利用好双踪示波器。
下面是我当时得到的效果,下面发射的波形上面接收的波形。
http://cache.amobbs.com/bbs_upload782111/files_32/ourdev_574345.jpg
(原文件名:40401.6404293171_F0082.jpg) 谢谢41楼的,我现在已经将2管脚的电阻调到2K了,而且也有距离显示,不为零。我测了下各管脚的电压:1、2.5V,2、2.5V,3、1.5V,4、0V,5、1.5V,6、0.9V,7、5V,8、5V,各管脚的电压是正常的。可是当我将所测的距离固定后,用示波器测得7脚的中断脉冲信号并不均匀,不知道是为什么?还请指教... 我现在有个问题,保持距离不变,转换的距离差别很大,为什么,还请高手指教!!! mark 收藏了,好贴.请问那个直射波能消除吗?是不是指的就是盲区?范围多大? 我的发射电路采用的是变压器推动,接受电路和the5moon的差不多,但是测试距离才4m多点,不知大家有何高见,小弟附上程序
#include<reg51.h>
#include<math.h> /*头文件*/
#include<intrins.h>
//#include<DS18B20.h>
#define uchar unsigned char /*缩定义*/
#define uint unsigned int
#define nop() _nop_() /*定义空操作指令*/
sbit vout=P1^1; /*声明40KHz脉冲信号输出口*/
//sbit Led1= P1^1; /*收到回波指示*/
//sbit Led2=P1^2; /*达到距离指示*/
//sbit Led3=P1^3; /* 不在测试范围指示*/
//sbit Out=P1^5;
sbit du=P2^6;
sbit we=P2^7;
uchar code num_table=
{0x3f,0x6,0x5b,0x4f,0x66,
0x6d,0x7d,0x27,0x7f,0x6f,0};
/*定义数码管显示字符跟数字的对应数组关系*/
uchar data bit_table[]={0xfe,0xfd,0xfb,0xf7};
/*定义每次扫描时需点亮的数码管*/
uchar dis_buff={0xff,0xff,0xff,0xfff}; /*定义段码缓冲数组*/
uint time,distance; /*定义接收时间与距离变量*/
bit rec_flag; /*定义接收成功标志位*/
uchar k,j,wm; /*定义脉冲个数与位选控制变量*/
int tempValue;
/**************************函数声明*****************************/
void Init(); /*初始化函数*/
void display(); /*显示子程序*/
/*************************延时函数*****************************/
void delay_1ms(uchar x)
{
uchar y;
while(x--)
for(y=0;y<100;y++);
}
/****************************主程序**************************/
void main()
{
uint i;
Init();
while(1)
{
// sendChangeCmd();
// tempValue = getTmpValue();
// dis_buff=num_table; /*温度显示数据*/
// dis_buff=num_table;
// dis_buff=num_table;
// dis_buff=num_table;
dis_buff=num_table; /*距离显示数据*/
dis_buff=num_table;
dis_buff=num_table;
dis_buff=num_table;
display();
if(rec_flag)
{
rec_flag=0;
// Led1=1;
for(i=400;i>0;i--); /*测量间隔控制(约4*100=400MS)*/
// display();
/* if(distance>=110&&distance<=140) /*测试距离设置*/
/* {
Led2=1;
Out=1;
Led3=0;
}
else
{
Led2=0;
Out=0;
Led3=1;
}*/
EA=1;
TR0=1;
}
}
}
/*******************************显示子函数***************************/
void display()
{
du=1;
P0=dis_buff;
du=0;
// delay_1ms(1);
we=1;
P0=bit_table;
we=0;
delay_1ms(1);
wm++;
if(wm==4)
wm=0;
}
/*void display()
{
P0=dis_buff;
P2=bit_table;
delay_1ms(1);
wm++;
if(wm==4)
wm=0;
} */
void Init() /*初始化函数*/
{
// Led1=0;
// Led2=0;
// Led3=0;
// DQ=0;
wm=0;
vout=0;
TMOD=0x21; /*T1为8位自动重装模式*/
TH0=0x00; /*65ms计数初值*/
TL0=0x00;
TH1=0xf2; /*12us计数初值*/
TL1=0xf2;
PX0=1;
PT1=1;
ET0=1;
EA=1;
TR0=1;
}
/*********************定时器T0中断程序**************************/
void TIMER0() interrupt 1
{
EA=0;
TH0=0x00;
TL0=0x00;
ET1=1;
EA=1;
TR1=1;
TR0=1;
}
/**********************定时器T1中断程序************************/
void TIMER1() interrupt 3
{
vout=!vout;
k++;
if(k>=8) /*超声波肪冲个数控制(为赋值的一半)*/
{
k=0;
// delay_1ms(1);
TR1=0;
ET1=0;
for(j=100;j>0;j--); /*1ms延时避开盲区*/
delay_1ms(2);
EX0=1; /*开启外部中断0*/
}
}
/***************************外部中断0程序***************************/
void PINT0() interrupt 0
{
EA=0;
TR0=0;
TR1=0;
ET1=0;
EX0=0;
// sendChangeCmd();
// tempValue = getTmpValue();
rec_flag=1; /*接收成功标志位置1*/
time=TH0;
time=time*256+TL0;
time=time-120; /*补偿软件或硬件带来的误差*/
// distance=time*(331.5+tempValue/1000*0.607)*0.00005;
distance=time*(331.5+20*0.607)*0.00005;
} 一定好好看看! 大家提提改进的建议吧, 余振时间设成2-2.3毫秒。 学习了,顶起 mark mark 我是新手,学习了,up up…… 先留着,也有问题 楼主能不能发我一个HCF4069的发射电路图 标记一下,回去学习 wyb4993 发表于 2009-3-3 17:26 static/image/common/back.gif
超声波测距已经成功。感谢以上朋友的热心帮忙,谢谢!
要严格按照CX20106A的电路图和74LS04非门驱动来做, ...
请问你这是什么软件啊? wyb4993 发表于 2009-3-3 17:26 static/image/common/back.gif
超声波测距已经成功。感谢以上朋友的热心帮忙,谢谢!
要严格按照CX20106A的电路图和74LS04非门驱动来做, ...
亲,你是的cx20106A与74LS04做的超声波测距是怎么做的啊,救一下急啊,我们小学期遇到难题,恰是做这个! 还有一种可能是CX20106本身就有问题,我这里两个CX20106,其中一个插上一直就是低电平,估计是坏了。另一个能用但是很不稳定,测量同一位置数据从8到60不等。还在找到底问题出在哪…… mark,留个脚印备用 收藏备用 非常好的!
页:
[1]