0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于51单片机的湿度监测仿真和程序

jf_eqg0Ui2u 来源:懂事电子设计 2023-07-05 09:55 次阅读

今天分享一个基于51单片机的湿度监测仿真和程序。

仿真所用的湿度传感器为SHT11。SHT11是瑞士Scnsirion公司推出的一款数字温湿度传感器芯片。该芯片广泛应用于暖通空调、汽车、消费电子、自动控制等领域。

其主要特点如下:

高度集成,将温度感测、湿度感测、信号变换、A/D转换和加热器等功能集成到一个芯片上;

提供二线数字串行接口SCK和DATA,接口简单,支持CRC传输校验,传输可靠性高;

测量精度可编程调节,内置A/D转换器(分辨率为8~12位,可以通过对芯片内部寄存器编程米选择);

wKgZomSkzaGAcjsCAAB11eRxi-k587.png

引脚 名称 功能
1 GND 地线
2 DATA 串行数据线
3 SCK 串行时钟线
4 VDD 电源
NC NC 悬空

传输启动

数据传输初始化:

当SCK时钟为高电平时,DATA翻转位低电平,紧接着SCK变为低电平,

随后在SCK时钟高电平时,DATA翻转为高电平。

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

void start_sht11(void)  //启动
//--------------------------------------------------------
{  
   DATA=1; SCK=0;                   //数据为1,SCK=0
   _nop_();
   SCK=1;                          //第一个脉冲
   _nop_();
   DATA=0;                         //数据跌落
   _nop_ ();
   SCK=0;                         //完成一个脉冲
   _nop_(); _nop_(); _nop_();
   SCK=1;                         //再一个脉冲
   _nop_();
   DATA=1;                        //数据变为1       
   _nop_();
   SCK=0;                         //完成该脉冲       
}

读写数据

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

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

控制器传感器发送命令的过程中,DATA在SCK上升沿有效,且在SCK高电平时必须保持稳定;DATA在SCK下降沿之后改变。(参考上图 DATA valid write 段)

从传感器读取数据读取数据的过程中,DATA Tv在SCK变低以后有效,且维持到下一个SCK的下降沿。(参考上图 DATA valid read 段)

char read(void) //读一个字节 返回应答信号
//----------------------------------------------------------------------------------
// 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;                           //释放数据总线
  for (i=0x80;i>0;i/=2)             //位移8位
  { 
    SCK=1;                          //上升沿读入
    if (DATA) val=(val | i);        //确定值  
    SCK=0;             
  }
  DATA=0;                        //读应答信号,有应答为1,为应答为0 通过CPU下拉为应答
  SCK=1;                            //第9个脉冲
  _nop_(); _nop_(); _nop_();          //pulswith approx. 5 us 
  SCK=0;                
  DATA=1;                           //释放数据总线
  temp_h=val;
  val=0;
 ////低8位/////////////////////////////
  DATA=1;                           //释放数据总线
  for (i=0x80;i>0;i/=2)             //位移8位
  { 
    SCK=1;                          //上升沿读入
    if (DATA) val=(val | i);        //确定值  
    SCK=0;             
  }
  DATA=1;//0;                       //不需要应答 通过CPU下拉为应答
  SCK=1;                            //第9个脉冲
  _nop_(); _nop_(); _nop_();          //pulswith approx. 5 us 
  SCK=0;                
  DATA=1;                           //释放数据总线
  temp_LL=val;
  return val ;
}
////////////




char write(unsigned char value) //写一个字节 返回应答信号
//---------------------------------------------------------
{ 
  unsigned char i ;
  ack=0;  
  for (i=0x80;i>0;i/=2)             //释放数据总线
  { if (i & value) DATA=1;          //写入值
    else DATA=0;                        
    SCK=1;                          //上升沿写入
     _nop_(); _nop_(); _nop_();        //延时  
    SCK=0;
  }
  DATA=1;                           //释放数据总线
  SCK=1;                            //第9个脉冲
  if  (DATA==1) ack=1;        //读应答信号
  SCK=0;        
  return ack;                     //error=1 表示没有应答
}

传感器复位

如果出现通讯中断,当DATA保持高电平时,触发SCK时钟9次或更多,然后发送“传输启动”时序就可以完成传感器的复位。

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

