找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3374|回复: 11
收起左侧

温湿度采集和测量系统的Proteus仿真(基于STC89C51+STH11+LCD1602)

  [复制链接]
ID:1002955 发表于 2022-3-15 11:09 | 显示全部楼层 |阅读模式
一、设计的技术要求:



    温湿度测量系统的软件部分是以Keil为开发平台,C语言为软件系统的开发语言,同时采用模块化编程。具体分为以下几个部分:主控制、温湿度采集程序、温湿度数据处理程序、LCD显示程序、按键设置程序和LED,蜂鸣器报警程序。系统通过SHT11温湿度传感器感应周围的环境的温度和湿度,通过单片机对采集到的数据进行读取处理,经过LCD1602显示模块实时显示温湿度数据,同时可以通过按键模块对温湿度报警上、下限值进行设定。当SHT11读取的温湿度值不在设定范围内时,报警模块LED灯指示故障信息,同时蜂鸣器报警;当温湿度读取数据正常后,LED灯熄灭,蜂鸣器关闭。

实现功能1:(SHT11读取处理+LCD1602显示模块
实现功能2按键模块对温湿度报警上、下限值进行设定。
实现功能3SHT11读取的温湿度值不在设定范围内时,报警模块LED灯指示故障信息,同时蜂鸣器报警;当温湿度读取数据正常后,LED灯熄灭,蜂鸣器关闭。



四、代码

  1. /***********************************************************************************
  2. ;功能说明:SHT11和STC89C51温湿度采集和测量系统的Proteus仿真
  3. ;文件名称:DU.c   
  4. ;版本号:v1.0.0  
  5. ;微处理器:STC89C51
  6. ;编译环境:Keil uVision V4.10
  7. ;作    者:Cui Xinghai
  8. ;创建日期:2022.2.24   
  9. ;***********************************************************************************/

  10. /*************定义接口********************
  11.          P0------DB0~DB7  (LCD1602)     
  12.          P2.0------RS      (LCD1602)
  13.          P2.1------RW      (LCD1602)
  14.          P2.2------E       (LCD1602)

  15.                  P2.6------SCK     (STH11)
  16.                  P2.7------DATA    (STH11)

  17.                  P1.5------SET     //定义调整键
  18.                  P1.6------ADD           //定义增加键
  19.                  P1.7------DEC     //定义减少键
  20.          P3.7------ESC     //定义退出键
  21.                  P1.4------BEEP    //定义蜂鸣器

  22.                  P1.0------t_green                     //温度过低灯
  23.                  P1.1------t_red                     //温度过高灯
  24.                  P1.2------rh_green                     //湿度过低灯
  25.                  P1.3------rh_red                     //湿度过高灯
  26. *****************************************/

  27. #include <reg52.h>         
  28. #include <intrins.h> //应用于程序设计,一般出C51单片机编程中,一般程序中需要使用到空指令_nop_();字符循环移位指令_crol_等时使用。
  29. #include <math.h>    //Keil library   
  30. #include <stdio.h>   //Keil library


  31. //*********************第一部分LCD1602设置 START****************************************
  32. #define      LCD_DB P0             //Data Bus数据总线,我们这里要做 1602 液晶的程序,因此先把用到的总线接口做一个统一声明
  33. sbit         LCD_RS=P2^0;   
  34. sbit         LCD_RW=P2^1;   
  35. sbit         LCD_E =P2^2;  
  36.                   
  37. /******定义函数****************/
  38. #define uchar unsigned char
  39. #define uint unsigned int

  40. void LCD_init(void);                           //初始化函数
  41. void LCD_write_command(uchar command);         //写指令函数
  42. void LCD_write_data(uchar dat);                //写数据函数
  43. void LCD_disp_char(uchar x,uchar y,uchar dat); //在某个屏幕位置上显示一个字符,X(0-15),y(1-2)
  44. void LCD_disp_str(uchar x,uchar y,uchar *str); //LCD1602显示字符串函数
  45. void delay_n10us(uint n);                      //延时函数

  46. /*--------------------------------------
  47. ;模块名称:LCD_init();
  48. ;功    能:初始化LCD1602
  49. ;-------------------------------------*/
  50. void LCD_init(void)                //括号中的void意思该函数的参数为空
  51. {
  52. delay_n10us(10);
  53. LCD_write_command(0x38);//指令6:工作方式设置指令,0x0011 1000设置8位格式数据接口,16*2行显示,5x7点阵
  54. delay_n10us(10);
  55. LCD_write_command(0x0c);//指令4:
  56.                                                 //整体显示,关光标,不闪烁,BCD0x00001 100
  57.                                                 //整体显示,开光标,  闪烁,BCD0x00001 111
  58. delay_n10us(10);
  59. LCD_write_command(0x06);//指令3:设定输入方式增量不移位,    0x00000110
  60. delay_n10us(10);
  61. LCD_write_command(0x01);//指令1:清除屏幕显示,光标复位到地址00H位置
  62. delay_n10us(100);       //延时清屏,延时函数,延时约n个10us
  63. }


  64. /*--------------------------------------
  65. ;模块名称:LCD_write_command();
  66. ;功    能:LCD1602写指令函数
  67. ;占用资源: P2.0--RS(LCD_RS),P2.1--RW(LCD_RW),P2.2--E(LCD_E).
  68. ;参数说明:dat为写命令参数
  69. ;-------------------------------------*/
  70. void LCD_write_command(uchar dat)
  71. {
  72. delay_n10us(10);
  73. LCD_RS=0;         //指令
  74. LCD_RW=0;         //写入
  75. LCD_E=1;          //允许
  76. LCD_DB=dat;
  77. delay_n10us(10);  //实践证明,我的LCD1602上,用for循环1次就能完成普通写指令。
  78. LCD_E=0;                  //读完撤销使能,防止液晶输出数据干扰 P0 总线
  79. delay_n10us(10);  //实践证明,LCD1602上,用for循环1次就能完成普通写指令。
  80. }


  81. /*--------------------------------------
  82. ;模块名称:LCD_write_data();
  83. ;功    能:LCD1602写数据函数
  84. ;占用资源: P2.0--RS(LCD_RS),P2.1--RW(LCD_RW),P2.2--E(LCD_E).
  85. ;参数说明:dat为写数据参数
  86. ;-------------------------------------*/
  87. void LCD_write_data(uchar dat)
  88. {
  89. delay_n10us(10);
  90. LCD_RS=1;          //数据
  91. LCD_RW=0;          //写入
  92. LCD_E=1;           //允许
  93. LCD_DB=dat;
  94. delay_n10us(10);
  95. LCD_E=0;
  96. delay_n10us(10);
  97. }


  98. /*--------------------------------------
  99. ;模块名称:LCD_disp_char();
  100. ;功    能:光标位置,LCD1602显示一个字符函数,在某个屏幕位置上显示一个字符,X(0-15),y(1-2)。
  101. ;参数说明:X为1602的列值(取值范围是0-15),y为1602的行值(取值范围是1-2),dat为所要显示字符对应的地址参数。
  102. ;-------------------------------------*/
  103. void LCD_disp_char(uchar x,uchar y,uchar dat)
  104. {
  105.   uchar address;
  106.   if(y==1)                                 //0x80和00H的区别:指令7
  107.          address=0x80+x; //二进制码中第一行首地址为10000000转换16进制为0x80,第二行首地址为11000000转换16进制为0xC0 加首地址是为了让LCD显示从第一位开始显示。
  108.   else
  109.          address=0xc0+x;
  110.   LCD_write_command(address);
  111.   LCD_write_data(dat);
  112. }



  113. /*--------------------------------------
  114. ;模块名称:LCD_disp_str();
  115. ;功    能:LCD1602显示字符串函数,在某个屏幕起始位置{X(0-15),y(1-2)}上显示一个字符串。
  116. ;参数说明:X为1602的列值(取值范围是0-15),y为1602的行值(取值范围是1-2),str为所要显示字符串对应的指针参数。
  117. ;-------------------------------------*/
  118. void LCD_disp_str(uchar x,uchar y,uchar *str)
  119. {
  120.   uchar address;
  121.   if(y==1)
  122.          address=0x80+x;
  123.   else
  124.          address=0xc0+x;
  125.   LCD_write_command(address);  //连续写入字符串数据,直到检测到结束符
  126.   while(*str!='\0')
  127.   {
  128.     LCD_write_data(*str);      //另外一种写法LCD_write_data(*str++)这行语句中对指针 str 的操作大家一定要理解透彻,先把 str指向的数据取出来用,然后 str 再加 1 以指向下一个数据,这是非常常用的一种简写方式
  129.     str++;
  130.   }
  131. }


  132. /*--------------------------------------
  133. ;模块名称:delay_n10us();
  134. ;功    能:延时函数,延时约n个10us
  135. ;修改日期:2022.02.26
  136. ;修改说明:修改为较精确的延时函数,"_nop_()"延时1us@12M晶振,代表运行一个机器周期。如果这个单片机的晶振是12M的,那么这调代码会运行1US;
  137. ;-------------------------------------*/
  138. void delay_n10us(uint n)  //延时n个10us@12M晶振
  139. {      
  140.         uint i;           
  141.         for(i=n;i>0;i--)   
  142.         {
  143.         _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
  144.                 }
  145. }                                    
  146. //*********************第一部分LCD1602设置 END****************************************



  147. //*********************第二部分SHT11设置   START****************************************
  148. sbit SCK  = P2^6;      //定义通讯时钟端口
  149. sbit DATA = P2^7;      //定义通讯数据端口

  150. typedef union                     //定义了两个共用体:如果没有typedef那么就是普通的定义了匿名联合的一个变量value.加了typedef后, 定义的就是类型别名, 当类型一样用
  151. {
  152. unsigned int i;        //i表示测量得到的温湿度数据(int 形式保存的数据)
  153.   float f;                            //f表示测量得到的温湿度数据(float 形式保存的数据)
  154. } value;

  155. enum {TEMP,HUMI};      //enum 枚举名 {枚举元素1,枚举元素2,……};TEMP=0,HUMI=1        枚举


  156. #define noACK        0      //用于判断是否结束通讯
  157. #define ACK          1      //结束数据传输
  158.                             //adr  command  r/w
  159. #define STATUS_REG_W 0x06   //000   0011    0
  160. #define STATUS_REG_R 0x07   //000   0011    1
  161. #define MEASURE_TEMP 0x03   //000   0001    1
  162. #define MEASURE_HUMI 0x05   //000   0010    1
  163. #define RESET        0x1e   //000   1111    0

  164. /****************定义函数****************/
  165. void s_transstart(void);               //启动传输函数
  166. void s_connectionreset(void);          //连接复位函数
  167. char s_write_byte(unsigned char value);//写函数
  168. char s_read_byte(unsigned char ack);   //读函数
  169. char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode);//测量温湿度函数
  170. void calc_SHT11(float *p_humidity ,float *p_temperature);//温湿度补偿



  171. /*--------------------------------------
  172. ;模块名称:s_transstart();
  173. ;功    能:启动传输函数
  174. ;-------------------------------------*/  
  175. void s_transstart(void)
  176. // generates a transmission start (SHT11发送命令,启动传输时序)  
  177. //       _____         ________
  178. // DATA:      |_______|
  179. //           ___     ___
  180. // SCK : ___|   |___|   |______
  181. {   
  182.    DATA=1; SCK=0;                   //Initial state
  183.    _nop_();
  184.    SCK=1;
  185.    _nop_();
  186.    DATA=0;
  187.    _nop_();
  188.    SCK=0;   
  189.    _nop_();_nop_();_nop_();
  190.    SCK=1;
  191.    _nop_();
  192.    DATA=1;        
  193.    _nop_();
  194.    SCK=0;        
  195. }

  196. /*--------------------------------------
  197. ;模块名称:s_connectionreset();
  198. ;功    能:连接复位函数
  199. ;-------------------------------------*/
  200. void s_connectionreset(void)
  201. // 通讯复位时序:如果与 SHT11 通讯中断,下列信号时序可以复位串口:DATA 保持高电平时,触发 SCK 时钟 9 次或更多。
  202. //       _____________________________________________________         ________
  203. // DATA:                                                      |_______|
  204. //          _    _    _    _    _    _    _    _    _        ___     ___
  205. // SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______|   |___|   |______
  206. {   
  207.   unsigned char i;  
  208.   DATA=1; SCK=0;                    //Initial state
  209.   for(i=0;i<9;i++)                  //9 SCK cycles,DATA保持高,SCK时钟触发9次,发送启动传输,通迅即复位
  210.   {
  211.     SCK=1;
  212.     SCK=0;
  213.   }
  214.   s_transstart();                   //transmission start
  215. }


  216. /*--------------------------------------
  217. ;模块名称:s_write_byte();
  218. ;功    能:SHT11写函数                                                
  219. ;-------------------------------------*/
  220. char s_write_byte(unsigned char value)
  221. //----------------------------------------------------------------------------------
  222. // 写入一个字节,并检查确认
  223. {  
  224.   unsigned char i,error=0;
  225.      
  226.   for (i=0x80;i>0;i/=2)             //0x1000 0000用于掩码的移位,高位为1,循环右移 https://zhidao.baidu.com/question/2144112204880805988.html
  227.   {  
  228.     if (i & value) DATA=1;          //和要发送的数相与,结果为发送的位
  229.               else DATA=0;                        
  230.     SCK=1;                           
  231.     _nop_();_nop_();_nop_();            
  232.     SCK=0;
  233.   }

  234.   DATA=1;                           //释放数据线
  235.   SCK=1;                            //clk #9 for ack  
  236.   error=DATA;                       //检查应答信号,确认通讯正常  
  237.   _nop_();_nop_();_nop_();
  238.   SCK=0;
  239.   DATA=1;                           //
  240.   return error;                     //error=1 in case of no acknowledge //返回:0成功,1失败
  241. }                        


  242. /*--------------------------------------
  243. ;模块名称:s_read_byte();
  244. ;功    能:SHT11读函数
  245. ;-------------------------------------*/
  246. char s_read_byte(unsigned char ack)   
  247. {  
  248.   unsigned char i,val=0;
  249.   DATA=1;                           //释放数据线
  250.   for (i=0x80;i>0;i/=2)              
  251.   {
  252.     SCK=1;                          //clk for SENSI-BUS
  253.     if (DATA) val=(val | i);        //读一位数据线的值   
  254.         _nop_();_nop_();_nop_();        //pulswith approx. 3 us
  255.     SCK=0;              
  256.   }
  257.   if(ack==1)DATA=0;                 //in case of "ack==1" pull down DATA-Line
  258.   else DATA=1;                      //如果是校验(ack==0),读取完后结束通讯
  259.   _nop_();_nop_();_nop_();          //pulswith approx. 3 us
  260.   SCK=1;                            //clk #9 for ack
  261.   _nop_();_nop_();_nop_();          //pulswith approx. 3 us  
  262.   SCK=0;                 
  263.   _nop_();_nop_();_nop_();          //pulswith approx. 3 us
  264.   DATA=1;                           //release DATA-line
  265.   return val;
  266. }




  267. /*--------------------------------------
  268. ;模块名称:s_measure();
  269. ;功    能:测量温湿度函数
  270. ;-------------------------------------*/
  271. char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode)
  272. // 进行温度或者湿度转换,由参数mode决定转换内容
  273. {  
  274.   unsigned error=0;
  275.   unsigned int i;

  276.   s_transstart();                   //transmission start

  277.   switch(mode){                     //选择发送命令
  278.     case TEMP  : error+=s_write_byte(MEASURE_TEMP); break;
  279.     case HUMI  : error+=s_write_byte(MEASURE_HUMI); break;
  280.     default     : break;   
  281.   }
  282.   for (i=0;i<65535;i++) if(DATA==0) break; //等待测量结束
  283.   if(DATA) error+=1;                // 如果长时间数据线没有拉低,说明测量错误
  284.   *(p_value)  =s_read_byte(ACK);    //读第一个字节,高字节 (MSB)
  285.   *(p_value+1)=s_read_byte(ACK);    //读第二个字节,低字节 (LSB)
  286.   *p_checksum =s_read_byte(noACK);  //read checksum
  287.    return error;
  288. }


  289. /*--------------------------------------
  290. ;模块名称:calc_SHT11();
  291. ;功    能:温湿度补偿函数
  292. ;备    注:SHT11湿度测量范围:0~100%RH;温度测量范围:-40~+123.8℃
  293. ;-------------------------------------*/
  294. void calc_SHT11(float *p_humidity ,float *p_temperature)
  295. // calculates temperature [C] and humidity [%RH]
  296. // input :  humi [Ticks] (12 bit)
  297. //          temp [Ticks] (14 bit)
  298. // output:  humi [%RH]
  299. //          temp [C]
  300.                                     //const表示常量,不允许修改里面的内容
  301. { const float C1=-4.0;              // 12位湿度精度 修正公式
  302.   const float C2=+0.0405;           // 12位湿度精度 修正公式
  303.   const float C3=-0.0000028;        // 12位湿度精度 修正公式
  304.   const float T1=+0.01;             // 14位温度精度 5V条件  修正公式
  305.   const float T2=+0.00008;          // 14位温度精度 5V条件  修正公式

  306.   float rh=*p_humidity;             // rh:      Humidity [Ticks] 12 Bit
  307.   float t=*p_temperature;           // t:       Temperature [Ticks] 14 Bit
  308.   float rh_lin;                     // rh_lin:  Humidity linear
  309.   float rh_true;                    // rh_true: Temperature compensated humidity
  310.   float t_C;                        // t_C   :  Temperature [C]

  311.   t_C=t*0.01 - 40;                  //补偿温度,14位温度精度 5V条件  修正公式
  312.   
  313.   rh_lin=C3*rh*rh + C2*rh + C1;     //相对湿度非线性补偿
  314.   rh_true=(t_C-25)*(T1+T2*rh)+rh_lin-3;   //相对湿度对于温度依赖性补偿

  315.   if(rh_true>100)rh_true=100;       //湿度最大修正
  316.   if(rh_true<0.1)rh_true=0.1;       //湿度最小修正

  317.   *p_temperature=t_C;               //返回温度结果
  318.   *p_humidity=rh_true;              //返回湿度结果
  319. }
  320. //*********************第二部分STH11设置   END****************************************


  321. //*********************第三部分报警设置   START****************************************
  322. #define N   0x00
  323. sbit SET =         P1^5;                   //定义调整键
  324. sbit ADD =        P1^6;                   //定义增加键
  325. sbit DEC =         P1^7;                   //定义减少键
  326. sbit ESC =  P3^7;                   //定义调整键
  327. sbit BEEP=  P1^4;                   //定义蜂鸣器

  328. sbit  t_green   =  P1^0;
  329. sbit  t_red     =  P1^1;
  330. sbit  rh_green  =  P1^2;
  331. sbit  rh_red    =  P1^3;

  332. int t_shangxian = 20;            //上限报警温度,默认值为 20C
  333. int t_xiaxian   = 10;            //下限报警温度,默认值为 10C
  334. int rh_shangxian= 50;            //上限报警湿度,默认值为50%
  335. int rh_xiaxian  = 40;            //下限报警湿度,默认值为40%

  336. uchar flag=0;


  337. /****************定义函数****************/
  338. void led_control( float *WENDU,  float *SHIDU);
  339. void key();
  340. void delay(uint j);
  341. /*--------------------------------------
  342. ;模块名称:led_control();
  343. ;功    能:LED状态控制
  344. ;-------------------------------------*/
  345. void led_control( float *WENDU,  float *SHIDU)                  
  346. {
  347. //温度过低报警指示
  348.   if(*WENDU <= t_xiaxian)    {t_green = 0;}
  349.   else {t_green=1;}
  350. //温度过高报警指示
  351.   if(*WENDU >= t_shangxian)  {t_red   = 0;}
  352.   else {t_red=1;}
  353. //湿度过低报警指示
  354.   if(*SHIDU <= rh_xiaxian)   {rh_green= 0;}
  355.   else {rh_green=1;}
  356. //湿度过高报警指示
  357.   if(*SHIDU >= rh_shangxian) {rh_red  = 0;}
  358.   else {rh_red=1;}
  359. //蜂鸣器警示
  360.   if(*WENDU <= t_xiaxian||*WENDU >= t_shangxian||*SHIDU <= rh_xiaxian||*SHIDU >= rh_shangxian)
  361.   {
  362.     BEEP = 0;
  363.   }
  364.   else
  365.   {
  366.     BEEP = 1;
  367.   }
  368. }

  369.            
  370. /*--------------------------------------
  371. ;模块名称:key();
  372. ;功    能:按键控制
  373. ;-------------------------------------*/
  374. void key()   
  375. {
  376. /****************设置键设置****************/
  377. if(SET == 0)
  378.   {
  379.     delay(50);               //按键消抖
  380.     if(SET == 0)
  381.      {
  382.       flag++;
  383.       if (flag==5)flag = 0;  //没有发生抖动
  384.           while(SET==0);         //若一直按下,循环

  385.     LCD_init();
  386.     s_connectionreset();     
  387.     LCD_disp_str(0,1,"TE:");
  388.     LCD_disp_str(0,2,"RH:");
  389.         LCD_disp_str(6,1,"-");
  390.         LCD_disp_str(6,2,"-");
  391.         LCD_disp_str(10,1,"C");
  392.         LCD_disp_str(10,2,"%");
  393.     delay_n10us(20);      
  394.     }

  395.   }
  396. //SHT11湿度测量范围:0~100%RH;温度测量范围:-40~+123.8℃;
  397. /****************温度下限设置****************/
  398.         if (flag==1)                                 
  399.      {
  400.       if(ADD==0)
  401.            {
  402.             delay(50);
  403.             t_xiaxian++;
  404.             if (t_xiaxian>(t_shangxian-1)) {t_xiaxian=(t_shangxian-1);}
  405.                 while(ADD==0);                                        //加上此句必须松按键才处理
  406.            }
  407.            if (DEC==0)
  408.            {
  409.             delay(50);                    
  410.             if(t_xiaxian<=-40)    {t_xiaxian=t_shangxian;}              //超过实际范围,重新赋值温度下限
  411.             else                                    t_xiaxian--;
  412.             while(DEC==0);                                        //加上此句必须松按键才处理
  413.            }
  414.        //温度下限显示
  415.                 LCD_disp_char(3,1,t_xiaxian/100+'0');                 //例如123/100=1
  416.                 LCD_disp_char(4,1,abs(t_xiaxian%100/10)+'0');         //例如123%100=23,23/10 =2 ,-12取绝对值12           
  417.         LCD_disp_char(5,1,abs(t_xiaxian%10)+'0');                           //例如123%10 =3
  418.         if(t_xiaxian<0)    {LCD_disp_str(12,2,"nega");}              //温度下限为负数,显示nega
  419.                  else                            {LCD_disp_str(12,2,"    ");}                  //去除负数提醒nega
  420.          }

  421. /****************温度上限设置****************/
  422.         if (flag==2)              
  423.           {
  424.            if(ADD==0)
  425.            {
  426.             delay(150);
  427.             t_shangxian++;
  428.             if (t_shangxian>123) {t_shangxian=123;}              //上限值达到最大值 123时,上限值保持为123
  429.             while(ADD==0);                                       //加上此句必须松按键才处理
  430.            }
  431.            if (DEC==0)
  432.            {
  433.             delay(150);
  434.             t_shangxian--;
  435.             if (t_shangxian<(t_xiaxian+1)) {t_shangxian=(t_xiaxian+1);}//确保设定的上限值不比下限低
  436.             while(DEC==0);                                       //加上此句必须松按键才处理
  437.            }
  438.        //温度上限显示
  439.                 LCD_disp_char(7,1,t_shangxian/100+'0');
  440.             LCD_disp_char(8,1,(t_shangxian%100)/10+'0');         
  441.             LCD_disp_char(9,1,(t_shangxian%10)+'0');      
  442.           }

  443. /****************湿度下限设置****************/
  444.         if (flag==3)            
  445.           {
  446.            if(ADD==0)
  447.            {
  448.             delay(150);
  449.             rh_xiaxian++;
  450.             if (rh_xiaxian>(rh_shangxian-1)) {rh_xiaxian=(rh_shangxian-1);}
  451.             while(ADD==0);                                      //加上此句必须松按键才处理
  452.            }
  453.            if (DEC==0)
  454.            {
  455.             delay(150);   
  456.             if (rh_xiaxian<=0) {rh_xiaxian=0;}                                        //下限值达到最小值0时,下限值保持为0
  457.             else rh_xiaxian--;
  458.             while(DEC==0);                                      //加上此句必须松按键才处理
  459.            }
  460.        //湿度下限显示
  461.                 LCD_disp_char(3,2,rh_xiaxian/100+'0');
  462.             LCD_disp_char(4,2,(rh_xiaxian%100)/10+'0');               
  463.             LCD_disp_char(5,2,(rh_xiaxian%10)+'0');
  464.           }


  465. /****************湿度上限设置****************/
  466.     if (flag==4)              
  467.           {
  468.            if(ADD==0)
  469.            {
  470.             delay(150);
  471.             rh_shangxian++;
  472.             if (rh_shangxian>99) {rh_shangxian=99;}            //上限值达到最大值 99时,上限值保持为 99
  473.             while(ADD==0);                                     //加上此句必须松按键才处理
  474.            }
  475.            if (DEC==0)
  476.            {
  477.             delay(150);
  478.             rh_shangxian--;
  479.             if (rh_shangxian<(rh_xiaxian+1)) {rh_shangxian=(rh_xiaxian+1);}//确保设定的上限值不比下限低
  480.             while(DEC==0);                                     //加上此句必须松按键才处理
  481.            }
  482.        //湿度上限显示
  483.                 LCD_disp_char(7,2,rh_shangxian/100+'0');         
  484.             LCD_disp_char(8,2,(rh_shangxian%100)/10+'0');         
  485.             LCD_disp_char(9,2,(rh_shangxian%10)+'0');     
  486.           }

  487. /****************退出键设置****************/                                             
  488. if(ESC==0)                     
  489. {                                          
  490.   delay(10);
  491.   if(ESC==0)
  492.     {           
  493.          while(ESC==0);
  494.          flag=0;
  495.      LCD_init();
  496.      s_connectionreset();     
  497.      }

  498.   }
  499. }  


  500. /*--------------------------------------
  501. ;模块名称:delay();
  502. ;功    能:延迟函数
  503. ;-------------------------------------*/
  504. void delay(uint j)                        //1ms,j取20
  505. {
  506.         uchar i=250;
  507.         for(;j>0;j--)
  508.         {
  509.                 while(--i);
  510.                 i=249;
  511.                 while(--i);
  512.                 i=250;
  513.         }
  514. }

  515. //*********************第三部分报警设置   END****************************************


  516. //*********主函数*****************
  517. void main(void)
  518. {
  519.                value humi_val,temp_val;                                     //185行,定义两个共同体,一个用于湿度,一个用于温度
  520.                unsigned char error,checksum;                          //用于检验是否出现错误
  521.                unsigned int wendu,shidu;                                 //最终,一位小数温湿度的值
  522.                    LCD_init();  
  523.            s_connectionreset();
  524.      
  525. //*********初始化温度显示区*********
  526.            LCD_disp_str(0,1,"TE:");
  527.            LCD_disp_str(3,1,"TTT.TC");

  528. //*********初始化湿度显示区*********
  529.            LCD_disp_str(0,2,"RH:");
  530.                    LCD_disp_str(3,2,"RRR.R%");
  531.            delay_n10us(2000);     //延时0.2s

  532.   while(1)
  533.         {
  534.                   LCD_disp_char(13,1,flag+'0');

  535.           key();
  536.      
  537.          if(flag==0)
  538.           {
  539.            error=0;                                                                                  //初始化error=0,即没有错误
  540.            error+=s_measure((unsigned char*) &humi_val.i,&checksum,HUMI);  //measure humidity
  541.            error+=s_measure((unsigned char*) &temp_val.i,&checksum,TEMP);  //measure temperature
  542.            if(error!=0) s_connectionreset();                 //in case of an error: connection reset
  543.            else
  544.             {
  545.              humi_val.f=(float)humi_val.i;                   //converts integer to float
  546.              temp_val.f=(float)temp_val.i;                   //converts integer to float
  547.              calc_SHT11(&humi_val.f,&temp_val.f);            //calculate humidity, temperature
  548.                               
  549.              LCD_disp_str(0,1,"TE:");
  550.              LCD_disp_str(0,2,"RH:");
  551.              LCD_disp_str(6,1,".");
  552.              LCD_disp_str(6,2,".");
  553.              LCD_disp_str(8,1,"C   ");
  554.              LCD_disp_str(8,2,"%   ");

  555.                      wendu=10*temp_val.f;                            //例如温度109.1→1091
  556.                         
  557.                          if(10*temp_val.f<0) {LCD_disp_str(12,2,"nega");}//实时温度为负数时,显示提示符nega        
  558.                      else {LCD_disp_str(12,2,"    ");}                         //实时温度为正数时,去除负数提醒nega
  559.                         
  560.                          LCD_disp_char(3,1,abs(wendu)/1000+'0');         //显示温度百位,加“0”是为了将字符的ASCII码大于48(即字符0的ASCII值),一般是将数字0,1,2……,9转换为字符“0”,“1”……,“9”;                        
  561.                          LCD_disp_char(4,1,abs(wendu)%1000/100+'0');     //显示温度十位
  562.              LCD_disp_char(5,1,abs(wendu)%100/10+'0');       //显示温度个位
  563.                      LCD_disp_char(7,1,abs(wendu)%10+'0');           //显示温度小数点后第一位

  564.                          shidu=10*humi_val.f;
  565.                          LCD_disp_char(3,2,shidu/1000+'0');               //显示湿度百位
  566.              LCD_disp_char(4,2,(shidu%1000)/100+'0');         //显示湿度十位
  567.              LCD_disp_char(5,2,(shidu%100)/10+'0');           //显示湿度个位
  568.                          LCD_disp_char(7,2,(shidu%10)+'0');               //显示湿度小数点后第一位
  569.          
  570.              led_control(&temp_val.f,&humi_val.f);

  571.            }
  572.           //----------wait approx. 0.8s to avoid heating up SHT11------------------------------      
  573.                   delay_n10us(800);                                //延时约0.8s      
  574.                   }

  575.       

  576.       }
  577. }
