51單片機超聲波測距程序

231117n01eph8wepho7y7r.png

完整程序文件下載:https://cos.mcmxzl.com/%E5%85...函數

主程序:學習

/***********************************************************************
超聲波測距儀
 
MCU是STC89C52RC
LCD1602A(16*2)模擬口線接線方式
鏈接線圖:        
       ---------------------------------------------------
       |LCM-----51   |        LCM-----51   |        LCM------51      |
       --------------------------------------------------|
       |DB0-----P2.0 |        DB4-----P2.4 |        RS-------P1.4    |
       |DB1-----P2.1 |        DB5-----P2.5 |        RW-------P1.5    |
       |DB2-----P2.2 |        DB6-----P2.6 |        E--------P1.6    |
       |DB3-----P2.3 |        DB7-----P2.7 |        VLCD接1K電阻到GND|
       ---------------------------------------------------
接線:模塊TRIG接 P1.0  ECH0 接P1.1
 
本程序源碼只供學習參考,不得應用於商業用途,若有須要請聯繫做者。
 
***********************************************************************/
#include <reg52.H>                //器件配置文件
#include <intrins.h>
#include "LCD1602.h"
 
#define uchar unsigned char
#define uint  unsigned int
 
sbit  RX = P1^1;
sbit  TX = P1^0;
 
 
unsigned char code mcustudio[] ={"www.mcmxzl.com"};
unsigned char code email[] =    {"676672384@qq.com "};
unsigned char code ASCII[15] =    {'0','1','2','3','4','5','6','7','8','9','.','-','M'};
static unsigned char DisNum = 0; //顯示用指針                                  
       unsigned int  time=0;
           unsigned long S=0;
           bit                          flag=1;
           unsigned char disbuff[4]           ={ 0,0,0,0,};
 
void Delay5Ms(void)
{
unsigned char i, j;
 
        i = 10;
        j = 183;
        do
        {
                while (--j);
        } while (--i);
}
 
 
//400ms延時
void Delay400Ms(void)
{
        unsigned char i, j, k;
 
        _nop_();
        i = 4;
        j = 11;
        k = 45;
        do
        {
                do
                {
                        while (--k);
                } while (--j);
        } while (--i);
}  
 
void delayms(unsigned int ms)
{
        for(;ms;ms--)
        {
                unsigned char i, j;
 
        i = 2;
        j = 239;
        do
        {
                while (--j);
        } while (--i);
        }
}
 
 
 
 
 
void InitTimer0(void)
{
    TMOD = 0x09;
        TH0=0; //設置初值
        TL0=0;
    EA = 1;
    ET0 = 1;
     
}
 
 
void Timer0Interrupt(void) interrupt 1
{
        TH0=0; //設置初值
        TL0=0;
        flag=1;
}
 
void Conut(void)
{
        time=TH0*256+TL0;
        TH0=0;
        TL0=0;        
        S=(time*1.7)/100;     //算出來是CM        
        Init_LCD1602(); //LCD初始化
        if((S>=500)) //超出測量範圍顯示「-」
        {
                 displaystring(0, 0,"Error:");
                 displaystring(0, 1,"Out of range!");                  
                  /*displaychar(0, 0, ASCII[11]);
                  displaychar(1, 0, ASCII[10]);        //顯示點
                  displaychar(2, 0, ASCII[11]);
                displaychar(3, 0, ASCII[11]);
                 displaychar(4, 0, ASCII[12]);        //顯示M*/
        }
        else
        {
                 displaystring(0, 0,"Distance:");
                  disbuff[0]=S%1000/100;
                  disbuff[1]=S%1000%100/10;
                  disbuff[2]=S%1000%10 %10;
                  displaychar(10, 0, ASCII[disbuff[0]]);
                  displaychar(11, 0, ASCII[10]);        //顯示點
                  displaychar(12, 0, ASCII[disbuff[1]]);
                  displaychar(13, 0, ASCII[disbuff[2]]);
                displaychar(14, 0, ASCII[12]);        //顯示M
        }
          
}
         
 
 
 
 
