目錄
1、測距原理
超聲波測距的原理是利用超聲波在空氣中的傳播速度爲已知,測量聲波在發射後遇到障礙物反射回來的時間,根據發射和接收的時間差計算出發射點到障礙物的實際距離。
超聲波發射器向某一方向發射超聲波,在發射時刻的同時開始計時,超聲波在空氣中傳播,途中碰到障礙物就立即返回來,超聲波接收器收到反射波就立即停止計時。超聲波在空氣中的傳播速度爲340m/s,根據計時器記錄的時間t,就可以計算出發射點距障礙物的距離(s),即:s=340t/2 。這就是所謂的時間差測距法。
這都是忽略了其它因素,如:溫度等,在代碼中聲速給定爲340m/s。精確度達到cm級。
2、超聲波原理圖
發射部分:JS2爲發射模塊,由NA1控制。
接收部分:JS1爲接收模塊,由NB1控制。
Rb3集電器:可以用於調節
其它部分:
在藍橋杯單片機的競賽綜合平臺CT107D中,超聲波模塊的TX引腳接到單片機的P1.0端口,RX引腳接到單片機的P1.1端口。在進行藍橋杯超聲波模塊測試前,要把跳線帽J2中的1—3,2—4相連接(sonic),這樣上述模塊就互相連接在一起了,然後在P10接口發射超聲波,P11接口接收超聲波。如果接收到反射回來的信號,P11(RX)引腳變爲低電平。
3、用到的頭文件說明
#include "intrins.h"
intrins.h,函數,應用於程序設計,一般出現在C51單片機編程中,一般程序中需要使用到空指令_nop_();字符循環移位指令_crol_等時使用。
內部函數:
_crol_ 字符循環左移
_cror_ 字符循環右移
_irol_ 整數循環左移
_iror_ 整數循環右移
_lrol_ 長整數循環左移
_lror_ 長整數循環右移
_nop_ 空操作 (相當於8051 NOP 指令)
_testbit_ 測試並清零位 (相當於8051 JBC 指令)
4、實現超聲波傳感器功能
下面是實現超聲波功能的代碼,最大測量距離爲99cm。
#include<STC15F2K60S2.H>
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();} //空指令操作
sbit TX = P1^0; // 發射引腳
sbit RX = P1^1; //接受引腳
uchar code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};//0-9,-,全滅
uchar yi,er,san,si,wu,liu,qi,ba;
unsigned int intr = 0;
bit s_flag;
unsigned int t = 0;
void send_wave(void);
void Timer0Init(void);
void Timer1Init(void);
void delayms(int ms);
void allinit();
void display1(uchar yi,uchar er);
void display2(uchar san,uchar si);
void display3(uchar wu,uchar liu);
void display4(uchar qi,uchar ba);
void main()
{
unsigned int distance;
Timer0Init();
Timer1Init();
EA = 1;
ET0 = 1; //打開定時器0中斷
allinit();
yi=11;er=11;san=11;si=11;wu=11;liu=0;qi=0;ba=0;
while(1)
{
if(s_flag) // 200毫秒更新一次數據
{
s_flag = 0;
send_wave(); //發送方波信號
TR1 = 1; //啓動計時
while((RX == 1) && (TF1 == 0)); //等待接受到脈衝
TR1 = 0; //關閉計時
if(TF1 == 1)//發生溢出
{
TF1 = 0;
distance = 9999; //無返回
}
else
{
t = TH1;// 計算時間
t <<= 8;
t |= TL1;
distance = (unsigned int)(t*0.017); //計算距離
distance = distance/12;
}
TH1 = 0;
TL1 = 0;
}
liu = distance/100;
qi = distance%100/10;
ba = distance%10;
display1(yi,er);
display2(san,si);
display3(wu,liu);
display4(qi,ba);
}
}
void Timer0Init(void) //2ms @11.0592MHz
{
AUXR |= 0x80; //定時器時鐘1T模式
TMOD &= 0xF0; //設計定時器模式 TMOD=0X01;
TL0 =(65536-2000)%256; //設置定時器初值
TH0 =(65536-2000)/256; //設置定時器初值
TF0 = 0; //清除TF0標誌
TR0 = 1; //定時器0開始計時
}
void Timer1Init(void) //2ms @11.0592MHz
{
AUXR |= 0x40; //定時器時鐘1T模式
TMOD &= 0x0F; //設計定時器模式 TMOD=0X02;
}
//定時器0中斷服務函數
void isr_timer_0(void) interrupt 1 //默認定時器中斷1
{
TL0 =(65536-2000)%256; //設置定時器初值
TH0 =(65536-2000)/256; //設置定時器初值
if(++intr == 100)
{
s_flag = 1;
intr = 0;
}
}
//TX引腳發送40kHZ方波信號驅動超聲波發送探頭
void send_wave(void)
{
unsigned char i = 8; //發送8個脈衝
do
{
TX = 1;
somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;
TX = 0;
somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;
}
while(i--);
}
void delayms(int ms)
{
int i,j;
for(i=ms;i>0;i--)
for(j=400;j>0;j--);
}
void allinit()
{
P2=0XA0;
P0=0X00;//關閉蜂鳴器、繼電器
P2=0X80;
P0=0XFF;//關閉LED燈
P2=0XC0;
P0=0XFF;//選擇所有的數碼管
P2=0XFF;
P0=0XFF;//關閉所有數碼管
}
void display1(uchar yi,uchar er)
{
P2=0XC0;//打開位選573 U8
P0=0X01;//選擇第一個數碼管
P2=0XFF;//打開斷選573 U7
P0=tab[yi];
delayms(1);
P2=0XC0;//打開位選573 U8
P0=0X02;//選擇第二個數碼管
P2=0XFF;//打開斷選573 U7
P0=tab[er];
delayms(1);
}
void display2(uchar san,uchar si)
{
P2=0XC0;
P0=0X04;//選擇第三個數碼管
P2=0XFF;
P0=tab[san];
delayms(1);
P2=0XC0;
P0=0X08;//選擇第四個數碼管
P2=0XFF;
P0=tab[si];
delayms(1);
}
void display3(uchar wu,uchar liu)
{
P2=0XC0;
P0=0X10;//選擇第五個數碼管
P2=0XFF;
P0=tab[wu];
delayms(1);
P2=0XC0;
P0=0X20;//選擇第六個數碼管
P2=0XFF;
P0=tab[liu];
delayms(1);
}
void display4(uchar qi,uchar ba)
{
P2=0XC0;
P0=0X40;//選擇第七個數碼管
P2=0XFF;
P0=tab[qi];
delayms(1);
P2=0XC0;
P0=0X80;//選擇第8個數碼管
P2=0XFF;
P0=tab[ba];
delayms(1);
}
上述代碼可以加以修改如下:
#include<stc15f2k60s2.h>
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}
sbit TX=P1^0;
sbit RX=P1^1;
uchar code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
uchar f1,f2,f3,f4,f5,f6,f7,f8;
unsigned int count;
bit num;
unsigned int t=0;
void Time0_Init();
void Timer1_Init();
void delay();
void all_Init();
void send_wave();
void display12(uchar f1,uchar f2);
void display34(uchar f3,uchar f4);
void display56(uchar f5,uchar f6);
void display78(uchar f7,uchar f8);
void main(){
unsigned int distance;
Time0_Init();
Timer1_Init();
EA=1;
ET0=1;
all_Init();
f1=11,f2=11,f3=11,f4=11,f5=11,f6=0,f7=0,f8=0;
while(1){
if(num==1)
{
num=0;
send_wave();
TR1=1;
while ((RX==1)&&(TF1==0));
TR1=0;
if(TF1==1)
{
TF1=0;
distance=9999;
}
else
{
t=TH1;
t <<= 8;
t|=TL1;
distance=(unsigned int)(t*0.017);
distance=distance/12;
}
TH1=0;
TL1=0;
}
f6=distance/100;
f7=distance%100/10;
f8=distance%100%10;
display12(f1,f2);
display34(f3,f4);
display56(f5,f6);
display78(f7,f8);
}
}
void Time0_Init()
{
AUXR|=0X80;
TMOD&=0XF0;
TH0=(65536-2000)/256;
TL0=(65536-2000)%256;
TF0=0;
TR0=1;
}
void service_Time0() interrupt 1
{
TH0=(65536-2000)/256;
TL0=(65536-2000)%256;
count++;
if(count==100)
{
num=1;
count=0;
}
}
void Timer1_Init(){
AUXR|=0X40;
TMOD&=0X0F;
}
void delay(){
int j,k;
for(j=0;j<1;j++)
for(k=0;k<400;k++);
}
void all_Init(){
P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
P2=0XC0;P0=0XFF;P2=0XFF;P0=0XFF;
}
void send_wave(){
uchar i=8;
do
{
TX=1;
somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;
TX=0;
somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;
}
while(i--);
}
void display12(uchar f1,uchar f2)
{
P2=0XC0;P0=0X01;P2=0XFF;P0=tab[f1];
delay();
P2=0XC0;P0=0X02;P2=0XFF;P0=tab[f2];
delay();
}
void display34(uchar f3,uchar f4)
{
P2=0XC0;P0=0X04;P2=0XFF;P0=tab[f3];
delay();
P2=0XC0;P0=0X08;P2=0XFF;P0=tab[f4];
delay();
}
void display56(uchar f5,uchar f6)
{
P2=0XC0;P0=0X10;P2=0XFF;P0=tab[f5];
delay();
P2=0XC0;P0=0X20;P2=0XFF;P0=tab[f6];
delay();
}
void display78(uchar f7,uchar f8)
{
P2=0XC0;P0=0X40;P2=0XFF;P0=tab[f7];
delay();
P2=0XC0;P0=0X80;P2=0XFF;P0=tab[f8];
delay();
}
超聲波實現的代碼,要做到知道每一步的操作過程,具體代碼有何用處,多加練習,最後應該不會有太大問題。