温湿度由OLED12864显示"/>
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 128x64的驱动程序:
#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,震荡频率=1000HzOLED_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); // 默认值0x00OLED_Write(OLED_CMD_MODE, 0x40); // 设置显示开始行 [5:0],默认值0OLED_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显示屏的驱动程序来控制显示屏。通过本文的学习,我们可以深入理解嵌入式系统中传感器的应用,为以后的项目开发奠定坚实的基础。
更多推荐
STM32驱动dht11检测温湿度由OLED12864显示
发布评论