找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3131|回复: 0
打印 上一主题 下一主题
收起左侧

51单片机学习实践:读取DHT11和DHT22测量的温湿度并在串口打印 附程序

[复制链接]
跳转到指定楼层
楼主
STC15单片机
实验名称:读取DHT11和DHT22测量的温度和湿度
实验内容:
        读取DHT11和DHT22测量的温度和湿度,使用串口打印
        读取DS18B20模块测量温度作为参考比较
实验器材:
        STC15W408AS_DIP16 x1
        DS18B20  x1
        DHT11    x1
        DHT22    x1

在STC15单片机上读取DHT11和DHT22测量的温度和湿度的基本方法:
1、MCU发送启动信号,等待DHT11/22响应
2、DHT11/22响应后,MCU开始读取40个字节测量数据;
3、检查校验和,计算测量结果


实验心得:
1、DHT11/22的单总线时序基本相同,可以合并读取代码,使用入参不同进行小部分区别处理;
2、DHT11/22的测量结果可以共用一个结构体类型;
3、DHT11/22的单总线时序很紧凑,MCU发送启动信号以后直到读取40个字节数据之间,代码尽量紧凑,避免使用printf这种耗时函数,否则容易出现读取失败;

图1:DHT11和DHT22模块



图2:串口打印效果




  1. //主函数
  2. void main(void)
  3. {
  4.         uint8 pdata uart_cmd_buf[64] = {0};

  5.         //设置STC15W408AS单片机端口为标准模式
  6.         Config_Port();

  7.         //串口初始化,波特率9600
  8.         UART_Config_1(9600);
  9.        
  10.         //定时器0设置,1ms循环
  11.         Timer0Init();

  12.         //启动DS18B20
  13.         DS18B20_Start();

  14.         // 事件处理循环
  15.         while(1)
  16.         {       
  17.                 UART_Cmd_Check(&uart_cmd_buf, sizeof(uart_cmd_buf)-1);
  18.                
  19.         if (timer_flag_10s)  //每隔10s执行以下分支
  20.         {
  21.                         printf("\r\n### timer_count %06u seconds ###\r\n", 10*++timer_count);
  22.             timer_flag_10s = 0;

  23.                         DS18B20_Update_Show();
  24.                         DHT_Update_Show();
  25.                 }
  26.                
  27.         }   
  28. }
复制代码
  1. void DHT_Update_Show(void)
  2. {
  3.         T_DHT_Data dht_data;
  4.         uint8 ret = 0;

  5.         memset(&dht_data, 0x0, sizeof(T_DHT_Data));
  6.         if(0 == DHT_Read(&dht_data, E_DHT11))
  7.         {
  8.                 printf(">>>DHT11  R: %4.1f %%\r\n", dht_data.R);
  9.                 printf(">>>DHT11  T: %4.1f c\r\n", dht_data.T);
  10.         }
  11.         else
  12.         {
  13.                 printf(">>>DHT11_Read failed.\r\n");
  14.         }

  15.         printf("\r\n");

  16.         memset(&dht_data, 0x0, sizeof(T_DHT_Data));
  17.         if(0 == DHT_Read(&dht_data, E_DHT22))
  18.         {
  19.                 printf(">>>DHT22  R: %4.1f %%\r\n", dht_data.R);
  20.                 printf(">>>DHT22  T: %4.1f c\r\n", dht_data.T);
  21.         }
  22.         else
  23.         {
  24.                 printf(">>>DHT22_Read failed.\r\n");
  25.         }

  26.         printf("\r\n");
  27. }
复制代码
  1. typedef struct _DHT_Data
  2. {
  3.         uint8 R_H_Byte;        //湿度高位字节
  4.         uint8 R_L_Byte;        //湿度低位字节
  5.         uint8 T_H_Byte;        //温度高位字节
  6.         uint8 T_L_Byte;        //湿度低位字节
  7.         uint8 Chk_Sum;        //读取校验和
  8.         uint8 Cal_Sum;        //计算校验和
  9.         float R;                //湿度计算结果
  10.         float T;                //温度计算结果
  11. } T_DHT_Data;

  12. typedef enum dht_type
  13. {
  14.         E_DHT11,
  15.         E_DHT22,
  16. } E_DHT_TYPE;

  17. sbit DHT11_DIO = P1^2; // DHT11数据端口
  18. sbit DHT22_DIO = P1^3; // DHT22数据端口

  19. bit DHT_Read(T_DHT_Data *Data, E_DHT_TYPE dht_type);
