Design of Indoor Air Quality Monitoring System Based on 51 Microcontroller

This system is designed based on the 51 microcontroller and features a comprehensive indoor air quality monitoring system that can monitor various air quality parameters in real-time, including temperature and humidity, CO2 concentration, formaldehyde concentration, methane concentration, and PM2.5 concentration, displaying the data through an LCD1602 screen. The system supports threshold settings and automatic control functions, automatically activating corresponding adjustment devices and issuing alarms when detected values exceed the set range.

System Composition

Hardware Components

  • Main Control Chip: STC89C51/52 Microcontroller

  • Temperature and Humidity Sensor: DHT11

  • Gas Sensors: MQ-4 (Methane Detection), SGP30 (CO2 and Formaldehyde Detection)

  • Particulate Matter Sensor: PM2.5 Detection Module

  • Display Module: LCD1602 Liquid Crystal Display

  • Actuators: Relay-controlled humidifier, dehumidifier, cooling equipment, heater, purifier, and ventilation equipment

  • Alarm Device: Buzzer

  • Input Device: Key Matrix

System Block Diagram:

Design of Indoor Air Quality Monitoring System Based on 51 MicrocontrollerEdit

Simulation Circuit:

Design of Indoor Air Quality Monitoring System Based on 51 MicrocontrollerEdit Introduction: This design uses the STC89C52 microcontroller as the core controller, along with other modules to form the entire indoor air detection system, which includes the central control part, input part, and output part. The central control part uses the STC89C52 microcontroller, whose main function is to acquire data from the input part, process it internally, and control the output part. The input consists of six parts: the first part is the SGP30 detection module, which can detect the current CO2 and formaldehyde concentrations; the second part is the PM2.5 detection module combined with the ADC0832 chip, which can detect the current PM2.5 concentration; the third part is the MQ-4 methane detection module combined with the ADC0832 chip, which can detect the current methane concentration; the fourth part is the DHT11 temperature and humidity detection module, which can detect the current temperature and humidity; the fifth part is independent keys, which can switch interfaces and adjust set values through three independent keys; the sixth part is the power supply circuit, which powers the entire system. The output consists of four parts: the first part is the LCD1602 display module, which can display the current CO2 concentration, formaldehyde concentration, methane concentration, PM2.5 concentration, temperature and humidity values, and modified set values; the second part is the relay, which closes when the measured gas concentration or temperature and humidity values are outside the set range for abnormal processing; the third part is the LED indicator, which lights up once each time a key is pressed; the fourth part is the buzzer, which issues intermittent alarms when the measured gas concentration or temperature and humidity values are outside the set range.

Software Functions

  • Multi-parameter real-time monitoring and display

  • Adjustable threshold setting system

  • Automatic environmental adjustment control

  • Over-limit alarm function

  • Multi-interface display switching

System Design and Implementation

Core Code Analysis

Main Loop Control

void main()
{
    // Initialize each module
    Lcd1602_Init();
    Delay_function(50);
    lcd1602_clean();
    Delay_function(50);
    DHT11_Init();
    Delay_function(50);

    while(1)
    {
        Key_function();        // Key processing
        Monitor_function();    // Data monitoring
        Display_function();    // Data display
        Manage_function();     // Device control

        Delay_function(10);    // 10ms delay
        time_jishi++;          // Timer increment
        if(time_jishi == 5000)
        {
            time_jishi = 0;
        }
    }
}

Key Function Implementation

The system uses 3 keys to implement all interactive functions:

  • Key 1: Mode switching (9 setting modes in total)

  • Key 2: Parameter increase

  • Key 3: Parameter decrease/display interface switching

void Key_function(void)
{
    key_num = Chiclet_Keyboard_Scan();  // Key scanning

    if(key_num != 0)
    {
        switch(key_num)
        {
            case 1:  // Mode switching
                flag_mode_display++;
                if(flag_mode_display == 9)
                    flag_mode_display = 0;
                lcd1602_clean();
                break;

            case 2:  // Parameter increase
                // Increase corresponding parameter based on current mode
                break;

            case 3:  // Parameter decrease/display switching
                // Decrease corresponding parameter based on current mode or switch display interface
                break;
        }
    }
}

Data Monitoring Function

The system periodically collects data from various sensors:

