久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 12808|回復: 0
收起左側

51單片機超聲波避障小車程序與原理圖

[復制鏈接]
ID:845320 發表于 2021-3-28 22:43 | 顯示全部樓層 |閱讀模式
制作出來的實物圖如下:

51單片機超聲波避障小車

51單片機超聲波避障小車


電路原理圖如下:
51hei.png

單片機源程序如下:
#include <REGX51.H>
#include "lcd1602.h"
#include "ds18b20.h"
#include "eeprom52.h"
#include "car_pwm.h"
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char

sbit trig=P2^1; //超聲波測距模塊Trig
sbit echo=P3^2; //超聲波測距模塊Echo

sbit key1=P2^0;
sbit key2=P2^2;
sbit key3=P2^3;
sbit key4=P2^4;           //按鍵IO口定義

bit key1_flag=1;
bit key2_flag=1;
bit key3_flag=1;
bit key4_flag=1;        //按鍵標志位
bit start_flag=0;        //開始測量標志位

bit start_flag1=0;        //開始測量標志位



sbit key5=P1^6;//紅外遙控
sbit key6=P2^5;

sbit key7=P3^3;
sbit key8=P3^4;



sbit LeftIRBZ=P2^6;//左循跡傳感器
sbit RightIRBZ=P2^7;//右循跡傳感器


bit beep1;           //蜂鳴器標志位
int temp;           //溫度變量
uchar count; //中斷累加變量
long int distance; //測量所得距離
uint distance_h=50;          //閾值
uchar system_ms,ms,t1ms1,ms1;        //累加時間
bit read_flag=1;        //讀數據標志位
bit memory_flag=0;        //存儲標志位
uint C;



void delay_nus(unsigned int i)  //延時:i>=12 ,i的最小延時單12 us
{
  i=i/10;
  while(--i);
}

void delay_nms(unsigned int n)  //延時n ms
{
  n=n+1;
  while(--n)  
  delay_nus(900);         //延時 1ms,同時進行補償

}







//對于掉電存儲,實際就是用的單片機自帶的EEPROM,對于這個EEPROM,使用起來要知道如下幾點
//“  EEPROM存儲區域分了好幾個扇區”
//“  存儲數據時,先擦除要存儲的扇區,然后寫入數據”
//“  讀數據的時候,直接讀取相應的扇區   
void memory()           //存儲子函數
{
        SectorErase(0x2000);
        byte_write(0x2000,distance_h/256);
        byte_write(0x2001,distance_h%256);
}

void read_memory() //讀存儲子函數
{
        distance_h=byte_read(0x2000)*256+byte_read(0x2001);
        if(distance_h>450) distance_h=50;
}

void delayt(uint x)        //延時x ms函數
{
        uchar j;
        while(x-- > 0)
        {
                for(j = 0;j < 125;j++)
                {
                        ;
                }
        }
}
/*
    對于顯示函數,本次設計用到的是LCD1602液晶,程序里用到的顯示函數主要有兩個,                LCD1602_write            LCD1602_writebyte
兩個都是有參函數,其中  LCD1602_write  ,要填寫兩個元素,第一個只能填寫0  1,當填寫0,就說明你第二個元素是命令,當填寫1,就
說明第二個元素是數據,例如          LCD1602_write(0,0x80);    ,說明0x80這個數據對于LCD1602來說是命令,其功能是 在第一行第0個位置
進行顯示。
LCD1602_writebyte  這個函數是顯示一串字符串

    液晶是字符屏,我們要顯示的也只能是字符,  temp_h/10%10         得到的是數據,是不能直接顯示的,而0x30是字符0,0x31是字符1,所以我們
直接用 數據加上0x30就得到對應的字符數據;


*/
void dis_play()         //顯示函數
{
        LCD1602_write(0,0x80);        //0是發命令,0x80是液晶第一行第一個位置
        LCD1602_writebyte(" ");
        LCD1602_write(1,'0'+temp/100%10);        
        LCD1602_write(1,'0'+temp/10%10);
        LCD1602_writebyte(".");
        LCD1602_write(1,'0'+temp%10);           //1是發送數據,顯示溫度數據,液晶只能顯示字符,所以在顯示的時候加一個‘0’,將數字轉換成字符進行顯示
        LCD1602_write(1,0xdf);
        LCD1602_writebyte(" D: ");
        LCD1602_write(1,'0'+distance/100%10);        
        LCD1602_write(1,'0'+distance/10%10);
        LCD1602_write(1,'0'+distance%10);
        LCD1602_writebyte("cm  ");
        LCD1602_write(0,0xc0);
        LCD1602_writebyte(" Alarm_Di:");
        LCD1602_write(1,'0'+distance_h/100%10);        
        LCD1602_write(1,'0'+distance_h/10%10);
        LCD1602_write(1,'0'+distance_h%10);
        LCD1602_writebyte("cm  ");
}



