基於51單片機的超聲波避障小車設計(含Proteus仿真)

超聲波避障程序隨處可見,基於51單片機的超聲波避障小車也很成熟,但是完整的Proteus仿真並不容易找到開源資料。

這次主要給大家分享其Proteus仿真部分。

涉及到的模塊有:超聲波模塊(hc-sr04)、L293D電機驅動器和直流減速電機。這/樣配合51單片機的控制,小車可以完成自主避障功能。

超聲波模塊

在這裏插入圖片描述
此圖爲Proteus 8 提供的超聲波模塊(SRF04),它有5個引腳,其中GND接地、VCC接高電平、NC可不接。TR用作激發信號的輸入,當超聲波模塊在TR引腳上檢測到了連續的10us以上的高電平時,超聲波模塊纔開始工作。ECHO用作反饋信號輸出,當超聲波檢測到有障礙物時,從該引腳輸出相應信號。

電機驅動模塊

在這裏插入圖片描述
上圖爲Proteus 8提供的電機驅動模塊(L293D),4個IN 引腳與單片機連接,控制電機轉動及方向,2個使EN 能引腳同樣與單片機連接。4個OUT,連接兩個直流電機。VSS引腳與VS引腳接高電平即可。

加載程序

雙擊添加的AT89C51單片機,出現如下對話框。
在這裏插入圖片描述

點擊 Program File 此行文件夾圖標,添加HEX文件(keil軟件編寫程序後編譯生成)
在這裏插入圖片描述
點擊運行即可。
在這裏插入圖片描述

示波器

在這裏插入圖片描述
示波器可以輔助我們調試程序和仿真,關於在Proteus裏調用示波器以及示波器的使用,我不做介紹,很多資料都能查到,本例中我運用示波器觀察超聲波模塊的TR引腳和ECHO引腳的波形。

超聲波模塊原理圖

在這裏插入圖片描述

電機驅動模塊原理

在這裏插入圖片描述

單片機最小系統

在這裏插入圖片描述

51程序

#include <at89x51.h> 
#include <intrins.h
#define  TX  P1_3
#define  RX  P1_2
#define Forward_L_DATA  180 //當前進不能走直線時,調節這兩個參數,理想是100,100,最大時256,最小是0.
#define Forward_R_DATA  180
sbit L293D_IN1=P0^0; 
sbit L293D_IN2=P0^1;
sbit L293D_IN3=P0^2;
sbit L293D_IN4=P0^3;
sbit L293D_EN1=P0^4;
sbit L293D_EN2=P0^5;
void Delay400Ms(void);//延時400毫秒函數
unsigned char disbuff[4]={0,0,0,0};//用於分別存放距離的值0.1mm,mm,cm,m
void Count(void);//距離計算函數
unsigned int  time=0;//用於存放定時器的時間值
unsigned long S=0;//用於存放距離的值
bit  flag =0;//量程溢出標誌位
bit  turn_right_flag;
void Delay1ms(unsigned int i) 
{ 
unsigned char j,k; 
do{ 
  j = 10; 
  do{ 
   k = 50; 
   do{ 
    _nop_(); 
   }while(--k);     
  }while(--j); 
}while(--i); 
} 
void Delay10us(unsigned char i) 
{ 
   unsigned char j; 
do{ 
  j = 10; 
  do{ 
   _nop_(); 
   }while(--j); 
}while(--i); 
}
void Forward()//前進
{
  L293D_IN1=1; 
  L293D_IN2=0;
  L293D_IN3=1;
  L293D_IN4=0;
}
void Stop(void)//剎車
{
  L293D_IN1=0; 
  L293D_IN2=0;
  L293D_IN3=0;
  L293D_IN4=0;
}
void Turn_Retreat()//後
{
 L293D_IN1=0; 
 L293D_IN2=1;
 L293D_IN3=0;
 L293D_IN4=1;
}
void Turn_left()//左
{
 L293D_IN1=0; 
 L293D_IN2=1;
 L293D_IN3=1;
 L293D_IN4=0;
}
void Conut(void)//計算距離
 {
  time=TH1*256+TL1;
  TH1=0;
  TL1=0;
  S=time*2;
  S=S*0.17;
  if(S<=300)
  {
  if(turn_right_flag!=1)
  {
      Stop();
      Delay1ms(5);
  }
  turn_right_flag=1;
  P1_7=0;
  P2_0=0;
  P0_6=0;
  Delay1ms(10);
  P1_7=1;
  P2_0=1;
  P0_6=1;
  Delay1ms(5);
  Turn_left();
  Delay1ms(10);
 }
 else
 {
 turn_right_flag=0;
 Forward();
 }
 if((S>=5000)||flag==1)//超出測量範圍
 {
 flag=0;
 }
 else
  {
   disbuff[0]=S%10;
   disbuff[1]=S/10%10;
   disbuff[2]=S/100%10;
   disbuff[3]=S/1000;
  }
 }
 void zd0() interrupt 3//T0中斷用來計數器溢出,超過測距範圍
 {
 flag=1;
 RX=0;
 }
 void Timer_Count(void)
 {
 TR1=1;//開啓計數
 while(RX);//當RX爲1計數並等待
 TR1=0;//關閉計數
 Conut();//計算
 }
 void  StartModule()//啓動模塊
 {
 TX=1;//啓動一次模塊
 Delay10us(2);
 TX=0;
 }
 void main(void)
 {
 unsigned char i;
 unsigned int a;
 Delay1ms(400);
 Delay1ms(5);
 TMOD=TMOD|0x10;
    EA=1;
    TH1=0;
    TL1=0;          
    ET1=1;
    turn_right_flag=0;
 B:  for(i=0;i<50;i++)//判斷k3是否按下
 {
 Delay1ms(1);
 if(P3_2!=0 )
 goto B;
 }
while(1)
   {
  RX=1;
     StartModule();
        for(a=951;a>0;a--)
     {
     
        if(RX==1)
     {
           Timer_Count();
     }
      }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章