复制代码
  1. bit DHT_Read(T_DHT_Data *Data, E_DHT_TYPE dht_type)
  2. {
  3.         uint8 ack = 0;
  4.         uint8 cnt = 0;
  5.         bit   chk = 0;

  6.         if(E_DHT11 == dht_type)
  7.                 if(DEBUG_MODE) printf(">>>DHT11_Read...\r\n");
  8.         else
  9.                 if(DEBUG_MODE) printf(">>>DHT22_Read...\r\n");

  10.         //发送起始信号
  11.         DHT_Start(dht_type);

  12.         _Set_IO_Input(dht_type); //DHT DIO数据端口设置为输入模式

  13.     //等待低电平
  14.         if(E_DHT11 == dht_type)
  15.                 while(DHT11_DIO);
  16.         else
  17.                 while(DHT22_DIO);

  18.     //DHT11会拉低40~80us
  19.         if(E_DHT11 == dht_type)
  20.                 while(!DHT11_DIO && 10 > cnt++) Delay10us();
  21.         else
  22.                 while(!DHT22_DIO && 10 > cnt++) Delay10us();

  23.         //这里不要使用printf这种耗时长的语句,否则会造成时序错乱
  24.         //printf(">>>DHT_Read 2-1(cnt=%bu)\r\n", cnt);

  25.         if(10 > cnt)
  26.         {
  27.                 //DHT11会继续拉高40~80us
  28.                 //Delay100us();

  29.                  cnt = 0;
  30.                  if(E_DHT11 == dht_type)
  31.                          while(DHT11_DIO && 10 > cnt++) Delay10us();
  32.                  else
  33.                          while(DHT22_DIO && 10 > cnt++) Delay10us();
  34.                  
  35.                  if(10 < cnt) return 1; //返回读取失败

  36.                 //这里不要使用printf这种耗时长的语句,否则会造成时序错乱
  37.                 //printf(">>>DHT_Read 2-1(cnt=%bu)\r\n", cnt);

  38.                 Data->R_H_Byte        = DHT_Read_Byte(dht_type); //读湿度数据高8位
  39.                 Data->R_L_Byte        = DHT_Read_Byte(dht_type); //读湿度数据低8位
  40.                 Data->T_H_Byte        = DHT_Read_Byte(dht_type); //读温度数据高8位
  41.                 Data->T_L_Byte        = DHT_Read_Byte(dht_type); //读温度数据低8位
  42.                 Data->Chk_Sum        = DHT_Read_Byte(dht_type); //读校验位

  43.                 _Set_IO_Output(dht_type);//DHT DIO数据端口设置为为输出模式
  44.                 //释放总线
  45.                 if(E_DHT11 == dht_type)
  46.                         DHT11_DIO = 0;
  47.                 else
  48.                         DHT22_DIO = 0;
  49.                 Delay10us();Delay10us();Delay10us(); //读取结束,拉低电平30us

  50.                 if(DEBUG_MODE) printf(">>>DHT_Read Data->R_H_Byte: %bu, Data->R_L_Byte: %bu\r\n", Data->R_H_Byte, Data->R_L_Byte);
  51.                 if(DEBUG_MODE) printf(">>>DHT_Read Data->T_H_Byte: %bu, Data->T_L_Byte: %bu\r\n", Data->T_H_Byte, Data->T_L_Byte);
  52.                 if(DEBUG_MODE) printf(">>>DHT_Read Data->Chk_Sum: %bu\r\n", Data->Chk_Sum);

  53.                 //将温湿度高低8位累加校验和,并强制转换为uint8类型
  54.                 Data->Cal_Sum = (uint8)(Data->R_L_Byte + Data->R_H_Byte + Data->T_L_Byte + Data->T_H_Byte);

  55.                 if(DEBUG_MODE) printf(">>>DHT_Read Chk_Sum: %bu, Cal_Sum: %bu\r\n", Data->Chk_Sum, Data->Cal_Sum);

  56.                 if(Data->Chk_Sum == Data->Cal_Sum)//校验正确
  57.                 {
  58.                         if(E_DHT11 == dht_type)
  59.                         {
  60.                                 Data->R = (float)((10 * Data->R_H_Byte + Data->R_L_Byte) / 10);//转换湿度数据
  61.                                 Data->T = (float)((10 * Data->T_H_Byte + Data->T_L_Byte) / 10);//转换温度数据
  62.                         }
  63.                         else
  64.                         {
  65.                                 Data->R = (float)((256 * Data->R_H_Byte + Data->R_L_Byte) / 10);//转换湿度数据
  66.                                 Data->T = (float)((256 * Data->T_H_Byte + Data->T_L_Byte) / 10);//转换温度数据                       
  67.                         }
  68.                         return 0; //返回读取成功
  69.                 }
  70.         }
  71.         return 1; //返回读取失败
  72. }
复制代码

完整代码如下:

图3:代码文件组成



UART_DHT_STC15W408AS.7z (17.04 KB, 下载次数: 76)




评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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