//////////////////////////////////
void sht_rest(void)  //复位 
{  
  unsigned char i; 
  DATA=1; SCK=0;                    //数据为1 时钟为0
  for(i=0;i<9;i++)                  //9 个脉冲为 复位
  { SCK=1;
    SCK=0;
  }
  start_sht11();                   //启动
}

Proteus仿真如下图。主要功能是利用SHT11进行湿度的采集,并通过LCD1602显示。在仿真中通过SHT11上面的操作按钮就可以改变SHT11的温度和湿度数值。该仿真没有对温度数据进行采集和现实。

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;  //数据
sbit SCK=P2^7;    //时钟
uchar cnt = 0 ;


unsigned char temp_h  ;  //全局应答变量
unsigned char temp_LL  ;//全局应答变量
unsigned char error  ;  //全局错误变量
unsigned char ack  ;  //全局应答变量


#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延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
 长度如下 T=tx2+5 uS 
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{   
 while(--t);
}
/*------------------------------------------------
 mS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(unsigned char t)
{
     
 while(t--)
 {
     //大致延时1mS
     DelayUs2x(245);
   DelayUs2x(245);
 }
}
/*------------------------------------------------
              判忙函数
------------------------------------------------*/
 bit LCD_Check_Busy(void) 
{ 
 DataPort= 0xFF; 
 RS_CLR; 
 RW_SET; 
 EN_CLR; 
 _nop_(); 
 EN_SET;
 return (bit)(DataPort & 0x80);
}
/*------------------------------------------------
              写入命令函数
------------------------------------------------*/
 void LCD_Write_Com(unsigned char com) 
{  
// while(LCD_Check_Busy()); //忙则等待
 DelayMs(5);
 RS_CLR; 
 RW_CLR; 
 EN_SET; 
 DataPort= com; 
 _nop_(); 
 EN_CLR;
 }
/*------------------------------------------------
              写入数据函数
------------------------------------------------*/
 void LCD_Write_Data(unsigned char Data) 
{ 
 //while(LCD_Check_Busy()); //忙则等待
 DelayMs(5);
 RS_SET; 
 RW_CLR; 
 EN_SET; 
 DataPort= Data; 
 _nop_();
 EN_CLR;
 }


/*------------------------------------------------
                清屏函数
------------------------------------------------*/
 void LCD_Clear(void) 
{ 
 LCD_Write_Com(0x01); 
 DelayMs(5);
 }
/*------------------------------------------------
              写入字符串函数
------------------------------------------------*/
 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 ++;     
   }
 }
/*------------------------------------------------
              写入字符函数
------------------------------------------------*/
 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);  
 }
/*------------------------------------------------
              初始化函数
------------------------------------------------*/
 void LCD_Init(void) 
{
   LCD_Write_Com(0x38);    /*显示模式设置*/ 
   DelayMs(5); 
   LCD_Write_Com(0x38); 
   DelayMs(5); 
   LCD_Write_Com(0x38); 
   DelayMs(5); 
   LCD_Write_Com(0x38);  
   LCD_Write_Com(0x08);    /*显示关闭*/ 
   LCD_Write_Com(0x01);    /*显示清屏*/ 
   LCD_Write_Com(0x06);    /*显示光标移动设置*/ 
   DelayMs(5); 
   LCD_Write_Com(0x0C);    /*显示开及光标设置*/
   }
/*------------------------------------------------
               定时器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;
}
/*******************************基本驱动程    *************************************/


/////////////////
//////////////////////
char read(void) //读一个字节 返回应答信号
//----------------------------------------------------------------------------------
// 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;                           //释放数据总线
  for (i=0x80;i>0;i/=2)             //位移8位
  { 
    SCK=1;                          //上升沿读入
    if (DATA) val=(val | i);        //确定值  
    SCK=0;             
  }
  DATA=0;                        //读应答信号,有应答为1,为应答为0 通过CPU下拉为应答
  SCK=1;                            //第9个脉冲
  _nop_(); _nop_(); _nop_();          //pulswith approx. 5 us 
  SCK=0;                
  DATA=1;                           //释放数据总线
  temp_h=val;
  val=0;
 ////低8位/////////////////////////////
  DATA=1;                           //释放数据总线
  for (i=0x80;i>0;i/=2)             //位移8位
  { 
    SCK=1;                          //上升沿读入
    if (DATA) val=(val | i);        //确定值  
    SCK=0;             
  }
  DATA=1;//0;                       //不需要应答 通过CPU下拉为应答
  SCK=1;                            //第9个脉冲
  _nop_(); _nop_(); _nop_();          //pulswith approx. 5 us 
  SCK=0;                
  DATA=1;                           //释放数据总线
  temp_LL=val;
  return val ;
}
////////////