void Monitor_function(void)
{
    if(time_jishi % 50 == 0)  // Collect once every 500ms
    {
        // Read data from each sensor
        co2_value = 400*((Adc0832_Get_Value(0)/256.0)*5)-1000;
        ch2o_value = 400*((Adc0832_Get_Value(1)/256.0)*5)-1000;
        ch4_value = 400*((Adc0832_Get_Value_1(0)/256.0)*5)-1000;
        pm25_value = 400*((Adc0832_Get_Value_1(1)/256.0)*5)-1000;
        Dht11_Get_Temp_Humi_Value(&temp_value,&humi_value);
    }
}

Device Control Function

The system automatically controls various environmental adjustment devices based on monitoring data:

void Manage_function(void)
{
    if(flag_mode_display == 0)  // Only execute control in monitoring mode
    {
        // Gas over-limit control
        if(co2_value > co2_value_max || ch2o_value > ch2o_value_max || 
           ch4_value > ch4_value_max || pm25_value > pm25_value_max)
        {
            RELAY_MOTOR = 0;      // Start ventilation
            RELAY_JINGHUA = 0;    // Start purification
            flag_beep_gas = 1;    // Trigger gas alarm
        }
        else
        {
            RELAY_MOTOR = 1;      // Stop ventilation
            RELAY_JINGHUA = 1;    // Stop purification
            flag_beep_gas = 0;    // Turn off gas alarm
        }

        // Temperature and humidity control logic...

        // Alarm control
        if(flag_beep_gas == 1 || flag_beep_temp == 1 || flag_beep_humi == 1)
        {
            if(time_jishi % 20 == 0) BEEP = 0;  // Intermittent alarm
            if(time_jishi % 40 == 0) BEEP = 1;
        }
        else
        {
            BEEP = 1;  // Turn off alarm
        }
    }
    else
    {
        BEEP = 1;  // Turn off alarm in setting mode
    }
}

Complete Main Function:

#include "main.h"
#include "lcd1602.h"
#include "key.h"
#include "adc.h"
#include "dht11_proteus.h"

/**********************************
Variable Definitions
**********************************/
uchar key_num = 0;                             // Key scanning flag variable
uchar flag_mode_display = 0;            // Display mode flag variable
uchar flag_display = 0;                     // Display interface flag variable
uchar flag_beep_gas = 0;                 // Buzzer gas flag variable
uchar flag_beep_temp = 0;                 // Buzzer temperature flag variable
uchar flag_beep_humi = 0;                 // Buzzer humidity flag variable
uint co2_value = 0;                             // CO2 concentration value variable
uint ch2o_value = 0;                         // Formaldehyde concentration value variable
uint ch4_value = 0;                             // Methane concentration value variable
uint pm25_value = 0;                          // PM2.5 concentration value variable
uint temp_value = 0;                          // Temperature value variable
uint humi_value = 0;                          // Humidity value variable
uint co2_value_max = 700;                  // Maximum CO2 concentration value variable
uint ch2o_value_max = 80;                  // Maximum formaldehyde concentration value variable
uint ch4_value_max = 150;                  // Maximum methane concentration value variable
uint pm25_value_max = 200;                // Maximum PM2.5 concentration value variable
uint temp_value_max = 35;                  // Maximum temperature value variable
uint temp_value_min = 20;                  // Minimum temperature value variable
uint humi_value_max = 60;                  // Maximum humidity value variable
uint humi_value_min = 30;                  // Minimum humidity value variable
uint time_jishi = 0;                          // 10ms timer variable

/**********************************
Function Declarations
**********************************/
void Delay_function(uint x);                     // Delay function (ms)
void Key_function(void);                             // Key function
void Monitor_function(void);                     // Monitoring function
void Display_function(void);                     // Display function
void Manage_function(void);                       // Processing function

/****
******* Main Function 
*****/
void main()
{
    Lcd1602_Init();                          // LCD1602 initialization
    Delay_function(50);                      // Delay 50ms
    lcd1602_clean();                          // Clear screen
    Delay_function(50);                      // Delay 50ms
    DHT11_Init();                               // DHT11 initialization
    Delay_function(50);                      // Delay 50ms

    while(1)
    {
        Key_function();                      // Key function
        Monitor_function();                  // Monitoring function
        Display_function();                  // Display function
        Manage_function();                   // Processing function

        Delay_function(10);                  // Delay 10ms
        time_jishi++;                          // Timer variable +1
        if(time_jishi == 5000)
        {
            time_jishi = 0;
        }
    }
}

