0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

基于51單片機的濕度監(jiān)測仿真和程序

jf_eqg0Ui2u ? 來源:懂事電子設(shè)計 ? 2023-07-05 09:55 ? 次閱讀

今天分享一個基于51單片機的濕度監(jiān)測仿真和程序。

仿真所用的濕度傳感器為SHT11。SHT11是瑞士Scnsirion公司推出的一款數(shù)字溫濕度傳感器芯片。該芯片廣泛應(yīng)用于暖通空調(diào)、汽車、消費電子、自動控制等領(lǐng)域。

其主要特點如下:

高度集成,將溫度感測、濕度感測、信號變換、A/D轉(zhuǎn)換和加熱器等功能集成到一個芯片上;

提供二線數(shù)字串行接口SCK和DATA,接口簡單,支持CRC傳輸校驗,傳輸可靠性高;

測量精度可編程調(diào)節(jié),內(nèi)置A/D轉(zhuǎn)換器(分辨率為8~12位,可以通過對芯片內(nèi)部寄存器編程米選擇);

wKgZomSkzaGAcjsCAAB11eRxi-k587.png

引腳 名稱 功能
1 GND 地線
2 DATA 串行數(shù)據(jù)線
3 SCK 串行時鐘
4 VDD 電源
NC NC 懸空

傳輸啟動

數(shù)據(jù)傳輸初始化:

當(dāng)SCK時鐘為高電平時,DATA翻轉(zhuǎn)位低電平,緊接著SCK變?yōu)榈碗娖剑?br />
隨后在SCK時鐘高電平時,DATA翻轉(zhuǎn)為高電平。

9b19e8d4-1a6a-11ee-962d-dac502259ad0.png

void start_sht11(void)  //啟動
//--------------------------------------------------------
{  
   DATA=1; SCK=0;                   //數(shù)據(jù)為1,SCK=0
   _nop_();
   SCK=1;                          //第一個脈沖
   _nop_();
   DATA=0;                         //數(shù)據(jù)跌落
   _nop_ ();
   SCK=0;                         //完成一個脈沖
   _nop_(); _nop_(); _nop_();
   SCK=1;                         //再一個脈沖
   _nop_();
   DATA=1;                        //數(shù)據(jù)變?yōu)?       
   _nop_();
   SCK=0;                         //完成該脈沖       
}

讀寫數(shù)據(jù)

9b3bb810-1a6a-11ee-962d-dac502259ad0.png

9b59b4dc-1a6a-11ee-962d-dac502259ad0.png

控制器傳感器發(fā)送命令的過程中,DATA在SCK上升沿有效,且在SCK高電平時必須保持穩(wěn)定;DATA在SCK下降沿之后改變。(參考上圖 DATA valid write 段)

從傳感器讀取數(shù)據(jù)讀取數(shù)據(jù)的過程中,DATA Tv在SCK變低以后有效,且維持到下一個SCK的下降沿。(參考上圖 DATA valid read 段)

char read(void) //讀一個字節(jié) 返回應(yīng)答信號
//----------------------------------------------------------------------------------
// reads a byte form the Sensibus and gives an acknowledge in case of "ack=1" 
{ 
  unsigned char i,val=0;
  temp_LL=0;
  temp_h=0;
  DATA=1;                           //釋放數(shù)據(jù)總線
  for (i=0x80;i>0;i/=2)             //位移8位
  { 
    SCK=1;                          //上升沿讀入
    if (DATA) val=(val | i);        //確定值  
    SCK=0;             
  }
  DATA=0;                        //讀應(yīng)答信號,有應(yīng)答為1,為應(yīng)答為0 通過CPU下拉為應(yīng)答
  SCK=1;                            //第9個脈沖
  _nop_(); _nop_(); _nop_();          //pulswith approx. 5 us 
  SCK=0;                
  DATA=1;                           //釋放數(shù)據(jù)總線
  temp_h=val;
  val=0;
 ////低8位/////////////////////////////
  DATA=1;                           //釋放數(shù)據(jù)總線
  for (i=0x80;i>0;i/=2)             //位移8位
  { 
    SCK=1;                          //上升沿讀入
    if (DATA) val=(val | i);        //確定值  
    SCK=0;             
  }
  DATA=1;//0;                       //不需要應(yīng)答 通過CPU下拉為應(yīng)答
  SCK=1;                            //第9個脈沖
  _nop_(); _nop_(); _nop_();          //pulswith approx. 5 us 
  SCK=0;                
  DATA=1;                           //釋放數(shù)據(jù)總線
  temp_LL=val;
  return val ;
}
////////////




