找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3426|回復: 3
打印 上一主題 下一主題
收起左側(cè)

采集溫度和測距,越限報警并傳送數(shù)據(jù)給上位機

[復制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:310962 發(fā)表于 2018-5-31 14:30 | 只看該作者 |只看大圖 回帖獎勵 |正序瀏覽 |閱讀模式
#include < reg51.h >
#include < intrins.h >
#define uchar unsigned char
#define uint   unsigned int
#define lcddata P0
sbit LCDRS=P2^0;              //液晶數(shù)據(jù)選擇命令端
sbit LCDRW=P2^1;             //液晶讀寫命令端
sbit LCDEN=P2^2;            //液晶使能端
uchar mos0,mos1;

sbit DQ = P1^2;   //定義DS18B20端口DQ
sbit trig=P2^3;      //超聲波測距模塊Trig
sbit echo=P3^2;     //超聲波測距模塊Echo
sbit baojing=P1^0;                //baojing
sbit baojing1=P3^7;
sbit baojing2=P3^6;
sbit baojing3=P3^5;
sbit baojing4=P3^4;
sbit baojing5=P3^3;
long int distance;    //測量所得距離
uchar  juli_CS[ ] = "000.0";
uchar  juli_H[ ] = "000";
uchar  juli_L[ ] = "000";

uchar count;           //中斷累加變量
sbit key_H1=P1^7;     //上限加
sbit key_H2=P1^6;     //上限減
sbit key_L1=P1^5;     //下限加
sbit key_L2=P1^4;     //下限減

long int distance1=4000;//上限值
long int        distance2=100;//下限值


bit presence;           //ds18b20 DQ被拉低 信號0允許,1禁止
uint cc,cc2;       //變量cc中保存讀出的溫度值
float cc1;
uchar flag;                   //flag為溫度值正負標志位,“1”表示溫度為復制,“0”表示為正值//flag為溫度值正負標志位,“1”表示溫度為復制,“0”表示為正值
void write_com(uchar com);

uchar code cdis0[ ] = {"Detection signal"};
uchar code cdis1[ ] = {"Plese wait . . ."};
uchar  cdis2[ ] = "+00.00";
uchar code cdis3[ ] = " DS18B20 ERR0R " ;
uchar code cdis4[ ] = "  Please check  " ;
uchar code table[ ]={"0123456789"}; //定義字符數(shù)組顯示數(shù)字

unsigned char data   temp_data[2] = {0x00,0x00} ;  //存儲16位溫度

/**********************************lcd1602********************************************/

//----------------------------------
void delaylcd(uint z)
{uchar x,y;
for(x=z;x>0;x--)
  {for(y=110;y>0;y--);
  }
}

/*------------------------------------------------
                  延時函數(shù)
------------------------------------------------*/
void delayt(uint x)
{
    uchar j;
    while(x-- > 0)
    {
              for(j = 0;j < 125;j++)
        {
          ;
        }
    }
}
/*lcd1602初始化        */
/**********************************/
void lcd_init(void)
{
        write_com(0x38);                 //使用8位數(shù)據(jù)開關(guān),顯示兩行,使用5*7字形
        write_com(0x0c);                //顯示器開,光標關(guān),字符不閃爍         0x0e 光標開
        write_com(0x06);           //字符不動,光標自動右移動一位
        write_com(0x01);          //清屏
}

/*寫命令to lcd        */
/**********************************/
void write_com(uchar com)//寫命令
{
   LCDRW=0;         //低電平為寫
   LCDRS=0;         //低電平為命令選擇
   LCDEN=1;
   lcddata=com;
   delaylcd(5);
   LCDEN=1;
   delaylcd(5);
   LCDEN=0;
}

/*寫數(shù)據(jù)to lcd             */
/**********************************/
void write_data(uchar  date)
{
        LCDRW=0;  //低電平為寫
        LCDRS=1;  //高電平為數(shù)據(jù)選擇
        LCDEN=1;
        lcddata=date;
        delaylcd(5);
        LCDEN=1;
        delaylcd(5);
        LCDEN=0;
}

/*設(shè)定顯示位置             */
/********************************/
void lcd_pos(uchar pos)
{                                    //第一行第幾列直接寫pos為幾,第二行pos從0x40開始
   write_com(pos | 0x80) ;   //數(shù)據(jù)指針=80+地址變量
}

void lcd_pos1(uchar pos1)
{                                    //第?行第幾列直接寫pos為幾,第二行pos從0x40開始
   write_com(pos1 | 0xc0) ;   //數(shù)據(jù)指針=80+地址變量
}

/*******************************ds18b20*******************************************/
/*ms級別      */
void ddelay(uint ms)
{
uint i;
uchar j;
for(i=0;i<ms;i++)
   for(j=0;j<250;j++)
   {
    _nop_();          //一個機器周期,1us
           _nop_();          //適用于精度高的
        _nop_();
    _nop_();
   }
}
/*********us級延時**********/
void Delayus(uchar i)
{
  while(--i);
}
/*復位,每次讀寫之前都要進行復位*/
/**********************************/
bit ow_reset(void)
{

        DQ = 0; //拉低約600us
        Delayus(150);
        Delayus(150);

        DQ = 1;//產(chǎn)生上升沿,延時約15~60us
        Delayus(30);

        if(DQ==0) {presence=0;}         
        else presence=1;
        return(presence); //等待應答信號 0允許,1禁止
}

/*讀取數(shù)據(jù)一位            */
//---------------------------------
bit Read_bit()
{
        uint i = 0;
        bit b = 0;

        DQ = 0; //產(chǎn)生讀時隙  
        i++;         //維持低電平至少1us

        DQ = 1; //1us以上后拉高
        Delayus(2); //延時8us,DO下降沿15內(nèi)ds18b20輸出的數(shù)據(jù)才有效
        b = DQ; //讀取數(shù)據(jù)
        Delayus(40);         //每個讀時隙至少持續(xù)60us
        return(b);
}

/*讀取一個字節(jié)             */
//------------------------------------
uchar Read_byte()
{
        uchar byte_read = 0;
        uchar i, j;

        for(i=0; i<8; i++)
          {
           j = Read_bit();
           byte_read = (j<<i) | byte_read; //低位讀起
          }

        return(byte_read);
}

//-----------------------------------------
/*寫一個字節(jié)         */
void Write_byte(uchar byte_to_write)
{
        uchar i = 0;
        uchar j = 0;
        bit write_bit = 0;

        for(j=0; j<8; j++)
          {
           write_bit =         (byte_to_write & 0x01);
            if(write_bit == 1) //寫1
          {
                  DQ = 0;  //產(chǎn)生寫時隙
                 Delayus(3);           //延時15us

                  DQ = 1;  //寫1
                  Delayus(40);   //延時,寫時隙不得低于60us
          }
        else
          {
                  DQ = 0;  //產(chǎn)生寫時隙
                  Delayus(50);   //延時,保持低約60us~120us
                  DQ = 1;  
                 i++;
          }
           byte_to_write = byte_to_write >> 1;
   }
}
//-----------------------------------
/*讀取溫度,啟動溫度轉(zhuǎn)換*/
/*啟動溫度轉(zhuǎn)換*/
void start_convert()
{
        ow_reset();          // 發(fā)出復位脈沖,每次操作都從復位開始
        ddelay(1);
        Write_byte(0xcc); //skip room命令,跳過序列號命令字
        Write_byte(0x44); //啟動溫度轉(zhuǎn)換命令
}

/*讀取溫度值*/
void read_tempreture()
{
        ow_reset();          // 發(fā)出復位脈沖,每次操作都從復位開始
        ddelay(1);
        Write_byte(0xcc); //skip room命令
        Write_byte(0xbe); //讀取暫存器命令
        temp_data[0] = Read_byte(); //存儲溫度低字節(jié)值 (整數(shù)部分低四位和小數(shù)部分) 先從低字節(jié)讀取
        temp_data[1] = Read_byte(); //存儲溫度高字節(jié)值 (其中高五位為符號位)
}
//--------------------------------------
/* Detection...顯示              */
void lcd_display()
{
        uchar   m ;
        lcd_pos(0) ;                 //設(shè)置顯示位置為第一行的第1個字符
      m = 0 ;
      while(cdis0[m] != '\0')
      {                          //顯示字符
        write_data(cdis0[m]) ;
        m++ ;
      }
        lcd_pos1(0) ;                 //設(shè)置顯示位置為第一行的第1個字符
      m = 0 ;
      while(cdis1[m] != '\0')
      {                          //顯示字符
        write_data(cdis1[m]) ;
        m++ ;
      }
}


//-----------------------------------
/*   ERR0R          */
/*PLEASE   CHECK  顯示    */
void Error_Menu ()
{
      uchar   m ;
      lcd_init() ;                 //初始化LCD
      lcd_pos(0) ;                 //設(shè)置顯示位置為第一行的第1個字符
      m = 0 ;
      while(cdis3[m] != '\0')
      {                          
        write_data(cdis3[m]) ;           //顯示字符
        m++ ;
      }

      lcd_pos(0x40) ;              //設(shè)置顯示位置為第二行第1個字符
      m = 0 ;
      while(cdis4[m] != '\0')
      {
        write_data(cdis4[m]) ;       //顯示字符
        m++ ;
      }
}

//------------------------------------
/*        ℃顯示        */
void temp_c()
{
        lcd_pos(6);                  
    write_data(0xdf);//
        lcd_pos(7);                  
   write_data('C');
}

//------------------------------------
/*溫度顯示                       */
void temperature_display()
{
          uchar m;
          flag=0;
    ddelay(2);
    EA=0;                                //DS18B20讀寫數(shù)據(jù)按照嚴格的時序,最好不要被打斷,故把所有中斷關(guān)閉
    start_convert();                          //啟動溫度轉(zhuǎn)換
    ddelay(250);
    read_tempreture();                          //讀取溫度
    EA=1;
   cc=temp_data[1]*256.0+temp_data[0];
    if(temp_data[1]>0xF8) {flag=1;cc=~cc+1;} else flag=0;
    cc1=cc*0.0625;
    cc2=cc1*100;
    cdis2[1]=cc2/1000+0x30;
    if(cdis2[1]==0x30)
    {cdis2[1]=0x20;}
    cdis2[2]=cc2/100%10+0x30;
    cdis2[4]=cc2%100/10+0x30;
    cdis2[5]=cc2%10+0x30;
    if(flag==1)
         cdis2[0]='-';
    else
         cdis2[0]='+';
                        lcd_pos(0) ;                 //設(shè)置顯示位置為第一行的第6個字符
                     m=0;
    while(cdis2[m]!='\0')
      {                          //顯示字符
                      write_data(cdis2[m]) ;
            m++;
      }                                                                  

}

/*--------------------------------------------
------------------超聲波函數(shù)-----------------
-------------------------------------------*/
/*------------------------------------------------
              1602顯示固定字符函數(shù)      
------------------------------------------------*/

void lcd_xianshi( )              
{   

         lcd_pos1(0);
           write_data('H');
         lcd_pos1(1);
           write_data('=');

         lcd_pos1(9);
           write_data('L');
         lcd_pos1(10);
           write_data('=');

         lcd_pos(12);
         write_data('.');
         lcd_pos(14);
         write_data('c');
         lcd_pos(15);
         write_data('m');
}


void init_t0()
{
                        PCON=0x00;  
                    SCON=0x50;

         TMOD=0x21;
                                                                                                                
         TL0=0x66;
         TH0=0xfc;              //1ms
                        TH1=0xfd;  
                   TL1=0xfd;  
                    TR1=1;
                     ET0=1;            
         EA=1;                     
}


/*------------------------------------------------
       超聲波模塊觸發(fā)信號
------------------------------------------------*/
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;      
}


