基于单片机的SHT11的温湿度监测
时间:10-02
整理:3721RD
点击:
我做的一个基于单片机的温湿度控制 传感器使用的是SHT11我自己找不出程序的错误 可是仿真确无法成功,望大侠指点一二啊 用液晶显示所测温湿度 接的是单片机P1口,由于只需要向其写数据 所以R/W接地,程序有详细的说明 求指教 急 谢谢了
#include<reg52.h>
#include<intrins.h>
#include<stdio.h>
#include<math.h>
#include<string.h>
#define uchar unsigned char
#define uint unsigned int
#define uiong unsigned long
sbit DAT=P2^7;//SHT11数据
sbit SCK=P2^6;//SHT11时钟
sbit lcden=P3^6;//LCD命令/时钟端口
sbit lcdrs=P3^7;//lcd使能端
uchar error;//全局错误变量
uchar ack;//全局应答变量
uchar data_h;//数据高位
uchar data_l;//数据低位
int temp;//温度显值
int humi;//湿度显值
int dis_buf[5];//显示缓冲区
uchar code dis1[]={"temp:"};//第一行显示表头
uchar code dis2[]={"Humi:"};//第二行显示表头
uchar code dis[]={"0123456789."};//显示数值
#define TEMP_ML 0x03//000 0001 1 温度命令
#define HUMI_ML 0x05//000 0010 1 湿度命令
void delay(uint count)//时间延时函数
{
uint i,j;
for(i=count;i>0;i--)
for(j=110;j>0;j--);
}
void sht11_start()//SHT11启动程序
{
DAT=1;SCK=0;
_nop_();
SCK=1;
_nop_();
DAT=0;
_nop_();
SCK=0;
_nop_();
_nop_();
_nop_();
SCK=1;
_nop_();
DAT=1;
_nop_();
SCK=0;
}
void sht11_rest(void)//SHT11复位程序
{
uchar i;
DAT=1;
SCK=0;
for(i=0;i<9;i++)
{
SCK=1;
SCK=0;
}
sht11_start();
}
void read(void)//读两个字节,返回应答信号
{
uchar i,val;
data_l=0;
data_h=0;
//SCK=0;
/*读高八位*/
DAT=1;//释放数据总线
for(i=0x80;i>0;i/=2)//移位8位
{
SCK=1;//上升沿读入
if(DAT)
val=(val | i);//确定值先读入高位
SCK=0;
}
DAT=0;//应答信号 有应答为0,无为1
SCK=1;//第九个脉冲
_nop_();_nop_();_nop_();//脉冲宽度为5us
SCK=0;DAT=1;//释放数据总线
data_h=val;//存测高字节
/*读低八位*/
val=0;
DAT=1;//释放数据总线
for(i=0x80;i>0;i/=2)
{
SCK=1;//上升沿读入
if(DAT)
val=(val | i);//确定值
SCK=0;
}
DAT=1;
SCK=1;//第九个脉冲
_nop_();_nop_();_nop_();//脉冲宽度为5us
SCK=0;
DAT=1;//释放数据总线
data_l=val;
}
char write(uchar value)//写一个字节返回应答信号
{
uchar i;
ack=0;//默认低电平表示有应答
SCK=0;
for(i=0x80;i>0;i/=2)//释放数据总线
{
if(i & value)//先写入高值
DAT=1;//写入值1
else
DAT=0;
SCK=1;//上升沿写入
_nop_();_nop_();_nop_();//脉冲宽度为5us
SCK=0;
}
DAT=1; //释放数据总线
SCK=1;//第九个脉冲
if(DAT==1)//读应答信号
ack=1;//高电平表示未应答,低电平表示有应答
SCK=0;
return ack;//返回ack,1为没有应答,0为有应答
}
void measure(uchar m1)//测量温度或者湿度返回校验值
{
uint i;
sht11_start();//启动
write(m1);//写入测温度或湿度指令
if(ack==1)//无应答
{
sht11_rest();//复位
write(m1);//再次写入
}
/* for(i=0;i<55535;i++)//判断是否处于忙状态
{
if(DAT==0)//有应答就退出
break;
else
_nop_();//无应答就显示
}*/
read();//度温度或湿度
}
void comp_temp(void)//计算温度
{
float aa=0,temp_zi;
aa=(float)(data_h*256)+(float)data_l;//高低字节合并
temp_zi=0.01*aa-40.1;
if(temp_zi<0)//低于0以0计算
{
temp_zi=0;
}
temp_zi=temp_zi*10;//保留一位
temp=(int)temp_zi;//温度
}
void comp_humi(void)//计算湿度
{
float aa=0,bb=0,humi_zi;
int abcd=0;
aa=(float)data_h*256+(float)data_l;//高低字节合并
bb=-4+0.0405*aa-aa*aa*0.0000028;
humi_zi=((float)(temp)/10-25)*(0.01+0.00008*aa)+bb;//湿度信号补偿
humi_zi=bb*10;//保留小数点后面1位
humi=(int)humi_zi;//湿度
}
void comp_temp_humi(void)//温湿度处理
{
error=0;
ack=0;
sht11_rest();//复位
measure(TEMP_ML);//测温度
comp_temp();//计算温度
measure(HUMI_ML);//测湿度
comp_humi();//计算湿度
}
void dat_wrt(uchar dat)//写数据
{
lcden=0;
delay(5);
lcdrs=1;//RS=1;为写数据
delay(5);
P1=dat;//写数据
delay(5);
lcden=1;//高电平写入
delay(5);
lcden=0;
}
void cmd_wrt(uchar cmd)//写命令
{
lcden=0;
delay(5);
lcdrs=0;//RS=1;为写命令
delay(5);
P1=cmd;//写入命令
delay(5);
lcden=1;//上升沿写入
delay(5);
lcden=0;
}
void init_1602(void)
{
cmd_wrt(0x01);//清屏
cmd_wrt(0x0c);//开显示,不显示光标,不闪烁
cmd_wrt(0x06);//光标左移显示不发生移位
cmd_wrt(0x38);//16*2显示,8位数据接口,5*7点阵
}
void lcd_start(uchar start)
{
cmd_wrt(start|0x80);//确保显示在LCD上的位置
}
uchar dat_adj(int dat1)
{
uchar i;
dis_buf[0]=(int)(dat1/1000);//千位
dis_buf[1]=(int)((dat1%1000)/100);//百位
dis_buf[2]=(int)((dat1%100)/10);//十位
dis_buf[3]=10;//小数点
dis_buf[4]=(int)(dat1%10);//小数点后个位
for(i=0;i<2;i++)
{
if(dis_buf[i]!=0)//明确显示位数
break;
}
return(i);
}
void disp(int dat,uchar k)
{
uchar temp,j;
temp=dat_adj(dat);
lcd_start(k+temp);//确定显示位置
for(j=temp;j<5;j++)
dat_wrt(dis[dis_buf[j]]);//写显示数据
}
void print(uchar *str)
{
while(*str!='\0')//直到字符串结束
{
dat_wrt(*str);
str++;//指向下一个字符
}
}
void main()
{
P0=0;
init_1602();//初始化液晶
lcd_start(0x00);//确定显示起始位置 第一行
print(dis1);//显示文字temp
lcd_start(0x40);//确定显示起始位置 第二行
print(dis2);//显示文字humi
while(1)
{
comp_temp_humi();//测温湿度并转换
disp(temp,0x06);//第一行显示温度
disp(humi,0x46);//第二行显示湿度
}
delay(200);
}
#include<reg52.h>
#include<intrins.h>
#include<stdio.h>
#include<math.h>
#include<string.h>
#define uchar unsigned char
#define uint unsigned int
#define uiong unsigned long
sbit DAT=P2^7;//SHT11数据
sbit SCK=P2^6;//SHT11时钟
sbit lcden=P3^6;//LCD命令/时钟端口
sbit lcdrs=P3^7;//lcd使能端
uchar error;//全局错误变量
uchar ack;//全局应答变量
uchar data_h;//数据高位
uchar data_l;//数据低位
int temp;//温度显值
int humi;//湿度显值
int dis_buf[5];//显示缓冲区
uchar code dis1[]={"temp:"};//第一行显示表头
uchar code dis2[]={"Humi:"};//第二行显示表头
uchar code dis[]={"0123456789."};//显示数值
#define TEMP_ML 0x03//000 0001 1 温度命令
#define HUMI_ML 0x05//000 0010 1 湿度命令
void delay(uint count)//时间延时函数
{
uint i,j;
for(i=count;i>0;i--)
for(j=110;j>0;j--);
}
void sht11_start()//SHT11启动程序
{
DAT=1;SCK=0;
_nop_();
SCK=1;
_nop_();
DAT=0;
_nop_();
SCK=0;
_nop_();
_nop_();
_nop_();
SCK=1;
_nop_();
DAT=1;
_nop_();
SCK=0;
}
void sht11_rest(void)//SHT11复位程序
{
uchar i;
DAT=1;
SCK=0;
for(i=0;i<9;i++)
{
SCK=1;
SCK=0;
}
sht11_start();
}
void read(void)//读两个字节,返回应答信号
{
uchar i,val;
data_l=0;
data_h=0;
//SCK=0;
/*读高八位*/
DAT=1;//释放数据总线
for(i=0x80;i>0;i/=2)//移位8位
{
SCK=1;//上升沿读入
if(DAT)
val=(val | i);//确定值先读入高位
SCK=0;
}
DAT=0;//应答信号 有应答为0,无为1
SCK=1;//第九个脉冲
_nop_();_nop_();_nop_();//脉冲宽度为5us
SCK=0;DAT=1;//释放数据总线
data_h=val;//存测高字节
/*读低八位*/
val=0;
DAT=1;//释放数据总线
for(i=0x80;i>0;i/=2)
{
SCK=1;//上升沿读入
if(DAT)
val=(val | i);//确定值
SCK=0;
}
DAT=1;
SCK=1;//第九个脉冲
_nop_();_nop_();_nop_();//脉冲宽度为5us
SCK=0;
DAT=1;//释放数据总线
data_l=val;
}
char write(uchar value)//写一个字节返回应答信号
{
uchar i;
ack=0;//默认低电平表示有应答
SCK=0;
for(i=0x80;i>0;i/=2)//释放数据总线
{
if(i & value)//先写入高值
DAT=1;//写入值1
else
DAT=0;
SCK=1;//上升沿写入
_nop_();_nop_();_nop_();//脉冲宽度为5us
SCK=0;
}
DAT=1; //释放数据总线
SCK=1;//第九个脉冲
if(DAT==1)//读应答信号
ack=1;//高电平表示未应答,低电平表示有应答
SCK=0;
return ack;//返回ack,1为没有应答,0为有应答
}
void measure(uchar m1)//测量温度或者湿度返回校验值
{
uint i;
sht11_start();//启动
write(m1);//写入测温度或湿度指令
if(ack==1)//无应答
{
sht11_rest();//复位
write(m1);//再次写入
}
/* for(i=0;i<55535;i++)//判断是否处于忙状态
{
if(DAT==0)//有应答就退出
break;
else
_nop_();//无应答就显示
}*/
read();//度温度或湿度
}
void comp_temp(void)//计算温度
{
float aa=0,temp_zi;
aa=(float)(data_h*256)+(float)data_l;//高低字节合并
temp_zi=0.01*aa-40.1;
if(temp_zi<0)//低于0以0计算
{
temp_zi=0;
}
temp_zi=temp_zi*10;//保留一位
temp=(int)temp_zi;//温度
}
void comp_humi(void)//计算湿度
{
float aa=0,bb=0,humi_zi;
int abcd=0;
aa=(float)data_h*256+(float)data_l;//高低字节合并
bb=-4+0.0405*aa-aa*aa*0.0000028;
humi_zi=((float)(temp)/10-25)*(0.01+0.00008*aa)+bb;//湿度信号补偿
humi_zi=bb*10;//保留小数点后面1位
humi=(int)humi_zi;//湿度
}
void comp_temp_humi(void)//温湿度处理
{
error=0;
ack=0;
sht11_rest();//复位
measure(TEMP_ML);//测温度
comp_temp();//计算温度
measure(HUMI_ML);//测湿度
comp_humi();//计算湿度
}
void dat_wrt(uchar dat)//写数据
{
lcden=0;
delay(5);
lcdrs=1;//RS=1;为写数据
delay(5);
P1=dat;//写数据
delay(5);
lcden=1;//高电平写入
delay(5);
lcden=0;
}
void cmd_wrt(uchar cmd)//写命令
{
lcden=0;
delay(5);
lcdrs=0;//RS=1;为写命令
delay(5);
P1=cmd;//写入命令
delay(5);
lcden=1;//上升沿写入
delay(5);
lcden=0;
}
void init_1602(void)
{
cmd_wrt(0x01);//清屏
cmd_wrt(0x0c);//开显示,不显示光标,不闪烁
cmd_wrt(0x06);//光标左移显示不发生移位
cmd_wrt(0x38);//16*2显示,8位数据接口,5*7点阵
}
void lcd_start(uchar start)
{
cmd_wrt(start|0x80);//确保显示在LCD上的位置
}
uchar dat_adj(int dat1)
{
uchar i;
dis_buf[0]=(int)(dat1/1000);//千位
dis_buf[1]=(int)((dat1%1000)/100);//百位
dis_buf[2]=(int)((dat1%100)/10);//十位
dis_buf[3]=10;//小数点
dis_buf[4]=(int)(dat1%10);//小数点后个位
for(i=0;i<2;i++)
{
if(dis_buf[i]!=0)//明确显示位数
break;
}
return(i);
}
void disp(int dat,uchar k)
{
uchar temp,j;
temp=dat_adj(dat);
lcd_start(k+temp);//确定显示位置
for(j=temp;j<5;j++)
dat_wrt(dis[dis_buf[j]]);//写显示数据
}
void print(uchar *str)
{
while(*str!='\0')//直到字符串结束
{
dat_wrt(*str);
str++;//指向下一个字符
}
}
void main()
{
P0=0;
init_1602();//初始化液晶
lcd_start(0x00);//确定显示起始位置 第一行
print(dis1);//显示文字temp
lcd_start(0x40);//确定显示起始位置 第二行
print(dis2);//显示文字humi
while(1)
{
comp_temp_humi();//测温湿度并转换
disp(temp,0x06);//第一行显示温度
disp(humi,0x46);//第二行显示湿度
}
delay(200);
}
将浮点数转换为长整形数更好些
顶新人、、、、、、
谢谢了 我已经找到哪里错啦
看看。。
/* for(i=0;i<55535;i++)//判断是否处于忙状态
{
if(DAT==0)//有应答就退出
break;
else
_nop_();//无应答就显示
}*/
在这一段取消掉注释 然后把_nop_();改为disp(temp,0x06);//第一行显示温度 和disp(humi,0x46);//第二行显示湿度并把主函数的着句注释掉就能运行成功啦
师兄,能不能发一份到我邮箱啊 410282727@qq.com
为什么只有图没程序
顶下。
小编好厉害
小编发个原理图呗!
good
学习了,支持一下
顶顶小编
不完整吧程序 很多初始化 的模块都没有呢
留些邮箱 我给你发一个 我这里有一个可以用
麻烦 大神 发一份给我 275492992@qq.com 谢谢啊 我毕设做这个。
怎么不显示啊,大侠,求回复,求大神把图和程序再发帖出来
1782614831@qq.com 谢谢了
谢谢分享!