89c52上的超声波芯模块:
首先是红外线发射器(我猜的咳咳,以后再补充这里)
引脚连接P1.0口,每隔一段时间P1.0发射脉冲,发出红外线
之后P1.1口连接红外线接收器CX20106A,原理图
一共7个引脚
来自:http://www.360doc.com/content/15/0412/18/1437142_462691828.shtml
所以当芯片收到信号后产生一个下降沿,I/O口检测到下降沿就可以利用往返时间来计算距离了。
工作原理:
时序图:
用定时器0每隔一段时间P1.0口向外发射8个40k的光波(相互之间间隔10us),这些间隔时间不计,可看成一个稳定的波,之后打开计时器1开始计时,直到P1.1为0收到信号,结束计时,之后通过时间计算距离。
另外波纹有一个极限距离,并且也要有一个极限时间,超过这个时间(就是定时器1赋值的时间到最大值65536的时间段)就当做无限远不再计算了。通过TF1是否为1判断溢出,就是已超过最大值。
代码:
#include "reg52.h"
#include "intrins.h"
#include "absacc.h"
#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();\
_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();}
sbit TX = P1^0;
sbit RX = P1^1;
code unsigned char tab[] = { 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,\
0xff};
unsigned char dspbuf[8] = {10,10,10,10,10,10,10,10};
unsigned char dspcom = 0;
unsigned int intr = 0;
bit s_flag;
unsigned int t = 0;
void send_wave(void);
void display(void);
void main(void)
{
unsigned int distance;
TMOD |= 0x11;
TH0 = (65536-2000)/256;
TL0 = (65536-2000)%256;
TH1 = 0;
TL1 = 0;
EA = 1;
ET0 = 1; //打开定时器0中断
TR0 = 1; // 启动定时器
while(1)
{
if(s_flag)//每隔200us更新一次数据
{
s_flag = 0;
send_wave(); //发送方波信号
TR1 = 1; //启动定时器1
while((RX == 1) && (TF1 == 0)); //收到信号或者发生溢出结束while
TR1 = 0; //关闭定时器1
if(TF1 == 1)//溢出
{
TF1 = 0;
distance = 9999;
}
else
{
t = TH1;
t <<= 8;
t |= TL1;
distance = (unsigned int)(t*0.017); //通过时间计算距离
}
TH1 = 0;
TL1 = 0;
}
dspbuf[5] = distance/100;
dspbuf[6] = distance%100/10;
dspbuf[7] = distance%10;
}
}
void isr_timer_0(void) interrupt 1
{
TH0 = (65536-2000)/256;
TL0 = (65536-2000)%256; //赋初值
display(); //2数码管显示
if(++intr == 200)
{
s_flag = 1;
intr = 0;
}
}
void display(void)
{
XBYTE[0xE000] = 0xff;
XBYTE[0xC000] = (1<<dspcom);
XBYTE[0xE000] = tab[dspbuf[dspcom]];
if(++dspcom == 8){
dspcom = 0;
}
}
void send_wave(void)
{
unsigned char i = 8; //发送8次
do
{
TX = 1;
somenop;
TX = 0;
somenop;
}
while(i--);
}