下面是原理图:

 

下面是SHT11与MCU连接的典型电路:

下面是源代码:

 
  
  1. #include <reg52.h>  
  2. #include <intrins.h>  
  3.  
  4. /********************************************************  
  5.                       宏定义  
  6. ********************************************************/ 
  7. #define uint unsigned int  
  8. #define uchar unsigned char  
  9. #define noACK 0       
  10. #define ACK   1              
  11. #define STATUS_REG_W 0x06    
  12. #define STATUS_REG_R 0x07     
  13. #define MEASURE_TEMP 0x03    
  14. #define MEASURE_HUMI 0x05    
  15. #define RESET        0x1e     
  16.  
  17. enum {TEMP,HUMI};  
  18.  
  19. typedef union               //定义共用同类型  
  20. {     
  21.     unsigned int i;  
  22.     float f;  
  23. } value;  
  24.  
  25.  
  26. /********************************************************  
  27.                       位定义  
  28. ********************************************************/ 
  29. sbit lcdrs=P2^0;  
  30. sbit lcdrw=P2^1;  
  31. sbit lcden=P2^2;  
  32. sbit SCK = P1^0;  
  33. sbit DATA = P1^1;  
  34.  
  35. /********************************************************  
  36.                      变量定义  
  37. ********************************************************/ 
  38. uchar table2[]="SHT11 温湿度检测";  
  39. uchar table3[]="温度为:      ℃";  
  40. uchar table4[]="湿度为:";  
  41. uchar table5[]=".";  
  42. uchar wendu[6];                
  43. uchar shidu[6];                
  44.  
  45. /********************************************************  
  46.                     1ms延时函数  
  47. ********************************************************/ 
  48. void delay(int z)          
  49. {  
  50.     int x,y;  
  51.     for(x=z;x>0;x--)  
  52.         for(y=125;y>0;y--);  
  53. }  
  54.  
  55. /********************************************************  
  56.                    50us延时函数  
  57. ********************************************************/ 
  58. void delay_50us(uint t)  
  59. {  
  60.     uint j;  
  61.     for(;t>0;t--)  
  62.         for(j=19;j>0;j--);  
  63. }  
  64.  
  65. /********************************************************  
  66.                    50ms延时函数  
  67. ********************************************************/ 
  68. void delay_50ms(uint t)  
  69. {  
  70.     uint j;  
  71.     for(;t>0;t--)  
  72.         for(j=6245;j>0;j--);  
  73. }  
  74.  
  75. /********************************************************  
  76.                   12864液晶写指令  
  77. ********************************************************/ 
  78. void write_12864com(uchar com)  
  79. {     
  80.     lcdrs=0;  
  81.     lcdrw=0;  
  82.     delay_50us(1);  
  83.     P0=com;  
  84.     lcden=1;  
  85.     delay_50us(10);  
  86.     lcden=0;  
  87.     delay_50us(2);  
  88. }  
  89.  
  90. /********************************************************  
  91.                   12864液晶写数据  
  92. ********************************************************/ 
  93. void write_dat(uchar dat)  
  94. {     
  95.     lcdrs=1;  
  96.     lcdrw=0;  
  97.     delay_50us(1);  
  98.     P0=dat;  
  99.     lcden=1;  
  100.     delay_50us(10);  
  101.     lcden=0;  
  102.     delay_50us(2);  
  103. }  
  104.  
  105. /********************************************************  
  106.                   12864液晶初始化  
  107. ********************************************************/ 
  108. void init12864lcd(void)  
  109. {  
  110.     delay_50ms(2);  
  111.     write_12864com(0x30);  
  112.     delay_50us(4);  
  113.     write_12864com(0x30);         
  114.     delay_50us(4);  
  115.     write_12864com(0x0f);  
  116.     delay_50us(4);  
  117.     write_12864com(0x01);  
  118.     delay_50us(240);  
  119.     write_12864com(0x06);  
  120.     delay_50us(10);  
  121.     write_12864com(0x0c);  
  122.     delay_50us(10);  
  123. }  
  124.  
  125. /********************************************************  
  126.                   12864液晶显示函数  
  127. ********************************************************/ 
  128. void display1(void)  
  129. {  
  130.     uchar i;  
  131.     write_12864com(0x80);     
  132.     for(i=0;i<18;i++)  
  133.     {  
  134.          write_dat(table2[i]);  
  135.          delay_50us(1);       
  136.     }  
  137. }  
  138.  
  139. /********************************************************  
  140.                   12864液晶显示函数  
  141. ********************************************************/ 
  142. void display2(void)  
  143. {  
  144.     uchar i;  
  145.     write_12864com(0x90);     
  146.     for(i=0;i<18;i++)  
  147.     {  
  148.          write_dat(table3[i]);  
  149.          delay_50us(1);       
  150.     }  
  151. }  
  152.  
  153. /********************************************************  
  154.                   12864液晶显示函数  
  155. ********************************************************/ 
  156. void display3(void)  
  157. {  
  158.     uchar i;  
  159.     write_12864com(0x88);     
  160.     for(i=0;i<8;i++)  
  161.     {  
  162.          write_dat(table4[i]);  
  163.          delay_50us(1);       
  164.     }  
  165. }  
  166.  
  167. /********************************************************  
  168.                   12864液晶显示函数  
  169. ********************************************************/ 
  170. void displaywendu(void)  
  171. {  
  172.     uchar i;  
  173.     write_12864com(0x94);     
  174.     for(i=0;i<3;i++)  
  175.     {  
  176.          write_dat(wendu[i]);  
  177.          delay_50us(1);       
  178.     }  
  179.     for(i=0;i<1;i++)  
  180.     {  
  181.          write_dat(table5[i]);  
  182.          delay_50us(1);       
  183.     }  
  184.     for(i=4;i<5;i++)  
  185.     {  
  186.          write_dat(wendu[i]);  
  187.          delay_50us(1);       
  188.     }  
  189. }  
  190.  
  191.  
  192. /********************************************************  
  193.                   12864液晶显示函数  
  194. ********************************************************/ 
  195. void displayshidu(void)  
  196. {  
  197.     uchar i;  
  198.     write_12864com(0x8C);     
  199.     for(i=0;i<3;i++)  
  200.     {  
  201.          write_dat(shidu[i]);  
  202.          delay_50us(1);       
  203.     }  
  204.     for(i=0;i<1;i++)  
  205.     {  
  206.          write_dat(table5[i]);  
  207.          delay_50us(1);       
  208.     }  
  209.     for(i=4;i<5;i++)  
  210.     {  
  211.          write_dat(shidu[i]);  
  212.          delay_50us(1);       
  213.     }  
  214. }  
  215.  
  216. /********************************************************  
  217.                  SHT11写字节程序  
  218. ********************************************************/ 
  219. char s_write_byte(unsigned char value)     
  220. {   
  221.     unsigned char i,error=0;   
  222.     for (i=0x80;i>0;i>>=1)             //高位为1,循环右移  
  223.     {   
  224.         if (i&value) DATA=1;          //和要发送的数相与,结果为发送的位  
  225.         else DATA=0;                          
  226.         SCK=1;                            
  227.         _nop_();_nop_();_nop_();        //延时3us   
  228.         SCK=0;  
  229.     }  
  230.     DATA=1;                           //释放数据线  
  231.     SCK=1;                              
  232.     error=DATA;                       //检查应答信号,确认通讯正常  
  233.     _nop_();_nop_();_nop_();  
  234.     SCK=0;          
  235.     DATA=1;  
  236.     return error;                     //error=1 通讯错误  
  237. }  
  238.  
  239. /********************************************************  
  240.                  SHT11读字节程序  
  241. ********************************************************/ 
  242. char s_read_byte(unsigned char ack)  
  243. {   
  244.     unsigned char i,val=0;  
  245.     DATA=1;                           //释放数据线  
  246.     for(i=0x80;i>0;i>>=1)             //高位为1,循环右移  
  247.     {   
  248.         SCK=1;                           
  249.         if(DATA) val=(val|i);             //读一位数据线的值   
  250.         SCK=0;         
  251.     }  
  252.     DATA=!ack;                        //如果是校验,读取完后结束通讯;  
  253.     SCK=1;                              
  254.     _nop_();_nop_();_nop_();          //延时3us   
  255.     SCK=0;     
  256.     _nop_();_nop_();_nop_();         
  257.     DATA=1;                           //释放数据线  
  258.     return val;  
  259. }  
  260.  
  261. /********************************************************  
  262.                  SHT11启动传输  
  263. ********************************************************/ 
  264. void s_transstart(void)  
  265. {   
  266.     DATA=1; SCK=0;                   //准备  
  267.     _nop_();  
  268.     SCK=1;  
  269.     _nop_();  
  270.     DATA=0;  
  271.     _nop_();  
  272.     SCK=0;   
  273.      _nop_();_nop_();_nop_();  
  274.     SCK=1;  
  275.     _nop_();  
  276.     DATA=1;       
  277.     _nop_();  
  278.     SCK=0;       
  279. }  
  280.  
  281.  
  282. /********************************************************  
  283.                  SHT11连接复位  
  284. ********************************************************/ 
  285. void s_connectionreset(void)  
  286. {   
  287.     unsigned char i;   
  288.     DATA=1; SCK=0;                    //准备  
  289.     for(i=0;i<9;i++)                  //DATA保持高,SCK时钟触发9次,发送启动传输,通迅即复位  
  290.     {   
  291.         SCK=1;  
  292.         SCK=0;  
  293.     }  
  294.     s_transstart();                   //启动传输  
  295. }  
  296.  
  297. /********************************************************  
  298.                  SHT11温湿度检测  
  299. ********************************************************/ 
  300. char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode)  
  301. {   
  302.     unsigned error=0;  
  303.     unsigned int i;  
  304.  
  305.     s_transstart();                   //启动传输  
  306.     switch(mode)                      //选择发送命令  
  307.         {     
  308.         case TEMP : error+=s_write_byte(MEASURE_TEMP); break;          //测量温度  
  309.                 case HUMI : error+=s_write_byte(MEASURE_HUMI); break;          //测量湿度  
  310.             default     : break;   
  311.     }  
  312.     for (i=0;i<65535;i++) if(DATA==0) break;        //等待测量结束  
  313.     if(DATA) error+=1;                              // 如果长时间数据线没有拉低,说明测量错误   
  314.     *(p_value) =s_read_byte(ACK);           //读第一个字节,高字节 (MSB)  
  315.     *(p_value+1)=s_read_byte(ACK);          //读第二个字节,低字节 (LSB)  
  316.     *p_checksum =s_read_byte(noACK);        //read CRC校验码  
  317.     return error;                   // error=1 通讯错误  
  318. }  
  319. /********************************************************  
  320.             SHT11温湿度值标度变换及温度补偿  
  321. ********************************************************/ 
  322. void calc_sth10(float *p_humidity ,float *p_temperature)  
  323. {   
  324.     const float C1=-4.0;              // 12位湿度精度 修正公式  
  325.     const float C2=+0.0405;           // 12位湿度精度 修正公式  
  326.     const float C3=-0.0000028;        // 12位湿度精度 修正公式  
  327.     const float T1=+0.01;             // 14位温度精度 5V条件  修正公式  
  328.     const float T2=+0.00008;          // 14位温度精度 5V条件  修正公式  
  329.  
  330.     float rh=*p_humidity;             // rh:      12位 湿度   
  331.     float t=*p_temperature;           // t:       14位 温度  
  332.     float rh_lin;                     // rh_lin: 湿度 linear值  
  333.     float rh_true;                    // rh_true: 湿度 ture值  
  334.     float t_C;                        // t_C   : 温度 ℃  
  335.  
  336.     t_C=t*0.01 - 40;                  //补偿温度  
  337.     rh_lin=C3*rh*rh + C2*rh + C1;     //相对湿度非线性补偿  
  338.     rh_true=(t_C-25)*(T1+T2*rh)+rh_lin;   //相对湿度对于温度依赖性补偿  
  339.     if(rh_true>100)rh_true=100;       //湿度最大修正  
  340.     if(rh_true<0.1)rh_true=0.1;       //湿度最小修正  
  341.  
  342.     *p_temperature=t_C;               //返回温度结果  
  343.     *p_humidity=rh_true;              //返回湿度结果  
  344. }  
  345. /********************************************************  
  346.                      主函数   
  347. ********************************************************/                                 
  348. void main(void)  
  349. {   
  350.     unsigned int temp,humi;  
  351.     value humi_val,temp_val;        //定义两个共同体,一个用于湿度,一个用于温度  
  352.     unsigned char error;            //用于检验是否出现错误  
  353.     unsigned char checksum;         //CRC              
  354.     init12864lcd();  
  355.     display1();   
  356.     display2();   
  357.     display3();           
  358.     s_connectionreset();               //启动连接复位  
  359.     while(1)  
  360.     {  
  361.         error=0;                       //初始化error=0,即没有错误  
  362.         error+=s_measure((unsigned char*)&temp_val.i,&checksum,TEMP); //温度测量  
  363.         error+=s_measure((unsigned char*)&humi_val.i,&checksum,HUMI); //湿度测量  
  364.         if(error!=0) s_connectionreset();                 如果发生错误,系统复位  
  365.         else 
  366.         {   
  367.             humi_val.f=(float)humi_val.i;                   //转换为浮点数  
  368.             temp_val.f=(float)temp_val.i;                   //转换为浮点数  
  369.             calc_sth10(&humi_val.f,&temp_val.f);            //修正相对湿度及温度  
  370.             temp=temp_val.f*10;  
  371.             humi=humi_val.f*10;  
  372.             wendu[0]=temp/1000+'0';             //温度百位   
  373.             wendu[1]=temp%1000/100+'0';         //温度十位    
  374.             wendu[2]=temp%100/10+'0';           //温度个位  
  375.             wendu[3]=0x2E;                      //小数点  
  376.             wendu[4]=temp%10+'0';               //温度小数点后第一位  
  377.             displaywendu();                        
  378.             shidu[0]=humi/1000+'0';             //湿度百位  
  379.             shidu[1]=humi%1000/100+'0';         //湿度十位    
  380.             shidu[2]=humi%100/10+'0';           //湿度个位  
  381.             shidu[3]=0x2E;                      //小数点  
  382.             shidu[4]=humi%10+'0';               //湿度小数点后第一位  
  383.             displayshidu();       
  384.         }    
  385.         delay(800);                             //等待足够长的时间,以现行下一次转换                     
  386.     }