/****
******* Delay x ms Function
*****/
void Delay_function(uint x)
{
    uint m,n;
    for(m=x;m>0;m--)
        for(n=110;n>0;n--);
}

/****
******* Key Function
*****/
void Key_function(void)
{
    key_num = Chiclet_Keyboard_Scan();    // Key scanning
    if(key_num != 0)                                    // If a key is pressed
    {
        switch(key_num)
        {
            case 1:                                            // Key 1
                flag_mode_display++;
                if(flag_mode_display == 9)    // A total of 9 modes
                    flag_mode_display = 0;

                lcd1602_clean();                          // Clear screen
                break;

            case 2:                                            // Key 2
                if(flag_mode_display == 1)    // Mode 1: CO2 maximum value +1
                {
                    co2_value_max++;
                    if(co2_value_max > 999)
                        co2_value_max = 999;
                }

                if(flag_mode_display == 2)    // Mode 2: Formaldehyde maximum value +1
                {
                    ch2o_value_max++;
                    if(ch2o_value_max > 999)
                        ch2o_value_max = 999;
                }

                if(flag_mode_display == 3)    // Mode 3: Methane maximum value +1
                {
                    ch4_value_max++;
                    if(ch4_value_max > 999)
                        ch4_value_max = 999;
                }

                if(flag_mode_display == 4)    // Mode 4: PM2.5 maximum value +1
                {
                    pm25_value_max++;
                    if(pm25_value_max > 999)
                        pm25_value_max = 999;
                }

                if(flag_mode_display == 5)    // Mode 5: Temperature maximum value +1
                {
                    temp_value_max++;
                    if(temp_value_max > 99)
                        temp_value_max = 99;
                }

                if(flag_mode_display == 6)    // Mode 6: Temperature minimum value +1
                {
                    if(temp_value_max > (temp_value_min+1))
                        temp_value_min++;
                }

                if(flag_mode_display == 7)    // Mode 7: Humidity maximum value +1
                {
                    humi_value_max++;
                    if(humi_value_max > 99)
                        humi_value_max = 99;
                }

                if(flag_mode_display == 8)    // Mode 8: Humidity minimum value +1
                {
                    if(humi_value_max > (humi_value_min+1))
                        humi_value_min++;
                }
                break;

            case 3:                                            // Key 3
                if(flag_mode_display == 0)    // Mode 0: Display measurement value flag +1
                {
                    flag_display++;
                    if(flag_display == 3)                // A total of 3 modes
                        flag_display = 0;

                    lcd1602_clean();                        // Clear screen
                }

                if(flag_mode_display == 1)    // Mode 1: CO2 maximum value -1
                {
                    if(co2_value_max > 0)
                        co2_value_max--;
                }

                if(flag_mode_display == 2)    // Mode 2: Formaldehyde maximum value -1
                {
                    if(ch2o_value_max > 0)
                        ch2o_value_max--;
                }

                if(flag_mode_display == 3)    // Mode 3: Methane maximum value -1
                {
                    if(ch4_value_max > 0)
                        ch4_value_max--;
                }

                if(flag_mode_display == 4)    // Mode 4: PM2.5 maximum value -1
                {
                    if(pm25_value_max > 0)
                        pm25_value_max--;
                }

                if(flag_mode_display == 5)    // Mode 5: Temperature maximum value -1
                {
                    if(temp_value_max > (temp_value_min+1))
                        temp_value_max--;
                }

                if(flag_mode_display == 6)    // Mode 6: Temperature minimum value -1
                {
                    if(temp_value_min > 0)
                        temp_value_min--;
                }

                if(flag_mode_display == 7)    // Mode 7: Humidity maximum value -1
                {
                    if(humi_value_max > (humi_value_min+1))
                        humi_value_max--;
                }

                if(flag_mode_display == 8)    // Mode 8: Humidity minimum value -1
                {
                    if(humi_value_min > 0)
                        humi_value_min--;
                }
                break;

            default:
                break;
        }
    }
}

