主页 > 互联网 > 内容页

基于51单片机+SHT30设计的环境温度与湿度检测设备(IIC模拟时序)-全球短讯

2023-06-19 09:08:51 来源:DS小龙哥-嵌入式技术
一、项目介绍

当前文章介绍基于51单片机和SHT30传感器设计的环境温度与湿度检测设备。设备采用IIC模拟时序通信协议,能够实时监测环境的温度和湿度,并将数据通过LCD显示屏显示出来;可以广泛应用于室内环境监测、气象观测、农业温室监测等领域。


(相关资料图)

在本项目中,使用了51单片机作为主控芯片,SHT30传感器作为温湿度传感器,LCD显示屏作为数据显示模块。通过51单片机的GPIO口模拟IIC通信协议,实现了与SHT30传感器的数据通信。

二、硬件设计2.1 硬件构成

本次设计所需的硬件主要包括以下部分:

STC89C52单片机SHT30温湿度传感器串口通信模块LCD1602显示屏电源模块杜邦线等连接线2.2 硬件接口及信号

本次设计使用51单片机通过IIC总线与SHT30传感器进行通信,同时使用串口与上位机进行数据传输,并使用液晶显示屏显示当前温湿度值。

具体接口和信号定义如下:

(1) 51单片机与SHT30传感器之间的IIC接口:

端口功能说明
P2.0SDA数据线
P2.1SCL时钟线
P2.2RESET复位线

(2) 51单片机与串口通信模块之间的接口:

端口功能说明
P3.0TXD发送线
P3.1RXD接收线
P3.2GND地线

(3) 51单片机与液晶屏之间的接口:

端口功能说明
P1.0-P1.7DB0-DB7数据线
P0.0RS指令/数据选择线
P0.1RW读/写选择线
P0.2E使能线
P0.3CS片选线
VCC电源正极5V
GND电源地
三、软件设计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);  // 主机发送写地址     write_byte(0x2C);  // 选择开始温度测量命令     write_byte(0x06);     stop(); ​     delay(15);    // 延时等待温度测量完成 ​     start();     write_byte(0x81);  // 主机发送读地址     temp_h=read_byte();       ack();     temp_l=read_byte();      ack();     crc=read_byte();     stop(); ​     temp = ((temp_h< <8)+temp_l)*175.0/0xffff - 45.0; // 温度值转换公式 ​     return temp; } ​ float measure_humi(void) {     uchar humi_h, humi_l, crc;     float humi; ​     start();     write_byte(0x80);  // 主机发送写地址     write_byte(0x2C);  // 选择开始湿度测量命令     write_byte(0x06);     stop(); ​     delay(15);    // 延时等待湿度测量完成 ​     start();     write_byte(0x81);  // 主机发送读地址     humi_h=read_byte();       ack();     humi_l=read_byte();      ack();     crc=read_byte();     stop(); ​     humi = ((humi_h< <8)+humi_l)*100.0/0xffff; // 湿度值转换公式 ​     return humi; } ​ void main() {        float temp, humi; ​     init_sht30();   // SHT30 初始化 ​     TMOD=0x20;      // 定时器0工作方式2,8位定时器,用于波特率设置     TH1=0xfd;       // 波特率9600     TL1=0xfd;     TR1=1;          // 启动定时器0 ​     SCON=0x50;      // 设置串口工作方式1,允许接收,允许接收中断     ES=1;           // 允许串口中断 ​     while(1)     {         temp = measure_temp();         humi = measure_humi();         printf("Temperature: %.1fC, Humidity: %.1f%\\n", temp, humi);         delay(500); // 间隔时间500ms     } } ​ void ser() interrupt 4 using 2 {     if(RI)          // 接收到数据     {         RI=0;       // 清除标志位     }     if(TI)          // 发送完毕     {         TI=0;       // 清除标志位     } }

在上面的代码中,定义了两个函数 measure_tempmeasure_humi,分别用于测量温度和湿度值,并返回结果。在主函数中,利用这两个函数得到当前的温湿度值,然后通过串口打印出来。

3.2 LCD1602显示屏代码

下面代码是LCD1602驱动代码,完成数字字符显示。

