<acronym id="xonnx"></acronym>
      <td id="xonnx"></td>
    1. <pre id="xonnx"></pre>

      1. 專注電子技術學習與研究
        當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

        51單片機超聲波四通道端口掃描方式測距

        作者:未知   來源:不詳   點擊數:  更新時間:2014年08月03日   【字體:

         超聲波四通道測距:超聲波測距實現分為三大塊:

        其一是12864帶字庫的液晶驅動程序:
        代碼如下:
        /////////////////12864驅動程序///////////////////////////
        //1寫數據
        void WriteDataLCD(unsigned char WDLCD)
        {
         ReadStatusLCD(); //檢測忙 
         LCD_RS = 1;
         LCD_RW = 0;
         LCD_Data = WDLCD;
         LCD_E = 1;
         LCD_E = 1;
         LCD_E = 1;
         LCD_E = 0;
        }
         
        //2寫指令
        void WriteCommandLCD(unsigned char WCLCD,BuysC) //BuysC為0時忽略忙檢測
        {
         if (BuysC) ReadStatusLCD(); //根據需要檢測忙 
         LCD_RS = 0;
         LCD_RW = 0; 
         LCD_Data = WCLCD;
         LCD_E = 1; 
         LCD_E = 1;
         LCD_E = 1;
         LCD_E = 0;  
        }
         
        //3讀數據
        unsigned char ReadDataLCD(void)
        {
         LCD_RS = 1; 
         LCD_RW = 1;
         LCD_E = 0;
         LCD_E = 0;
         LCD_E = 1;
         return(LCD_Data);
        }
         
        //4讀狀態
        unsigned char ReadStatusLCD(void)
        {
         LCD_Data = 0xFF; 
         LCD_RS = 0;
         LCD_RW = 1; 
         LCD_E = 1;
         while (LCD_Data & Busy); //檢測忙信號
         LCD_E = 0;
         return(LCD_Data);
        }
         
        void LCDInit(void) //5LCM初始化
        {
         WriteCommandLCD(0x30,1); //顯示模式設置,開始要求每次檢測忙信號
         WriteCommandLCD(0x01,1); //顯示清屏
         WriteCommandLCD(0x06,1); // 顯示光標移動設置
         WriteCommandLCD(0x0C,1); // 顯示開及光標設置
        }
        void LCDClear(void) //6清屏
        {
         WriteCommandLCD(0x01,1); //顯示清屏
         WriteCommandLCD(0x34,1); // 顯示光標移動設置
         WriteCommandLCD(0x30,1); // 顯示開及光標設置
        }
         
        void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
        {
         if(Y<1)
          Y=1;
         if(Y>4)
          Y=4;
         X &= 0x0F; //限制X不能大于16,Y不能大于1
         switch(Y){
        case 1:X|=0X80;break;
        case 2:X|=0X90;break;
        case 3:X|=0X88;break;
        case 4:X|=0X98;break;
        }
         WriteCommandLCD(X, 0); //這里不檢測忙信號,發送地址碼
         WriteDataLCD(DData);
        }
         
        //9按指定位置顯示一串字符
        void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
        {
         unsigned char ListLength,X2;
          ListLength = 0;
          X2=X;
         if(Y<1)
          Y=1;
         if(Y>4)
          Y=4;
         X &= 0x0F; //限制X不能大于16,Y在1-4之內
         switch(Y){
        case 1:X2|=0X80;break; //根據行數來選擇相應地址
        case 2:X2|=0X90;break;
        case 3:X2|=0X88;break;
        case 4:X2|=0X98;break;
        }
         WriteCommandLCD(X2, 1); //10發送地址碼
          while (DData[ListLength]>=0x20) //若到達字串尾則退出
          {
           if (X <= 0x0F) //X坐標應小于0xF
            {
             WriteDataLCD(DData[ListLength]); //
             ListLength++;
        X++;
        Delay5Ms();
            }
          }
        }
        其二是超聲波模塊的檢測部分程序:該部分程序的超聲波發射與接受程序沒有采用外部中斷的方式實現畢竟51單片機的外部中斷稀少比較珍貴,也最多只能驅動2組,達不到預期所需要的。故在本程序中我是才用的端口掃描的方式實現的。
        程序代碼如下:void tran4(void)///可通過設置K數值選擇執行相應的I0發射超聲波
        {
        uchar i;
        float temp;
        TMOD=0XF0;
        TMOD |=0X01;
        TL0=0X47;
        TH0=0XFF;
        TR0=0;
        ET0=0;//關閉timme0中斷?
        csb4=1;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
         
        csb4=0;
        TR0=0;
        TH0=0;
        TL0=0;
        while(in4==0);
        TR0=1;
        while(in4==1);
        TR0=0;
        temp=(TH0*256+TL0)*1.08/58; //1.08為分頻之后的數
        //蜂鳴器響
        if(temp<20)beef=0;
        delay_nms(60);
        beef=1;
        //
        if(temp>4000)temp=4000;
        dis =(unsigned int)temp;//dis將直接用于顯示函數
        delay_nms(60);
        display(dis);
        shuju[0]=shuju[0]+3;
        for(i=0;i<6;i++)
        DisplayOneChar(i,4,shuju[i]); //顯示字庫中的中文數子
        }
        超聲波測距需要:現發送一組超聲波,當超聲波受到障礙物被彈回后經超聲波接受線路接受后根據高低電平進行計算這段時間,并將該時間與超聲波傳輸的速度之間的關系換算成與物體之間的距離:
        這就是其三:將接受到發揮的超聲波所需時間轉換程與物體之間的距離:
        換算程序如下:
        void display(uint dat)
        {
         
        uchar i,j,k;//定義變量
        i=dat/100;//白
        j=dat0/10;//十位
        k=dat0;//個
         
        shuju[0]=65;
        shuju[1]=i+48;//根據asc碼值要加48才能正確在液晶上顯示字符(具體參考液晶手冊)
        shuju[2]='.';
        shuju[3]=j+48;
        shuju[4]=k+48;
        shuju[5]=109;//或者shuju[4]='m';
        }
         
        以上三步完成程序也就相當容易了:
        完整超聲波四通道端口掃描方式測距程序如下:
        #include
        #include
        #include
        #define uchar unsigned char
        #define uint unsigned int
        #define nop _nop_()
        #define LCD_Data P0
        #define Busy    0x80 //用于檢測LCD狀態字中的Busy標識
         
        sbit csb1=P1^0;//tr 40KHz超聲波發射腳
        sbit in1=P1^1;
         
        sbit csb2=P1^2;
        sbit in2=P1^3;
         
        sbit  csb3=P2^2;
        sbit  in3=P2^3;
         
        sbit in4=P2^0;
        sbit  csb4=P2^1;
         
        sbit LCD_RS=P3^5;//定義引腳
        sbit LCD_RW=P3^6;
        sbit LCD_E=P3^4;
        //sbit PSB =P3^7;
        sbit PSB =P3^1; //PSB腳為12864-12系列的串、并通訊功能切換,我們使用8位并行接口,PSB=1
        sbit beef =P2^6;
        //LCD顯示字符函數
        void WriteDataLCD(unsigned char WDLCD);
        void WriteCommandLCD(unsigned char WCLCD,BuysC);
        unsigned char ReadDataLCD(void);
        unsigned char ReadStatusLCD(void);
        void LCDInit(void);
        void LCDClear(void);
        //void LCDFlash(void);
        void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
        void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);
        //void DisplayImage (unsigned char code *DData);
        void Delay5Ms(void);
        void Delay400Ms(void);
        /////////////////////////////超聲波發射接收子函數體
         
        void  delay100us();
        void delay_nms(uint n);
        void tran1(void);
        void tran2(void);
        void tran3(void);
        void tran4(void);
        void display(uint dat);
        unsigned char  shuju[5];//////////////////////////////字符定義;
         
        ////////////////////////////////////////////////超聲波發射接收全局變量
        unsigned char flag;
        unsigned int tmp,dis,high_time ,low_time ;
        ///////////////////////////////////////////////
        /////////////////////////////////////////////////主程序函數
        void main(void)
        {
         
        Delay400Ms(); //啟動等待,等LCD講入工作狀態
         LCDInit(); //LCM初始化
         Delay5Ms(); //延時片刻(可不要)
         
        while(1)
        {
        // uint i;
        tran1( );
         
        // Delay400Ms();
        // Delay400Ms();//通過延時防止因csb1接收引起中斷
        //// display(200);
        // for(i=0;i<5;i++)
        // DisplayOneChar(i,1,shuju[i]); //顯示字庫中的中文數子
        tran2( );
        // Delay400Ms();
        // Delay400Ms();//通過延時防止因csb1接收引起中斷
        tran3( );
        // Delay400Ms();
        // Delay400Ms();//通過延時防止因csb1接收引起中斷
        tran4( );
        Delay400Ms();
        Delay400Ms();
        // Delay400Ms();
        // Delay400Ms();//通過延時防止因csb1接收引起中斷
        // LCDClear();//清屏
        // Delay400Ms();
        // LCDClear();
         
        }
        }
        ////////////////////////////////////////////////////
         
        //延時函數體
        void  delay100us()
        {
            uchar i;
                for(i=0;i<50;i++)
                    ;
        }
        void delay_nms(uint n)
        {
        uchar i; 
        while(n--)
        {
        for(i=123;i>0;i--);
        }
        }
        //////超聲波發射程序
        void tran1(void)///可通過設置K數值選擇執行相應的I0發射超聲波
        {
        uchar i;
        float temp;
        TMOD=0XF0;
        TMOD |=0X01;
        TL0=0X47;
        TH0=0XFF;
        TR0=0;
        ET0=0;//關閉timme0中斷?
        csb1=1;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
         
        csb1=0;
        TR0=0;
        TH0=0;
        TL0=0;
        while(in1==0);
        TR0=1;
        while(in1==1);
        TR0=0;
        temp=(TH0*256+TL0)*1.08/58; //1.08為分頻之后的數
        //蜂鳴器響
        if(temp<20)beef=0;
        delay_nms(60);
        beef=1;
        //
        if(temp>4000)temp=4000;
        dis =(unsigned int)temp;//dis將直接用于顯示函數
        delay_nms(60);
        display(dis);
        for(i=0;i<6;i++)
        DisplayOneChar(i,1,shuju[i]); //顯示字庫中的中文數子
        }
         
        void tran2(void)///可通過設置K數值選擇執行相應的I0發射超聲波
        {
        uchar i;
        float temp;
        TMOD=0XF0;
        TMOD |=0X01;
        TL0=0X47;
        TH0=0XFF;
        TR0=0;
        ET0=0;//關閉timme0中斷?
        csb2=1;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
         
        csb2=0;
        TR0=0;
        TH0=0;
        TL0=0;
        while(in2==0);
        TR0=1;
        while(in2==1);
        TR0=0;
        temp=(TH0*256+TL0)*1.08/58; //1.08為分頻之后的數
        //蜂鳴器響
        if(temp<20)beef=0;
        delay_nms(60);
        beef=1;
        //
        if(temp>4000)temp=4000;
        dis =(unsigned int)temp;//dis將直接用于顯示函數
        delay_nms(60);
        display(dis);
        shuju[0]=shuju[0]+1;
        for(i=0;i<6;i++)
        DisplayOneChar(i,2,shuju[i]); //顯示字庫中的中文數子
        }
        void tran3(void)///可通過設置K數值選擇執行相應的I0發射超聲波
        {
        uchar i;
        float temp;
        TMOD=0XF0;
        TMOD |=0X01;
        TL0=0X47;
        TH0=0XFF;
        TR0=0;
        ET0=0;//關閉timme0中斷?
        csb3=1;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
         
        csb3=0;
        TR0=0;
        TH0=0;
        TL0=0;
        while(in3==0);
        TR0=1;
        while(in3==1);
        TR0=0;
        temp=(TH0*256+TL0)*1.08/58; //1.08為分頻之后的數
        //蜂鳴器響
        if(temp<20)beef=0;
        delay_nms(60);
        beef=1;
        //
        if(temp>4000)temp=4000;
        dis =(unsigned int)temp;//dis將直接用于顯示函數
        delay_nms(60);
        display(dis);
        shuju[0]=shuju[0]+2;
        for(i=0;i<6;i++)
        DisplayOneChar(i,3,shuju[i]); //顯示字庫中的中文數子
        }
        void tran4(void)///可通過設置K數值選擇執行相應的I0發射超聲波
        {
        uchar i;
        float temp;
        TMOD=0XF0;
        TMOD |=0X01;
        TL0=0X47;
        TH0=0XFF;
        TR0=0;
        ET0=0;//關閉timme0中斷?
        csb4=1;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
         
        csb4=0;
        TR0=0;
        TH0=0;
        TL0=0;
        while(in4==0);
        TR0=1;
        while(in4==1);
        TR0=0;
        temp=(TH0*256+TL0)*1.08/58; //1.08為分頻之后的數
        //蜂鳴器響
        if(temp<20)beef=0;
        delay_nms(60);
        beef=1;
        //
        if(temp>4000)temp=4000;
        dis =(unsigned int)temp;//dis將直接用于顯示函數
        delay_nms(60);
        display(dis);
        shuju[0]=shuju[0]+3;
        for(i=0;i<6;i++)
        DisplayOneChar(i,4,shuju[i]); //顯示字庫中的中文數子
        }
        ///////////////////////////////////
        void display(uint dat)
        {
         
        uchar i,j,k;//定義變量
        i=dat/100;//白
        j=dat0/10;//十位
        k=dat0;//個
         
        shuju[0]=65;
        shuju[1]=i+48;
        shuju[2]='.';
        shuju[3]=j+48;
        shuju[4]=k+48;
        shuju[5]=109;//或者shuju[4]='m';
        }
         
         
         
        ////////////////////////////////////////////
        //1寫數據
        void WriteDataLCD(unsigned char WDLCD)
        {
         ReadStatusLCD(); //檢測忙 
         LCD_RS = 1;
         LCD_RW = 0;
         LCD_Data = WDLCD;
         LCD_E = 1;
         LCD_E = 1;
         LCD_E = 1;
         LCD_E = 0;
        }
         
        //2寫指令
        void WriteCommandLCD(unsigned char WCLCD,BuysC) //BuysC為0時忽略忙檢測
        {
         if (BuysC) ReadStatusLCD(); //根據需要檢測忙 
         LCD_RS = 0;
         LCD_RW = 0; 
         LCD_Data = WCLCD;
         LCD_E = 1; 
         LCD_E = 1;
         LCD_E = 1;
         LCD_E = 0;  
        }
         
        //3讀數據
        unsigned char ReadDataLCD(void)
        {
         LCD_RS = 1; 
         LCD_RW = 1;
         LCD_E = 0;
         LCD_E = 0;
         LCD_E = 1;
         return(LCD_Data);
        }
         
        //4讀狀態
        unsigned char ReadStatusLCD(void)
        {
         LCD_Data = 0xFF; 
         LCD_RS = 0;
         LCD_RW = 1; 
         LCD_E = 1;
         while (LCD_Data & Busy); //檢測忙信號
         LCD_E = 0;
         return(LCD_Data);
        }
         
        void LCDInit(void) //5LCM初始化
        {
         WriteCommandLCD(0x30,1); //顯示模式設置,開始要求每次檢測忙信號
         WriteCommandLCD(0x01,1); //顯示清屏
         WriteCommandLCD(0x06,1); // 顯示光標移動設置
         WriteCommandLCD(0x0C,1); // 顯示開及光標設置
        }
        void LCDClear(void) //6清屏
        {
         WriteCommandLCD(0x01,1); //顯示清屏
         WriteCommandLCD(0x34,1); // 顯示光標移動設置
         WriteCommandLCD(0x30,1); // 顯示開及光標設置
        }
         
        void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
        {
         if(Y<1)
          Y=1;
         if(Y>4)
          Y=4;
         X &= 0x0F; //限制X不能大于16,Y不能大于1
         switch(Y){
        case 1:X|=0X80;break;
        case 2:X|=0X90;break;
        case 3:X|=0X88;break;
        case 4:X|=0X98;break;
        }
         WriteCommandLCD(X, 0); //這里不檢測忙信號,發送地址碼
         WriteDataLCD(DData);
        }
         
        //9按指定位置顯示一串字符
        void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
        {
         unsigned char ListLength,X2;
          ListLength = 0;
          X2=X;
         if(Y<1)
          Y=1;
         if(Y>4)
          Y=4;
         X &= 0x0F; //限制X不能大于16,Y在1-4之內
         switch(Y){
        case 1:X2|=0X80;break; //根據行數來選擇相應地址
        case 2:X2|=0X90;break;
        case 3:X2|=0X88;break;
        case 4:X2|=0X98;break;
        }
         WriteCommandLCD(X2, 1); //10發送地址碼
          while (DData[ListLength]>=0x20) //若到達字串尾則退出
          {
           if (X <= 0x0F) //X坐標應小于0xF
            {
             WriteDataLCD(DData[ListLength]); //
             ListLength++;
        X++;
        Delay5Ms();
            }
          }
        }
        //125ms延時
        void Delay5Ms(void)
        {
         unsigned int TempCyc = 5552;
         while(TempCyc--);
        }
         
        //13400ms延時
        void Delay400Ms(void)
        {
         unsigned char TempCycA = 5;
         unsigned int TempCycB;
         while(TempCycA--)
         {
          TempCycB=7269;
          while(TempCycB--);
         };
        }
         
        以上代碼經本人親自測試基本功能都能實現最大測量距離是5米,精度達到1厘米:
        關閉窗口

        相關文章

        欧美性色欧美精品视频,99热这里只有精品mp4,日韩高清亚洲日韩精品一区二区,2020国自产拍精品高潮