/****
******* Monitoring Function
*****/
void Monitor_function(void)
{
    if(time_jishi % 50 == 0)                                                                            // Check once every 500ms
    {
        co2_value = 400*((Adc0832_Get_Value(0)/256.0)*5)-1000;            // Get CO2 value
        ch2o_value = 400*((Adc0832_Get_Value(1)/256.0)*5)-1000;            // Get formaldehyde value
        ch4_value = 400*((Adc0832_Get_Value_1(0)/256.0)*5)-1000;        // Get methane value
        pm25_value = 400*((Adc0832_Get_Value_1(1)/256.0)*5)-1000;        // Get PM2.5 value
        Dht11_Get_Temp_Humi_Value(&temp_value,&humi_value);                    // Get temperature and humidity values
    }
}

/****
******* Display Function
*****/
void Display_function(void)
{
    switch(flag_mode_display)                                                        // Display different interfaces based on different display mode flags
    {
        case 0:                                                                                // Mode 0: Display CO2, formaldehyde, methane, PM2.5, temperature, humidity
            switch(flag_display)
            {
                case 0:
                    lcd1602_display_str(1,0,"CO2=");                        // Display CO2
                    lcd1602_display_gas(1,4,co2_value);

                    lcd1602_display_str(2,0,"CH2O=");                        // Display formaldehyde
                    lcd1602_display_gas(2,5,ch2o_value);
                    break;

                case 1:
                    lcd1602_display_str(1,0,"CH4=");                        // Display methane
                    lcd1602_display_gas(1,4,ch4_value);

                    lcd1602_display_str(2,0,"PM2.5=");                    // Display PM2.5
                    lcd1602_display_pm25(2,6,pm25_value);
                    break;

                case 2:
                    lcd1602_display_str(1,0,"Temp=");                        // Display temperature
                    lcd1602_display_temp(1,5,temp_value);

                    lcd1602_display_str(2,0,"Humi=");                        // Display humidity
                    lcd1602_display_humi(2,5,humi_value);
                    break;
            }
            break;

        case 1:                                                                                // Mode 1: Display set CO2 maximum value
            lcd1602_display_str(1,0,"CO2_Max=");
            lcd1602_display_str(2,0,"CH2O_Max=");
            if(time_jishi % 20 == 0)
            {
                lcd1602_display_num(1, 8, co2_value_max);
                lcd1602_display_num(2, 9, ch2o_value_max);
            }
            if(time_jishi % 40 == 0)
            {
                lcd1602_display_str(1, 8, "    ");
            }
            break;

        case 2:                                                                                // Mode 2: Display set formaldehyde maximum value
            lcd1602_display_str(1,0,"CO2_Max=");
            lcd1602_display_str(2,0,"CH2O_Max=");
            if(time_jishi % 20 == 0)
            {
                lcd1602_display_num(1, 8, co2_value_max);
                lcd1602_display_num(2, 9, ch2o_value_max);
            }
            if(time_jishi % 40 == 0)
            {
                lcd1602_display_str(2, 9, "    ");
            }
            break;

        case 3:                                                                                // Mode 3: Display set methane maximum value
            lcd1602_display_str(1,0,"CH4_Max=");
            lcd1602_display_str(2,0,"PM2.5_Max=");
            if(time_jishi % 20 == 0)
            {
                lcd1602_display_num(1, 8, ch4_value_max);
                lcd1602_display_num(2, 10, pm25_value_max);
            }
            if(time_jishi % 40 == 0)
            {
                lcd1602_display_str(1, 8, "    ");
            }
            break;

        case 4:                                                                                // Mode 4: Display set PM2.5 maximum value
            lcd1602_display_str(1,0,"CH4_Max=");
            lcd1602_display_str(2,0,"PM2.5_Max=");
            if(time_jishi % 20 == 0)
            {
                lcd1602_display_num(1, 8, ch4_value_max);
                lcd1602_display_num(2, 10, pm25_value_max);
            }
            if(time_jishi % 40 == 0)
            {
                lcd1602_display_str(2, 10, "    ");
            }
            break;

        case 5:                                                                                // Mode 5: Display set temperature maximum value
            lcd1602_display_str(1,0,"Temp_Max=");
            lcd1602_display_str(2,0,"Temp_min=");
            if(time_jishi % 20 == 0)
            {
                lcd1602_display_num(1, 9, temp_value_max);
                lcd1602_display_num(2, 9, temp_value_min);
            }
            if(time_jishi % 40 == 0)
            {
                lcd1602_display_str(1, 9, "    ");
            }
            break;

        case 6:                                                                                // Mode 6: Display set temperature minimum value
            lcd1602_display_str(1,0,"Temp_Max=");
            lcd1602_display_str(2,0,"Temp_min=");
            if(time_jishi % 20 == 0)
            {
                lcd1602_display_num(1, 9, temp_value_max);
                lcd1602_display_num(2, 9, temp_value_min);
            }
            if(time_jishi % 40 == 0)
            {
                lcd1602_display_str(2, 9, "    ");
            }
            break;

        case 7:                                                                                // Mode 7: Display set humidity maximum value
            lcd1602_display_str(1,0,"Humi_Max=");
            lcd1602_display_str(2,0,"Humi_min=");
            if(time_jishi % 20 == 0)
            {
                lcd1602_display_num(1, 9, humi_value_max);
                lcd1602_display_num(2, 9, humi_value_min);
            }
            if(time_jishi % 40 == 0)
            {
                lcd1602_display_str(1, 9, "    ");
            }
            break;

        case 8:                                                                                // Mode 8: Display set humidity minimum value
            lcd1602_display_str(1,0,"Humi_Max=");
            lcd1602_display_str(2,0,"Humi_min=");
            if(time_jishi % 20 == 0)
            {
                lcd1602_display_num(1, 9, humi_value_max);
                lcd1602_display_num(2, 9, humi_value_min);
            }
            if(time_jishi % 40 == 0)
            {
                lcd1602_display_str(2, 9, "    ");
            }
            break;

            default:
                break;
    }
}

