求帮忙看一下我的程序哪里出问题了,dht11+stc12c5a60s2+LCD1602

2019-07-15 12:04发布

LCD1602能够正常显示,但是读取到的温湿度数据保持不变,并且明显是错误的数据。程序下载: DHT11.rar (35.73 KB, 下载次数: 12)


QQ图片20170126164725.jpg

  1. #include<reg51.h>
  2. #include<intrins.h>
  3. #include"1602.h"

  4. #define uchar unsigned char
  5. #define uint unsigned int
  6. sbit Data=P3^6;   //定义数据线
  7. uchar rec_dat[9];   //用于显示的接收数据数组

  8. void delay_us(uchar n)
  9. {
  10.         unsigned char a;
  11.     while(--n);
  12.         for(a=3;a>0;a--);
  13. }

  14. void delay_ms(uint z)
  15. {
  16.    uint i;
  17.    unsigned char a,b,c;
  18.    for(i=z;i>0;i--)
  19.             for(c=1;c>0;c--)
  20.         for(b=43;b>0;b--)
  21.             for(a=127;a>0;a--);
  22. }

  23. void DHT11_start()
  24. {
  25.    Data=1;
  26.    delay_us(1);
  27.    Data=0;
  28.    delay_ms(20);   //延时18ms以上
  29.    Data=1;
  30.    delay_us(40);
  31. }

  32. uchar DHT11_rec_byte()      //接收一个字节
  33. {
  34.    uchar i,dat=0;
  35.   for(i=0;i<8;i++)    //从高到低依次接收8位数据
  36.    {         
  37.               while(!Data);   //等待50us低电平过去
  38.               delay_us(70);     //延时60us,如果还为高则数据为1,否则为0
  39.               dat<<=1;           //移位使正确接收8位数据,数据为0时直接移位
  40.               if(Data==1)                 //数据为1时,使dat加1来接收数据1
  41.             {  
  42.                  dat+=1;
  43.                 }
  44.               while(Data);  //等待数据线拉低   
  45.     }  
  46.     return dat;
  47. }

  48. void DHT11_receive()      //接收40位的数据
  49. {
  50.     uchar R_H,R_L,T_H,T_L,RH,RL,TH,TL,revise;
  51.     DHT11_start();
  52.     if(Data==0)
  53.     {
  54.         while(Data==0);   //等待拉高     
  55.         delay_us(90);  //拉高后延时80us
  56.         R_H=DHT11_rec_byte();    //接收湿度高八位  
  57.         R_L=DHT11_rec_byte();    //接收湿度低八位  
  58.         T_H=DHT11_rec_byte();    //接收温度高八位  
  59.         T_L=DHT11_rec_byte();    //接收温度低八位
  60.         revise=DHT11_rec_byte(); //接收校正位

  61.         delay_us(25);    //结束

  62.         if((R_H+R_L+T_H+T_L)==revise)      //校正
  63.         {
  64.                    RH=R_H;
  65.             RL=R_L;
  66.             TH=T_H;
  67.             TL=T_L;
  68.         }
  69.         /*数据处理,方便显示*/
  70.         rec_dat[0]='0'+(RH/10);
  71.         rec_dat[1]='0'+(RH%10);
  72.         rec_dat[2]='%';
  73.         rec_dat[3]='R';
  74.         rec_dat[4]='H';
  75.         rec_dat[5]=' ';
  76.         rec_dat[6]='0'+(TH/10);
  77.         rec_dat[7]='0'+(TH%10);
  78.         rec_dat[8]='C';
  79.     }
  80. }


  81. void main()
  82. {
  83.    uchar i;   
  84.    Init_LCD1602();   //lcd1602初始化
  85.    displaystring(0, 0, "Happy new year!");
  86.    while(1)
  87.    {
  88.                                 
  89.                delay_ms(1500);    //DHT11上电后要等待1S以越过不稳定状态在此期间不能发送任何指令
  90.                DHT11_receive();
  91.                for(i=0;i<9;i++)                  
  92.                   displaychar(i,1, rec_dat[i]);//写入当前字符并显示
  93.                   
  94.                            
  95.    }
  96. }
