找回密码
 立即注册
搜索
热搜: 中医 针灸 咳嗽
查看: 194|回复: 0

DHT11采集温度LCD1602显示数据

[复制链接]

3711

主题

1

回帖

1万

积分

管理员

积分
11949
发表于 2023-2-28 12:51:42 | 显示全部楼层 |阅读模式
说明:
实际硬件参数如下
晶振:11.0592
IC:STC89C52RC


LCD1602部分:

移植了之前写的LCD1602驱动,因为该驱动显示方式丰富,有整数,小数,字符串三种方式显示内容,移植性很高

DHT11部分:

DHT11部分,将上电延时等待改为2秒,根据温度要求每次采集的时间应该间隔2秒,这样更符合文档要求

其他说明:
整体采用了分文件的方式进行编写,有利于下次更加方便移植.

main.c

  1. #include "DHT11.h"   // 包含头文件
  2. #include "LCD1602.h" // 包含头文件

  3. void main()
  4. {

  5.     uchar rec_dat[4]; // 定义一个温湿度存储数组01 存储温度高低位23存储湿度高低位
  6.     float temp_float; // 温度值
  7.     float HU_float;   // 湿度值
  8.     uchar *dis_str;
  9.     int count;
  10.     DU = 0; // 关闭开发板上的数码管段显示
  11.     WE = 0; // 关闭开发板上的数码管位显示

  12.     lcd_init();

  13.     while (1) { // 循环显示温湿度

  14.         count++;              // 统计采集次数
  15.         DHT11_delay_ms(2000); // dht11上电后等待1秒,为了确保数据精确性,与采集间隔2秒限制,直接延迟2秒
  16.         // 数据采集部分-----------------------------------------
  17.         dis_str = DHT11_receive(&rec_dat);
  18.         // 数据计算部分-----------------------------------------
  19.         temp_float = rec_dat[0] + (float)((float)rec_dat[1] / 100);
  20.         HU_float   = rec_dat[2] + (float)((float)rec_dat[3] / 100);

  21.         // 数据显示部分----------------------------------------
  22.         lcd_show_str(0, 0, "TEMP:");      // 显示温度前缀修饰
  23.         lcd_show_float(6, 0, HU_float);   // 显示湿度在第0行
  24.         lcd_show_str(12, 0, "C");         // 显示温度单位
  25.         lcd_show_str(0, 1, "HU:");        // 显示湿前缀修饰
  26.         lcd_show_float(4, 1, temp_float); // 显示温度在第1行
  27.         lcd_show_str(9, 1, "%");         // 显示湿度百分百符号
  28.         lcd_show_int(11, 1, count);       // 采集次数显示
  29.     }
  30. }
复制代码



DHT11.C
  1. #include "DHT11.h"

  2. // DHT11延时函数
  3. void DHT11_delay_us(uchar n)
  4. {
  5.     while (--n)
  6.         ;
  7. }
  8. void DHT11_delay_ms(uint z)
  9. {
  10.     uint i, j;
  11.     for (i = z; i > 0; i--)
  12.         for (j = 110; j > 0; j--)
  13.             ;
  14. }
  15. // DHT11驱动
  16. void DHT11_start()
  17. {
  18.     Data = 1;
  19.     DHT11_delay_us(2);
  20.     Data = 0;
  21.     DHT11_delay_ms(25); // 延时18ms以上
  22.     Data = 1;
  23.     DHT11_delay_us(30);
  24. }
  25. // DHT11接收8位二进制数
  26. uchar DHT11_rec_byte()
  27. {
  28.     uchar i, dat = 0;
  29.     for (i = 0; i < 8; i++) {
  30.         while (!Data)
  31.             ;
  32.         DHT11_delay_us(8); // 延时60ms,如果p3^6口仍然为高电平,则 为1,反之为0
  33.         dat <<= 1;
  34.         if (Data == 1)
  35.             dat += 1;
  36.         while (Data)
  37.             ;
  38.     }
  39.     return dat;
  40. }

  41. // DHT11接收40位数据 void DHT11_receive()
  42. uchar *DHT11_receive(uchar rec_dat[])
  43. {
  44.     uchar R_H, R_L, T_H, T_L, RH, RL, TH, TL, revise;
  45.     DHT11_start();
  46.     if (Data == 0) {
  47.         while (Data == 0)
  48.             ;
  49.         DHT11_delay_us(40);
  50.         R_H    = DHT11_rec_byte(); // 接收湿度高八位
  51.         R_L    = DHT11_rec_byte(); // 接收湿度低八位
  52.         T_H    = DHT11_rec_byte(); // 接收温度高八位
  53.         T_L    = DHT11_rec_byte(); // 接收温度低八位
  54.         revise = DHT11_rec_byte(); // 接收校正位
  55.         DHT11_delay_us(25);
  56.         if ((R_H + R_L + T_H + T_L) == revise) // 判断接收数据是否正确
  57.         {
  58.             RH = R_H;
  59.             RL = R_L;
  60.             TH = T_H;
  61.             TL = T_L;
  62.         }
  63.         rec_dat[0] = RH; // 温度高位
  64.         rec_dat[1] = RL; // 温度低位
  65.         rec_dat[2] = TH; // 湿度高位
  66.         rec_dat[3] = TL; // 湿度低位
  67.     }
  68.     return &rec_dat;
  69. }

  70. void DHT11() // 调用列子
  71. {
  72.     uchar rec_dat[4]; // 定义一个温湿度存储数组01 存储温度高低位23存储湿度高低位
  73.     float temp_float; // 温度值
  74.     float HU_float;   // 湿度值
  75.     uchar *dis_str;
  76.     int count;

  77.     count++;              // 统计采集次数
  78.         DHT11_delay_ms(2000); // dht11上电后等待1秒,为了确保数据精确性,与采集间隔2秒限制,直接延迟2秒
  79.     // 数据采集部分-----------------------------------------
  80.     dis_str = DHT11_receive(&rec_dat);
  81.     // 数据计算部分-----------------------------------------
  82.     temp_float = rec_dat[0] + (float)((float)rec_dat[1] / 100);
  83.     HU_float   = rec_dat[2] + (float)((float)rec_dat[3] / 100);
  84. }