/****
******* Processing Function
*****/
void Manage_function(void)
{
    if(flag_mode_display == 0)                                        // When the display mode is 0
    {
        if(co2_value > co2_value_max || ch2o_value > ch2o_value_max || ch4_value > ch4_value_max || pm25_value > pm25_value_max)        // Gas concentration greater than set concentration
        {
            RELAY_MOTOR = 0;                                                    // Fan relay pulled low to enable
            RELAY_JINGHUA = 0;                                                // Air purification relay pulled low to enable
            flag_beep_gas = 1;                                                // Buzzer gas flag set to 1
        }
        else // Gas concentration less than set concentration
        {
            RELAY_MOTOR = 1;                                                    // Fan relay pulled high to disable
            RELAY_JINGHUA = 1;                                                // Air purification relay pulled high to disable
            flag_beep_gas = 0;                                                // Buzzer gas flag set to 0
        }

        if(temp_value > temp_value_max*10)                    // Temperature greater than set maximum temperature
        {
            RELAY_TEMP_UP = 1;                                                // Heating relay pulled high to disable
            RELAY_TEMP_DOWN = 0;                                            // Cooling relay pulled low to enable
            flag_beep_temp = 1;                                                // Buzzer temperature flag set to 1
        }
        else if(temp_value < temp_value_min*10)            // Temperature less than set minimum temperature
        {
            RELAY_TEMP_UP = 0;                                                // Heating relay pulled low to enable
            RELAY_TEMP_DOWN = 1;                                            // Cooling relay pulled high to disable
            flag_beep_temp = 1;                                                // Buzzer temperature flag set to 1
        }
        else // Temperature within threshold
        {
            RELAY_TEMP_UP = 1;                                                // Heating relay pulled high to disable
            RELAY_TEMP_DOWN = 1;                                            // Cooling relay pulled high to disable
            flag_beep_temp = 0;                                                // Buzzer temperature flag set to 0
        }

        if(humi_value > humi_value_max*10)                    // Humidity greater than set maximum humidity
        {
            RELAY_HUMI_UP = 1;                                                // Humidifier relay pulled high to disable
            RELAY_HUMI_DOWN = 0;                                            // Dehumidifier relay pulled low to enable
            flag_beep_humi = 1;                                                // Buzzer humidity flag set to 1
        }
        else if(humi_value < humi_value_min*10)
        {
            RELAY_HUMI_UP = 0;                                                // Humidifier relay pulled low to enable
            RELAY_HUMI_DOWN = 1;                                            // Dehumidifier relay pulled high to disable
            flag_beep_humi = 1;                                                // Buzzer humidity flag set to 1
        }
        else
        {
            RELAY_HUMI_UP = 1;                                                // Humidifier relay pulled high to disable
            RELAY_HUMI_DOWN = 1;                                            // Dehumidifier relay pulled high to disable
            flag_beep_humi = 0;                                                // Buzzer humidity flag set to 0
        }

        if(flag_beep_gas == 1 || flag_beep_temp == 1 || flag_beep_humi == 1)    // If buzzer gas flag is 1 or buzzer temperature flag is 1 or buzzer humidity flag is 1
        {
            if(time_jishi % 20 == 0)                                    // Intermittent alarm
                BEEP = 0;
            if(time_jishi % 40 == 0)
                BEEP = 1;
        }
        else
        {
            BEEP = 1;                                                                    // No alarm
        }
    }
    else
    {
        BEEP = 1;                                                                        // No alarm
    }
}