复制代码
  1. //使用方法: 使用前调用Init_LCD1602()初始化,显示方法displaystring(0, 0, "This is a test.");

  2. #ifndef _LCD1602_
  3. #define _LCD1602_

  4. #define uchar unsigned char
  5. #define uint  unsigned int
  6. //#define _PORT_REV_            //如果数据端口高低位交换,请去掉此注释

  7. #include <intrins.h>            //包含_nop_()指令

  8. sbit LCD1602_RS = P2^0;         //控件引脚定义,移植请修改
  9. sbit LCD1602_RW = P2^1;
  10. sbit LCD1602_E  = P2^2;

  11. #define LCD_PORT            P1  //输出数据总线端口定义,移植请修改

  12. #define LCD_COMMAND         0       // Command
  13. #define LCD_DATA            1       // Data
  14. #define LCD_CLEAR_SCREEN    0x01    // 清屏
  15. #define LCD_HOMING          0x02    // 光标返回原点
  16. #define LCD_SHOW            0x04    //显示开
  17. #define LCD_HIDE            0x00    //显示关      
  18. #define LCD_CURSOR          0x02    //显示光标
  19. #define LCD_NO_CURSOR       0x00    //无光标            
  20. #define LCD_FLASH           0x01    //光标闪动
  21. #define LCD_NO_FLASH        0x00    //光标不闪动
  22. #define LCD_AC_UP           0x02
  23. #define LCD_AC_DOWN         0x00    // default
  24. #define LCD_MOVE            0x01    // 画面可平移
  25. #define LCD_NO_MOVE         0x00    //default


  26. void delay10us(unsigned char t)   //误差 -0.234375us
  27. {       
  28.         while(--t)
  29.         {
  30.     unsigned char i;
  31.         _nop_();
  32.         _nop_();
  33.         _nop_();
  34.         i = 24;
  35.         while (--i);}
  36. }

  37. /*********************************************************************************************
  38. 函数名:8位数据高低位交叉互换
  39. 调  用:uchar = DataReverse(uchar);
  40. 参  数:输入的端口(0000 0XXX 其中XXX是设置输入端口号,可用十进制0~7表示,0表示P1.0,7表示P1.7)
  41. 返回值:交换后的8位数据
  42. 结  果:交换数据高低位D7→D0,D6→D1.....,D0→D7,并返回交换后的结果
  43. 备  注:
  44. /**********************************************************************************************/
  45. unsigned char DataReverse(unsigned char datOld)
  46. {
  47.     unsigned char datNew=0,i;
  48.     for (i=0; i<8; i++)
  49.     {
  50.         if (datOld & (1<<i))        //如果某位为1,则或上一个1
  51.             datNew |= (0x80>>i);
  52.     }
  53.     return datNew;
  54. }
  55. /**********************************************************************************************/

  56. /*********************************************************************************************
  57. 函数名:LCD1602等待函数
  58. 调  用:uchar = LCD_Wait();
  59. 参  数:无
  60. 返回值:LCD1602数据总线的值
  61. 结  果:等待LCD1602内部指令执行完成
  62. 备  注:返回结果可不用
  63. /**********************************************************************************************/
  64. unsigned char LCD_Wait(void)
  65. {
  66.     LCD1602_RS = 0;
  67.     LCD1602_RW = 1; delay10us(2);
  68.     LCD1602_E = 1;  delay10us(2);

  69. #ifdef _PORT_REV_                       //如果数据线高低位交换,则需要处理数据
  70.     while(DataReverse(LCD_PORT)&0x80);
  71.     LCD1602_E = 0;
  72.     return DataReverse(LCD_PORT);
  73. #else                                   //正常情况下不需要交换
  74.     while(LCD_PORT&0x80);
  75.     LCD1602_E = 0;
  76.     return LCD_PORT;
  77. #endif
  78. }
  79. /**********************************************************************************************/

  80. /*********************************************************************************************
  81. 函数名:LCD1602数据写函数
  82. 调  用:LCD_Wait(bit, uchar);
  83. 参  数:数据类型,数据值
  84. 返回值:无
  85. 结  果:将指定数据类型的数据写入1602
  86. 备  注:数据类型:LCD_COMMAND(0)、LCD_DATA(1)
  87. /**********************************************************************************************/
  88. void LCD_Write(bit DataStyle, unsigned char DAT)
  89. {
  90.     LCD1602_E = 0;
  91.     LCD1602_RS = DataStyle;
  92.     LCD1602_RW = 0;    delay10us(2);

  93. #ifdef _PORT_REV_
  94.     LCD_PORT = DataReverse(DAT);
  95. #else
  96.     LCD_PORT = DAT;
  97. #endif

  98.     _nop_();
  99.     LCD1602_E = 1;     delay10us(2);//注意顺序
  100.     LCD1602_E = 0;     delay10us(2);
  101.     LCD_Wait();                 //等待1602内部执行完,proteus仿真时请注释此句
  102. }
  103. /**********************************************************************************************/

  104. /*********************************************************************************************
  105. 函数名:LCD1602显示设置函数
  106. 调  用:LCD_SetDisplay(uchar);
  107. 参  数:显示模式
  108. 返回值:无
  109. 结  果:正常设置1602显示模式
  110. 备  注:内部函数,初始化时调用
  111. /**********************************************************************************************/
  112. void LCD_SetDisplay(unsigned char DisplayMode)
  113. {
  114.     LCD_Write(LCD_COMMAND, 0x08|DisplayMode);   
  115. }
  116. /**********************************************************************************************/

  117. /*********************************************************************************************
  118. 函数名:LCD1602显示设置函数
  119. 调  用:LCD_Setinput(uchar);
  120. 参  数:显示模式
  121. 返回值:无
  122. 结  果:正常设置1602显示模式
  123. 备  注:内部函数,初始化时调用
  124. /**********************************************************************************************/
  125. void LCD_SetInput(unsigned char InputMode)
  126. {
  127.     LCD_Write(LCD_COMMAND, 0x04|InputMode);
  128. }
  129. /**********************************************************************************************/

  130. /*********************************************************************************************
  131. 函数名:LCD1602初始化函数
  132. 调  用:Init_LCD1602();
  133. 参  数:无
  134. 返回值:无
  135. 结  果:初始化1602函数
  136. 备  注:
  137. /**********************************************************************************************/
  138. void Init_LCD1602()
  139. {
  140.     LCD_Write(LCD_COMMAND, 0x38);               //8位数据端口,2行显示,5*7点阵
  141.     LCD_Write(LCD_COMMAND, 0x38);
  142.     LCD_Write(LCD_COMMAND, 0x38);
  143.     LCD_SetDisplay(LCD_SHOW | LCD_NO_CURSOR);   //开启显示, 无光标
  144.     LCD_Write(LCD_COMMAND, LCD_CLEAR_SCREEN);   //清屏
  145.     LCD_SetInput(LCD_AC_UP | LCD_NO_MOVE);      //AC递增, 画面不动
  146. }
  147. /**********************************************************************************************/

  148. /*********************************************************************************************
  149. 函数名:LCD1602数据写函数
  150. 调  用:LCD1602_DispString(uchar, uchar, *uchar);
  151. 参  数:x坐标,y坐标,字符串
  152. 返回值:无
  153. 结  果:在指定坐标显示字符串
  154. 备  注:x: 0~15; y:0、1
  155. /**********************************************************************************************/
  156. void displaystring(unsigned char x, unsigned char y, unsigned char *s)
  157. {
  158.     if(y == 0)
  159.         LCD_Write(LCD_COMMAND, 0x80|x);
  160.     if(y == 1)
  161.         LCD_Write(LCD_COMMAND, 0x80|(x-0x40));
  162.     while(*s != '')
  163.     {
  164.         LCD_Write(LCD_DATA, *s);
  165.         s++;
  166.     }
  167. }
  168. /**********************************************************************************************/

  169. //字符显示初始地址设置
  170. void LCD_SET_XY(uchar X,uchar Y)
  171. {
  172.           if(Y == 0)
  173.         LCD_Write(LCD_COMMAND, 0x80|X);
  174.     if(Y == 1)
  175.         LCD_Write(LCD_COMMAND, 0x80|(X-0x40));
  176. }
  177. //在第X行Y列开始显示Wdata所对应的单个字符
  178. void displaychar(uchar X,uchar Y,uchar Wdata)
  179. {
  180.   LCD_SET_XY(X,Y);//写地址
  181.   LCD_Write(LCD_DATA, Wdata);//写入当前字符并显示
  182. }
  183. #endif
复制代码

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。