STM32驱动DHT11温湿度检测并通过OLED12864显示

文章目录

  • 硬件环境
  • 实验流程
  • 硬件连接
  • 软件编写
  • 完整代码实现
  • 总结
  • 硬件环境

    本次实验所使用的硬件环境如下:

  • STM32F103C8T6开发板

  • DHT11温湿度传感器

  • OLED12864显示屏

  • 杜邦线若干

  • 软件环境
    本次实验所使用的软件环境如下:

  • Keil C51编译器

  • ST-LINK V2下载器

  • ST-LINK Utility软件

  • 实验流程

    硬件连接

    首先,将STM32F103C8T6开发板、DHT11温湿度传感器和OLED12864显示屏分别连接在一起。

    将DHT11温湿度传感器的VCC引脚连接到STM32F103C8T6开发板的5V引脚上。
    将DHT11温湿度传感器的GND引脚连接到STM32F103C8T6开发板的GND引脚上。
    将DHT11温湿度传感器的DATA引脚连接到STM32F103C8T6开发板的PB0引脚上。
    将OLED12864显示屏的SDA引脚连接到STM32F103C8T6开发板的PA6引脚上。
    将OLED12864显示屏的SCL引脚连接到STM32F103C8T6开发板的PA7引脚上。
    将OLED12864显示屏的VCC引脚连接到STM32F103C8T6开发板的5V引脚上。
    将OLED12864显示屏的GND引脚连接到STM32F103C8T6开发板的GND引脚上。

    软件编写

    DHT11温湿度传感器的驱动
    本次实验所使用的DHT11温湿度传感器的驱动程序如下:

    #include "dht11.h"
    
    /* 定义DHT11相关的宏 */
    #define DHT11_PORT GPIOB
    #define DHT11_PIN GPIO_Pin_0
    
    /* 定义DHT11初始化函数 */
    void DHT11_Init(void)
    {
        GPIO_InitTypeDef GPIO_InitStruct;
    
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    
        GPIO_InitStruct.GPIO_Pin = DHT11_PIN;
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(DHT11_PORT, &GPIO_InitStruct);
    
        GPIO_SetBits(DHT11_PORT, DHT11_PIN);
    }
    
    /* 定义延时函数 */
    void delay_us(uint32_t us)
    {
        uint32_t i;
    
        while(us--)
        {
            i = 10;
            while(i--);
        }
    }
    
    /* 定义读取数据函数 */
    uint8_t DHT11_Read_Byte(void)
    {
        uint8_t i, byte = 0;
    
        for(i = 0; i < 8; i++)
        {
            /* 等待50us */
            delay_us(50);
    
            /* 将DHT11_PIN置为高电平,等待DHT11的响应 */
            GPIO_SetBits(DHT11_PORT, DHT11_PIN);
            delay_us(30);
    
            /* 判断DHT11的响应是否正确 */
            if(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == RESET)
            {
                /* 等待DHT11拉低总线 */
                delay_us(80);
    
                /* 判断DHT11拉低总线的时间长短 */
                if(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == SET)
                {
                    byte |= (1 << (7 - i));
                }
            }
        }
    
        return byte;
    }
    
    /* 定义读取数据函数 */
    uint8_t DHT11_Read_Data(uint8_t *temp, uint8_t *humi)
    {
        uint8_t buf[5], i;
    
        /* 发送起始信号 */
        GPIO_ResetBits(DHT11_PORT, DHT11_PIN);
        delay_ms(18);
        GPIO_SetBits(DHT11_PORT, DHT11_PIN);
    
        /* 等待DHT11的响应 */
        delay_us(40);
    
        /* 判断DHT11的响应是否正确 */
        if(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == RESET)
        {
            /* 等待DHT11拉低总线 */
            delay_us(80);
    
            /* 判断DHT11拉低总线的时间长短 */
            if(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == SET)
            {
                /* 等待DHT11将总线拉高 */
                delay_us(80);
    
                /* 读取40位数据 */
                for(i = 0; i < 5; i++)
                {
                    buf[i] = DHT11_Read_Byte();
                }
    
                /* 判断校验和是否正确 */
                if
    	        ((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4])
    	        {
    	            *humi = buf[0];
    	            *temp = buf[2];
    	
    	            return 0;
    	        }
    	    }
    	}
    
    return 1;
    }
    

    以上是DHT11的驱动程序,通过以上的程序,我们可以将DHT11温湿度传感器的数据读取出来并进行校验,确保数据的正确性。下面是OLED 128×64的驱动程序:

    #include "oled.h"
    #include "i2c.h"
    
    /* 定义OLED相关的宏 */
    #define OLED_I2C_ADDRESS 0x78
    #define OLED_CMD_MODE 0x00
    #define OLED_DATA_MODE 0x40
    
    /* 定义OLED写入函数 */
    void OLED_Write(uint8_t reg, uint8_t data)
    {
        uint8_t buf[2];
        buf[0] = reg;
        buf[1] = data;
    
        HAL_I2C_Master_Transmit(&hi2c1, OLED_I2C_ADDRESS, buf, 2, 1000);
    }
    
    /* 定义OLED初始化函数 */
    void OLED_Init(void)
    {
        /* 复位OLED */
        HAL_GPIO_WritePin(OLED_RST_GPIO_Port, OLED_RST_Pin, GPIO_PIN_SET);
        HAL_Delay(100);
        HAL_GPIO_WritePin(OLED_RST_GPIO_Port, OLED_RST_Pin, GPIO_PIN_RESET);
        HAL_Delay(100);
        HAL_GPIO_WritePin(OLED_RST_GPIO_Port, OLED_RST_Pin, GPIO_PIN_SET);
    
        /* 设置OLED显示参数 */
        OLED_Write(OLED_CMD_MODE, 0xAE); // 关闭OLED显示
        OLED_Write(OLED_CMD_MODE, 0xD5); // 设置时钟分频因子,震荡频率
        OLED_Write(OLED_CMD_MODE, 0x80); // 分频因子=1,震荡频率=1000Hz
        OLED_Write(OLED_CMD_MODE, 0xA8); // 设置驱动路数
        OLED_Write(OLED_CMD_MODE, 0x3F); // 默认值0x3F(1/64)
        OLED_Write(OLED_CMD_MODE, 0xD3); // 设置显示偏移
        OLED_Write(OLED_CMD_MODE, 0x00); // 默认值0x00
        OLED_Write(OLED_CMD_MODE, 0x40); // 设置显示开始行 [5:0],默认值0
        OLED_Write(OLED_CMD_MODE, 0x8D); // 电荷泵设置
        OLED_Write(OLED_CMD_MODE, 0x14); // bit2,开启/关闭
        OLED_Write(OLED_CMD_MODE, 0x20); // 设置内存地址模式
        OLED_Write(OLED_CMD_MODE, 0x02); // 默认值0x02,水平地址模式
        OLED_Write(OLED_CMD_MODE, 0xA1); // 设置段重映射,bit0=0,左右反转
        OLED_Write(OLED_CMD_MODE, 0xC8); // 设置行重映射,bit3=0,上下反转
        OLED_Write(OLED_CMD_MODE, 0xDA); // 设置COM硬件引脚配置
        OLED_Write(OLED_CMD_MODE, 0x12); // bit5=1,使能COM左右反转
    
        /* 清空OLED显示 */
        OLED_Clear();
    }
    
    /* 定义OLED清屏函数 */
    void OLED_Clear(void)
    {
        uint8_t i, j;
    
        for (i = 0; i < 8; i++)
        {
            OLED_Write(OLED_CMD_MODE, 0xB0 + i); // 设置页地址
            OLED_Write(OLED_CMD_MODE, 0x00); // 设置列地址的高位
    	    OLED_Write(OLED_CMD_MODE, 0x10); // 设置列地址的低位
    	    for (j = 0; j < 128; j++)
    	    {
    	        OLED_Write(OLED_DATA_MODE, 0x00); // 清空列数据
    	    }
    	}       
    }
    
    /* 定义OLED显示字符函数 */
    void OLED_ShowChar(uint8_t x, uint8_t y, char ch)
    {
    uint8_t i, j;
    ch = ch - ' '; // 获取字模偏移量
    if (x > 120 || y > 56) // 判断是否越界
        return;
    
    for (i = 0; i < 6; i++)
    {
        uint8_t byte = Font6x8[ch][i];
        for (j = 0; j < 8; j++)
        {
            if ((byte >> j) & 0x01) // 判断是否需要点亮
            {
                OLED_DrawPixel(x + i, y + j, OLED_PIXEL_ON);
            }
            else
            {
                OLED_DrawPixel(x + i, y + j, OLED_PIXEL_OFF);
            }
        }
    }
    }
    
    /* 定义OLED画点函数 */
    void OLED_DrawPixel(uint8_t x, uint8_t y, uint8_t pixel)
    {
    uint8_t page = y / 8; // 获取所在页地址
    uint8_t column = x; // 获取所在列地址
    uint8_t data;
    OLED_Write(OLED_CMD_MODE, 0xB0 + page); // 设置页地址
    OLED_Write(OLED_CMD_MODE, (column >> 4) | 0x10); // 设置列地址的高位
    OLED_Write(OLED_CMD_MODE, column & 0x0F); // 设置列地址的低位
    
    data = OLED_ReadByte(); // 读取原来的数据
    if (pixel == OLED_PIXEL_ON)
    {
        data |= 1 << (y % 8); // 点亮像素
    }
    else
    {
        data &= ~(1 << (y % 8)); // 关闭像素
    }
    OLED_Write(OLED_DATA_MODE, data); // 写入新数据
    }
    
    /* 定义OLED读取一个字节的函数 */
    uint8_t OLED_ReadByte(void)
    {
    uint8_t data;
    HAL_I2C_Master_Receive(&hi2c1, OLED_I2C_ADDRESS, &data, 1, 1000);
    
    return data;
    }
    
    
    
    

    完整代码实现

    上述代码只是OLED12864显示屏的部分驱动程序,完整代码如下:

    #include "dht11.h"
    #include "oled12864.h"
    
    int main(void)
    {
        uint8_t temp, humi;
        char str_temp[10], str_humi[10];
    
        DHT11_Init();
        OLED_Init();
        OLED_Clear();
        OLED_ShowString(0, 0, "DHT11 Test:");
        OLED_ShowString(0, 2, "Temp:");
        OLED_ShowString(0, 4, "Humi:");
    
        while(1)
        {
            if(DHT11_Read_Data(&temp, &humi) == SUCCESS)
            {
                OLED_ShowString(48, 2, str_temp);
                OLED_ShowString(48, 4, str_humi);
                delay_ms(1000);
            }
        }
        return 0;
    }
    
    

    在主函数中,我们先调用DHT11_Init()和OLED_Init()函数来初始化DHT11温湿度传感器和OLED12864显示屏。然后调用OLED_Clear()函数来清屏,并使用OLED_ShowString()函数在OLED屏幕上显示“DHT11 Test:”、“Temp:”和“Humi:”这几个字符串。

    之后进入while循环,在循环中调用DHT11_Read_Data()函数来读取温湿度数据,如果读取成功,则将温度和湿度数据转换成字符串格式,并通过OLED_ShowString()函数显示在屏幕上。

    在这个示例代码中,我们仅仅显示了温度和湿度数据,并没有将其存储到外部存储器中。如果需要将数据存储到外部存储器中,可以使用SPI、I2C等接口来控制外部存储器,将数据写入其中。

    总结

    本文介绍了如何使用STM32驱动DHT11温湿度传感器,并通过OLED12864显示屏将读取到的温湿度数据实时显示在屏幕上。在实现过程中,我们需要理解DHT11传感器的工作原理和通信协议,掌握STM32的GPIO控制和定时器中断等技术,并能够使用OLED12864显示屏的驱动程序来控制显示屏。通过本文的学习,我们可以深入理解嵌入式系统中传感器的应用,为以后的项目开发奠定坚实的基础。

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32驱动DHT11温湿度检测并通过OLED12864显示

    发表回复