ADC Collection:

#include "adc.h"

/**********************************
Function Definitions
**********************************/
/****
******* Get ADC Value Function
******* Parameter Definition: CH: Channel Number  0: Channel 0   1: Channel 1
******* Return Value: ADC Value
*****/
uint Adc0832_Get_Value(uchar CH)
{
    uint dat = 0x00; 
    uchar i,test,adval;
    adval = 0x00;
    test = 0x00;

    // Initialization
    ADC_CLK = 0;      
    ADC_DATI = 1;
    _nop_();   _nop_();
    ADC_CS = 0;
    _nop_();
    ADC_CLK = 1;
    _nop_();  _nop_();

    // Channel Selection
    if(CH == 0x00)     
    {
        ADC_CLK = 0;
        ADC_DATI = 1;       // First bit of channel 0
        _nop_();
        ADC_CLK = 1;
        _nop_();  _nop_();

        ADC_CLK = 0;
        ADC_DATI = 0;       // Second bit of channel 0
        _nop_();  _nop_();

        ADC_CLK = 1;
        _nop_();
    } 
    else
    {
        ADC_CLK = 0;
        ADC_DATI = 1;       // First bit of channel 1
        _nop_();  _nop_();
        ADC_CLK = 1;
        _nop_();  _nop_();

        ADC_CLK = 0;
        ADC_DATI = 1;       // Second bit of channel 1
        _nop_();
        ADC_CLK = 1;
        _nop_();
    }

    ADC_CLK = 0;   _nop_();
    ADC_DATI = 1;

    for( i = 0;i < 8;i++ )       // Read the first 8 bits
    {
        _nop_();
        adval <<= 1;
        ADC_CLK = 1;
        _nop_();  _nop_();

        ADC_CLK = 0;
        _nop_();

        if (ADC_DATO)
            adval |= 0x01;
        else
            adval |= 0x00;
    }
    for (i = 0; i < 8; i++)       // Read the last 8 bits
    {
        test >>= 1;
        if (ADC_DATO)
            test |= 0x80;
        else
            test |= 0x00;
        _nop_();
        ADC_CLK = 1;
        _nop_();  _nop_();

        ADC_CLK = 0;
        _nop_();
    }

    // Compare the first 8 bits with the last 8 bits, if they are not the same, discard. If it always shows zero, please remove this line
    if (adval == test)     
        dat = test;
    _nop_();  _nop_();
    ADC_CS = 1;         // Release ADC0832
    ADC_DATO = 1;
    ADC_CLK = 1;

    return dat;
}