/*********************************************************/
void main(void)
{        
        uchar i=0;
        InitTimer0();         //初始化定時器
        Delay400Ms(); //啓動等待,等LCD講入工做狀態
        Init_LCD1602(); //LCD初始化
        Delay5Ms(); //延時片刻(可不要)
        displaystring(0, 0, mcustudio);//顯示網站
        displaystring(0, 1, email);//顯示電子郵箱
        delayms(1000);//延時1s
        Init_LCD1602();//LCD清屏
        Delay5Ms();
         
        /******************************************
        顯示 歡迎使用超聲波測距儀
        ******************************************/
        displaystring(0, 0,"Welcome to use U");
        displaystring(0, 1,"ltrasonic distan");  
        delayms(2000);
        Init_LCD1602();
        Delay5Ms();
        displaystring(0, 0,"ce measuring ins");
        displaystring(0, 1,"trument!");
        delayms(2000);
        /*******************************************/
        Init_LCD1602(); //LCD初始化
        delayms(5);        
        while(1)
        {
                TX=1;
                _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
                TX=0;                
                while(!RX);                //當RX爲零時等待
            TR0=1;                            //開啓計數
            while(RX);                        //當RX爲1計數並等待
            TR0=0;                                //關閉計數
        Conut();                        //計算
                delayms(280);        //延時,反正發射信號對迴響信號的影響
        }
}

LCD1602顯示程序:網站

//使用方法: 使用前調用Init_LCD1602()初始化,顯示方法displaystring(0, 0, "This is a test.");
 
#ifndef _LCD1602_
#define _LCD1602_
  
#define uchar unsigned char
#define uint  unsigned int
//#define _PORT_REV_            //若是數據端口高低位交換,請去掉此註釋
 
#include <intrins.h>            //包含_nop_()指令
 
sbit LCD1602_RS = P1^4;         //控件引腳定義,移植請修改
sbit LCD1602_RW = P1^5;
sbit LCD1602_E  = P1^6;
 
#define LCD_PORT            P2  //輸出數據總線端口定義,移植請修改
 
#define LCD_COMMAND         0       // Command
#define LCD_DATA            1       // Data
#define LCD_CLEAR_SCREEN    0x01    // 清屏
#define LCD_HOMING          0x02    // 光標返回原點
#define LCD_SHOW            0x04    //顯示開
#define LCD_HIDE            0x00    //顯示關      
#define LCD_CURSOR          0x02    //顯示光標
#define LCD_NO_CURSOR       0x00    //無光標             
#define LCD_FLASH           0x01    //光標閃動
#define LCD_NO_FLASH        0x00    //光標不閃動
#define LCD_AC_UP           0x02
#define LCD_AC_DOWN         0x00    // default
#define LCD_MOVE            0x01    // 畫面可平移
#define LCD_NO_MOVE         0x00    //default
 
 
void delay10us(unsigned char t)   //偏差 -0.234375us
{        
        while(--t)
        {
    unsigned char a,b;
    for(b=1;b>0;b--)
       /* for(a=1;a>0;a--)*/;}
}
 
/*********************************************************************************************
函數名:8位數據高低位交叉互換
調  用:uchar = DataReverse(uchar);
參  數:輸入的端口(0000 0XXX 其中XXX是設置輸入端口號,可用十進制0~7表示,0表示P1.0,7表示P1.7)
返回值:交換後的8位數據
結  果:交換數據高低位D7→D0,D6→D1.....,D0→D7,並返回交換後的結果
備  注:
/**********************************************************************************************/
unsigned char DataReverse(unsigned char datOld)
{
    unsigned char datNew=0,i;
    for (i=0; i<8; i++)
    {
        if (datOld & (1<<i))        //若是某位爲1,則或上一個1
            datNew |= (0x80>>i);
    }
    return datNew;
}
/**********************************************************************************************/
 
/*********************************************************************************************
函數名:LCD1602等待函數
調  用:uchar = LCD_Wait();
參  數:無
返回值:LCD1602數據總線的值
結  果:等待LCD1602內部指令執行完成
備  注:返回結果可不用
/**********************************************************************************************/
unsigned char LCD_Wait(void)
{
    LCD1602_RS = 0;
    LCD1602_RW = 1; delay10us(1);
    LCD1602_E = 1;  delay10us(1);
 
#ifdef _PORT_REV_                       //若是數據線高低位交換,則須要處理數據
    while(DataReverse(LCD_PORT)&0x80);
    LCD1602_E = 0;
    return DataReverse(LCD_PORT);
#else                                   //正常狀況下不須要交換
    while(LCD_PORT&0x80);
    LCD1602_E = 0;
    return LCD_PORT;
#endif
}
/**********************************************************************************************/
 
