最近在做设计需要用到温湿度传感器,DHT12是DHT11的升级版;兼容旧版单总线数据传输模式,也可使用I2C通讯。在google、百度找了一大圈,基本都是使用STM32实现的,毕竟STM32更加强大方便;但是这次想用51来做,选择的是IIC通讯方式,调试过程很艰辛,于是开这篇文章记录下。
硬件:STC89C52最小系统、DHT12、LCD1602.
官方手册:云盘下载 提取码:n1ye
特别注意:
1.用于接SCL和SDA的单片IO口应接入1KΩ~10KΩ的上拉电阻,官方文档也有说明。
2.器件IIC通信和普通的IIC通信略有区别,应特别注意文档中的数据读取时序:
数据读取:
具体重要程序段:
/***********数据读取及处理***********/
void Data_Read()
{
/**temp_H 温度高八位(温度整数部分);temp_L 温度低八位(温度小数部分)
* humi_H 湿度高八位(湿度整数部分);humi_L 湿度低八位(湿度小数部分)
* temp_C 校验数据和
**/
uchar temp_H,temp_L,humi_H,humi_L,temp_C,temp;
IIC_Start(); //主机发送起始信号
IIC_Write_Byte(0Xb8); //发送器件地址
IIC_Response(); //应答
IIC_Write_Byte(0x00); //写字节,DHT12读取地址0X00~0X04
IIC_Response(); //应答
IIC_Start(); //主机再次发起始信号
IIC_Write_Byte(0Xb9); //发送读指令,为器件寻址地址+1;
IIC_Response(); //应答
humi_H=IIC_Read_Byte(); //读取数据
ACK(); //每次读完都要给应答
humi_L=IIC_Read_Byte();
ACK();
temp_H=IIC_Read_Byte();
ACK();
temp_L=IIC_Read_Byte();
ACK();
temp_C=IIC_Read_Byte(); //接受校验位后给非应答结束通讯
NACK();
IIC_Stop(); //IIC停止信号
//数据校验
temp=0xff&(humi_H+humi_L+temp_H+temp_L);
if(temp==temp_C) //满足校验,才显示数据
{
if(temp_L&0x80) //判断温度是否为负
{
//将低八位8bit位的负号位置0
T=temp_H+int2float(temp_L&0x7f);
DisplayOneChar(0,0,'-'); //温度显示负号
}
else{
//int2float()函数为整型数据转换float
T=temp_H+int2float(temp_L);
}
H=humi_H+int2float(humi_L);
//num2str()函数为数字转字符数组
//形参分别为 (小数,存储数组名,需要保留的小数位数)
num2str(T,Tp,2);
num2str(H,Hu,2);
LcdShowStr(1,0,Tp);
LcdShowStr(9,0,Hu);
}
}
说明:
LcdShowStr(x,y,*str) 表示显示字符数组从lcd的横坐标第x格,纵向只有0和1,0表示第一行,1表示第二行
DisplayOneChar(x,y,str); x,y同上,但此函数只能显示一个字符。
文件说明:
main.c | 程序入口,引入其它头文件,直接调用其函数 |
DHT12.h | 温湿度传感器头文件,存有相关IIC通讯、数据读取的函数 |
mytools.h | 为了避免引入C语言库,带来程序冗余,自己按需复写相关工具函数 |
lcd.h | 为LCD1602的头文件,引入后可直接调用使用,内IO接口可自行修改 |
完整文件下载:云盘下载 提取码:hva9