uint Adc0832_Get_Value_1(uchar CH)
{
    uint dat = 0x00; 
    uchar i,test,adval;
    adval = 0x00;
    test = 0x00;

    // Initialization
    ADC_CLK_1 = 0;      
    ADC_DATI_1 = 1;
    _nop_();   _nop_();
    ADC_CS_1 = 0;
    _nop_();
    ADC_CLK_1 = 1;
    _nop_();  _nop_();

    // Channel Selection
    if(CH == 0x00)     
    {
        ADC_CLK_1 = 0;
        ADC_DATI_1 = 1;       // First bit of channel 0
        _nop_();
        ADC_CLK_1 = 1;
        _nop_();  _nop_();

        ADC_CLK_1 = 0;
        ADC_DATI_1 = 0;       // Second bit of channel 0
        _nop_();  _nop_();

        ADC_CLK_1 = 1;
        _nop_();
    } 
    else
    {
        ADC_CLK_1 = 0;
        ADC_DATI_1 = 1;       // First bit of channel 1
        _nop_();  _nop_();
        ADC_CLK_1 = 1;
        _nop_();  _nop_();

        ADC_CLK_1 = 0;
        ADC_DATI_1 = 1;       // Second bit of channel 1
        _nop_();
        ADC_CLK_1 = 1;
        _nop_();
    }

    ADC_CLK_1 = 0;   _nop_();
    ADC_DATI_1 = 1;

    for( i = 0;i < 8;i++ )       // Read the first 8 bits
    {
        _nop_();
        adval <<= 1;
        ADC_CLK_1 = 1;
        _nop_();  _nop_();

        ADC_CLK_1 = 0;
        _nop_();

        if (ADC_DATO_1)
            adval |= 0x01;
        else
            adval |= 0x00;
    }
    for (i = 0; i < 8; i++)       // Read the last 8 bits
    {
        test >>= 1;
        if (ADC_DATO_1)
            test |= 0x80;
        else
            test |= 0x00;
        _nop_();
        ADC_CLK_1 = 1;
        _nop_();  _nop_();

        ADC_CLK_1 = 0;
        _nop_();
    }

    // Compare the first 8 bits with the last 8 bits, if they are not the same, discard. If it always shows zero, please remove this line
    if (adval == test)     
        dat = test;
    _nop_();  _nop_();
    ADC_CS_1 = 1;         // Release ADC0832
    ADC_DATO_1 = 1;
    ADC_CLK_1 = 1;

    return dat;
}

DHT11 Temperature and Humidity Detection

/**********************************
Author: Turnas Electronics
Website: https://www.mcude.com
Contact: 46580829 (QQ)
Taobao Store: Turnas Electronics
**********************************/

/**********************************
Include Header Files
**********************************/
#include "dht11_proteus.h"

/**********************************
Function Definitions
**********************************/
/****
******* DHT11 Write Byte Function
*****/
char s_write_byte(unsigned char value)
{
    unsigned char i, error = 0;
    for (i = 0x80; i>0; i >>= 1)            // High bit is 1, loop right shift  
    {
        if (i&value) DHT11_DATA = 1;           // AND with the number to be sent, result is the sent bit  
        else DHT11_DATA = 0;
        DHT11_SCK = 1;
        _nop_(); _nop_(); _nop_();         // Delay 3us   
        DHT11_SCK = 0;
    }
    DHT11_DATA = 1;                           // Release data line  
    DHT11_SCK = 1;
    error = DHT11_DATA;                        // Check response signal to confirm communication is normal  
    _nop_(); _nop_(); _nop_();
    DHT11_SCK = 0;
    DHT11_DATA = 1;
    return error;                      // error=1 Communication error  
}

/****
******* DHT11 Read Byte Function
*****/
char s_read_byte(unsigned char ack)
{
    unsigned char i, val = 0;
    DHT11_DATA = 1;                            // Release data line  
    for (i = 0x80; i>0; i >>= 1)            // High bit is 1, loop right shift  
    {
        DHT11_SCK = 1;
        if (DHT11_DATA) val = (val | i);            // Read a bit data line value   
        DHT11_SCK = 0;
    }
    DHT11_DATA = !ack;                         // If it is a check, end communication after reading;  
    DHT11_SCK = 1;
    _nop_(); _nop_(); _nop_();          // Delay 3us   
    DHT11_SCK = 0;
    _nop_(); _nop_(); _nop_();
    DHT11_DATA = 1;                            // Release data line  
    return val;
}

/****
******* DHT11 Start Transmission Function
*****/
void s_transstart(void)
{
    DHT11_DATA = 1; DHT11_SCK = 0;                    // Prepare  
    _nop_();
    DHT11_SCK = 1;
    _nop_();
    DHT11_DATA = 0;
    _nop_();
    DHT11_SCK = 0;
    _nop_(); _nop_(); _nop_();
    DHT11_SCK = 1;
    _nop_();
    DHT11_DATA = 1;
    _nop_();
    DHT11_SCK = 0;
}