复制代码


DHT11.h
  1. #ifndef DHT11_H // 防止重复 include
  2. #define DHT11_H
  3. #endif
  4. #include <reg52.h>

  5. #define uchar unsigned char
  6. #define uint  unsigned int

  7. // 声明全局变量

  8. sbit Data = P2 ^ 0; // 定义dht11数据线
  9. sbit rs   = P3 ^ 5;
  10. sbit rw   = P3 ^ 6;
  11. sbit en   = P3 ^ 4;
  12. //  uchar rec_dat[30]; // 接收1602显示数据数组
  13. sbit DU = P2 ^ 6; // 关闭数码段位
  14. sbit WE = P2 ^ 7; // 关闭数码管位
  15. // 声明计函数
  16. void DHT11_delay_ms(uint z);
  17. void DHT11_start();
  18. uchar DHT11_rec_byte();
  19. uchar *DHT11_receive(uchar rec_dat[]);
  20. void DHT11();
  21. void DHT11_delay_us(uchar n);
  22. void DHT11_delay_ms(uint z);
复制代码
LCD1602.C
  1. #include "LCD1602.h" //包含了STC89C52的头文件

  2. void delay(unsigned int i)
  3. { // 延迟函数,i为延迟时间
  4.     unsigned int j;
  5.     for (; i > 0; i--) {
  6.         for (j = 0; j < 125; j++)
  7.             ;
  8.     }
  9. }

  10. void lcd_busy()
  11. { // 判断LCD是否忙的函数
  12.     unsigned char busy;
  13.     P0 = 0xFF; // 将P0口设为输入模式
  14.     RS = 0;    // RS置为低电平
  15.     RW = 1;    // RW置为高电平
  16.     EN = 0;    // 使能引脚EN置为低电平
  17.     delay(5);  // 延时5ms
  18.     do {
  19.         EN   = 1;          // 使能引脚EN置为高电平
  20.         busy = P0;         // 读取P0口的值
  21.         EN   = 0;          // 使能引脚EN置为低电平
  22.     } while (busy & 0x80); // 判断busy的最高位是否为1
  23.     P0 = 0x00;             // 将P0口设为输出模式
  24. }

  25. void lcd_write_cmd(unsigned char cmd)
  26. {               // 发送命令的函数
  27.     lcd_busy(); // 判断LCD是否忙
  28.     RS = 0;     // RS置为低电平
  29.     RW = 0;     // RW置为低电平
  30.     EN = 0;     // 使能引脚EN置为低电平
  31.     P0 = cmd;   // 将命令写入P0口
  32.     EN = 1;     // 使能引脚EN置为高电平
  33.     EN = 0;     // 使能引脚EN置为低电平
  34. }

  35. void lcd_write_data(unsigned char dat)
  36. {               // 发送数据的函数
  37.     lcd_busy(); // 判断LCD是否忙
  38.     RS = 1;     // RS置为高电平
  39.     RW = 0;     // RW置为低电平
  40.     EN = 0;     // 使能引脚EN置为低电平
  41.     P0 = dat;   // 将数据写入P0口
  42.     EN = 1;     // 使能引脚EN置为高电平
  43.     EN = 0;     // 使能引脚EN置为低电平
  44. }

  45. void lcd_set_pos(unsigned char x, unsigned char y)
  46. { // 设置显示位置的函数
  47.     unsigned char pos;

  48.     if (y == 0) {       // 第一行
  49.         pos = 0x80 + x; // 计算显示位置
  50.     } else {            // 第二行
  51.         pos = 0xC0 + x; // 计算显示位置
  52.     }
  53.     lcd_write_cmd(pos); // 发送命令,设置显示位置
  54. }

  55. void lcd_init()
  56. {                        // LCD初始化函数
  57.     lcd_write_cmd(0x38); // 设置LCD显示模式为2行,5*7点阵
  58.     lcd_write_cmd(0x0C); // 显示开,不显示光标,不闪烁
  59.     lcd_write_cmd(0x06); // 文字不动,地址自动+1
  60.     lcd_write_cmd(0x01); // 清屏
  61. }

  62. void lcd_show_char(unsigned char x, unsigned char y, unsigned char dat)
  63. {                        // 显示单个字符的函数
  64.     lcd_set_pos(x, y);   // 设置显示位置
  65.     lcd_write_data(dat); // 发送数据,显示字符
  66. }

  67. void lcd_show_str(unsigned char x, unsigned char y, char *str)
  68. {                               // 显示字符串的函数
  69.     lcd_set_pos(x, y);          // 设置显示位置
  70.     while (*str) {              // 当字符串不为空
  71.         lcd_write_data(*str++); // 发送数据,显示字符
  72.     }
  73. }
  74. /*
  75. 参数1 x:第几行
  76. 参数2 y:第几列
  77. 参数3 num:具体数值
  78. */
  79. void lcd_show_float(unsigned char x, unsigned char y, float num)
  80. {                            // 显示浮点数的函数
  81.     int integer  = (int)num; // 整数部分
  82.     int integer2 = integer;
  83.     int decimal  = (int)((num - integer) * 100); // 小数部分,保留2位
  84.     int wei_cout = 0;
  85.     while (integer2) {
  86.         integer2 /= 10;
  87.         wei_cout++;
  88.     }
  89.     // 计算整数部分位数

  90.     lcd_show_int(x, y, integer);                        // 先显示整数部分
  91.     lcd_write_data('.');                                // 小数点
  92.     if (wei_cout == 0) {                                // 如果整数部分=0
  93.         if (decimal > 10) {                             // 如果小数部分>0.1
  94.             lcd_show_int(x + wei_cout + 2, y, decimal); // 再显示小数部分
  95.         } else {                                        // 如果小数部分<=0.1
  96.             lcd_show_int(x + wei_cout + 2, y, 0);
  97.             lcd_show_int(x + wei_cout + 3, y, decimal);
  98.         }

  99.     } else {                                            // 如果整数部分大于0
  100.                                                         // lcd_show_int(x + wei_cout + 1, y, decimal); // 再显示小数部分
  101.         if (decimal > 10) {                             // 如果小数部分>0.1
  102.             lcd_show_int(x + wei_cout + 1, y, decimal); // 再显示小数部分
  103.         } else {                                        // 如果小数部分<=0.1
  104.             lcd_show_int(x + wei_cout + 1, y, 0);
  105.             lcd_show_int(x + wei_cout + 2, y, decimal);
  106.         }
  107.     }
  108. }

  109. void lcd_show_int(unsigned char x, unsigned char y, int num)
  110. {                            // 显示整数的函数
  111.     char str[16];            // 定义一个字符串数组
  112.     sprintf(str, "%d", num); // 将整数转换为字符串
  113.     lcd_show_str(x, y, str); // 调用显示字符串的函数,显示整数
  114. }

  115. void LCD1602() // LCD1602 调用列子
  116. {
  117.     lcd_init();                         // 初始化LCD
  118.     lcd_show_str(0, 0, "Hello World!"); // 显示字符串
  119.     lcd_show_int(0, 1, 123);            // 显示整数
  120.     lcd_show_float(6, 1, 596.0422);     // 显示浮点数
  121.     while (1)
  122.         ; // 循环等待
  123. }