复制代码

Keil代码与Proteus仿真下载: STC89C51+STH11.7z (4.26 MB, 下载次数: 161)

评分

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

查看全部评分

回复

使用道具 举报

ID:1002955 发表于 2022-3-15 11:19 | 显示全部楼层
新人,有什么不足的希望大佬指点
回复

使用道具 举报

ID:1002955 发表于 2022-3-18 20:53 | 显示全部楼层
文档部分改了一些,有什么不足之处 请指正 STC89C51+STH11.7z (3.81 MB, 下载次数: 74)
回复

使用道具 举报

ID:1002955 发表于 2022-4-22 08:45 | 显示全部楼层
candy0122 发表于 2022-4-13 16:50
为什么我运行不了,仿真都没现象

发个图我看看
回复

使用道具 举报

ID:1002955 发表于 2022-4-22 08:49 | 显示全部楼层
polar0806 发表于 2022-4-18 21:55
仿真图为什么我打不开呢 一打开就回到原界面,我的是8.12版本

同版本应该没问题
回复

使用道具 举报

ID:1002955 发表于 2022-4-22 08:50 | 显示全部楼层
candy0122 发表于 2022-4-13 16:50
为什么我运行不了,仿真都没现象

这个与单片机仿真软件版本有关,在高版本中制作的仿真文件在低版本软件中运行可能会出现这种情况。
还有一个就是配置hex文件路径
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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