/****
******* DHT11 Initialization Function
*****/
void DHT11_Init(void)
{
    unsigned char i;
    DHT11_DATA = 1; DHT11_SCK = 0;                     // Prepare  
    for (i = 0; i<9; i++)                   // DATA remains high, SCK clock triggers 9 times, sends start transmission, communication resets  
    {
        DHT11_SCK = 1;
        DHT11_SCK = 0;
    }
s_transstart();                    // Start transmission  
}

/****
******* DHT11 Temperature and Humidity Detection Function
*****/
char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode)
{
    unsigned error = 0;
    unsigned int i;

    s_transstart();                    // Start transmission  
    switch (mode)                       // Select send command  
    {
        case TEMP: error += s_write_byte(DHT11_MEASURE_TEMP); break;          // Measure temperature  
        case HUMI: error += s_write_byte(DHT11_MEASURE_HUMI); break;          // Measure humidity  
        default: break;
    }
    for (i = 0; i<65535; i++) if (DHT11_DATA == 0) break;         // Wait for measurement to end  
    if (DHT11_DATA) error += 1;                               // If the data line has not been pulled low for a long time, it indicates measurement error   
    *(p_value) = s_read_byte(DHT11_ACK);            // Read the first byte, high byte (MSB)  
    *(p_value + 1) = s_read_byte(DHT11_ACK);           // Read the second byte, low byte (LSB)  
    *p_checksum = s_read_byte(DHT11_NOACK);         // Read CRC checksum  
    return error;                    // error=1 Communication error  
}

/****
******* DHT11 Temperature and Humidity Value Scale Transformation and Temperature Compensation Function
*****/
void calc_sth10(float *p_humidity, float *p_temperature)
{
    const float C1 = -4.0;              // 12-bit humidity precision correction formula  
    const float C2 = +0.0405;           // 12-bit humidity precision correction formula  
    const float C3 = -0.0000028;        // 12-bit humidity precision correction formula  
    const float T1 = +0.01;             // 14-bit temperature precision 5V condition correction formula  
    const float T2 = +0.00008;          // 14-bit temperature precision 5V condition correction formula  

    float rh = *p_humidity;             // rh:      12-bit humidity   
    float t = *p_temperature;           // t:       14-bit temperature  
    float rh_lin;                      // rh_lin: Humidity linear value  
    float rh_true;                     // rh_true: Humidity true value  
    float t_C;                         // t_C   : Temperature ℃  

    t_C = t*0.01 - 40;                  // Compensate temperature  
    rh_lin = C3*rh*rh + C2*rh + C1;     // Relative humidity non-linear compensation  
//    rh_true = (t_C - 25)*(T1 + T2*rh) + rh_lin;   // Relative humidity temperature dependency compensation
    rh_true = rh_lin; 
    if (rh_true>100) rh_true = 100;      // Maximum humidity correction  
    if (rh_true<0.1) rh_true = 0.1;      // Minimum humidity correction  

    *p_temperature = t_C;               // Return temperature result  
    *p_humidity = rh_true;              // Return humidity result  
}

/****
******* DHT11 Get Temperature and Humidity Value Function
*****/
void Dht11_Get_Temp_Humi_Value(uint *temp,uint *humi)
{
//    unsigned int temp, humi;
    unsigned char error;                 // Used to check for errors
    unsigned char checksum;              // CRC
    value humi_val, temp_val;           // Define a union for humidity and temperature

    error = 0;                        // Initialize error=0, that is, no error  
    error += s_measure((unsigned char*)&temp_val.i, &checksum, TEMP); // Temperature measurement  
    error += s_measure((unsigned char*)&humi_val.i, &checksum, HUMI); // Humidity measurement  
    if (error != 0) DHT11_Init();                  // If an error occurs, reset the system  
    else
    {
        humi_val.f = (float)humi_val.i;                   // Convert to float  
        temp_val.f = (float)temp_val.i;                   // Convert to float  
        calc_sth10(&humi_val.f, &temp_val.f);             // Correct relative humidity and temperature  
        *temp = temp_val.f * 10;
        *humi = (humi_val.f - 3.3 )* 10;
    }
}

Project Resources:Design and Implementation of Indoor Air Quality Monitoring System Based on 51 Microcontroller

Leave a Comment