找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 22925|回复: 25
收起左侧

SHT11温湿度传感器的proteus仿真与程序源码

  [复制链接]
ID:344131 发表于 2018-6-3 18:48 | 显示全部楼层 |阅读模式
我最近做项目,接触到了sht11温湿度传感器,分享给大家

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
51hei.png
0.png 0.png

单片机源程序如下:
  1. /***********************************************************************************
  2. ;功能说明:DHT90与LCD1602的温湿度显示
  3. ;文件名称:DHT90.c   

  4. ;微处理器:AT89S52
  5. ;编译环境:Keil uVision V2.38a

  6. ;作    者:Huang Yanxiang
  7. ;版    权:(c)Huang Yanxiang
  8. ;创建日期:2008.08.15   
  9. ;版    本:V1.2  
  10. ;修改日期:2008.08.26
  11. ;修改说明:添加了一个LCD_disp_str()函数,修改了延时函数的注释。(感谢ouravr的网友wyb4993的提醒)
  12. ;***********************************************************************************/

  13. /*************定义接口********************
  14.          P0------DB0~DB7  (LCD1602)     
  15.          P2.0------RS      (LCD1602)
  16.          P2.1------RW      (LCD1602)
  17.          P2.2------E       (LCD1602)
  18.                  P2.6------SCK     (DHT90)
  19.                  P2.7------DATA    (DHT90)
  20. *****************************************/

  21. #include <reg52.h>
  22. #include <intrins.h>
  23. #include <math.h>    //Keil library   
  24. #include <stdio.h>   //Keil library

  25. //*********************第一部分LCD1602设置 START****************************************
  26. #define LCD_DB        P0
  27.         sbit         LCD_RS=P2^0;   //P2^0是p2.0的意思;LCD_RS与P2.0等效起来,对LCD_RS 读写,就是对P2.0读写 好处在于LCD_RS含义直接明了,写程序多了就会知道有必要de
  28.         sbit         LCD_RW=P2^1;   //P2^1是p2.1的意思
  29.         sbit         LCD_E=P2^2;    //P2^2是p2.2的意思

  30. /******定义函数****************/
  31. #define uchar unsigned char
  32. #define uint unsigned int
  33. void LCD_init(void);                          //初始化函数
  34. void LCD_write_command(uchar command);        //写指令函数
  35. void LCD_write_data(uchar dat);               //写数据函数
  36. void LCD_disp_char(uchar x,uchar y,uchar dat);//在某个屏幕位置上显示一个字符,X(0-15),y(1-2)
  37. void LCD_disp_str(uchar x,uchar y,uchar *str); //LCD1602显示字符串函数
  38. void delay_n10us(uint n);                     //延时函数


  39. /*--------------------------------------
  40. ;模块名称:LCD_init();
  41. ;功    能:初始化LCD1602
  42. ;占用资源:--
  43. ;参数说明:--
  44. ;创建日期:2008.08.15
  45. ;版    本:FV1.0(函数版本Function Version)
  46. ;修改日期:--
  47. ;修改说明:--
  48. ;-------------------------------------*/
  49. void LCD_init(void)
  50. {
  51. delay_n10us(10);
  52. LCD_write_command(0x38);//设置8位格式,2行,5x7
  53. delay_n10us(10);
  54. LCD_write_command(0x0c);//整体显示,关光标,不闪烁
  55. delay_n10us(10);
  56. LCD_write_command(0x06);//设定输入方式,增量不移位
  57. delay_n10us(10);
  58. LCD_write_command(0x01);//清除屏幕显示
  59. delay_n10us(100);       //延时清屏,延时函数,延时约n个10us
  60. }


  61. /*--------------------------------------
  62. ;模块名称:LCD_write_command();
  63. ;功    能:LCD1602写指令函数
  64. ;占用资源: P2.0--RS(LCD_RS),P2.1--RW(LCD_RW),P2.2--E(LCD_E).
  65. ;参数说明:dat为写命令参数
  66. ;创建日期:2008.08.15
  67. ;版    本:FV1.0(函数版本Function Version)
  68. ;修改日期:--
  69. ;修改说明:--
  70. ;-------------------------------------*/
  71. void LCD_write_command(uchar dat)
  72. {
  73. delay_n10us(10);
  74. LCD_RS=0;         //指令
  75. LCD_RW=0;         //写入
  76. LCD_E=1;          //允许
  77. LCD_DB=dat;
  78. delay_n10us(10);  //实践证明,我的LCD1602上,用for循环1次就能完成普通写指令。
  79. LCD_E=0;
  80. delay_n10us(10);  //实践证明,我的LCD1602上,用for循环1次就能完成普通写指令。
  81. }


  82. /*--------------------------------------
  83. ;模块名称:LCD_write_data();
  84. ;功    能:LCD1602写数据函数
  85. ;占用资源: P2.0--RS(LCD_RS),P2.1--RW(LCD_RW),P2.2--E(LCD_E).
  86. ;参数说明:dat为写数据参数
  87. ;创建日期:2008.08.15
  88. ;版    本:FV1.0(函数版本Function Version)
  89. ;修改日期:--
  90. ;修改说明:--
  91. ;-------------------------------------*/
  92. void LCD_write_data(uchar dat)
  93. {
  94. delay_n10us(10);
  95. LCD_RS=1;          //数据
  96. LCD_RW=0;          //写入
  97. LCD_E=1;           //允许
  98. LCD_DB=dat;
  99. delay_n10us(10);
  100. LCD_E=0;
  101. delay_n10us(10);
  102. }


  103. /*--------------------------------------
  104. ;模块名称:LCD_disp_char();
  105. ;功    能:LCD1602显示一个字符函数,在某个屏幕位置上显示一个字符,X(0-15),y(1-2)。
  106. ;占用资源:--
  107. ;参数说明:X为1602的列值(取值范围是0-15),y为1602的行值(取值范围是1-2),dat为所要显示字符对应的地址参数。
  108. ;创建日期:2008.08.15
  109. ;版    本:FV1.0(函数版本Function Version)
  110. ;修改日期:--
  111. ;修改说明:--
  112. ;-------------------------------------*/
  113. void LCD_disp_char(uchar x,uchar y,uchar dat)
  114. {
  115.   uchar address;
  116.   if(y==1)
  117.          address=0x80+x;
  118.   else
  119.          address=0xc0+x;
  120.   LCD_write_command(address);
  121.   LCD_write_data(dat);
  122. }



  123. /*--------------------------------------
  124. ;模块名称:LCD_disp_str();
  125. ;功    能:LCD1602显示字符串函数,在某个屏幕起始位置{X(0-15),y(1-2)}上显示一个字符串。
  126. ;占用资源:--
  127. ;参数说明:X为1602的列值(取值范围是0-15),y为1602的行值(取值范围是1-2),str为所要显示字符串对应的指针参数。
  128. ;创建日期:2008.08.16
  129. ;版    本:FV1.0(函数版本Function Version)
  130. ;修改日期:--
  131. ;修改说明:--
  132. ;-------------------------------------*/
  133. void LCD_disp_str(uchar x,uchar y,uchar *str)
  134. {
  135.   uchar address;
  136.   if(y==1)
  137.          address=0x80+x;
  138.   else
  139.          address=0xc0+x;
  140.   LCD_write_command(address);
  141.   while(*str!='\0')
  142.   {
  143.     LCD_write_data(*str);   
  144.     str++;
  145.   }
  146. }


  147. /*--------------------------------------
  148. ;模块名称:delay_n10us();
  149. ;功    能:延时函数,延时约n个10us
  150. ;占用资源:--
  151. ;参数说明:--
  152. ;创建日期:2008.08.15
  153. ;版    本:FV1.1(函数版本Function Version)
  154. ;修改日期:2008.08.26
  155. ;修改说明:修改为较精确的延时函数,"_nop_()"延时1us@12M晶振
  156. ;-------------------------------------*/
  157. void delay_n10us(uint n)  //延时n个10us@12M晶振
  158. {      
  159.         uint i;           
  160.         for(i=n;i>0;i--)   
  161.         {
  162.         _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
  163.                 }
  164. }                                    

  165. //*********************第一部分LCD1602设置 END****************************************


  166. //*********************第二部分DHT90设置   START****************************************
  167. sbit SCK  = P2^6;      //定义通讯时钟端口
  168. sbit DATA = P2^7;      //定义通讯数据端口

  169. typedef union  
  170. { unsigned int i;      //定义了两个共用体
  171.   float f;
  172. } value;

  173. enum {TEMP,HUMI};      //TEMP=0,HUMI=1


  174. #define noACK 0             //用于判断是否结束通讯
  175. #define ACK   1             //结束数据传输
  176.                             //adr  command  r/w
  177. #define STATUS_REG_W 0x06   //000   0011    0
  178. #define STATUS_REG_R 0x07   //000   0011    1
  179. #define MEASURE_TEMP 0x03   //000   0001    1
  180. #define MEASURE_HUMI 0x05   //000   0010    1
  181. #define RESET        0x1e   //000   1111    0

  182. /****************定义函数****************/
  183. void s_transstart(void);               //启动传输函数
  184. void s_connectionreset(void);          //连接复位函数
  185. char s_write_byte(unsigned char value);//DHT90写函数
  186. char s_read_byte(unsigned char ack);   //DHT90读函数
  187. char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode);//测量温湿度函数
  188. void calc_dht90(float *p_humidity ,float *p_temperature);//温湿度补偿



  189. /*--------------------------------------
  190. ;模块名称:s_transstart();
  191. ;功    能:启动传输函数
  192. ;占用资源:--
  193. ;参数说明:--
  194. ;创建日期:2008.08.15
  195. ;版    本:FV1.0(函数版本Function Version)
  196. ;修改日期:--
  197. ;修改说明:--
  198. ;-------------------------------------*/  
  199. void s_transstart(void)
  200. // generates a transmission start  
  201. //       _____         ________
  202. // DATA:      |_______|
  203. //           ___     ___
  204. // SCK : ___|   |___|   |______
  205. {   
  206.    DATA=1; SCK=0;                   //Initial state
  207.    _nop_();
  208.    SCK=1;
  209.    _nop_();
  210.    DATA=0;
  211.    _nop_();
  212.    SCK=0;   
  213.    _nop_();_nop_();_nop_();
  214.    SCK=1;
  215.    _nop_();
  216.    DATA=1;        
  217.    _nop_();
  218.    SCK=0;        
  219. }

  220. /*--------------------------------------
  221. ;模块名称:s_connectionreset();
  222. ;功    能:连接复位函数
  223. ;占用资源:--
  224. ;参数说明:--
  225. ;创建日期:2008.08.15
  226. ;版    本:FV1.0(函数版本Function Version)
  227. ;修改日期:--
  228. ;修改说明:--
  229. ;-------------------------------------*/
  230. void s_connectionreset(void)
  231. // communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart
  232. //       _____________________________________________________         ________
  233. // DATA:                                                      |_______|
  234. //          _    _    _    _    _    _    _    _    _        ___     ___
  235. // SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______|   |___|   |______
  236. {   
  237.   unsigned char i;  
  238.   DATA=1; SCK=0;                    //Initial state
  239.   for(i=0;i<9;i++)                  //9 SCK cycles
  240.   {
  241.     SCK=1;
  242.     SCK=0;
  243.   }
  244.   s_transstart();                   //transmission start
  245. }


  246. /*--------------------------------------
  247. ;模块名称:s_write_byte();
  248. ;功    能:DHT90写函数
  249. ;占用资源:--
  250. ;参数说明:--
  251. ;创建日期:2008.08.15
  252. ;版    本:FV1.0(函数版本Function Version)
  253. ;修改日期:--
  254. ;修改说明:--
  255. ;-------------------------------------*/
  256. char s_write_byte(unsigned char value)
  257. //----------------------------------------------------------------------------------
  258. // writes a byte on the Sensibus and checks the acknowledge  
  259. {  
  260.   unsigned char i,error=0;   
  261.   for (i=0x80;i>0;i/=2)             //shift bit for masking
  262.   {  
  263.     if (i & value) DATA=1;          //masking value with i , write to SENSI-BUS
  264.     else DATA=0;                        
  265.     SCK=1;                          //clk for SENSI-BUS
  266.     _nop_();_nop_();_nop_();        //pulswith approx. 3 us     
  267.     SCK=0;
  268.   }
  269.   DATA=1;                           //release DATA-line
  270.   SCK=1;                            //clk #9 for ack  
  271.   error=DATA;                       //check ack (DATA will be pulled down by DHT90),DATA在第9个上升沿将被DHT90自动下拉为低电平。
  272.   _nop_();_nop_();_nop_();
  273.   SCK=0;
  274.   DATA=1;                           //release DATA-line
  275.   return error;                     //error=1 in case of no acknowledge //返回:0成功,1失败
  276. }


  277. /*--------------------------------------
  278. ;模块名称:s_read_byte();
  279. ;功    能:DHT11读函数
  280. ;占用资源:--
  281. ;参数说明:--
  282. ;创建日期:2008.08.15
  283. ;版    本:FV1.0(函数版本Function Version)
  284. ;修改日期:--
  285. ;修改说明:--
  286. ;-------------------------------------*/
  287. char s_read_byte(unsigned char ack)  
  288. // reads a byte form the Sensibus and gives an acknowledge in case of "ack=1"  
  289. {  
  290.   unsigned char i,val=0;
  291.   DATA=1;                           //release DATA-line
  292.   for (i=0x80;i>0;i/=2)             //shift bit for masking
  293.   { SCK=1;                          //clk for SENSI-BUS
  294.     if (DATA) val=(val | i);        //read bit   
  295.         _nop_();_nop_();_nop_();        //pulswith approx. 3 us
  296.     SCK=0;              
  297.   }
  298.   if(ack==1)DATA=0;                 //in case of "ack==1" pull down DATA-Line
  299.   else DATA=1;                      //如果是校验(ack==0),读取完后结束通讯
  300.   _nop_();_nop_();_nop_();          //pulswith approx. 3 us
  301.   SCK=1;                            //clk #9 for ack
  302.   _nop_();_nop_();_nop_();          //pulswith approx. 3 us  
  303.   SCK=0;                 
  304.   _nop_();_nop_();_nop_();          //pulswith approx. 3 us
  305.   DATA=1;                           //release DATA-line
  306.   return val;
  307. }




  308. /*--------------------------------------
  309. ;模块名称:s_measure();
  310. ;功    能:测量温湿度函数
  311. ;占用资源:--
  312. ;参数说明:--
  313. ;创建日期:2008.08.15
  314. ;版    本:FV1.0(函数版本Function Version)
  315. ;修改日期:--
  316. ;修改说明:--
  317. ;-------------------------------------*/
  318. char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode)
  319. // makes a measurement (humidity/temperature) with checksum
  320. {  
  321.   unsigned error=0;
  322.   unsigned int i;

  323.   s_transstart();                   //transmission start
  324.   switch(mode){                     //send command to sensor
  325.     case TEMP  : error+=s_write_byte(MEASURE_TEMP); break;
  326.     case HUMI  : error+=s_write_byte(MEASURE_HUMI); break;
  327.     default     : break;   
  328.   }
  329.   for (i=0;i<65535;i++) if(DATA==0) break; //wait until sensor has finished the measurement
  330.   if(DATA) error+=1;                // or timeout (~2 sec.) is reached
  331.   *(p_value)  =s_read_byte(ACK);    //read the first byte (MSB)
  332.   *(p_value+1)=s_read_byte(ACK);    //read the second byte (LSB)
  333.   *p_checksum =s_read_byte(noACK);  //read checksum
  334.   return error;
  335. }


  336. /*--------------------------------------
  337. ;模块名称:calc_dht90();
  338. ;功    能:温湿度补偿函数
  339. ;占用资源:--
  340. ;参数说明:--
  341. ;创建日期:2008.08.15
  342. ;版    本:FV1.0(函数版本Function Version)
  343. ;修改日期:--
  344. ;修改说明:--
  345. ;-------------------------------------*/
  346. void calc_dht90(float *p_humidity ,float *p_temperature)
  347. // calculates temperature [C] and humidity [%RH]
  348. // input :  humi [Ticks] (12 bit)
  349. //          temp [Ticks] (14 bit)
  350. // output:  humi [%RH]
  351. //          temp [C]
  352. { const float C1=-4.0;              // for 12 Bit
  353.   const float C2=+0.0405;           // for 12 Bit
  354.   const float C3=-0.0000028;        // for 12 Bit
  355.   const float T1=+0.01;             // for 14 Bit @ 5V
  356.   const float T2=+0.00008;           // for 14 Bit @ 5V

  357.   float rh=*p_humidity;             // rh:      Humidity [Ticks] 12 Bit
  358.   float t=*p_temperature;           // t:       Temperature [Ticks] 14 Bit
  359.   float rh_lin;                     // rh_lin:  Humidity linear
  360.   float rh_true;                    // rh_true: Temperature compensated humidity
  361.   float t_C;                        // t_C   :  Temperature [C]

  362.   t_C=t*0.01 - 40;                  //calc. temperature from ticks to [C]
  363.   rh_lin=C3*rh*rh + C2*rh + C1;     //calc. humidity from ticks to [%RH]
  364.   rh_true=(t_C-25)*(T1+T2*rh)+rh_lin-3;   //calc. temperature compensated humidity [%RH]
  365.   if(rh_true>100)rh_true=100;       //cut if the value is outside of
  366.   if(rh_true<0.1)rh_true=0.1;       //the physical possible range

  367.   *p_temperature=t_C;               //return temperature [C]
  368.   *p_humidity=rh_true;              //return humidity[%RH]
  369. }




  370. //*********************第二部分DHT90设置   END****************************************

  371. //*********主函数*****************
  372. void main(void)
  373. {
  374.                 value humi_val,temp_val;
  375.         unsigned char error,checksum;
  376.         unsigned int wendu,shidu;
  377.         LCD_init();        
  378.         s_connectionreset();
  379.         LCD_disp_str(0,1,"TE");
  380.                 LCD_disp_str(0,2,"RH");


  381. //*********初始化温度显示区*********
  382.         LCD_disp_str(2,1,"TTT.TC");

  383. //*********初始化湿度显示区*********
  384.         LCD_disp_str(2,2,"RRR.R%");

  385.         delay_n10us(20000);     //延时0.2s

  386.         while(1)
  387.         { error=0;
  388.           error+=s_measure((unsigned char*) &humi_val.i,&checksum,HUMI);  //measure humidity
  389.           error+=s_measure((unsigned char*) &temp_val.i,&checksum,TEMP);  //measure temperature
  390.           if(error!=0) s_connectionreset();                 //in case of an error: connection reset
  391.           else
  392.           { humi_val.f=(float)humi_val.i;                   //converts integer to float
  393.             temp_val.f=(float)temp_val.i;                   //converts integer to float
  394.             calc_dht90(&humi_val.f,&temp_val.f);            //calculate humidity, temperature
  395.                         wendu=10*temp_val.f;
  396.                         LCD_disp_char(2,1,wendu/1000+'0');              //显示温度百位
  397.             LCD_disp_char(3,1,(wendu%1000)/100+'0');        //显示温度十位
  398.             LCD_disp_char(4,1,(wendu%100)/10+'0');          //显示温度个位
  399.                         LCD_disp_char(6,1,(wendu%10)+'0');              //显示温度小数点后第一位

  400.                         shidu=10*humi_val.f;
  401.                         LCD_disp_char(2,2,shidu/1000+'0');               //显示湿度百位
  402.             LCD_disp_char(3,2,(shidu%1000)/100+'0');         //显示湿度十位
  403.             LCD_disp_char(4,2,(shidu%100)/10+'0');           //显示湿度个位
  404.                         LCD_disp_char(6,2,(shidu%10)+'0');               //显示湿度小数点后第一位
  405.           }
  406.           //----------wait approx. 0.8s to avoid heating up SHTxx------------------------------      
  407.                   delay_n10us(80000);                                //延时约0.8s
  408.         }
  409. }