char write(unsigned char value) //寫一個字節(jié) 返回應(yīng)答信號
//---------------------------------------------------------
{ 
  unsigned char i ;
  ack=0;  
  for (i=0x80;i>0;i/=2)             //釋放數(shù)據(jù)總線
  { if (i & value) DATA=1;          //寫入值
    else DATA=0;                        
    SCK=1;                          //上升沿寫入
     _nop_(); _nop_(); _nop_();        //延時  
    SCK=0;
  }
  DATA=1;                           //釋放數(shù)據(jù)總線
  SCK=1;                            //第9個脈沖
  if  (DATA==1) ack=1;        //讀應(yīng)答信號
  SCK=0;        
  return ack;                     //error=1 表示沒有應(yīng)答
}

傳感器復(fù)位

如果出現(xiàn)通訊中斷,當(dāng)DATA保持高電平時,觸發(fā)SCK時鐘9次或更多,然后發(fā)送“傳輸啟動”時序就可以完成傳感器的復(fù)位。

9b76bd34-1a6a-11ee-962d-dac502259ad0.png

//////////////////////////////////
void sht_rest(void)  //復(fù)位 
{  
  unsigned char i; 
  DATA=1; SCK=0;                    //數(shù)據(jù)為1 時鐘為0
  for(i=0;i<9;i++)                  //9 個脈沖為 復(fù)位
  { SCK=1;
    SCK=0;
  }
  start_sht11();                   //啟動
}

Proteus仿真如下圖。主要功能是利用SHT11進行濕度的采集,并通過LCD1602顯示。在仿真中通過SHT11上面的操作按鈕就可以改變SHT11的溫度和濕度數(shù)值。該仿真沒有對溫度數(shù)據(jù)進行采集和現(xiàn)實。

9b8b3f48-1a6a-11ee-962d-dac502259ad0.png

完整的程序如下

#include 
#include
#define  uint unsigned int
#define uchar unsigned char   
/*------------------------------------------------
                 硬件端口定義
------------------------------------------------*/
sbit RS = P2^0;   //定義端口 
sbit RW = P2^1;
sbit EN = P2^2;
sbit LED = P2^4 ;


sbit RELAY = P1^0 ;


#define DataPort P0 
sbit DATA =P2^6;  //數(shù)據(jù)
sbit SCK=P2^7;    //時鐘
uchar cnt = 0 ;


unsigned char temp_h  ;  //全局應(yīng)答變量
unsigned char temp_LL  ;//全局應(yīng)答變量
unsigned char error  ;  //全局錯誤變量
unsigned char ack  ;  //全局應(yīng)答變量


#define RS_CLR RS=0 
#define RS_SET RS=1


#define RW_CLR RW=0 
#define RW_SET RW=1 


#define EN_CLR EN=0
#define EN_SET EN=1


#define TEMP_ML 0x03       //000   0001    1 溫度命令
#define HUMI_ML 0x05       //000   0010    1 溫度命令


unsigned  int  xianzhi_h=0;//濕度顯值




uchar key ;
uchar key_buf ;
uchar temp ;
uchar frq_cnt = 0;
bit updat = 0 ;
uchar delay_cnt = 0 ;


#define  TH0_BUF 0x3c
#define  TL0_BUF 0xaf