#include < REG52.h > ​ #define LCD1602_DB P0 sbit  RS = P2^5; sbit  RW = P2^6; sbit  E  = P2^7; ​ void delay(int n) {     int i;     while(n--)     {         for(i=0; i< 120; i++);     } } ​ void main() {        //LCD 初始化     delay(1000);     LCD1602_DB = 0x38;     E = 1;     delay(5);     E = 0; ​     delay(500);     LCD1602_DB = 0x08;     E = 1;     delay(5);     E = 0; ​     delay(500);     LCD1602_DB = 0x01;     E = 1;     delay(5);     E = 0; ​     delay(500);     LCD1602_DB = 0x06;     E = 1;     delay(5);     E = 0; ​     delay(500);     LCD1602_DB = 0x0C;     E = 1;     delay(5);     E = 0; ​     while(1)     {         //向LCD中写入数字12345         RS = 0;  //选择指令寄存器​         LCD1602_DB = 0x80;  //设置地址为第一行的第一个字符位置(0x80 + 0x00) ​         E = 1;         delay(5);         E = 0; ​         RS = 1;  //选择数据寄存器 ​         LCD1602_DB = 0x31;  //写入数字1         E = 1;         delay(5);         E = 0; ​         LCD1602_DB = 0x32;  //写入数字2         E = 1;         delay(5);         E = 0; ​         LCD1602_DB = 0x33;  //写入数字3         E = 1;         delay(5);         E = 0; ​         LCD1602_DB = 0x34;  //写入数字4         E = 1;         delay(5);         E = 0; ​         LCD1602_DB = 0x35;  //写入数字5         E = 1;         delay(5);         E = 0; ​         delay(500); //间隔时间为500ms     } }

在上面的代码中,定义了函数 delay用于延时等待,并且实现了LCD1602的初始化和写入操作。在主函数中,执行LCD1602的初始化操作,然后循环不断向LCD中写入数字12345,并且间隔时间为500ms。

3.3 完整代码
#include< reg52.h > #include< intrins.h > ​ #define uchar unsigned char #define uint unsigned int ​ sbit SDA = P2^0;    //定义SDA引脚 sbit SCL = P2^1;    //定义SCL引脚 sbit CS = P0^3;     //定义液晶屏片选引脚 sbit RW = P0^1;     //定义液晶屏读/写引脚 sbit RS = P0^0;     //定义液晶屏指令/数据引脚 sbit E = P0^2;      //定义液晶屏使能引脚 ​ void delay(int n)   //延时函数,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()   //SHT30初始化 {     start();     write_byte(0x80);     if(read_byte() != 0x5A)     {         stop();         return;     }     write_byte(0xBE);     if(read_byte() != 0x08 || read_byte() != 0x00)     {         stop();         return;     }     stop(); } ​ void measure()          //测量温湿度值 {     float humi, temp;     uint i;     start();     write_byte(0x80);     read_byte();     read_byte();     read_byte();     write_byte(0x2C);     write_byte(0x06);     for(i=0; i< 40000; i++); //等待测量结果     start();     write_byte(0x80);     read_byte();     read_byte();     read_byte();     humi = read_byte() * 256;     humi += read_byte();     temp = read_byte() * 256;     temp += read_byte();     stop();     temp = -45 + (175*temp)/65535;  //转化温度     humi = 100 * humi / 65535;      //转化湿度     //将温湿度值通过串口发送     printf("Temperature: %.1fC\\n", temp);     printf("Humidity: %.1f%%RH\\n", humi); } ​ void init_lcd()         //液晶屏初始化 {     RW = 0;     RS = 0;     E = 0;     delay(15);     write_byte(0x30);     delay(15);     write_byte(0x30);     delay(5);     write_byte(0x30);     delay(5);     write_byte(0x38);     write_byte(0x08);     write_byte(0x01);     write_byte(0x06);     write_byte(0x0c); } ​ void display(float temp, float humi)    //显示温湿度值 {     uchar i;     uchar temp_str[5];     uchar humi_str[5];     //转化为字符串     sprintf(temp_str, "%.1f", temp);     sprintf(humi_str, "%.1f", humi);     //显示温度     RS = 0;     E = 1;     P1 = 0x80;  //第一行第一个字符     E = 0;     RS = 1;     for(i=0; i< 5; i++)     {         E = 1;         P1 = temp_str[i];         E = 0;     }     //显示湿度     RS = 0;     E = 1;     P1 = 0xc0;  //第二行第一个字符     E = 0;     RS = 1;     for(i=0; i< 5; i++)     {         E = 1;         P1 = humi_str[i];         E = 0;     } } ​ void main() {     init_sht30();   //SHT30初始化     init_lcd();     //液晶屏初始化     while(1)     {         measure();  //测量温湿度值并通过串口发送         delay(1000);         display(temp, humi);    //显示温湿度值     } } ​

审核编辑:汤梓红

标签:

上一篇:变色龙九年级课文原文(变色龙契科夫课文音频) 全球速读
下一篇:最后一页