[范例教程] DHT11温湿度+1602液晶显示程序

[复制链接]
1479|15
 楼主| rosemoore 发表于 2023-7-16 08:00 | 显示全部楼层 |阅读模式
  1. #include<intrins.h>

  2. #define uchar unsigned char        //无符号字符型类型数据
  3. #define uint unsigned int //无符号整型数据
  4. #define IODATA  P0

  5. uchar dat_r[4];          //用于存放从DHT11读取到的数值

  6. sbit DATA=P2^2;   //定义数据线
  7. sbit RS=P1^0; //定义rs端口
  8. sbit RW=P1^1; //定义rw端口
  9. sbit E=P2^5; //定义en端口


  10. /*********************************************************************************************
  11. 函数名:延时函数
  12. 调  用:Delay30us();/Delay20ms();/Delay1s();
  13. 参  数:无
  14. 返回值:无
  15. 结  果:延时相应时间
  16. 备  注:振荡晶体为11.0592MHz(所有延时函数Copy自STC-ISP(v6.85).exe)
  17. **********************************************************************************************/
  18. void Delay30us()                //@11.0592MHz-40
  19. {
  20.         unsigned char i;

  21.         i = 11;
  22.         while (--i);
  23. }


  24. void Delay20ms()                //@11.0592MHz
  25. {
  26.         unsigned char i, j;

  27.         i = 36;
  28.         j = 217;
  29.         do
  30.         {
  31.                 while (--j);
  32.         } while (--i);
  33. }


  34. void Delay1s()                //@11.0592MHz
  35. {
  36.         unsigned char i, j, k;

  37.         _nop_();
  38.         i = 8;
  39.         j = 1;
  40.         k = 243;
  41.         do
  42.         {
  43.                 do
  44.                 {
  45.                         while (--k);
  46.                 } while (--j);
  47.         } while (--i);
  48. }


  49. /*********************************************************************************************
  50. 函数名:DHT11启动函数
  51. 调  用:无
  52. 参  数:无
  53. 返回值:无
  54. 结  果:DHT11开始工作
  55. 备  注:
  56. **********************************************************************************************/
  57. void DHT11_start()                 // 主机控制DHT11开始工作
  58. {
  59.    DATA=1;                                 // 主线空闲状态
  60.    _nop_();
  61.    _nop_();
  62.    DATA=0;                                 // 主机发送开始工作信号
  63.    Delay20ms();   //延时18ms以上
  64.    DATA=1;                                 // 拉高并延时等待DHT11响应
  65.    Delay30us();
  66. }
  67. /*********************************************************************************************
  68. 函数名:DHT11读数据函数
  69. 调  用:? = DHT11_rec_byte();
  70. 参  数:无
  71. 返回值:
  72. 结  果:读DHT11数据并保存到dat
  73. 备  注:
  74. **********************************************************************************************/

  75. uchar DHT11_rec_byte()      //接收一个字节
  76. {
  77.    uchar i,dat=0;
  78.   for(i=0;i<8;i++)    //从高到低依次接收8位数据
  79.    {         
  80.       while(!DATA);   ////等待50us低电平过去
  81.       Delay30us();
  82.           Delay30us();     //延时60us,如果还为高则数据为1,否则为0
  83.       dat<<=1;           //左移位使正确接收8位数据,数据为0时直接移位
  84.       if(DATA==1)    //数据为1时,使dat加1来接收数据1
  85.          dat+=1;
  86.       while(DATA);  //等待数据线拉低   
  87.     }  
  88.     return dat;
  89. }

  90. /*********************************************************************************************
  91. 函数名:接收DHT11的40位的数据并校验
  92. 调  用:? = DHT11_receive();
  93. 参  数:无
  94. 返回值:无
  95. 结  果:结果保存到dat_r[i]中
  96. 备  注:
  97. **********************************************************************************************/
  98. void DHT11_receive()      //接收40位的数据
  99. {
  100.     uchar R_H,R_L,T_H,T_L,RH,RL,TH,TL,revise;
  101.     DHT11_start();                 // 主机控制DHT11开始工作
  102.     if(DATA==0)
  103.     {
  104.         while(DATA==0);   //等待拉高     
  105.         Delay30us();
  106.                 Delay30us();
  107.                 Delay30us();  //拉高后延时80us
  108.         R_H=DHT11_rec_byte();    //接收湿度高八位  
  109.         R_L=DHT11_rec_byte();    //接收湿度低八位  
  110.         T_H=DHT11_rec_byte();    //接收温度高八位  
  111.         T_L=DHT11_rec_byte();    //接收温度低八位
  112.         revise=DHT11_rec_byte(); //接收校正位

  113.         Delay30us();    //结束

  114.         if((R_H+R_L+T_H+T_L)==revise)      //校正
  115.         {
  116.             RH=R_H;
  117.             RL=R_L;
  118.             TH=T_H;
  119.             TL=T_L;
  120.         }
  121.         /*数据处理,方便显示*/
  122.         dat_r[0]='0'+(RH/10);
  123.         dat_r[1]='0'+(RH%10);
  124.         dat_r[2]='0'+(TH/10);
  125.         dat_r[3]='0'+(TH%10);
  126.     }
  127. }

  128. /********************************************************************
  129. * 名称 : bit Busy(void)
  130. * 功能 : 这个是一个读状态函数,读出函数是否处在忙状态
  131. * 输入 : 输入的命令值
  132. * 输出 : 无
  133. ***********************************************************************/
  134. void Busy(void)
  135. {
  136. bit busy_flag = 1;
  137. IODATA  = 0xff;
  138. RS = 0;          //指令关
  139. Delay30us();
  140. RW = 1;          //读状态
  141. Delay30us();
  142. E = 1;        //使能高电平
  143. while(1)
  144. {
  145. busy_flag = (bit)(IODATA  & 0x80); //强制取最高位
  146. if(busy_flag == 0)
  147. {
  148. break;
  149. }
  150. }
  151. E = 0;           //E 1->0,rs=0,rw=1,
  152.            //将数据寄存器内的数据读到DB0~DB7,分别将状态标志BF和地址计数器(AC)内容读到DB7和DB6~DB0。

  153. }

  154. /********************************************************************
  155. * 名称 : lcd1602_write_cmd(uchar del)
  156. * 功能 : 1602命令函数
  157. * 输入 : 输入的命令值
  158. * 输出 : 无
  159. ***********************************************************************/
  160. void lcd1602_write_cmd(uchar del)
  161. {
  162. RS = 0;
  163. Delay30us();
  164. RW = 0;
  165. Delay30us();
  166. E = 0;
  167. Delay30us();
  168. IODATA  = del;
  169. Delay30us();
  170. E = 1;
  171. Delay30us();
  172. E = 0;                        //E 1->0,rs=0,rw=0, 将指令代码写入指令寄存器中
  173. }

  174. /********************************************************************
  175. * 名称 : lcd1602_write_data(uchar del)
  176. * 功能 : 1602写数据函数
  177. * 输入 : 需要写入1602的数据
  178. * 输出 : 无
  179. ***********************************************************************/

  180. void lcd1602_write_data(uchar del)
  181. {
  182. Busy();      
  183. Delay30us();
  184. RS = 1;
  185. Delay30us();
  186. RW = 0;
  187. Delay30us();
  188. E = 0;
  189. Delay30us();
  190. IODATA  = del;
  191. Delay30us();
  192. E = 1;
  193. Delay30us();
  194. E = 0;                          //E 1->0,rs=1,rw=0, 数据写入数据寄存器中
  195. }

  196. /********************************************************************
  197. * 名称 : lcd1602_init()
  198. * 功能 : 1602初始化,请参考1602的资料
  199. * 输入 : 无
  200. * 输出 : 无
  201. ***********************************************************************/
  202. void lcd1602_init(void)
  203. {
  204. Delay20ms();
  205. lcd1602_write_cmd(0x38);         //8位数据,双列,5*7字形
  206. Delay20ms();
  207. lcd1602_write_cmd(0x38);
  208. Delay20ms();
  209. lcd1602_write_cmd(0x38);
  210. Busy();
  211. lcd1602_write_cmd(0x08);// 只开显示
  212. Busy();   
  213. lcd1602_write_cmd(0x01);        //清屏
  214. Busy();
  215. lcd1602_write_cmd(0x06);//显示地址递增,即写一个数据后,显示位置右移一位
  216. Busy();
  217. lcd1602_write_cmd(0x0c);        //开启显示屏,关光标,光标不闪烁
  218. }

  219. /********************************************************************
  220. * 名称 : lcd1602_char(uchar hang,uchar lie,char sign)
  221. * 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符显示"b" ,调用该函数如下
  222. L1602_char(1,5,'b')
  223. * 输入 : 行,列,需要输入1602的数据
  224. * 输出 : 无
  225. ***********************************************************************/
  226. void lcd1602_char(uchar hang,uchar lie,char sign)
  227. {
  228. uchar a;
  229. if(hang == 1)
  230. {
  231. a = 0x80;
  232. }
  233. if(hang == 2)
  234. {
  235. a = 0xc0;
  236. }
  237. a = a + lie - 1;
  238. Busy();
  239. lcd1602_write_cmd(a);  //置数据存贮器地址
  240. Busy();
  241. lcd1602_write_data(sign);
  242. }

  243. /********************************************************************
  244. * 名称 : lcd1602_string(uchar hang,uchar lie,uchar *p)
  245. * 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
  246. L1602_string(1,5,"ab cd ef;")
  247. * 输入 : 行,列,需要输入1602的数据
  248. * 输出 : 无
  249. ***********************************************************************/
  250. void lcd1602_string(uchar hang,uchar lie,uchar *p)
  251. {
  252. uchar a;
  253. if(hang == 1)
  254. {
  255. a = 0x80;
  256. }
  257. if(hang == 2)
  258. {
  259. a = 0xc0;
  260. }
  261. a = a + lie - 1;
  262. while(1)
  263. {
  264. Busy();
  265. lcd1602_write_cmd(a);
  266. Busy();
  267. lcd1602_write_data(*p);
  268. a++;
  269. p++;   
  270. if((*p == '\0')||(a==0x90)||(a==0xd0)) //字符结束或每行最后一个字符
  271. {
  272. break;
  273. }
  274. }
  275. }

  276. /*********************************************************************************************
  277. 函数名:主函数
  278. 调  用:无
  279. 参  数:无
  280. 返回值:无
  281. 结  果:读DHT11数据并送到1602显示
  282. 备  注:
  283. **********************************************************************************************/
  284. void main (void)
  285. {
  286.         
  287.         Delay20ms();
  288.         lcd1602_init();                //LCD初始化
  289.         while(1)
  290.         {
  291.                 Delay1s();                //经测试,两次连读要至少延时80ms        
  292.                 DHT11_receive();//接受数据
  293.                 lcd1602_string(1,1,"SHIDU:");
  294.                 lcd1602_string(2,1,"WENDU:");
  295.                 lcd1602_char(1,7,dat_r[0]);
  296.                 lcd1602_char(1,8,dat_r[1]);
  297.                 lcd1602_char(2,7,dat_r[2]);
  298.                 lcd1602_char(2,8,dat_r[3]);
  299.                 lcd1602_string(1,9,"%");
  300.                 lcd1602_char(2,9,0XDF);
  301.                 lcd1602_string(2,10,"C");
  302.                
  303.         }
  304. }


