天天看點

基于52單片機的超音波測距子產品(hc-sr04超音波測距子產品+1602液晶顯示器)

二年級課設做了超音波測障儀,用的是hc-sr04超音波測距子產品+1602液晶顯示器和52單片機。

由于自己之前的學習很是不牢固,在課設的時候沒少走彎路,最後在第二個周的星期五做了出來,浪費了很多的時間,是以就想着把這個東西寫出來,一則加強自己的了解,二則或許能幫助幫助别人。

HC-SR04超音波子產品工作原理

 (1).采用IO口觸發測距,給至少10us高電平脈沖;

 (2).子產品自動發送八個40khz方波,并自主檢測是否有電波傳回;

  (3)當有信号傳回時,通過IO口輸出一個高電平,高電平的持續時間就是超音波從發送到傳回的時間;

  (4)測距公式:距離=(高電平時間*聲速)/2;

  (5)超音波子產品時序圖如圖6所示:

基于52單片機的超音波測距子產品(hc-sr04超音波測距子產品+1602液晶顯示器)

圖6:超音波子產品時序圖

(子產品的原理很重要,隻有把原理弄懂了才能很好地做出來你想要的東西)

程式的核心在于中斷,即單片機内部的計數器中斷。

具體的程式分為兩個部分:1602顯示部分和主程式(見下)

1602程式,基本上都是一些簡單的時序問題。

首先對1602進行初始化,定義1602對應接口的接線方式。然後進行寫指令,寫資料操作,最後将得到的距離數(3位數,以cm為機關)按照個十百分為三個單獨的數字輸出到液晶顯示器上,最後輸出機關cm。

#include "lcd.h"

void Lcd1602_Delay1ms(uint c)   //誤差 0ms

{

    uchar a,b;

for (; c>0; c--)

{

for (b=199;b>0;b--)

{

  for(a=1;a>0;a--);

}      

}

}

#ifndef LCD1602_4PINS //當沒有定義這個LCD1602_4PINS時

void LcdWriteCom(uchar com)   //寫入指令

{

LCD1602_E = 0;     //使能

LCD1602_RS = 0;    //選擇發送指令

LCD1602_RW = 0;    //選擇寫入

LCD1602_DATAPINS = com;     //放入指令

Lcd1602_Delay1ms(1); //等待資料穩定

LCD1602_E = 1;           //寫入時序

Lcd1602_Delay1ms(5);   //保持時間

LCD1602_E = 0;

}

#else 

void LcdWriteCom(uchar com)   //寫入指令

{

LCD1602_E = 0; //使能清零

LCD1602_RS = 0; //選擇寫入指令

LCD1602_RW = 0; //選擇寫入

LCD1602_DATAPINS = com; //由于4位的接線是接到P0口的高四位,是以傳送高四位不用改

Lcd1602_Delay1ms(1);

LCD1602_E = 1; //寫入時序

Lcd1602_Delay1ms(5);

LCD1602_E = 0;

LCD1602_DATAPINS = com << 4; //發送低四位

Lcd1602_Delay1ms(1);

LCD1602_E = 1; //寫入時序

Lcd1602_Delay1ms(5);

LCD1602_E = 0;

}

#endif

#ifndef LCD1602_4PINS    

void LcdWriteData(uchar dat) //寫入資料

{

LCD1602_E = 0; //使能清零

LCD1602_RS = 1; //選擇輸入資料

LCD1602_RW = 0; //選擇寫入

LCD1602_DATAPINS = dat; //寫入資料

Lcd1602_Delay1ms(1);

LCD1602_E = 1;   //寫入時序

Lcd1602_Delay1ms(5);   //保持時間

LCD1602_E = 0;

}

#else

void LcdWriteData(uchar dat) //寫入資料

{

LCD1602_E = 0;   //使能清零

LCD1602_RS = 1;   //選擇寫入資料

LCD1602_RW = 0;   //選擇寫入

LCD1602_DATAPINS = dat; //由于4位的接線是接到P0口的高四位,是以傳送高四位不用改

Lcd1602_Delay1ms(1);

LCD1602_E = 1;   //寫入時序

Lcd1602_Delay1ms(5);

LCD1602_E = 0;

LCD1602_DATAPINS = dat << 4; //寫入低四位

Lcd1602_Delay1ms(1);

LCD1602_E = 1;   //寫入時序

Lcd1602_Delay1ms(5);

LCD1602_E = 0;

}

#endif

#ifndef LCD1602_4PINS

void LcdInit()   //LCD初始化子程式

{

  LcdWriteCom(0x38);  //開顯示

LcdWriteCom(0x0c);  //開顯示不顯示光标

LcdWriteCom(0x06);  //寫一個指針加1

LcdWriteCom(0x01);  //清屏

LcdWriteCom(0x80);  //設定資料指針起點

}

#else

void LcdInit()   //LCD初始化子程式

{

LcdWriteCom(0x32); //将8位總線轉為4位總線

LcdWriteCom(0x28); //在四位線下的初始化

LcdWriteCom(0x0c);  //開顯示不顯示光标

LcdWriteCom(0x06);  //寫一個指針加1

LcdWriteCom(0x01);  //清屏

LcdWriteCom(0x80);  //設定資料指針起點

}

#endif

主程式:主程式的核心在于中斷

首先對于單片機的IO口進行初始化,1602液晶顯示器的初始化,超音波子產品的初始化。初始化的同時打開了定時器,同時内部中斷打開并開始計數操作,待超音波的輸入端接收到傳回波之後關閉内部中斷,停止計數,接下來通過記到的時間計算被測物的距離(s=time*340/2m)。

#include "reg52.h" //此檔案中定義了單片機的一些特殊功能寄存器

#include "lcd.h"

#include "intrins.h"

typedef unsigned int u16;   //對資料類型進行聲明定義

typedef unsigned char u8;

sbit Trig = P2^1;

sbit Echo = P2^0; 

sbit key =P1^1; 

sbit key1 = P3^2;

sbit led = P1^0;

u16 time = 0,S = 0; 

void Time_Init()

{

TMOD=0x01;    //設T0為方式1,GATE=1;

TH0=0;

TL0=0;  

EA=1;

TR0 = 0;        

}  

void Conut(void)

{

  Trig=1;                      //啟動一次子產品

  _nop_(); 

  _nop_(); 

  _nop_(); 

  _nop_(); 

  _nop_(); 

  _nop_(); 

  _nop_(); 

  _nop_(); 

  _nop_(); 

  _nop_(); 

  _nop_(); 

  _nop_(); 

  _nop_(); 

  _nop_(); 

  _nop_(); 

  _nop_();

  Trig=0;

  while(!Echo);

      TR0=1;    

  while(Echo);

    TR0=0; 

time=TH0*256+TL0;

TH0=0;

TL0=0;

S=(time*1.7)/100;     //算出來是CM

}

void delayms(u16 xms)

{

u8 i,j;

for(i=0;i<110;i++)

   for(j=0;j<xms;j++);  

}

void main(void)

{

  Time_Init();

  LcdInit();

  while(1)

  {

     Conut();

LcdWriteData((S/100)+0x30);

LcdWriteData((S/10)%10+0x30);

      LcdWriteData((S%10)+0x30);

LcdWriteData('C');

LcdWriteData('M');

delayms(20);

LcdWriteCom(0x80);  //設定資料指針起點

}

}

 void Time0() interrupt 1

 {

    Echo = 1;

 }

硬體仿真圖如下:

基于52單片機的超音波測距子產品(hc-sr04超音波測距子產品+1602液晶顯示器)

希望對你有些幫助。。。

繼續閱讀