各位高手,51單片機讀DHT12,I2C,只能讀出濕度值,溫度值和校驗值都是FF,換了一個傳感器還是這樣,已經一周了,折騰的夠嗆,請高手幫忙分析一下程序,多謝了!
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit I2C_SCL = P1^6; //DHT12時鐘線
sbit I2C_SDA = P1^7; //DHT12數據線
void delay_ms(uint tim); //毫秒級延時函數聲明
void delay_n10us(uchar tim); //10倍微秒級延時函數聲明
void I2C_delay(void);
void I2C_Start(void);
void I2C_Stop(void);
void I2C_Ack(void);
void I2C_NAck(void);
uchar I2C_Wait_Ack(void);
void I2C_WriteByte(uchar txd);
uchar I2C_ReadByte(uchar ack);
void Init_DHT12(); //初始化
void Read_DHT12(uchar *sht); //測量DHT12的溫度濕度值,指針
void main()
{
uchar read_dht[5]; //存放從DHT12讀取的數據
float temperature=0.0,humidity=0.0; //將溫濕度轉為小數(保留2位)
Init_DHT12();
delay_ms(2000);
while(1)
{
Read_DHT12(read_dht); //從DHT12中讀數據
temperature = 1.0 * read_dht[2] + 0.1 * read_dht[3];
humidity = 1.0 * read_dht[0] + 0.1 * read_dht[1];
}
}
//產生起始信號
void I2C_Start(void)
{
I2C_SDA = 1; //注意先拉高SDA,否則可能會誤認為是停止信號
delay_n10us(1);
I2C_SCL = 1;
delay_n10us(5);
I2C_SDA = 0;
delay_n10us(5);
I2C_SCL = 0;
delay_n10us(1);
}
//產生停止信號
void I2C_Stop(void)
{
I2C_SCL = 0;
delay_n10us(1);
I2C_SDA = 0;
delay_n10us(5);
I2C_SCL = 1;
delay_n10us(5);
I2C_SDA = 1;
delay_n10us(1);
}
//主機產生應答信號
void I2C_Ack(void)
{
I2C_SCL = 0;
delay_n10us(1);
I2C_SDA = 0;
delay_n10us(5);
I2C_SCL = 1;
delay_n10us(5);
I2C_SCL = 0;
delay_n10us(1);
}
//主機產生不應答信號
void I2C_NAck(void)
{
I2C_SCL = 0;
delay_n10us(1);
I2C_SDA = 1;
delay_n10us(5);
I2C_SCL = 1;
delay_n10us(5);
I2C_SCL = 0;
delay_n10us(1);
}
//主機等待從機應答信號
//返回值為0,接收應答成功,返回值為1,接收應答失敗
uchar I2C_Wait_Ack(void)
{
uchar tempTime = 0;
I2C_SCL = 0;
delay_n10us(1);
I2C_SDA = 1;
delay_n10us(5); //增加等待從動件發送應答信號的時間,怕有些器件反應慢
I2C_SCL = 1;
delay_n10us(5);
while(I2C_SDA == 1)//等于1,則無應答
{
tempTime++;
if( tempTime > 250 )//一直無應答
{
I2C_Stop();
return 1;
}
delay_n10us(2);
}
I2C_SCL = 0;
delay_n10us(5);
return 0;
}
//發送一個字節
void I2C_WriteByte(uchar txd)
{
uchar i = 0;
I2C_SCL = 0; //拉低SCL為發送數據準備
for(i = 0; i < 8; i++)
{
I2C_SCL = 0;
I2C_SDA = (txd & 0x80) >> 7;
txd = txd << 1; //左移1位
delay_n10us(5);
I2C_SCL = 1; //拉高SCL
delay_n10us(5);
}
I2C_SCL = 0;
}
//讀取一個字節
uchar I2C_ReadByte(uchar ack)
{
uchar i = 0;
uchar rxd = 0;
I2C_SCL = 0;
delay_n10us(1);
I2C_SDA = 1;
delay_n10us(5); //等待從機準備信號
for(i = 0; i < 8; i++)
{
I2C_SCL = 0;
delay_n10us(10); //等待從機準備信號
I2C_SCL = 1; //拉高SCL
delay_n10us(10);
rxd = rxd << 1; //左移一位,最低位補0
rxd = rxd | I2C_SDA; //然后與SDA的狀態取或
}
I2C_SCL = 0;
if(ack == 0)
I2C_NAck();
else
I2C_Ack();
return rxd;
}
void Init_DHT12()
{
I2C_SDA = 1;
delay_n10us(1);
I2C_SCL = 1;
delay_n10us(1);
}
//讀取DHT12的溫度濕度值
void Read_DHT12(uchar *dht)
{
I2C_Start();
I2C_WriteByte(0xB8); //DHT12寫地址0xB8,讀地址為0xB9
I2C_Wait_Ack();
I2C_WriteByte(0x00); //寫地址
I2C_Wait_Ack(); //等待從機響應
I2C_Start();
I2C_WriteByte(0xB9); //讀指令
I2C_Wait_Ack(); //等待從機響應
dht[0] = I2C_ReadByte(1); //讀濕度整數位
dht[1] = I2C_ReadByte(1); //讀濕度小數位
dht[2] = I2C_ReadByte(1); //讀溫度整數位
dht[3] = I2C_ReadByte(1); //讀溫度小數位
dht[4] = I2C_ReadByte(0); //讀校驗位
I2C_Stop();
}
|