STC8G1K08 读取 DHT11 温湿度并在两线 LCD1602 显示实现方案
演示视频:
【开源】51单片机读取DHT11温湿度传感器显示在lcd1602上,并通过蓝牙模块发送到手机app
一、硬件准备与连接
1. 核心器件
-
主控:STC8G1K08(5V 供电,需外接 11.0592MHz 晶振)
-
温湿度传感器:DHT11(单总线通信)
-
显示模块:两线 LCD1602(I2C 接口,含 PCF8574 转接板)
-
辅助:10KΩ 上拉电阻(DHT11 专用)、杜邦线、5V 电源
2. 引脚连接表
| 器件 | 引脚 | STC8G1K08 引脚 | 说明 |
|---|---|---|---|
| DHT11 | VCC | 5V | 传感器供电 |
| DHT11 | GND | GND | 共地 |
| DHT11 | DATA | P3.2 | 数据引脚,接 10KΩ 上拉 |
| 两线 LCD1602 | SDA | P1.2 | I2C 数据线 |
| 两线 LCD1602 | SCL | P1.3 | I2C 时钟线 |
| 两线 LCD1602 | VCC | 5V | 显示模块供电 |
| 两线 LCD1602 | GND | GND | 共地 |
二、软件编程实现(Keil C51 环境)
1. 头文件与宏定义
\#include \<STC8.H>
\#include \<intrins.h>
// DHT11引脚定义
sbit DHT11\_DATA = P3^2;
// LCD1602 I2C引脚定义
sbit LCD\_SDA = P1^2;
sbit LCD\_SCL = P1^3;
// LCD1602 I2C地址(默认0x4E,可根据转接板调整)
\#define LCD\_ADDR 0x4E
// 温湿度存储变量
unsigned char temp\_h, temp\_l, humi\_h, humi\_l, check;
2. DHT11 数据读取函数
// 延时函数(1us,STC8G1K08@11.0592MHz)
void Delay1us(void) {
  \_nop\_();
}
// DHT11起始信号发送
bit DHT11\_Start(void) {
  bit ack;
  DHT11\_DATA = 0;
  Delay1us() \* 180; // 拉低至少18ms
  DHT11\_DATA = 1;
  Delay1us() \* 30; // 拉高20-40us
  ack = DHT11\_DATA; // 等待DHT11拉低响应
  while(!DHT11\_DATA); // 等待DHT11拉高
  return ack;
}
// 读取1字节数据
unsigned char DHT11\_ReadByte(void) {
  unsigned char i, dat = 0;
  for(i=0; i<8; i++) {
  while(DHT11\_DATA); // 等待低电平
  while(!DHT11\_DATA); // 等待高电平
  Delay1us() \* 30; // 延时30us判断电平
  dat <<= 1;
  if(DHT11\_DATA) dat |= 1; // 高电平为1,低电平为0
  while(DHT11\_DATA); // 等待高电平结束
  }
  return dat;
}
// 读取温湿度数据(返回0成功,1失败)
bit DHT11\_ReadData(void) {
  if(DHT11\_Start() == 0) {
  humi\_h = DHT11\_ReadByte(); // 湿度整数
  humi\_l = DHT11\_ReadByte(); // 湿度小数
  temp\_h = DHT11\_ReadByte(); // 温度整数
  temp\_l = DHT11\_ReadByte(); // 温度小数
  check = DHT11\_ReadByte(); // 校验和
  // 校验(humi\_h + humi\_l + temp\_h + temp\_l == check)
  if((humi\_h + humi\_l + temp\_h + temp\_l) == check) return 0;
  }
  return 1;
}
3. 两线 LCD1602 驱动函数
// I2C起始信号
void I2C\_Start(void) {
  LCD\_SDA = 1;
  LCD\_SCL = 1;
  Delay1us();
  LCD\_SDA = 0;
  Delay1us();
  LCD\_SCL = 0;
}
// I2C停止信号
void I2C\_Stop(void) {
  LCD\_SDA = 0;
  LCD\_SCL = 1;
  Delay1us();
  LCD\_SDA = 1;
  Delay1us();
}
// I2C发送应答
void I2C\_Ack(bit ack) {
  LCD\_SDA = ack;
  Delay1us();
  LCD\_SCL = 1;
  Delay1us();
  LCD\_SCL = 0;
  Delay1us();
}
// I2C等待应答
bit I2C\_WaitAck(void) {
  bit ack;
  LCD\_SDA = 1;
  Delay1us();
  LCD\_SCL = 1;
  Delay1us();
  ack = LCD\_SDA;
  LCD\_SCL = 0;
  Delay1us();
  return ack;
}
// I2C发送1字节
void I2C\_SendByte(unsigned char dat) {
  unsigned char i;
  for(i=0; i<8; i++) {
  LCD\_SDA = dat & 0x80;
  Delay1us();
  LCD\_SCL = 1;
  Delay1us();
  LCD\_SCL = 0;
  dat <<= 1;
  }
  I2C\_WaitAck();
}
// LCD1602写命令
void LCD\_WriteCmd(unsigned char cmd) {
  I2C\_Start();
  I2C\_SendByte(LCD\_ADDR); // 写地址
  I2C\_SendByte(0x00); // 命令标志(RS=0)
  I2C\_SendByte(cmd); // 命令数据
  I2C\_Stop();
  Delay1us() \* 200; // 命令执行延时
}
// LCD1602写数据
void LCD\_WriteData(unsigned char dat) {
  I2C\_Start();
  I2C\_SendByte(LCD\_ADDR); // 写地址
  I2C\_SendByte(0x01); // 数据标志(RS=1)
  I2C\_SendByte(dat); // 显示数据
  I2C\_Stop();
  Delay1us() \* 200;
}
// LCD1602初始化
void LCD\_Init(void) {
  LCD\_WriteCmd(0x38); // 8位总线,2行显示,5\*8点阵
  LCD\_WriteCmd(0x0C); // 开显示,关光标
  LCD\_WriteCmd(0x06); // 光标右移,画面不滚动
  LCD\_WriteCmd(0x01); // 清屏
}
// LCD1602指定位置显示字符串
void LCD\_ShowStr(unsigned char x, unsigned char y, unsigned char \*str) {
  if(y == 0) LCD\_WriteCmd(0x80 + x); // 第一行
  else LCD\_WriteCmd(0xC0 + x); // 第二行
  while(\*str) {
  LCD\_WriteData(\*str++);
  }
}
4. 主函数逻辑
void main(void) {
  unsigned char disp\_buf\[20];
  LCD\_Init(); // 初始化LCD1602
  LCD\_ShowStr(0,0,"Temp: C"); // 第一行显示格式
  LCD\_ShowStr(0,1,"Humi: %"); // 第二行显示格式
   
  while(1) {
  if(DHT11\_ReadData() == 0) { // 成功读取数据
  // 格式化温度(整数部分)
  disp\_buf\[0] = temp\_h / 10 + '0';
  disp\_buf\[1] = temp\_h % 10 + '0';
  disp\_buf\[2] = '\0';
  LCD\_ShowStr(5,0,disp\_buf); // 温度显示在第一行第5位
   
  // 格式化湿度(整数部分)
  disp\_buf\[0] = humi\_h / 10 + '0';
  disp\_buf\[1] = humi\_h % 10 + '0';
  disp\_buf\[2] = '\0';
  LCD\_ShowStr(5,1,disp\_buf); // 湿度显示在第二行第5位
  }
  // 1秒刷新一次
  unsigned int i;
  for(i=0; i<60000; i++) Delay1us() \* 17;
  }
}
三、调试与注意事项
-
硬件排查:确保 DHT11 数据引脚接 10KΩ 上拉电阻,LCD1602 I2C 地址与代码一致(可通过万用表测量转接板确定)。
-
延时校准:若数据读取失败,调整 DHT11_Start 函数中的延时(如拉低时间改为 20ms),确保与 DHT11 时序匹配。
-
显示异常:若 LCD 只亮背光不显示,检查初始化命令(0x38、0x0C)是否正确,或 I2C 引脚接线是否反接。
-
电源稳定:建议给系统加 100uF 滤波电容,避免供电波动导致数据异常。
2618

被折叠的 条评论
为什么被折叠?