void Robot_Traction()                     //機器人循跡子程序
{

        if(key5==1)
        {
                        run();
                         delay_nms (1000);
                stop();
}
        
        
                if(key6==1)
        {
                        leftrun();
                         delay_nms (1000);
                stop();
}
        
                if(key7==1)
        {
                        rightrun();
                         delay_nms (1000);
                stop();
}
        
                if(key8==1)
        {
                        back();
                         delay_nms (1000);
                stop();
}
else {
        
   if(LeftIRBZ  == 0 && RightIRBZ == 0)    //兩個紅外檢測到黑線,就前進         Left_1_led           Right_1_led
   {
      run_1();                     
      delay_nms (100);
                 run_1();

         
   }

    if(LeftIRBZ  == 1 && RightIRBZ == 0)
   {

                 leftrun_1();
      delay_nms (10);
   }

    if(LeftIRBZ  == 0 &&  RightIRBZ == 1)
   {
      rightrun_1();                        
         
      delay_nms (10);
   }
         
   if(LeftIRBZ  == 1 &&  RightIRBZ == 1)
   {

          stop();                        
         
      delay_nms (10);
   }
         
        }

}

void Robot_A()                     
{

        
        if(key5==1)
        {
                        run();
                         delay_nms (1000);
                stop();
}
        
        
                if(key6==1)
        {
                        leftrun();
                         delay_nms (1000);
                stop();
}
        
                if(key7==1)
        {
                        rightrun();
                         delay_nms (1000);
                stop();
}
        
                if(key8==1)
        {
                        back();
                         delay_nms (1000);
                stop();
}

}
//按鍵處理函數,常規的處理方式是,判斷按鍵按下-短延時消抖-再次判斷按鍵按下-執行函數體-按鍵死循環等待
//常規的有一個弊端,就是我按鍵一直按下,程序就一直等待按鍵死循環釋放,程序不往下執行。所以這里采用另一種方式
//標志位判斷的方式,按鍵送開的時候,將一個標志位置一,然后按鍵按下,判斷標志位只要是1,就執行函數體,同時將標志位置零
//這時候,如果我按鍵還是按下,由于標志位已經置零,是不能再執行函數體的,只有按鍵松開,才會將標志位再次置一
//這個處理方式,可以放到定時器里面,效果最好,定時器本身就是定時一段時間執行一次,放到定時器里,變相的實現了定時掃描按鍵的作用
//并且可以消除抖動
void key_scan()          //
{
        if(!key1)           //判斷按鍵按下
        {
                if(key1_flag)
                {
                        key1_flag=0;
                        if(distance_h<450) distance_h++;  //閾值自加
                }
        }
        else                                    //松開按鍵
        {
                if(key1_flag==0)
                {
                        memory_flag=1;        //存儲標志位置1一次
                        key1_flag=1;
                }
        }
        if(!key2)
        {
                if(key2_flag)
                {
                        key2_flag=0;
                        if(distance_h>0) distance_h--;          //閾值自減
                }
        }
        else
        {
                if(key2_flag==0)
                {
                        memory_flag=1;
                        key2_flag=1;
                }
        }
        if(!key3)
        {
                if(key3_flag)
                {
                        key3_flag=0;
                        start_flag=1; //開始測量
                        start_flag1=0;
                }
        }
        else key3_flag=1;
        if(!key4)
        {
                if(key4_flag)
                {
                        key4_flag=0;
                        start_flag=0; //停止測量
                start_flag1=1;
                        
                }
        }
        else key4_flag=1;
}

void Time_init()        //配置定時器
{
        TMOD=0x11;         //定時器0和1都是方式1
//        TH1=0X4C;
//        TL1=0X00;         //50ms初值
        TH1=0XFc;          //1Ms定時
    TL1=0X18;

        ET1=1;
        TR1=1;                  //打開定時器1
        TL0=0x66;
        TH0=0xfc; //1ms
        ET0=1;                 //設置定時器0
        EA=1;                 //打開總中斷
}

void trigger()        //啟動測量
{
        trig=0;
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        trig=1;
}

void init_measuring()         //初始化超聲波
{
        trig=1;
        echo=1;
        count=0;
}

void measuring()        //測量函數
{
        uchar l;
        uint h,y;
        TR0 = 1;
        while(echo==1)
        {
                ;
        }
        TR0 = 0;
        l = TL0;
        h = TH0;
        y = (h << 8) + l;
        y = y - 0xfc66;//us部分
        distance = y + 1000 * count;//計算總時間,單位是微秒
        TL0 = 0x66;
        TH0 = 0xfc;
        delayt(30);
        C=331.45+0.061*temp;
        distance = C* distance / 20000;//原始為:(0.34毫米/us)*時間/2//
}