weifeng90 发表于 2023-7-17 08:30 来自手机 | 显示全部楼层
还有用1602显示屏的吗?
jf101 发表于 2023-7-24 13:39 | 显示全部楼层
weifeng90 发表于 2023-7-17 08:30
还有用1602显示屏的吗?

这种小屏确实用的比较少了,建议还是使用LCD的吧
小小蚂蚁举千斤 发表于 2023-7-25 09:46 | 显示全部楼层
很经典的样例程序尤其是1602
小夏天的大西瓜 发表于 2023-7-25 10:16 | 显示全部楼层
1602液晶的案例还是挺多的
OKAKAKO 发表于 2023-7-25 13:06 | 显示全部楼层
DHT11温湿度计使用IIC通信的嘛?
LOVEEVER 发表于 2023-7-26 17:45 | 显示全部楼层
DHT11温湿度具体硬件参数有吗
linfelix 发表于 2023-8-7 07:36 | 显示全部楼层
DHT11检测温湿度求教              
geraldbetty 发表于 2023-8-7 08:20 | 显示全部楼层
dht11温度传感器显示屏不亮怎么回事
biechedan 发表于 2023-8-7 08:26 | 显示全部楼层
在读取DHT11传感器的温湿度数据后,需要进行适当的数据处理和格式化,以便在液晶显示屏上进行正确的显示。
wangdezhi 发表于 2023-8-7 19:45 | 显示全部楼层
在使用1602液晶显示屏之前,需要进行初始化设置。这通常包括设置显示模式、光标和光标闪烁等。
lihuami 发表于 2023-8-7 21:56 | 显示全部楼层
DHT11传感器具有一定的响应时间,通常建议在两次读取之间留出适当的延迟时间,以确保传感器有足够的时间完成测量和数据更新。
plsbackup 发表于 2023-8-9 15:38 | 显示全部楼层
在读取DHT11的数据之前,需要适当的延时以确保传感器完成数据采集和转换
hilahope 发表于 2023-8-14 09:06 | 显示全部楼层
DHT11的精度可能会受到环境条件和其他因素的影响
adolphcocker 发表于 2023-8-14 13:21 | 显示全部楼层
应用中可能需要进行温湿度校准。可以通过与其他已知准确度的传感器进行比较或使用校准算法来调整读取到的数据。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

64

主题

1613

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部