char write(unsigned char value) //写一个字节 返回应答信号
//---------------------------------------------------------
{ 
  unsigned char i ;
  ack=0;  
  for (i=0x80;i>0;i/=2)             //释放数据总线
  { if (i & value) DATA=1;          //写入值
    else DATA=0;                        
    SCK=1;                          //上升沿写入
     _nop_(); _nop_(); _nop_();        //延时  
    SCK=0;
  }
  DATA=1;                           //释放数据总线
  SCK=1;                            //第9个脉冲
  if  (DATA==1) ack=1;        //读应答信号
  SCK=0;        
  return ack;                     //error=1 表示没有应答
}
////////


void start_sht11(void)  //启动
//--------------------------------------------------------
{  
   DATA=1; SCK=0;                   //数据为1,SCK=0
   _nop_();
   SCK=1;                          //第一个脉冲
   _nop_();
   DATA=0;                         //数据跌落
   _nop_ ();
   SCK=0;                         //完成一个脉冲
   _nop_(); _nop_(); _nop_();
   SCK=1;                         //再一个脉冲
   _nop_();
   DATA=1;                        //数据变为1       
   _nop_();
   SCK=0;                         //完成该脉冲       
}
//////////////////////////////////
void sht_rest(void)  //复位 
{  
  unsigned char i; 
  DATA=1; SCK=0;                    //数据为1 时钟为0
  for(i=0;i<9;i++)                  //9 个脉冲为 复位
  { SCK=1;
    SCK=0;
  }
  start_sht11();                   //启动
}


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




//测量温度或者是温度,返回校验值
void convert_data(unsigned char ml)
{ 
   unsigned int i;
   start_sht11();                   //启动
   write(ml);//写入测温度
  if(ack==1) 
  {
    sht_rest() ;//复位
        write(ml);//写入测温度
    }  
  for (i=0;i<55535;i++){ if(DATA==0) break; }
   read();//读温度
}




/////////湿度采集处理//////


void get_humidata(void)
{
    error=0;
    ack=0;
      sht_rest() ;      //复位
     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%");        //初始显示内容
  Timer_Init();      //定时器初始化
  while(1)
    {  
    if(updat)       //数更新
    {
      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);
    }
     } 
}
如果需要仿真程序和源文件可以发送“51单片机湿度检测”获取相应的下载链接。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 传感器
    +关注

    关注

    2526

    文章

    48093

    浏览量

    740051
  • 转换器
    +关注

    关注

    27

    文章

    8206

    浏览量

    141805
  • 仿真
    +关注

    关注

    50

    文章

    3872

    浏览量

    132158
  • 51单片机
    +关注

    关注

    269

    文章

    5649

    浏览量

    120700
  • 程序
    +关注

    关注

    114

    文章

    3631

    浏览量

    79541