void text_jisuan_humi(void);
/*------------------------------------------------
 uS延時函數(shù),含有輸入參數(shù) unsigned char t,無返回值
 unsigned char 是定義無符號字符變量,其值的范圍是
 0~255 這里使用晶振12M,精確延時請使用匯編,大致延時
 長度如下 T=tx2+5 uS 
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{   
 while(--t);
}
/*------------------------------------------------
 mS延時函數(shù),含有輸入?yún)?shù) unsigned char t,無返回值
 unsigned char 是定義無符號字符變量,其值的范圍是
 0~255 這里使用晶振12M,精確延時請使用匯編
------------------------------------------------*/
void DelayMs(unsigned char t)
{
     
 while(t--)
 {
     //大致延時1mS
     DelayUs2x(245);
   DelayUs2x(245);
 }
}
/*------------------------------------------------
              判忙函數(shù)
------------------------------------------------*/
 bit LCD_Check_Busy(void) 
{ 
 DataPort= 0xFF; 
 RS_CLR; 
 RW_SET; 
 EN_CLR; 
 _nop_(); 
 EN_SET;
 return (bit)(DataPort & 0x80);
}
/*------------------------------------------------
              寫入命令函數(shù)
------------------------------------------------*/
 void LCD_Write_Com(unsigned char com) 
{  
// while(LCD_Check_Busy()); //忙則等待
 DelayMs(5);
 RS_CLR; 
 RW_CLR; 
 EN_SET; 
 DataPort= com; 
 _nop_(); 
 EN_CLR;
 }
/*------------------------------------------------
              寫入數(shù)據(jù)函數(shù)
------------------------------------------------*/
 void LCD_Write_Data(unsigned char Data) 
{ 
 //while(LCD_Check_Busy()); //忙則等待
 DelayMs(5);
 RS_SET; 
 RW_CLR; 
 EN_SET; 
 DataPort= Data; 
 _nop_();
 EN_CLR;
 }


/*------------------------------------------------
                清屏函數(shù)
------------------------------------------------*/
 void LCD_Clear(void) 
{ 
 LCD_Write_Com(0x01); 
 DelayMs(5);
 }
/*------------------------------------------------
              寫入字符串函數(shù)
------------------------------------------------*/
 void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) 
{     
 if (y == 0) 
   {     
   LCD_Write_Com(0x80 + x);     //表示第一行
   }
 else 
   {      
   LCD_Write_Com(0xC0 + x);      //表示第二行
   }        
 while (*s) 
   {     
 LCD_Write_Data( *s);     
 s ++;     
   }
 }
/*------------------------------------------------
              寫入字符函數(shù)
------------------------------------------------*/
 void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) 
{     
 if (y == 0) 
   {     
   LCD_Write_Com(0x80 + x);     
   }    
 else 
   {     
   LCD_Write_Com(0xC0 + x);     
   }        
 LCD_Write_Data( Data);  
 }
/*------------------------------------------------
              初始化函數(shù)
------------------------------------------------*/
 void LCD_Init(void) 
{
   LCD_Write_Com(0x38);    /*顯示模式設(shè)置*/ 
   DelayMs(5); 
   LCD_Write_Com(0x38); 
   DelayMs(5); 
   LCD_Write_Com(0x38); 
   DelayMs(5); 
   LCD_Write_Com(0x38);  
   LCD_Write_Com(0x08);    /*顯示關(guān)閉*/ 
   LCD_Write_Com(0x01);    /*顯示清屏*/ 
   LCD_Write_Com(0x06);    /*顯示光標移動設(shè)置*/ 
   DelayMs(5); 
   LCD_Write_Com(0x0C);    /*顯示開及光標設(shè)置*/
   }
/*------------------------------------------------
               定時器0中斷
------------------------------------------------*/
void TIM0_ISR() interrupt 1
{
  TR0=0;      
  TH0 = TH0_BUF ; 
  TL0 = TL0_BUF ;
  if(cnt<5)
  {
    cnt ++ ;
  }else
  {
    cnt = 0 ;
    updat = 1 ;
  }
  TR0=1;
}
/*******************************基本驅(qū)動程    *************************************/