/*------------------------------------------------
   超聲波模塊相應端口初始化函數(shù)
------------------------------------------------*/
void init_measuring()
{
        trig=1;
        echo=1;
        count=0;
}


/*------------------------------------------------
     超聲波模塊距離測試函數(shù)
------------------------------------------------*/
void measuring()
{
        uchar l;
        uint h,y;
             while(echo==0);
        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);
        distance = 3453* distance / 20000;//算出來毫米,原始為:(0.34毫米/us)*時間/2//

}


/*------------------------------------------------
       超聲波模塊測量結(jié)果顯示函數(shù)
------------------------------------------------*/
void display(uint x)
{
        uchar bai,shi,ge,xiaoshu;
        bai=x/1000;
        shi=(x/100)%10;
        ge=(x/10)%10;
        xiaoshu=x%10;

                  juli_CS[0]=bai+0x30;
                  juli_CS[1]=shi+0x30;                  
                  juli_CS[2]=ge+0x30;
                  juli_CS[4]=xiaoshu+0x30;

        lcd_pos(9);//單位是厘米//
        write_data(table[bai]);//百位顯示
                  write_data(table[shi]);//十位顯示
                  write_data(table[ge]);//各位顯示
             lcd_pos(13);
                   write_data(table[xiaoshu]);//小數(shù)點后一位顯示

}
/*------------------------------------------
                                        延時函數(shù)1ms
-------------------------------------------*/

