网站导航: 首页 > 设计参考 > 正文 文章搜索
基于DHT90和LCD1602的,、湿度显示程序(C51)
 
文章编号:
091114225608
文章分类: 单片机 51系列
点 击:
...
关 键 词: DHT90,LCD1602,温度,湿度
文章来源:
网络
摘 要:

 
  1. /***********************************************************************************   
  2. ;功能说明:DHT90与LCD1602的温湿度显示KeilC程序  
  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()函数,修改了延时函数的注释。  
  12. ;***********************************************************************************/  
  13.   
  14. /*************定义接口********************  
  15. P0------DB0~DB7  (LCD1602)       
  16. P2.0------RS      (LCD1602)  
  17. P2.1------RW      (LCD1602)  
  18. P2.2------E       (LCD1602)  
  19. P2.6------SCK     (DHT90)  
  20. P2.7------DATA    (DHT90)  
  21. *****************************************/  
  22.   
  23. #include <AT89x51.h>   
  24. #include <intrins.h>    
  25. #include <math.h>    //Keil library      
  26. #include <stdio.h>   //Keil library    
  27.   
  28. //*********************第一部分LCD1602设置 START****************************************   
  29. #define LCD_DB        P0   
  30. sbit         LCD_RS=P2^0;   //P2^0是p2.0的意思;LCD_RS与P2.0等效起来,对LCD_RS 读写,就是对P2.0读写 好处在于LCD_RS含义直接明了,写程序多了就会知道有必要de   
  31. sbit         LCD_RW=P2^1;   //P2^1是p2.1的意思   
  32. sbit         LCD_E=P2^2;    //P2^2是p2.2的意思   
  33.   
  34. /******定义函数****************/   
  35. #define uchar unsigned char   
  36. #define uint unsigned int   
  37. void LCD_init(void);                          //初始化函数   
  38. void LCD_write_command(uchar command);        //写指令函数   
  39. void LCD_write_data(uchar dat);               //写数据函数   
  40. void LCD_disp_char(uchar x,uchar y,uchar dat);//在某个屏幕位置上显示一个字符,X(0-15),y(1-2)   
  41. void LCD_disp_str(uchar x,uchar y,uchar *str); //LCD1602显示字符串函数   
  42. void delay_n10us(uint n);                     //延时函数   
  43.   
  44. /*--------------------------------------   
  45. ;模块名称:LCD_init();   
  46. ;功    能:初始化LCD1602   
  47. ;占用资源:--  
  48. ;参数说明:--  
  49. ;创建日期:2008.08.15   
  50. ;版    本:FV1.0(函数版本Function Version)  
  51. ;修改日期:--  
  52. ;修改说明:--  
  53. ;-------------------------------------*/    
  54. void LCD_init(void)   
  55. {   
  56.     delay_n10us(10);   
  57.     LCD_write_command(0x38);//设置8位格式,2行,5x7   
  58.     delay_n10us(10);   
  59.     LCD_write_command(0x0c);//整体显示,关光标,不闪烁   
  60.     delay_n10us(10);   
  61.     LCD_write_command(0x06);//设定输入方式,增量不移位   
  62.     delay_n10us(10);   
  63.     LCD_write_command(0x01);//清除屏幕显示   
  64.     delay_n10us(100);       //延时清屏,延时函数,延时约n个10us   
  65. }   
  66.   
  67. /*--------------------------------------   
  68. ;模块名称:LCD_write_command();   
  69. ;功    能:LCD1602写指令函数   
  70. ;占用资源: P2.0--RS(LCD_RS),P2.1--RW(LCD_RW),P2.2--E(LCD_E).  
  71. ;参数说明:dat为写命令参数  
  72. ;创建日期:2008.08.15   
  73. ;版    本:FV1.0(函数版本Function Version)  
  74. ;修改日期:--  
  75. ;修改说明:--  
  76. ;-------------------------------------*/    
  77. void LCD_write_command(uchar dat)   
  78. {   
  79.     delay_n10us(10);   
  80.     LCD_RS=0;         //指令   
  81.     LCD_RW=0;         //写入   
  82.     LCD_E=1;          //允许   
  83.     LCD_DB=dat;   
  84.     delay_n10us(10);  //实践证明,我的LCD1602上,用for循环1次就能完成普通写指令。   
  85.     LCD_E=0;   
  86.     delay_n10us(10);  //实践证明,我的LCD1602上,用for循环1次就能完成普通写指令。   
  87. }   
  88.   
  89. /*--------------------------------------   
  90. ;模块名称:LCD_write_data();   
  91. ;功    能:LCD1602写数据函数   
  92. ;占用资源: P2.0--RS(LCD_RS),P2.1--RW(LCD_RW),P2.2--E(LCD_E).  
  93. ;参数说明:dat为写数据参数  
  94. ;创建日期:2008.08.15   
  95. ;版    本:FV1.0(函数版本Function Version)  
  96. ;修改日期:--  
  97. ;修改说明:--  
  98. ;-------------------------------------*/  
  99. void LCD_write_data(uchar dat)   
  100. {   
  101.     delay_n10us(10);   
  102.     LCD_RS=1;          //数据   
  103.     LCD_RW=0;          //写入   
  104.     LCD_E=1;           //允许   
  105.     LCD_DB=dat;   
  106.     delay_n10us(10);   
  107.     LCD_E=0;   
  108.     delay_n10us(10);   
  109. }   
  110.   
  111. /*--------------------------------------   
  112. ;模块名称:LCD_disp_char();   
  113. ;功    能:LCD1602显示一个字符函数,在某个屏幕位置上显示一个字符,X(0-15),y(1-2)。  
  114. ;占用资源:--  
  115. ;参数说明:X为1602的列值(取值范围是0-15),y为1602的行值(取值范围是1-2),dat为所要显示字符对应的地址参数。  
  116. ;创建日期:2008.08.15   
  117. ;版    本:FV1.0(函数版本Function Version)  
  118. ;修改日期:--  
  119. ;修改说明:--  
  120. ;-------------------------------------*/  
  121. void LCD_disp_char(uchar x,uchar y,uchar dat)   
  122. {   
  123.     uchar address;   
  124.     if(y==1)   
  125.         address=0x80+x;   
  126.     else  
  127.         address=0xc0+x;   
  128.     LCD_write_command(address);   
  129.     LCD_write_data(dat);   
  130. }   
  131.   
  132. /*--------------------------------------   
  133. ;模块名称:LCD_disp_str();   
  134. ;功    能:LCD1602显示字符串函数,在某个屏幕起始位置{X(0-15),y(1-2)}上显示一个字符串。  
  135. ;占用资源:--  
  136. ;参数说明:X为1602的列值(取值范围是0-15),y为1602的行值(取值范围是1-2),str为所要显示字符串对应的指针参数。  
  137. ;创建日期:2008.08.16   
  138. ;版    本:FV1.0(函数版本Function Version)  
  139. ;修改日期:--  
  140. ;修改说明:--   
  141. ;-------------------------------------*/  
  142. void LCD_disp_str(uchar x,uchar y,uchar *str)   
  143. {   
  144.     uchar address;   
  145.     if(y==1)   
  146.         address=0x80+x;   
  147.     else  
  148.         address=0xc0+x;   
  149.     LCD_write_command(address);   
  150.     while(*str!='\0')   
  151.     {    
  152.         LCD_write_data(*str);      
  153.         str++;   
  154.     }   
  155. }   
  156.   
  157. /*--------------------------------------   
  158. ;模块名称:delay_n10us();   
  159. ;功    能:延时函数,延时约n个10us  
  160. ;占用资源:--  
  161. ;参数说明:--  
  162. ;创建日期:2008.08.15   
  163. ;版    本:FV1.1(函数版本Function Version)  
  164. ;修改日期:2008.08.26  
  165. ;修改说明:修改为较精确的延时函数,"_nop_()"延时1us@12M晶振  
  166. ;-------------------------------------*/  
  167. void delay_n10us(uint n)  //延时n个10us@12M晶振   
  168. {          
  169.     uint i;              
  170.     for(i=n;i>0;i--)       
  171.     {   
  172.         _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();    
  173.     }   
  174. }     
  175.   
  176. //*********************第一部分LCD1602设置 END****************************************   
  177.   
  178. //*********************第二部分DHT90设置   START****************************************    
  179. sbit SCK  = P2^6;      //定义通讯时钟端口   
  180. sbit DATA = P2^7;      //定义通讯数据端口   
  181.   
  182. typedef union     
  183. {    
  184.     unsigned int i;      //定义了两个共用体   
  185.     float f;    
  186. } value;    
  187.   
  188. enum {TEMP,HUMI};      //TEMP=0,HUMI=1   
  189.   
  190. #define noACK 0             //用于判断是否结束通讯   
  191. #define ACK   1             //结束数据传输   
  192. //adr  command  r/w    
  193. #define STATUS_REG_W 0x06   //000   0011    0    
  194. #define STATUS_REG_R 0x07   //000   0011    1    
  195. #define MEASURE_TEMP 0x03   //000   0001    1    
  196. #define MEASURE_HUMI 0x05   //000   0010    1    
  197. #define RESET        0x1e   //000   1111    0    
  198.   
  199. /****************定义函数****************/   
  200. void s_transstart(void);               //启动传输函数   
  201. void s_connectionreset(void);          //连接复位函数   
  202. char s_write_byte(unsigned char value);//DHT90写函数   
  203. char s_read_byte(unsigned char ack);   //DHT90读函数   
  204. char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode);//测量温湿度函数   
  205. void calc_dht90(float *p_humidity ,float *p_temperature);//温湿度补偿   
  206.   
  207. /*--------------------------------------   
  208. ;模块名称:s_transstart();   
  209. ;功能:启动传输函数  
  210. ;占用资源:--  
  211. ;参数说明:--  
  212. ;创建日期:2008.08.15   
  213. ;版本:FV1.0(函数版本Function Version)  
  214. ;修改日期:--  
  215. ;修改说明:--  
  216. ;-------------------------------------*/     
  217. void s_transstart(void)    
  218. // generates a transmission start     
  219. //       _____         ________    
  220. // DATA:      |_______|    
  221. //           ___     ___    
  222. // SCK : ___|   |___|   |______    
  223. {      
  224.     DATA=1; SCK=0;                   //Initial state    
  225.     _nop_();    
  226.     SCK=1;    
  227.     _nop_();    
  228.     DATA=0;    
  229.     _nop_();    
  230.     SCK=0;      
  231.     _nop_();_nop_();_nop_();    
  232.     SCK=1;    
  233.     _nop_();    
  234.     DATA=1;           
  235.     _nop_();    
  236.     SCK=0;           
  237. }    
  238.   
  239. /*--------------------------------------   
  240. ;模块名称:s_connectionreset();   
  241. ;功    能:连接复位函数  
  242. ;占用资源:--  
  243. ;参数说明:--  
  244. ;创建日期:2008.08.15   
  245. ;版    本:FV1.0(函数版本Function Version)  
  246. ;修改日期:--  
  247. ;修改说明:--  
  248. ;-------------------------------------*/    
  249. void s_connectionreset(void)    
  250. // communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart    
  251. //       _____________________________________________________         ________    
  252. // DATA:                                                      |_______|    
  253. //          _    _    _    _    _    _    _    _    _        ___     ___    
  254. // SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______|   |___|   |______    
  255. {      
  256.     unsigned char i;     
  257.     DATA=1;    
  258.     SCK=0;                    //Initial state    
  259.     for(i=0;i<9;i++)                  //9 SCK cycles    
  260.     {    
  261.         SCK=1;   
  262.         SCK=0;    
  263.     }    
  264.     s_transstart();                   //transmission start    
  265. }    
  266.   
  267. /*--------------------------------------   
  268. ;模块名称:s_write_byte();   
  269. ;功    能:DHT90写函数  
  270. ;占用资源:--  
  271. ;参数说明:--  
  272. ;创建日期:2008.08.15   
  273. ;版    本:FV1.0(函数版本Function Version)  
  274. ;修改日期:--  
  275. ;修改说明:--  
  276. ;-------------------------------------*/    
  277. char s_write_byte(unsigned char value)    
  278. //----------------------------------------------------------------------------------    
  279. // writes a byte on the Sensibus and checks the acknowledge     
  280. {     
  281.     unsigned char i,error=0;      
  282.     for (i=0x80;i>0;i/=2)             //shift bit for masking    
  283.     {     
  284.         if (i & value)    
  285.             DATA=1;          //masking value with i , write to SENSI-BUS    
  286.         else  
  287.             DATA=0;                            
  288.         SCK=1;                          //clk for SENSI-BUS    
  289.         _nop_();_nop_();_nop_();        //pulswith approx. 3 us        
  290.         SCK=0;    
  291.     }    
  292.     DATA=1;                           //release DATA-line    
  293.     SCK=1;                            //clk #9 for ack     
  294.     error=DATA;                       //check ack (DATA will be pulled down by DHT90),DATA在第9个上升沿将被DHT90自动下拉为低电平。    
  295.     _nop_();_nop_();_nop_();   
  296.     SCK=0;   
  297.     DATA=1;                           //release DATA-line    
  298.     return error;                     //error=1 in case of no acknowledge //返回:0成功,1失败   
  299. }    
  300.   
  301. /*--------------------------------------   
  302. ;模块名称:s_read_byte();   
  303. ;功    能:DHT90读函数  
  304. ;占用资源:--  
  305. ;参数说明:--  
  306. ;创建日期:2008.08.15   
  307. ;版    本:FV1.0(函数版本Function Version)  
  308. ;修改日期:--  
  309. ;修改说明:--  
  310. ;-------------------------------------*/    
  311. char s_read_byte(unsigned char ack)     
  312. // reads a byte form the Sensibus and gives an acknowledge in case of "ack=1"     
  313. {     
  314.     unsigned char i,val=0;    
  315.     DATA=1;                           //release DATA-line    
  316.     for (i=0x80;i>0;i/=2)             //shift bit for masking    
  317.     {    
  318.         SCK=1;                          //clk for SENSI-BUS    
  319.         if (DATA)    
  320.             val=(val | i);        //read bit      
  321.         _nop_();_nop_();_nop_();        //pulswith approx. 3 us   
  322.         SCK=0;                 
  323.     }    
  324.     if(ack==1)   
  325.         DATA=0;                 //in case of "ack==1" pull down DATA-Line    
  326.     else  
  327.         DATA=1;                      //如果是校验(ack==0),读取完后结束通讯   
  328.     _nop_();_nop_();_nop_();          //pulswith approx. 3 us    
  329.     SCK=1;                            //clk #9 for ack    
  330.     _nop_();_nop_();_nop_();          //pulswith approx. 3 us     
  331.     SCK=0;                    
  332.     _nop_();_nop_();_nop_();          //pulswith approx. 3 us    
  333.     DATA=1;                           //release DATA-line    
  334.     return val;    
  335. }    
  336.   
  337. /*--------------------------------------   
  338. ;模块名称:s_measure();   
  339. ;功    能:测量温湿度函数  
  340. ;占用资源:--  
  341. ;参数说明:--  
  342. ;创建日期:2008.08.15   
  343. ;版    本:FV1.0(函数版本Function Version)  
  344. ;修改日期:--  
  345. ;修改说明:--  
  346. ;-------------------------------------*/    
  347. char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode)    
  348. // makes a measurement (humidity/temperature) with checksum    
  349. {     
  350.     unsigned error=0;    
  351.     unsigned int i;    
  352.        
  353.     s_transstart();                   //transmission start    
  354.     switch(mode)   
  355.     {                     //send command to sensor    
  356.     case TEMP  : error+=s_write_byte(MEASURE_TEMP); break;    
  357.     case HUMI  : error+=s_write_byte(MEASURE_HUMI); break;    
  358.     default     : break;       
  359.     }    
  360.     for (i=0;i<65535;i++)    
  361.         if(DATA==0)   
  362.             break//wait until sensor has finished the measurement    
  363.         if(DATA)    
  364.             error+=1;                // or timeout (~2 sec.) is reached    
  365.         *(p_value)  =s_read_byte(ACK);    //read the first byte (MSB)    
  366.         *(p_value+1)=s_read_byte(ACK);    //read the second byte (LSB)    
  367.         *p_checksum =s_read_byte(noACK);  //read checksum    
  368.         return error;    
  369. }    
  370.   
  371. /*--------------------------------------   
  372. ;模块名称:calc_dht90();   
  373. ;功    能:温湿度补偿函数  
  374. ;占用资源:--  
  375. ;参数说明:--  
  376. ;创建日期:2008.08.15   
  377. ;版    本:FV1.0(函数版本Function Version)  
  378. ;修改日期:--  
  379. ;修改说明:--  
  380. ;-------------------------------------*/    
  381. void calc_dht90(float *p_humidity ,float *p_temperature)   
  382. // calculates temperature [C] and humidity [%RH]    
  383. // input :  humi [Ticks] (12 bit)    
  384. //          temp [Ticks] (14 bit)   
  385. // output:  humi [%RH]   
  386. //          temp [C]   
  387. const float C1=-4.0;              // for 12 Bit   
  388. const float C2=+0.0405;           // for 12 Bit   
  389. const float C3=-0.0000028;        // for 12 Bit   
  390. const float T1=+0.01;             // for 14 Bit @ 5V   
  391. const float T2=+0.00008;           // for 14 Bit @ 5V    
  392.   
  393. float rh=*p_humidity;             // rh:      Humidity [Ticks] 12 Bit    
  394. float t=*p_temperature;           // t:       Temperature [Ticks] 14 Bit   
  395. float rh_lin;                     // rh_lin:  Humidity linear   
  396. float rh_true;                    // rh_true: Temperature compensated humidity   
  397. float t_C;                        // t_C   :  Temperature [C]   
  398.   
  399. t_C=t*0.01 - 40;                  //calc. temperature from ticks to [C]   
  400. rh_lin=C3*rh*rh + C2*rh + C1;     //calc. humidity from ticks to [%RH]   
  401. rh_true=(t_C-25)*(T1+T2*rh)+rh_lin;   //calc. temperature compensated humidity [%RH]   
  402. if(rh_true>100)rh_true=100;       //cut if the value is outside of   
  403. if(rh_true<0.1)rh_true=0.1;       //the physical possible range   
  404.   
  405. *p_temperature=t_C;               //return temperature [C]   
  406. *p_humidity=rh_true;              //return humidity[%RH]   
  407. }   
  408.   
  409. //*********************第二部分DHT90设置   END****************************************   
  410.   
  411. //*********主函数*****************   
  412. void main(void)   
  413. {   
  414.     value humi_val,temp_val;   
  415.     unsigned char error,checksum;    
  416.     unsigned int wendu,shidu;   
  417.     LCD_init();    
  418.     s_connectionreset();    
  419.     LCD_disp_str(0,1,"TE");   
  420.     LCD_disp_str(0,2,"RH");   
  421.        
  422.     //*********初始化温度显示区*********   
  423.     LCD_disp_str(2,1,"TTT.TC");   
  424.        
  425.     //*********初始化湿度显示区*********   
  426.     LCD_disp_str(2,2,"RRR.R%");   
  427.        
  428.     delay_n10us(20000);     //延时0.2s   
  429.        
  430.     while(1)    
  431.     {    
  432.         error=0;    
  433.         error+=s_measure((unsigned char*) &humi_val.i,&checksum,HUMI);  //measure humidity    
  434.         error+=s_measure((unsigned char*) &temp_val.i,&checksum,TEMP);  //measure temperature    
  435.         if(error!=0)    
  436.             s_connectionreset();                 //in case of an error: connection reset    
  437.         else    
  438.         {    
  439.             humi_val.f=(float)humi_val.i;                   //converts integer to float   
  440.             temp_val.f=(float)temp_val.i;                   //converts integer to float   
  441.             calc_dht90(&humi_val.f,&temp_val.f);            //calculate humidity, temperature   
  442.             wendu=10*temp_val.f;   
  443.             LCD_disp_char(2,1,wendu/1000+'0');              //显示温度百位   
  444.             LCD_disp_char(3,1,(wendu%1000)/100+'0');        //显示温度十位   
  445.             LCD_disp_char(4,1,(wendu%100)/10+'0');          //显示温度个位   
  446.             LCD_disp_char(6,1,(wendu%10)+'0');              //显示温度小数点后第一位   
  447.                
  448.             shidu=10*humi_val.f;   
  449.             LCD_disp_char(2,2,shidu/1000+'0');               //显示湿度百位   
  450.             LCD_disp_char(3,2,(shidu%1000)/100+'0');         //显示湿度十位   
  451.             LCD_disp_char(4,2,(shidu%100)/10+'0');           //显示湿度个位   
  452.             LCD_disp_char(6,2,(shidu%10)+'0');               //显示湿度小数点后第一位   
  453.         }    
  454.         //----------wait approx. 0.8s to avoid heating up SHTxx------------------------------          
  455.         delay_n10us(80000);                                //延时约0.8s   
  456.     }   
  457. }   

 

 
相关文章:

 
最新开源项目
 
 
  查看更多...  
 
本站相关产品   淘宝网店
 




 
  查看更多...  

 

本站程序由百合电子工作室开发和维护
Copyright @ baihe electric studio
渝ICP备09006681号-4