/////////////////
//////////////////////
char read(void) //讀一個字節(jié) 返回應(yīng)答信號
//----------------------------------------------------------------------------------
// reads a byte form the Sensibus and gives an acknowledge in case of "ack=1" 
{ 
  unsigned char i,val=0;
  temp_LL=0;
  temp_h=0;
  DATA=1;                           //釋放數(shù)據(jù)總線
  for (i=0x80;i>0;i/=2)             //位移8位
  { 
    SCK=1;                          //上升沿讀入
    if (DATA) val=(val | i);        //確定值  
    SCK=0;             
  }
  DATA=0;                        //讀應(yīng)答信號,有應(yīng)答為1,為應(yīng)答為0 通過CPU下拉為應(yīng)答
  SCK=1;                            //第9個脈沖
  _nop_(); _nop_(); _nop_();          //pulswith approx. 5 us 
  SCK=0;                
  DATA=1;                           //釋放數(shù)據(jù)總線
  temp_h=val;
  val=0;
 ////低8位/////////////////////////////
  DATA=1;                           //釋放數(shù)據(jù)總線
  for (i=0x80;i>0;i/=2)             //位移8位
  { 
    SCK=1;                          //上升沿讀入
    if (DATA) val=(val | i);        //確定值  
    SCK=0;             
  }
  DATA=1;//0;                       //不需要應(yīng)答 通過CPU下拉為應(yīng)答
  SCK=1;                            //第9個脈沖
  _nop_(); _nop_(); _nop_();          //pulswith approx. 5 us 
  SCK=0;                
  DATA=1;                           //釋放數(shù)據(jù)總線
  temp_LL=val;
  return val ;
}
////////////




char write(unsigned char value) //寫一個字節(jié) 返回應(yīng)答信號
//---------------------------------------------------------
{ 
  unsigned char i ;
  ack=0;  
  for (i=0x80;i>0;i/=2)             //釋放數(shù)據(jù)總線
  { if (i & value) DATA=1;          //寫入值
    else DATA=0;                        
    SCK=1;                          //上升沿寫入
     _nop_(); _nop_(); _nop_();        //延時  
    SCK=0;
  }
  DATA=1;                           //釋放數(shù)據(jù)總線
  SCK=1;                            //第9個脈沖
  if  (DATA==1) ack=1;        //讀應(yīng)答信號
  SCK=0;        
  return ack;                     //error=1 表示沒有應(yīng)答
}
////////


void start_sht11(void)  //啟動
//--------------------------------------------------------
{  
   DATA=1; SCK=0;                   //數(shù)據(jù)為1,SCK=0
   _nop_();
   SCK=1;                          //第一個脈沖
   _nop_();
   DATA=0;                         //數(shù)據(jù)跌落
   _nop_ ();
   SCK=0;                         //完成一個脈沖
   _nop_(); _nop_(); _nop_();
   SCK=1;                         //再一個脈沖
   _nop_();
   DATA=1;                        //數(shù)據(jù)變?yōu)?       
   _nop_();
   SCK=0;                         //完成該脈沖       
}
//////////////////////////////////
void sht_rest(void)  //復(fù)位 
{  
  unsigned char i; 
  DATA=1; SCK=0;                    //數(shù)據(jù)為1 時鐘為0
  for(i=0;i<9;i++)                  //9 個脈沖為 復(fù)位
  { SCK=1;
    SCK=0;
  }
  start_sht11();                   //啟動
}


////////////////////////////////




//測量溫度或者是溫度,返回校驗值
void convert_data(unsigned char ml)
{ 
   unsigned int i;
   start_sht11();                   //啟動
   write(ml);//寫入測溫度
  if(ack==1) 
  {
    sht_rest() ;//復(fù)位
        write(ml);//寫入測溫度
    }  
  for (i=0;i<55535;i++){ if(DATA==0) break; }
   read();//讀溫度
}




/////////濕度采集處理//////


void get_humidata(void)
{
    error=0;
    ack=0;
      sht_rest() ;      //復(fù)位
     convert_data(HUMI_ML);
      text_jisuan_humi();
}