void delay_key(uchar m)
{

  uchar i,j;
  for(i=0;i<m;i++)
  for(j=0;j<24;j++);

}

void key()
{
        key_H1=1;     //上限加
        key_H2=1;     //上限減
        key_L1=1;     //下限加
        key_L2=1;       
        if(key_H1==0)
         {
                delay_key(1);       
                if(key_H1==0)
                {
                 distance1 = distance1+10;       
                }
         }

         if(key_H2==0)
         {
                delay_key(1);       
                if(key_H2==0)
                {
                 distance1 = distance1-10;       
                }
         }
               
         if(key_L1==0)
         {
                delay_key(1);       
                if(key_L1==0)
                {
                 distance2 = distance2+10;       
                }
         }

         if(key_L2==0)
         {
                delay_key(1);       
                if(key_L2==0)
                {
                  distance2 = distance2-10;
                  if(distance2<0)
                          {
                                distance2=0;
                        }
                }
         }
}
/*-----------------------------------------------*/
/*--------------上下限顯示----------------------*/
void display_H_L()
{       
        uchar H_bai,H_shi,H_ge;
        uchar L_bai,L_shi,L_ge;
        key();

        H_bai=distance1/1000;
   H_shi=(distance1/100)%10;
   H_ge=(distance1/10)%10;
        juli_H[0] = H_bai+0X30;
        juli_H[1] = H_shi+0X30;
        juli_H[2] = H_ge+0X30;


        L_bai=distance2/1000;
   L_shi=(distance2/100)%10;
   L_ge=(distance2/10)%10;
        juli_L[0] = L_bai+0X30;
        juli_L[1] = L_shi+0X30;
        juli_L[2] = L_ge+0X30;

   lcd_pos1(2);//單位是厘米//
   write_data(table[H_bai]);//百位顯示
        write_data(table[H_shi]);//十位顯示
        write_data(table[H_ge]);//各位顯示
        write_data('c');//各位顯示
        write_data('m');//各位顯示


   lcd_pos1(11);//單位是厘米//
   write_data(table[L_bai]);//百位顯示
        write_data(table[L_shi]);//十位顯示
        write_data(table[L_ge]);//各位顯示
        write_data('c');//各位顯示
        write_data('m');//各位顯示

}