复制代码

所有资料51hei提供下载:
sth11.zip (79.36 KB, 下载次数: 795)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:562801 发表于 2019-6-17 21:32 | 显示全部楼层
为什么我下载了打不开dsn文件啊?
回复

使用道具 举报

ID:328014 发表于 2019-6-17 21:35 | 显示全部楼层
llh0303 发表于 2019-6-17 21:32
为什么我下载了打不开dsn文件啊?

因为你Proteus版本太高了,这个dns只能用7.8以下的版本,我刚用Proteus7.5成功打开了
回复

使用道具 举报

ID:332241 发表于 2018-6-13 09:40 | 显示全部楼层
具体实现什么功能?麻烦说一下
谢谢
回复

使用道具 举报

ID:354942 发表于 2018-6-20 10:34 | 显示全部楼层
具体能实现什么功能呢?????
回复

使用道具 举报

ID:239427 发表于 2018-9-30 21:05 | 显示全部楼层
谢谢,试试
回复

使用道具 举报

ID:435643 发表于 2018-12-4 23:26 | 显示全部楼层
非常好的SHT11仿真!
回复

使用道具 举报

ID:120108 发表于 2019-1-9 10:24 | 显示全部楼层
谢谢 有用的资料
回复

使用道具 举报

ID:351608 发表于 2019-4-8 06:58 来自手机 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