///////計算濕度//////
void text_jisuan_humi(void)
{
    float aa=0,bb=0,humi_zi;
  int   abcd=0;
  abcd = temp_h ;
  abcd = abcd <<8|temp_LL;
  aa = (float) abcd ;
   bb=aa*aa*2.8/1000000;
   aa=0.0405*aa;
   aa=aa-4-bb;
   humi_zi=aa;
    humi_zi=(humi_zi-3.3)*10;
     xianzhi_h=(int)humi_zi;
}


void Timer_Init(void)
{
  TMOD|=0x01;   //置定時器0工作方式1
  EA=1;         //打開全局中斷
  ET0=1;        //打開 定時器0 中斷
  TR0=1;
}
void main(void)
{
  char delay_cnt = 0;
  LED = 0 ;
  RELAY = 0 ;
  LCD_Init();       //液晶初始化
  LCD_Clear();    //清屏
  LCD_Write_String(0,0,"Humi:00.0%");        //初始顯示內(nèi)容
  Timer_Init();      //定時器初始化
  while(1)
    {  
    if(updat)       //數(shù)更新
    {
      updat = 0 ;
      get_humidata();
      LCD_Write_Char(5,0,0x30+xianzhi_h/100%10);
      LCD_Write_Char(6,0,0x30+xianzhi_h/10%10);
      LCD_Write_Char(8,0,0x30+xianzhi_h%10);
    }
     } 
}
如果需要仿真程序和源文件可以發(fā)送“51單片機濕度檢測”獲取相應(yīng)的下載鏈接。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 傳感器
    +關(guān)注

    關(guān)注

    2541

    文章

    49935

    瀏覽量

    747419
  • 轉(zhuǎn)換器
    +關(guān)注

    關(guān)注

    27

    文章

    8500

    瀏覽量

    145947
  • 仿真
    +關(guān)注

    關(guān)注

    50

    文章

    3969

    瀏覽量

    132948
  • 51單片機
    +關(guān)注

    關(guān)注

    272

    文章

    5689

    瀏覽量

    122132
  • 程序
    +關(guān)注

    關(guān)注

    115

    文章

    3719

    瀏覽量

    80355