收藏 人收藏

    评论

    相关推荐

    基于51单片机的SHT11温湿度监测系统,LCD1602显示,上下限按键设置

    40; } 资源内容 (1)基于51单片机和SHT11的温湿度监控系统仿真毕设论文完整版; (2)Proteus仿真文件; (3)Kei
    发表于 03-26 17:44

    基于51单片机的数字湿度计的仿真设计

    本帖最后由 eehome 于 2013-1-5 09:48 编辑   求基于单片机的数字湿度计的仿真设计电路图和程序,proteus绘图,结合keil
    发表于 05-22 22:39

    基于单片机的远程温湿度监测系统。(有报酬)

    基于单片机的远程温湿度监测系统。单片机监测温湿度,在LCD上面显示出来。用zigbee再把温湿度
    发表于 05-14 16:26

    基于51单片机的温湿度监测系统

    基于51单片机的温湿度监测系统,具体功能:1、LCD1602液晶第一行显示当前的烟雾值,第二行显示当前的温度和湿度值;2、可以设置烟雾、温
    发表于 07-20 07:38

    基于单片机仓库温湿度监测报警系统仿真设计的相关资料分享

    045【毕设课设】基于单片机仓库温湿度监测报警系统仿真设计,温湿度监测报警系统,可以通过按键设定
    发表于 11-10 08:16

    基于单片机的温度监测仿真电路

    基于单片机的温度监测仿真电路主要包括DS18B20温度采集电路、LCD温度显示电路、蜂鸣器LED灯报警电路和按键切换电路等。具体功能如下:1、烧录程序后,
    发表于 11-18 06:33

    使用C51单片机和Proteus仿真设计远程仓库湿度监测系统的应用实例

    本文档的主要内容详细介绍的是使用C51单片机和Proteus仿真设计远程仓库湿度监测系统的应用实例资料合集免费下载。
    发表于 05-21 08:00 13次下载
    使用C<b class='flag-5'>51</b><b class='flag-5'>单片机</b>和Proteus<b class='flag-5'>仿真</b>设计远程仓库<b class='flag-5'>湿度</b><b class='flag-5'>监测</b>系统的应用实例

    基于51单片机6264扩展内存仿真设计(proteus仿真+程序

    基于51单片机6264扩展内存仿真设计(proteus仿真+程序)(单片机原理及应用)-基于
    发表于 07-22 11:45 78次下载
    基于<b class='flag-5'>51</b><b class='flag-5'>单片机</b>6264扩展内存<b class='flag-5'>仿真</b>设计(proteus<b class='flag-5'>仿真</b>+<b class='flag-5'>程序</b>)

    基于51单片机的智能温控器设计包含源程序仿真

    基于51单片机的智能温控器设计包含源程序仿真(手把手教你学单片机)-基于51
    发表于 07-22 14:56 87次下载
    基于<b class='flag-5'>51</b><b class='flag-5'>单片机</b>的智能温控器设计包含源<b class='flag-5'>程序</b>及<b class='flag-5'>仿真</b>

    基于51单片机的智能温控器设计(包含源程序仿真

    基于51单片机的智能温控器设计(包含源程序仿真)(单片机课程设计)-基于51
    发表于 07-22 15:02 136次下载
    基于<b class='flag-5'>51</b><b class='flag-5'>单片机</b>的智能温控器设计(包含源<b class='flag-5'>程序</b>及<b class='flag-5'>仿真</b>)

    基于51单片机的货车超重监测系统仿真设计资料

    基于51单片机的货车超重监测系统仿真设计资料
    发表于 10-25 10:33 4次下载

    基于51单片机的远程仓库湿度监测系统仿真设计资料包

    基于51单片机的远程仓库湿度监测系统仿真设计资料包
    发表于 10-25 10:37 1次下载

    51单片机如何跳出wile循环_51单片机竞赛设计44例全部带proteus仿真+程序

    51单片机如何跳出wile循环_51单片机竞赛设计44例全部带proteus仿真+程序
    发表于 11-21 13:06 63次下载
    <b class='flag-5'>51</b><b class='flag-5'>单片机</b>如何跳出wile循环_<b class='flag-5'>51</b><b class='flag-5'>单片机</b>竞赛设计44例全部带proteus<b class='flag-5'>仿真</b>+<b class='flag-5'>程序</b>

    基于51单片机的甲烷监测系统Proteus仿真

    基于51单片机的甲烷监测系统Proteus仿真
    发表于 12-27 09:47 19次下载

    分享一个基于51单片机湿度监测仿真程序

    仿真所用的湿度传感器为SHT11。SHT11是瑞士Scnsirion公司推出的一款数字温湿度传感器芯片。该芯片广泛应用于暖通空调、汽车、消费电子、自动控制等领域。
    发表于 07-05 09:55 445次阅读
    分享一个基于<b class='flag-5'>51</b><b class='flag-5'>单片机</b>的<b class='flag-5'>湿度</b><b class='flag-5'>监测</b><b class='flag-5'>仿真</b>和<b class='flag-5'>程序</b>