帮我写一个DHT22的keil代码,要求数码管显示当前时间,温度湿度,温湿度采样周期每两秒采样一次,时间与温湿度值切换时间为2s,温湿度的值通过串口上传至电脑
时间: 2024-05-12 17:13:13 浏览: 97
DHT90和LCD1602的 温湿度实时显示的KEIL程序
4星 · 用户满意度95%
很高兴为您提供帮助!以下是DHT22的Keil代码,请根据您的硬件配置进行适当修改:
```c
#include <reg52.h>
#include <stdio.h>
#include <intrins.h>
typedef unsigned char uchar;
typedef unsigned int uint;
sbit DHT22_IO=P2^0; //DHT22数据线
uchar temperature_h, temperature_l, humidity_h, humidity_l;
uint temperature, humidity;
//延时函数
void delay_us(uint t)
{
while(t--);
}
//发送起始信号
void send_start_signal()
{
DHT22_IO = 0;
delay_us(20000); //至少拉低18ms
DHT22_IO = 1;
delay_us(30); //拉高20~40us
}
//接收响应信号
bit receive_response()
{
uint t = 0;
while(DHT22_IO && t < 100) //等待拉低
{
delay_us(1);
t++;
}
if(t >= 100) return 0; //超时,接收失败
t = 0;
while(!DHT22_IO && t < 100) //等待拉高
{
delay_us(1);
t++;
}
if(t >= 100) return 0; //超时,接收失败
t = 0;
while(DHT22_IO && t < 100) //等待拉低
{
delay_us(1);
t++;
}
if(t >= 100) return 0; //超时,接收失败
return 1; //接收成功
}
//接收一个位的数据
uchar receive_bit()
{
uint t = 0;
while(!DHT22_IO && t < 100) //等待拉高
{
delay_us(1);
t++;
}
t = 0;
while(DHT22_IO && t < 100) //等待拉低
{
delay_us(1);
t++;
}
if(t >= 50) return 1; //高电平持续时间大于50us,认为是1
else return 0; //否则认为是0
}
//接收一个字节的数据
uchar receive_byte()
{
uchar data = 0;
for(int i = 0; i < 8; i++)
{
data <<= 1;
data |= receive_bit();
}
return data;
}
//读取温湿度值
bit read_dht22()
{
send_start_signal();
if(!receive_response()) return 0; //接收响应失败
humidity_h = receive_byte();
humidity_l = receive_byte();
temperature_h = receive_byte();
temperature_l = receive_byte();
uchar sum = receive_byte();
if(sum != (humidity_h+humidity_l+temperature_h+temperature_l)) return 0; //校验和错误
humidity = ((uint)humidity_h << 8) | humidity_l;
temperature = ((uint)temperature_h << 8) | temperature_l;
return 1; //读取成功
}
//数码管显示函数
void display(uint num, uchar dot)
{
uchar code table[] = { //数码管段码表
0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,
0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71
};
uchar digit[4] = {0}; //四位数码管的值
uint tmp = num;
digit[0] = table[tmp % 10]; //个位
tmp /= 10;
digit[1] = table[tmp % 10]; //十位
tmp /= 10;
digit[2] = table[tmp % 10]; //百位
tmp /= 10;
digit[3] = table[tmp % 10]; //千位
for(int i = 0; i < 4; i++) //显示四位数码管
{
P0 = digit[i];
if(i == dot) P0 &= 0x7f; //小数点
P2 = ~(0x01 << i);
delay_us(500); //延时一段时间,使数码管亮度合适
}
}
//串口发送函数
void send_data(uchar dat)
{
SBUF = dat;
while(!TI);
TI = 0;
}
//主函数
void main()
{
TMOD = 0x20; //定时器1工作在方式2
TH1 = 0xfd; //波特率为9600bps
TL1 = 0xfd;
SCON = 0x50; //8位数据,无校验,1位停止位
TR1 = 1; //启动定时器1
EA = 1; //开启总中断
ES = 1; //开启串口中断
while(1)
{
if(read_dht22()) //读取温湿度成功
{
display(temperature, 1); //显示温度(带一位小数)
delay_us(2000); //延时2s
display(humidity, 2); //显示湿度(带一位小数)
delay_us(2000); //延时2s
}
//上传温湿度数据到电脑(使用串口通信)
uchar buffer[10];
sprintf(buffer, "%d.%d,%d.%d\r\n", temperature/10, temperature%10, humidity/10, humidity%10);
for(int i = 0; i < 10; i++)
{
send_data(buffer[i]);
}
//显示当前时间
uchar second = TH1;
display(second, 2); //显示秒数(带一位小数)
delay_us(2000); //延时2s
display(0, 2); //显示空白
delay_us(2000); //延时2s
}
}
//串口中断函数
void serial() interrupt 4
{
if(RI) //接收到数据
{
RI = 0;
}
if(TI) //发送完成
{
TI = 0;
}
}
```
注:以上代码中的数码管显示和串口通信部分可能需要根据您的具体硬件配置进行修改。
阅读全文