ID:191910 发表于 2019-4-17 17:12 | 显示全部楼层
下来学习一下,这精度不大高啊
回复

使用道具 举报

ID:503018 发表于 2019-5-11 15:55 | 显示全部楼层
具体实现什么功能?麻烦说一下 谢谢
回复

使用道具 举报

ID:553060 发表于 2019-6-2 16:18 | 显示全部楼层
JohnnyYue 发表于 2018-6-13 09:40
具体实现什么功能?麻烦说一下
谢谢

应该是用来模拟检测温湿度并用LCD显示出来
回复

使用道具 举报

ID:553060 发表于 2019-6-2 16:19 | 显示全部楼层
ycl 发表于 2018-6-20 10:34
具体能实现什么功能呢?????

应该是用来模拟传感器检测环境的温湿度并用LCD显示读数
回复

使用道具 举报

ID:553060 发表于 2019-6-2 16:40 | 显示全部楼层
很有用
回复

使用道具 举报

ID:530333 发表于 2019-6-3 08:44 来自手机 | 显示全部楼层
液晶屏
回复

使用道具 举报

ID:366617 发表于 2019-6-3 13:42 | 显示全部楼层
不错不错,参考一下
回复

使用道具 举报

ID:579428 发表于 2019-7-7 16:14 | 显示全部楼层
这个是DHT90的程序,图中的是SHT10,标题是SHT11.我有点不明白,可以麻烦大佬们解释一下么
回复

