一、項(xiàng)目介紹
當(dāng)前文章介紹基于51單片機(jī)和SHT30傳感器設(shè)計(jì)的環(huán)境溫度與濕度檢測(cè)設(shè)備。設(shè)備采用IIC模擬時(shí)序通信協(xié)議,能夠?qū)崟r(shí)監(jiān)測(cè)環(huán)境的溫度和濕度,并將數(shù)據(jù)通過LCD顯示屏顯示出來;可以廣泛應(yīng)用于室內(nèi)環(huán)境監(jiān)測(cè)、氣象觀測(cè)、農(nóng)業(yè)溫室監(jiān)測(cè)等領(lǐng)域。
在本項(xiàng)目中,使用了51單片機(jī)作為主控芯片,SHT30傳感器作為溫濕度傳感器,LCD顯示屏作為數(shù)據(jù)顯示模塊。通過51單片機(jī)的GPIO口模擬IIC通信協(xié)議,實(shí)現(xiàn)了與SHT30傳感器的數(shù)據(jù)通信。
二、硬件設(shè)計(jì)
2.1 硬件構(gòu)成
本次設(shè)計(jì)所需的硬件主要包括以下部分:
2.2 硬件接口及信號(hào)
本次設(shè)計(jì)使用51單片機(jī)通過IIC總線與SHT30傳感器進(jìn)行通信,同時(shí)使用串口與上位機(jī)進(jìn)行數(shù)據(jù)傳輸,并使用液晶顯示屏顯示當(dāng)前溫濕度值。
具體接口和信號(hào)定義如下:
(1) 51單片機(jī)與SHT30傳感器之間的IIC接口:
端口 | 功能 | 說明 |
---|---|---|
P2.0 | SDA | 數(shù)據(jù)線 |
P2.1 | SCL | 時(shí)鐘線 |
P2.2 | RESET | 復(fù)位線 |
(2) 51單片機(jī)與串口通信模塊之間的接口:
端口 | 功能 | 說明 |
---|---|---|
P3.0 | TXD | 發(fā)送線 |
P3.1 | RXD | 接收線 |
P3.2 | GND | 地線 |
(3) 51單片機(jī)與液晶屏之間的接口:
端口 | 功能 | 說明 |
---|---|---|
P1.0-P1.7 | DB0-DB7 | 數(shù)據(jù)線 |
P0.0 | RS | 指令/數(shù)據(jù)選擇線 |
P0.1 | RW | 讀/寫選擇線 |
P0.2 | E | 使能線 |
P0.3 | CS | 片選線 |
VCC | 電源正極 | 5V |
GND | 電源地 | 地 |
三、軟件設(shè)計(jì)
3.1 SHT30傳感器代碼
下面代碼讀取SHT30傳感器的值并通過串口打印。
#include < REG52.h >
#include < stdio.h >
?
#define uchar unsigned char
#define uint unsigned int
?
sbit SDA=P2^0;
sbit SCL=P2^1;
?
void delay(int n)
{
int i;
while(n--)
{
for(i=0; i< 120; i++);
}
}
?
void start()
{
SDA = 1;
_nop_();
SCL = 1;
_nop_();
SDA = 0;
_nop_();
SCL = 0;
_nop_();
}
?
void stop()
{
SDA = 0;
_nop_();
SCL = 1;
_nop_();
SDA = 1;
_nop_();
}
?
void ack()
{
SDA = 0;
_nop_();
SCL = 1;
_nop_();
SCL = 0;
_nop_();
SDA = 1;
_nop_();
}
?
void nack()
{
SDA = 1;
_nop_();
SCL = 1;
_nop_();
SCL = 0;
_nop_();
}
?
void write_byte(uchar dat)
{
uchar i;
for(i=0; i< 8; i++)
{
SDA = dat & 0x80;
_nop_();
SCL = 1;
_nop_();
SCL = 0;
_nop_();
dat < <= 1;
}
ack();
}
?
uchar read_byte()
{
uchar i, dat;
for(i=0; i< 8; i++)
{
dat < <= 1;
SCL = 1;
_nop_();
dat |= SDA;
SCL = 0;
_nop_();
}
return dat;
}
?
void init_sht30()
{
start();
write_byte(0x80);
if(read_byte() != 0x5A)
{
stop();
return;
}
write_byte(0xBE);
if(read_byte() != 0x08 || read_byte() != 0x00)
{
stop();
return;
}
stop();
}
?
float measure_temp(void)
{
uchar temp_h, temp_l, crc;
float temp;
?
start();
write_byte(0x80); // 主機(jī)發(fā)送寫地址
write_byte(0x2C); // 選擇開始溫度測(cè)量命令
write_byte(0x06);
stop();
?
delay(15); // 延時(shí)等待溫度測(cè)量完成
?
start();
write_byte(0x81); // 主機(jī)發(fā)送讀地址
temp_h=read_byte();
ack();
temp_l=read_byte();
ack();
crc=read_byte