/////////////////////////////////////////////
/*                串口                  */
////////////////////////////////////////////


void comm(uchar *parr)       //串口發(fā)送;  
{  
    do  
    {  
        SBUF=*parr++;  
        while(!TI);  
        TI=0;  
    }while(*parr!='\0');  
}  

//-------------------------------------------
/*主函數(shù)             */
void main()
{       

        baojing=0;
        baojing1=0;//由于此單片機驅(qū)動電流太小
        baojing2=0;//所以用空閑的I/O口作并聯(lián)
        baojing3=0;//以提高輸出電流
        baojing4=0;
        baojing5=0;
        lcd_init();                 //初始化LCD
    init_t0();          //定時器0初始化
    init_measuring();  //超聲波相應端口初始化
    lcd_display(); //顯示Detection
    ddelay(1000);   //顯示Detection1s
    ddelay(1000);   //顯示Detection1s
    ddelay(1000);   //顯示Detection1s
         write_com(0x01);//清屏
    ow_reset();//DS18B20復位
         while(1)
         {       
                 comm(cdis2);
                comm("\r\n");
                comm(juli_CS);
                comm("\r\n");
                comm(juli_H);
                comm("\r\n");
                comm(juli_L);
                comm("\r\n");
                comm("\r\n");            
                 if(presence==0)
             {          
                
                 temperature_display();//溫度顯示
                                temp_c();//顯示℃                            

             }
                   else
            {
                 Error_Menu ();//顯示字符串DS18B20 ERR0R Please check
                 while(1)
                 {
                          ow_reset();//DS18B20復位
                          if(presence==0)
                                   {
                                temperature_display();//溫度顯示
                                   }
                 }
            }

                   lcd_xianshi( ) ;  //液晶顯示特定字符
        trigger();      //觸發(fā)超聲波啟動

        measuring();           //進行距離測量
                  display_H_L();//顯示上下限
                  if(distance>distance1||distance<distance2)
                                  {
                                        baojing=1;
                                        baojing1=1;//由于此單片機驅(qū)動電流太小
                                        baojing2=1;//所以用空閑的I/O口作并聯(lián)
                                        baojing3=1;//以提高輸出電流
                                        baojing4=1;
                                        baojing5=1;
                                }
                  else
                                  {
                                        baojing=0;
                                        baojing1=0;//由于此單片機驅(qū)動電流太小
                                        baojing2=0;//所以用空閑的I/O口作并聯(lián)
                                        baojing3=0;//以提高輸出電流
                                        baojing4=0;
                                        baojing5=0;
                                }
        display(distance);    //對測量結(jié)果進行顯示
        init_measuring();    //超聲波相應端口初始化
         }
}
//……………………………………………中斷服務函數(shù)……

void T_0()interrupt 1
{

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


QQ截圖20180531142459.png (71.77 KB, 下載次數(shù): 66)

仿真原理圖

仿真原理圖

評分

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

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂 踩
回復

使用道具 舉報

地板
ID:438586 發(fā)表于 2021-2-28 10:30 | 只看該作者
1121060090 發(fā)表于 2020-1-2 01:23
發(fā)送數(shù)據(jù)給上位機的代碼呢?

主程序里的while(1)循環(huán)的前幾行就是啊
回復

使用道具 舉報

板凳
ID:439030 發(fā)表于 2020-1-2 01:23 | 只看該作者
發(fā)送數(shù)據(jù)給上位機的代碼呢?
回復

使用道具 舉報

沙發(fā)
ID:383374 發(fā)表于 2019-1-22 21:02 來自手機 | 只看該作者
如何區(qū)分數(shù)據(jù)
回復

使用道具 舉報

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

本版積分規(guī)則

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

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表