收藏 人收藏

    評論

    相關(guān)推薦

    51單片機流水燈程序

    51單片機流水燈程序 51單片機流水燈程序
    發(fā)表于 12-21 15:52 ?170次下載

    秒表protues仿真 51單片機秒表仿真程序設(shè)計 protue

    秒表protues仿真 51單片機秒表仿真程序設(shè)計 protues秒表仿真設(shè)計
    發(fā)表于 01-14 22:32 ?112次下載

    頻率計仿真 基于51單片機頻率計protues仿真程序設(shè)計 頻率

    頻率計仿真 基于51單片機頻率計protues仿真程序設(shè)計 頻率計程序
    發(fā)表于 01-14 22:32 ?221次下載

    使用C51單片機和Proteus仿真設(shè)計遠程倉庫濕度監(jiān)測系統(tǒng)的應(yīng)用實例

    本文檔的主要內(nèi)容詳細介紹的是使用C51單片機和Proteus仿真設(shè)計遠程倉庫濕度監(jiān)測系統(tǒng)的應(yīng)用實例資料合集免費下載。
    發(fā)表于 05-21 08:00 ?13次下載
    使用C<b class='flag-5'>51</b><b class='flag-5'>單片機</b>和Proteus<b class='flag-5'>仿真</b>設(shè)計遠程倉庫<b class='flag-5'>濕度</b><b class='flag-5'>監(jiān)測</b>系統(tǒng)的應(yīng)用實例

    基于51單片機6264擴展內(nèi)存仿真設(shè)計(proteus仿真+程序

    基于51單片機6264擴展內(nèi)存仿真設(shè)計(proteus仿真+程序)(單片機原理及應(yīng)用)-基于
    發(fā)表于 07-22 11:45 ?82次下載
    基于<b class='flag-5'>51</b><b class='flag-5'>單片機</b>6264擴展內(nèi)存<b class='flag-5'>仿真</b>設(shè)計(proteus<b class='flag-5'>仿真</b>+<b class='flag-5'>程序</b>)

    基于51單片機的智能溫控器設(shè)計包含源程序仿真

    基于51單片機的智能溫控器設(shè)計包含源程序仿真(手把手教你學(xué)單片機)-基于51
    發(fā)表于 07-22 14:56 ?87次下載
    基于<b class='flag-5'>51</b><b class='flag-5'>單片機</b>的智能溫控器設(shè)計包含源<b class='flag-5'>程序</b>及<b class='flag-5'>仿真</b>

    基于51單片機的智能溫控器設(shè)計(包含源程序仿真

    基于51單片機的智能溫控器設(shè)計(包含源程序仿真)(單片機課程設(shè)計)-基于51
    發(fā)表于 07-22 15:02 ?136次下載
    基于<b class='flag-5'>51</b><b class='flag-5'>單片機</b>的智能溫控器設(shè)計(包含源<b class='flag-5'>程序</b>及<b class='flag-5'>仿真</b>)

    基于51單片機+NRF24L01模塊的無線溫濕度監(jiān)測系統(tǒng)設(shè)計

    基于51單片機+NRF24L01模塊的無線溫濕度監(jiān)測系統(tǒng)設(shè)計
    發(fā)表于 10-25 10:05 ?17次下載

    基于51單片機的貨車超重監(jiān)測系統(tǒng)仿真設(shè)計資料

    基于51單片機的貨車超重監(jiān)測系統(tǒng)仿真設(shè)計資料
    發(fā)表于 10-25 10:33 ?4次下載

    基于51單片機的遠程倉庫濕度監(jiān)測系統(tǒng)仿真設(shè)計資料包

    基于51單片機的遠程倉庫濕度監(jiān)測系統(tǒng)仿真設(shè)計資料包
    發(fā)表于 10-25 10:37 ?1次下載

    51單片機如何跳出wile循環(huán)_51單片機競賽設(shè)計44例全部帶proteus仿真+程序

    51單片機如何跳出wile循環(huán)_51單片機競賽設(shè)計44例全部帶proteus仿真+程序
    發(fā)表于 11-21 13:06 ?64次下載
    <b class='flag-5'>51</b><b class='flag-5'>單片機</b>如何跳出wile循環(huán)_<b class='flag-5'>51</b><b class='flag-5'>單片機</b>競賽設(shè)計44例全部帶proteus<b class='flag-5'>仿真</b>+<b class='flag-5'>程序</b>

    基于51單片機的甲烷監(jiān)測系統(tǒng)Proteus仿真

    基于51單片機的甲烷監(jiān)測系統(tǒng)Proteus仿真
    發(fā)表于 12-27 09:47 ?20次下載

    基于51單片機單片機串口通信仿真設(shè)計

    基于51單片機單片機串口通信仿真設(shè)計,資料包含仿真及源程序
    發(fā)表于 04-20 16:15 ?3次下載

    基于51單片機的熱敏電阻測溫仿真程序

    基于51單片機的熱敏電阻測溫仿真設(shè)計(包含仿真及源程序
    發(fā)表于 05-19 16:16 ?13次下載

    分享一個基于51單片機濕度監(jiān)測仿真程序

    仿真所用的濕度傳感器為SHT11。SHT11是瑞士Scnsirion公司推出的一款數(shù)字溫濕度傳感器芯片。該芯片廣泛應(yīng)用于暖通空調(diào)、汽車、消費電子、自動控制等領(lǐng)域。
    發(fā)表于 07-05 09:55 ?781次閱讀
    分享一個基于<b class='flag-5'>51</b><b class='flag-5'>單片機</b>的<b class='flag-5'>濕度</b><b class='flag-5'>監(jiān)測</b><b class='flag-5'>仿真</b>和<b class='flag-5'>程序</b>