使用道具 举报

ID:663131 发表于 2019-12-13 14:40 来自手机 | 显示全部楼层
怎么加一个电机去检测温湿度
回复

使用道具 举报

ID:714117 发表于 2020-3-23 15:52 | 显示全部楼层
谢谢分享,先看看
回复

使用道具 举报

ID:239620 发表于 2020-5-26 16:03 | 显示全部楼层
谢谢分享,下载下来学习一下
回复

使用道具 举报

ID:116607 发表于 2020-6-11 09:16 | 显示全部楼层
刚好要用到,谢谢分享啊
回复

使用道具 举报

ID:790170 发表于 2020-6-27 21:44 | 显示全部楼层
谢谢分享,好好学习一下
回复

使用道具 举报

ID:615183 发表于 2020-6-29 11:43 | 显示全部楼层
谢谢楼主提供的资料,非常有用!帮助了我的学习!
回复

使用道具 举报

ID:935717 发表于 2021-6-9 21:56 | 显示全部楼层
为什么电路都是一样的就是仿真不了
回复

使用道具 举报

ID:849985 发表于 2021-6-19 09:13 | 显示全部楼层
这个可以控制温度吗
回复

使用道具 举报

ID:1015563 发表于 2022-4-4 12:49 | 显示全部楼层
有没有程序的流程图
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表