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:串口打印效果
- //主函数
- void main(void)
- {
- uint8 pdata uart_cmd_buf[64] = {0};
- //设置STC15W408AS单片机端口为标准模式
- Config_Port();
- //串口初始化,波特率9600
- UART_Config_1(9600);
-
- //定时器0设置,1ms循环
- Timer0Init();
- //启动DS18B20
- DS18B20_Start();
- // 事件处理循环
- while(1)
- {
- UART_Cmd_Check(&uart_cmd_buf, sizeof(uart_cmd_buf)-1);
-
- if (timer_flag_10s) //每隔10s执行以下分支
- {
- printf("\r\n### timer_count %06u seconds ###\r\n", 10*++timer_count);
- timer_flag_10s = 0;
- DS18B20_Update_Show();
- DHT_Update_Show();
- }
-
- }
- }
复制代码- void DHT_Update_Show(void)
- {
- T_DHT_Data dht_data;
- uint8 ret = 0;
- memset(&dht_data, 0x0, sizeof(T_DHT_Data));
- if(0 == DHT_Read(&dht_data, E_DHT11))
- {
- printf(">>>DHT11 R: %4.1f %%\r\n", dht_data.R);
- printf(">>>DHT11 T: %4.1f c\r\n", dht_data.T);
- }
- else
- {
- printf(">>>DHT11_Read failed.\r\n");
- }
- printf("\r\n");
- memset(&dht_data, 0x0, sizeof(T_DHT_Data));
- if(0 == DHT_Read(&dht_data, E_DHT22))
- {
- printf(">>>DHT22 R: %4.1f %%\r\n", dht_data.R);
- printf(">>>DHT22 T: %4.1f c\r\n", dht_data.T);
- }
- else
- {
- printf(">>>DHT22_Read failed.\r\n");
- }
- printf("\r\n");
- }
复制代码- typedef struct _DHT_Data
- {
- uint8 R_H_Byte; //湿度高位字节
- uint8 R_L_Byte; //湿度低位字节
- uint8 T_H_Byte; //温度高位字节
- uint8 T_L_Byte; //湿度低位字节
- uint8 Chk_Sum; //读取校验和
- uint8 Cal_Sum; //计算校验和
- float R; //湿度计算结果
- float T; //温度计算结果
- } T_DHT_Data;
- typedef enum dht_type
- {
- E_DHT11,
- E_DHT22,
- } E_DHT_TYPE;
- sbit DHT11_DIO = P1^2; // DHT11数据端口
- sbit DHT22_DIO = P1^3; // DHT22数据端口
- bit DHT_Read(T_DHT_Data *Data, E_DHT_TYPE dht_type);
复制代码- bit DHT_Read(T_DHT_Data *Data, E_DHT_TYPE dht_type)
- {
- uint8 ack = 0;
- uint8 cnt = 0;
- bit chk = 0;
- if(E_DHT11 == dht_type)
- if(DEBUG_MODE) printf(">>>DHT11_Read...\r\n");
- else
- if(DEBUG_MODE) printf(">>>DHT22_Read...\r\n");
- //发送起始信号
- DHT_Start(dht_type);
- _Set_IO_Input(dht_type); //DHT DIO数据端口设置为输入模式
- //等待低电平
- if(E_DHT11 == dht_type)
- while(DHT11_DIO);
- else
- while(DHT22_DIO);
- //DHT11会拉低40~80us
- if(E_DHT11 == dht_type)
- while(!DHT11_DIO && 10 > cnt++) Delay10us();
- else
- while(!DHT22_DIO && 10 > cnt++) Delay10us();
- //这里不要使用printf这种耗时长的语句,否则会造成时序错乱
- //printf(">>>DHT_Read 2-1(cnt=%bu)\r\n", cnt);
- if(10 > cnt)
- {
- //DHT11会继续拉高40~80us
- //Delay100us();
- cnt = 0;
- if(E_DHT11 == dht_type)
- while(DHT11_DIO && 10 > cnt++) Delay10us();
- else
- while(DHT22_DIO && 10 > cnt++) Delay10us();
-
- if(10 < cnt) return 1; //返回读取失败
- //这里不要使用printf这种耗时长的语句,否则会造成时序错乱
- //printf(">>>DHT_Read 2-1(cnt=%bu)\r\n", cnt);
- Data->R_H_Byte = DHT_Read_Byte(dht_type); //读湿度数据高8位
- Data->R_L_Byte = DHT_Read_Byte(dht_type); //读湿度数据低8位
- Data->T_H_Byte = DHT_Read_Byte(dht_type); //读温度数据高8位
- Data->T_L_Byte = DHT_Read_Byte(dht_type); //读温度数据低8位
- Data->Chk_Sum = DHT_Read_Byte(dht_type); //读校验位
- _Set_IO_Output(dht_type);//DHT DIO数据端口设置为为输出模式
- //释放总线
- if(E_DHT11 == dht_type)
- DHT11_DIO = 0;
- else
- DHT22_DIO = 0;
- Delay10us();Delay10us();Delay10us(); //读取结束,拉低电平30us
- 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);
- 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);
- if(DEBUG_MODE) printf(">>>DHT_Read Data->Chk_Sum: %bu\r\n", Data->Chk_Sum);
- //将温湿度高低8位累加校验和,并强制转换为uint8类型
- Data->Cal_Sum = (uint8)(Data->R_L_Byte + Data->R_H_Byte + Data->T_L_Byte + Data->T_H_Byte);
- if(DEBUG_MODE) printf(">>>DHT_Read Chk_Sum: %bu, Cal_Sum: %bu\r\n", Data->Chk_Sum, Data->Cal_Sum);
- if(Data->Chk_Sum == Data->Cal_Sum)//校验正确
- {
- if(E_DHT11 == dht_type)
- {
- Data->R = (float)((10 * Data->R_H_Byte + Data->R_L_Byte) / 10);//转换湿度数据
- Data->T = (float)((10 * Data->T_H_Byte + Data->T_L_Byte) / 10);//转换温度数据
- }
- else
- {
- Data->R = (float)((256 * Data->R_H_Byte + Data->R_L_Byte) / 10);//转换湿度数据
- Data->T = (float)((256 * Data->T_H_Byte + Data->T_L_Byte) / 10);//转换温度数据
- }
- return 0; //返回读取成功
- }
- }
- return 1; //返回读取失败
- }
复制代码
完整代码如下:
图3:代码文件组成
UART_DHT_STC15W408AS.7z
(17.04 KB, 下载次数: 88)
|