void police()           //報警函數
{
        if(distance<distance_h)        
                {
                        back_1();
                delay_nms (1000);
                stop();
                        delay_nms (1000);
                        rightrun_1();
                        delay_nms (500);
                        stop();
                }

        else
        {
//                beep=1;                 //否則停止報警
                run();
                //beep1=0;
        }
}









void main()
{
        do
        {
                temp=Temper();
        }while(temp==850); //溫度傳感器上電會讀一個850,這里用do{}while()語句將850過濾掉
        Time_init();  //調用定時器初始化函數
        LCD1602_cls(); //調用液晶初始化函數
        init_measuring(); //超聲波相應端口初始化
        read_memory();         //上電把存儲的數據讀出來
        while(1)
        {
               
               
               
               
               
        //        Robot_Traction();        
               
               
               
        //Robot_A();
               
                if(memory_flag)          //如果存儲標志位是1
                {
                        memory_flag=0; //清0
                        memory();          //存儲一次數據
                }
               
                ms1++;
                if(distance>=3)          //如果距離大于3cm
                {
                        if(ms1>=distance)        //根據距離的遠近,報警頻率不同
                        {
                                ms1=0;
//                                if(beep1) beep=!beep;
        //                        else beep=1;
                        }
                }
                else        //否則小于3cm,用最快的報警頻率
                {
                        if(ms1>=3)
                        {
                                ms1=0;
//                                if(beep1) beep=!beep;
        //                        else beep=1;
                        }
                }
               
                dis_play();        //液晶顯示函數
                if(start_flag) police();  //如果開始測量,調用報警函數
                //if(start_flag1) Robot_Traction();        
                if(read_flag)          //如果讀數據標志位是1
                {
                        read_flag=0;  //置0
                        temp=Temper();        //讀溫度數據
                        if(start_flag)          //如果開始測量
                        {
                                
                                trigger(); //觸發超聲波啟動
                                while(echo==0) //等待回聲
                                {
                                        ;
                                }
                                measuring(); //進行距離測量
                                init_measuring(); //超聲波相應端口初始化
                        }
                        else  //否則
                        {
                                //beep1=0;        //停止報警,測量距離是0
                                stop();
                                distance=0;
                        }
                }        
        }
}
//……………………………………………中斷服務函數…………………………………………………//

void T_0()interrupt 1
{
        TF0 = 0;
  TL0 = 0x66;
        TH0 = 0xfc;
        

        count++;
        
        if(count==18)
        {
                TR0 =0;
                TL0 = 0x66;
                TH0 = 0xfc;
                count = 0;
        }
        
        

}

void time1() interrupt 3
{
        t1ms1++;
        TH1=0XFc;          //1Ms定時
         TL1=0X18;
        if(t1ms1>=50)
        {
                t1ms1=0;
                key_scan();          //調用按鍵處理函數
                ms++;
        }
        if(ms%10==0)
        {
                read_flag=1;   //每10*50ms=500ms將讀數據標志位置1一次
        }
        if(ms>=40)
        {
                ms=0;
        }

         time3++;
         pwm_val_left++;
         pwm_val_right++;
         pwm_out_left_moto();
         pwm_out_right_moto();
}

全部資料51hei下載地址:
B65037資料20210322.zip (242.92 KB, 下載次數: 66)

評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 午夜丁香视频在线观看 | 日韩在线精品视频 | 在线观看免费高清av | 亚洲福利网 | 五月天婷婷久久 | 成人欧美一区二区三区 | 最新午夜综合福利视频 | aaa一区| 国产精品免费在线 | 久久乐国产精品 | 一区二区三区视频在线观看 | 亚洲欧美精品久久 | 久草热视频 | 欧美mv日韩mv国产网站91进入 | 一区二区三区四区五区在线视频 | 91久久国产综合久久91精品网站 | 欧美色偷拍 | 国产精品久久久久久久久久 | 亚洲欧美一区二区三区国产精品 | 99亚洲精品 | 欧美日韩成人影院 | 黄网站免费观看 | 国产免费一区二区三区免费视频 | 国产一区二区在线免费观看 | 国产精品视频一区二区三区 | 久久久久精 | 麻豆亚洲 | 亚洲综合区 | 欧美综合国产精品久久丁香 | 波多野结衣电影一区 | 91精品一区二区三区久久久久久 | 国产专区在线 | 精品久久一区 | 999热精品| 伊人网伊人网 | 日本免费黄色一级片 | 日本午夜网站 | 国产成人99久久亚洲综合精品 | 一级a爱片久久毛片 | 国产一区二区三区亚洲 | 亚洲高清在线免费观看 |