复制代码



LCD1602.H

  1. #ifndef LCD1602_H // 防止重复 include
  2. #define LCD1602_H
  3. #endif

  4. #include <reg52.h>
  5. #include <stdio.h>

  6. // 声明全局变量
  7. sbit RS = P3 ^ 5; // 将寄存器选择引脚RS定义为P3.5
  8. sbit RW = P3 ^ 6; // 将读写选择引脚RW定义为P3.6
  9. sbit EN = P3 ^ 4; // 将使能引脚EN定义为P3.4
  10. // 声明函数
  11. void lcd_show_int(unsigned char x, unsigned char y, int num);
  12. void lcd_show_float(unsigned char x, unsigned char y, float num);
  13. void lcd_show_str(unsigned char x, unsigned char y, char *str);
  14. void lcd_show_char(unsigned char x, unsigned char y, unsigned char dat);
  15. void lcd_init();
  16. void lcd_set_pos(unsigned char x, unsigned char y);
  17. void lcd_write_data(unsigned char dat);
  18. void lcd_write_cmd(unsigned char cmd);
  19. void lcd_busy();
  20. void delay(unsigned int i);
  21. void LCD1602();
复制代码


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

本版积分规则

Archiver|手机版|小黑屋|私人站点 ( 冀ICP备2023028127号-2 )

GMT+8, 2025-8-22 23:34 , Processed in 0.106204 second(s), 21 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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