/*********************************************************************************************
函數名:LCD1602數據寫函數
調  用:LCD_Wait(bit, uchar);
參  數:數據類型,數據值
返回值:無
結  果:將指定數據類型的數據寫入1602
備  注:數據類型:LCD_COMMAND(0)、LCD_DATA(1)
/**********************************************************************************************/
void LCD_Write(bit DataStyle, unsigned char DAT)
{
    LCD1602_E = 0;
    LCD1602_RS = DataStyle;
    LCD1602_RW = 0;    delay10us(1);
 
#ifdef _PORT_REV_
    LCD_PORT = DataReverse(DAT);
#else
    LCD_PORT = DAT;
#endif
 
    _nop_();
    LCD1602_E = 1;     delay10us(1);//注意順序
    LCD1602_E = 0;     delay10us(1);
    LCD_Wait();                 //等待1602內部執行完,Proteus仿真時請註釋此句
}
/**********************************************************************************************/
 
/*********************************************************************************************
函數名:LCD1602顯示設置函數
調  用:LCD_SetDisplay(uchar);
參  數:顯示模式
返回值:無
結  果:正常設置1602顯示模式
備  注:內部函數,初始化時調用
/**********************************************************************************************/
void LCD_SetDisplay(unsigned char DisplayMode)
{
    LCD_Write(LCD_COMMAND, 0x08|DisplayMode);   
}
/**********************************************************************************************/
 
/*********************************************************************************************
函數名:LCD1602顯示設置函數
調  用:LCD_SetInput(uchar);
參  數:顯示模式
返回值:無
結  果:正常設置1602顯示模式
備  注:內部函數,初始化時調用
/**********************************************************************************************/
void LCD_SetInput(unsigned char InputMode)
{
    LCD_Write(LCD_COMMAND, 0x04|InputMode);
}
/**********************************************************************************************/
 
/*********************************************************************************************
函數名:LCD1602初始化函數
調  用:Init_LCD1602();
參  數:無
返回值:無
結  果:初始化1602函數
備  注:
/**********************************************************************************************/
void Init_LCD1602()
{
    LCD_Write(LCD_COMMAND, 0x38);               //8位數據端口,2行顯示,5*7點陣
    LCD_Write(LCD_COMMAND, 0x38);
    LCD_Write(LCD_COMMAND, 0x38);
    LCD_SetDisplay(LCD_SHOW | LCD_NO_CURSOR);   //開啓顯示, 無光標
    LCD_Write(LCD_COMMAND, LCD_CLEAR_SCREEN);   //清屏
    LCD_SetInput(LCD_AC_UP | LCD_NO_MOVE);      //AC遞增, 畫面不動
}
/**********************************************************************************************/
 
/*********************************************************************************************
函數名:LCD1602數據寫函數
調  用:LCD1602_DispString(uchar, uchar, *uchar);
參  數:x座標,y座標,字符串
返回值:無
結  果:在指定座標顯示字符串
備  注:x: 0~15; y:0、1
/**********************************************************************************************/
void displaystring(unsigned char x, unsigned char y, unsigned char *s)
{
    if(y == 0)
        LCD_Write(LCD_COMMAND, 0x80|x);
    if(y == 1)
        LCD_Write(LCD_COMMAND, 0x80|(x-0x40));
    while(*s != '\0')
    {
        LCD_Write(LCD_DATA, *s);
        s++;
    }
}
/**********************************************************************************************/
 
//字符顯示初始地址設置
void LCD_SET_XY(uchar X,uchar Y)
{
          if(Y == 0)
        LCD_Write(LCD_COMMAND, 0x80|X);
    if(Y == 1)
        LCD_Write(LCD_COMMAND, 0x80|(X-0x40));
}
//在第X行Y列開始顯示Wdata所對應的單個字符
void displaychar(uchar X,uchar Y,uchar Wdata)
{
  LCD_SET_XY(X,Y);//寫地址
  LCD_Write(LCD_DATA, Wdata);//寫入當前字符並顯示
}
#endif
相關文章
相關標籤/搜索