51单片机温湿度控制,温度达到范围led灯和继电器没有运作,请问是什么地方出了问题?谢谢大家!
#include <reg52.h>
#include <intrins.h>
#include <absacc.h>
#include <math.h> //包含头文件
#define uchar unsigned char
#define uint unsigned int //宏定义
//定义四个输出端口
sbit Led_fengshan1=P3^2;
sbit Led_fengshan2=P3^3;
sbit Led_fengshan3=P3^4;
sbit Led_penwu=P3^6;
//定义24C02数据口
sbit SCL = P1^0;
sbit SDA = P1^1;
//定义DHT11数据口
sbit DATA = P1^7;
//定义LCD1602端口
sbit E=P1^3; //1602使能引脚
//sbit RW=P2^6; //1602读写引脚 我们只需要向液晶里写数据,不需要读取数据,所以就把读写引脚直接接地,程序里就不用单独控制了
sbit RS=P1^2; //1602数据/命令选择引脚
//定义全局变量
uchar U8FLAG,U8temp,U8comdata,U8RH_data_H_temp,U8RH_data_L_temp,U8T_data_H_temp,U8T_data_L_temp,U8checkdata_temp; //定义读取温湿度变量
uchar U8RH_data_H,U8RH_data_L,U8T_data_H,U8T_data_L,U8checkdata;
uchar Mode,humidity,temperature; //设置模式、读取到的湿度温度数据存储变量
bit bdata FlagStartRH,hot,cold,humid,dry; //开启转换温湿度标志位、热冷湿干
//定时器0初始化
void Timer0_Init()
{
ET0 = 1; //允许定时器0中断
TMOD = 0x11; //定时器工作方式选择
TL0 = 0xb0;
TH0 = 0x3c; //定时器赋予初值50ms
TR0 = 1; //启动定时器T0
}
//定时器0中断
void Timer0_ISR (void) interrupt 1 using 0
{
uchar RHCounter; //定义计数变量
TL0 = 0xb0;
TH0 = 0x3c; //定时器赋予初值
RHCounter++; //每进一次中断就是50ms,此变量加一
if(RHCounter%10==0) //加到10的整数倍
//每2秒钟启动一次温湿度转换
if (RHCounter >= 40) //计数到40次,就是2s,启动一次温湿度转换
{
FlagStartRH = 1; //启动转换变量置1
RHCounter = 0; //计数变量清零
}
}
/*以下程序为24c02的程序,都是官方的实例程序,可以参考时序图理解,都是固定的*/
/*********************************
BASE DRIVE
**********************************/
void DELAY(unsigned int t) //延时函数
{
while(t!=0)
t--;
}
/******************************
IIC DRIVE
******************************/
void IICStart(void) //24c02的开始函数,关于24c02的函数多看下24c02的手册
{
SCL=0; //SCL引脚拉低
DELAY(1); //短延时
SDA=1; SCL=1; DELAY(1); //SDA拉高,SCL拉高,短延时
SDA=0; DELAY(1); //SDA拉低,短延时
SCL=0; //SCL拉低
}
void IICStop(void) //停止
{
SDA=0;SCL=1; DELAY(1); //注释略
SDA=1; DELAY(1);
SCL=0;
}
void SEND0(void) //发送
{
SDA=0;
SCL=1;
DELAY(1);
SCL=0;
}
void SEND1(void)
{
SDA=1;
DELAY(1);
SCL=1;
DELAY(1);
SCL=0;
}
bit Check_Ack(void) //应答
{
unsigned char errtime=250; //定义变量
DELAY(1);
SCL=1;
DELAY(1);
CY=SDA; //SDA引脚高电平就是1,低电平就是0,赋值给CY
while(CY) //如果CY为1,就执行此while
{
errtime--; //变量减
CY=SDA; //赋值
if (!errtime) //判断有没有减到0
{
IICStop(); //停止24C02
return 1; //返回1
}
}
DELAY(1);
SCL=0;
return 0;
}
void Write_byte(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
if((dat<<i)&0x80)
SEND1();
else
SEND0();
}
}
unsigned char Read_byte(void)
{
unsigned char i,temp=0;
for(i=0;i<8;i++)
{
SDA=1;
SCL=1;
DELAY(1);
if(SDA==1)
{
temp=temp<<1;
temp=temp|0x01;
}
else
temp=temp<<1;
SCL=0;
}
return temp;
}
/************************************
EEPROM DRIVE
Addr:from 0x00-->
*************************************/
unsigned char rdeeprom(unsigned char addr)
{
unsigned char temp=0;
bit flag=0;
IICStart();
Write_byte(0xa0);
Check_Ack();
Write_byte(addr);
Check_Ack();
IICStart();
Write_byte(0xa1);
Check_Ack();
temp=Read_byte();
SEND1();
IICStop();
return temp;
}
void wrteeprom(unsigned char addr,unsigned char dat)
{
IICStart();
Write_byte(0xa0);
Check_Ack();
Write_byte(addr);
Check_Ack();
Write_byte(dat);
Check_Ack();
IICStop();
}
/*以下程序为DHT11温湿度传感器程序,官方的实例程序*/
void Delay1(uint j) //延时程序
{
uchar i;
for(;j>0;j--)
{
for(i=0;i<27;i++);
}
}
void Delay_10us(void) //延时函数,大约10us,不精确
{
uchar i;
i--;
i--;
i--;
i--;
i--;
i--;
}
void COM(void) //读取温湿度函数
{
uchar i;
for(i=0;i<8;i++)
{
U8FLAG=2;
while((!DATA)&&U8FLAG++);
Delay_10us();
Delay_10us();
Delay_10us();
U8temp=0;
if(DATA)U8temp=1;
U8FLAG=2;
while((DATA)&&U8FLAG++);
//超时则跳出for循环
if(U8FLAG==1)break;
//判断数据位是0还是1
// 如果高电平高过预定0高电平值则数据位为 1
U8comdata<<=1;
U8comdata|=U8temp; //0
}//rof
}
//--------------------------------
//-----温湿度读取子程序 ------------
//--------------------------------
//----以下变量均为全局变量--------
//----温度高8位== U8T_data_H------
//----温度低8位== U8T_data_L------
//----湿度高8位== U8RH_data_H-----
//----湿度低8位== U8RH_data_L-----
//----校验 8位 == U8checkdata-----
//----调用相关子程序如下----------
//---- Delay();, Delay_10us();,COM();
//--------------------------------
uchar RH(void)
{
//主机拉低18ms
DATA=0;
Delay1(180); //原来为5
DATA=1;
//总线由上拉电阻拉高 主机延时20us
Delay_10us();
Delay_10us();
Delay_10us();
Delay_10us();
//主机设为输入 判断从机响应信号
DATA=1;
//判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行
if(!DATA) //T !
{
U8FLAG=2;
//判断从机是否发出 80us 的低电平响应信号是否结束
while((!DATA)&&U8FLAG++);
U8FLAG=2;
//判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
while((DATA)&&U8FLAG++);
//数据接收状态
COM();
U8RH_data_H_temp=U8comdata;
COM();
U8RH_data_L_temp=U8comdata;
COM();
U8T_data_H_temp=U8comdata;
COM();
U8T_data_L_temp=U8comdata;
COM();
U8checkdata_temp=U8comdata;
DATA=1;
//数据校验
U8temp=(U8T_data_H_temp+U8T_data_L_temp+U8RH_data_H_temp+U8RH_data_L_temp);
if(U8temp==U8checkdata_temp)
{
U8RH_data_H=U8RH_data_H_temp;
U8RH_data_L=U8RH_data_L_temp;
U8T_data_H=U8T_data_H_temp;
U8T_data_L=U8T_data_L_temp;
U8checkdata=U8checkdata_temp;
}
return 1;
}
else //传感器不响应
{
return 0;
}
}
/********************************************************************
* 文件名 : 液晶1602显示.c
* 描述 : 该程序实现了对液晶1602的控制。
***********************************************************************/
/********************************************************************
* 名称 : delay()
* 功能 : 延时,延时时间大概为140US。
* 输入 : 无
* 输出 : 无
***********************************************************************/
void delay()
{
int i,j;
for(i=0; i<=10; i++)
for(j=0; j<=2; j++);
}
/********************************************************************
* 名称 : enable(uchar del)
* 功能 : 1602命令函数
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/
void enable(uchar del)
{
P0 = del; //数据发送到P0口
RS = 0; //RS引脚拉低
E = 1; //E引脚高电平
delay(); //延时
E = 0; //E引脚低电平
delay(); //延时
}
/********************************************************************
* 名称 : write(uchar del)
* 功能 : 1602写数据函数
* 输入 : 需要写入1602的数据
* 输出 : 无
***********************************************************************/
void write(uchar del)
{
P0 = del; //同上
RS = 1;
E = 1;
delay();
E = 0;
delay();
}
/********************************************************************
* 名称 : L1602_init()
* 功能 : 1602初始化,请参考1602的资料
* 输入 : 无
* 输出 : 无
***********************************************************************/
void L1602_init(void)
{
enable(0x38); //设置液晶工作模式,意思:16*2行显示,5*7点阵,8位数据
enable(0x0c); //开显示不显示光标
enable(0x06); //整屏不移动,光标自动右移
enable(0x01); //清屏
}
/********************************************************************
* 名称 : L1602_char(uchar hang,uchar lie,char sign)
* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符显示"b" ,调用该函数如下
L1602_char(1,5,'b')
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void L1602_char(uchar hang,uchar lie,char sign)
{
uchar a; //定义变量
if(hang == 1) a = 0x80; //如果hang变量为1,让地址数据为0x80就是第一行的
if(hang == 2) a = 0xc0; //如果hang变量为0,让地址数据为0xc0就是第二行的
a = a + lie - 1; //列数据减一,因为液晶屏的列是从0开始的
enable(a); //发送行和列数据
write(sign); //写显示内容
}
/********************************************************************
* 名称 : L1602_string(uchar hang,uchar lie,uchar *p)
* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
L1602_string(1,5,"ab cd ef;")
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void L1602_string(uchar hang,uchar lie,uchar *p)
{
uchar a;
if(hang == 1) a = 0x80; //第一行地址
if(hang == 2) a = 0xc0; //第二行地址
a = a + lie - 1; //行和列数据加一起
enable(a); //发送行列数据
while(1) //进入循环
{
if(*p == '\0') break; //发送完字符串后跳出while循环
write(*p); //没发送完就继续发
p++; //字符串指针地址加1
}
}
//显示整型的温湿度数据用,共占用4位,其中一位符号位
void L1602_int(uchar hang, uchar lie, int num)
{
uint temp;
uint gewei,shiwei,baiwei,sign;
if (num >= 0) //如果温度值大于等于0
sign = 0; //符号为正
else //反之
sign = 1; //符号为负
temp = abs(num); //温度值取绝对值
baiwei = temp / 100; //除以100得到温度值百位
temp = temp - baiwei*100; //温度值减去百位得到十位和个位的数
shiwei = temp / 10; //除以10得到十位的数据
gewei = temp - shiwei*10; //减去十位的数据得到个位的数
num = abs(num); //温度取绝对值
if (num>=100) //如果温度大于100
{
// L1602_char(hang, lie+1, baiwei+48);
L1602_char(hang, lie+2, shiwei+48); //显示十位和个位
L1602_char(hang, lie+3, gewei+48);
}
else if (num>=10) //温度大于10
{
if (sign == 1) //负数时
L1602_char(hang, lie+1, '-'); //显示负号
L1602_char(hang, lie+2, shiwei+48); //显示十位和个位数
L1602_char(hang, lie+3, gewei+48);
}
else //温度小于10
{
if (sign == 1) //负数时
L1602_char(hang, lie+2, '-'); //显示负号
else //正数
L1602_char(hang, lie+2, ' '); //十位不显示
L1602_char(hang, lie+3, gewei+48); //显示个位数
}
}
void display() //显示函数
{
if(Mode==0) //不是设置状态
{
L1602_int(1,3,temperature); //显示温度数据
L1602_char(1,7,0xdf); //显示摄氏度的°
L1602_int(1,12,humidity); //显示湿度数据
if(hot==1&&cold==0&&humid==0&&dry==0) //温度过高
{L1602_string(2,1," It's very hot! ");} //显示热
else if(hot==1&&cold==0&&humid==1&&dry==0) //温度高,湿度高
{L1602_string(2,1," Hot and humid! ");} //显示热 ,湿
else if(hot==1&&cold==0&&humid==0&&dry==1) //温度高 ,湿度低
{L1602_string(2,1," Hot and dry! ");} //显示热 ,干
else if(hot==0&&cold==1&&humid==0&&dry==0) //温度低
{L1602_string(2,1," It's very cold!");} //显示冷
else if(hot==0&&cold==1&&humid==1&&dry==0) //温度低 ,湿度高
{L1602_string(2,1," Cold and humid!");} //显示冷 ,湿
else if(hot==0&&cold==1&&humid==0&&dry==1) //温度低 ,湿度低
{L1602_string(2,1," Cold and dry! ");} //显示冷 ,干
else if(hot==0&&cold==0&&humid==1&&dry==0) //湿度高
{L1602_string(2,1,"It's very humid!");} //显示潮湿
else if(hot==0&&cold==0&&humid==0&&dry==1) //湿度低
{L1602_string(2,1," It's very dry! ");} //显示干燥
else if(hot==0&&cold==0&&humid==0&&dry==0) //都在范围内
{L1602_string(2,1,"Good environment");} //显示环境好
}
}
//数据初始化
void Data_Init()
{
Led_fengshan1 = 1;
Led_fengshan2 = 1;
Led_fengshan3 = 1;
Led_penwu = 1; //熄灭四个继电器
}
/********************************************************************
* 名称 : Main()
* 功能 : 主函数
***********************************************************************/
void main()
{
uint i, j, testnum;
EA = 0; //关闭定时器
Timer0_Init(); //定时器0初始化
Data_Init(); //数据初始化
EA = 1; //打开定时器
L1602_init(); //液晶屏初始化
L1602_string(1,1," Welcome to T&H ");
L1602_string(2,1," Control System!"); //开机显示界面
//延时
for (i=0;i<1000;i++) //延时
for (j=0;j<100;j++)
{;}
//清屏
L1602_string(1,1," ");
L1602_string(2,1," ");
L1602_string(1,1,"Tem: C Hum: %");
L1602_string(2,1,"Good environment"); //显示待机界面
while(1) //进入while循环
{
if (FlagStartRH == 1) //温湿度转换标志检查
{
TR0 = 0; //关闭定时器
testnum = RH(); //读取温湿度
FlagStartRH = 0; //转换标志清零
TR0 = 1; //打开定时器
humidity = U8RH_data_H; //读出湿度,只取整数部分
temperature = U8T_data_H; //读出温度
if(Mode==0) //温湿度控制
{
if (humidity > 90)
{
humid=1;
dry=0;
}
else if(humidity<25)
{
dry=1;
humid=0;
}
if (temperature < 25)
{
Led_fengshan1 = 1;
Led_fengshan2 = 1;
Led_fengshan3 = 1;
Led_penwu = 1;
hot=0;
cold=0;
}
else if(25 < temperature < 30)
{
Led_fengshan1 = 0;
Led_fengshan2 = 1;
Led_fengshan3 = 1;
Led_penwu = 1;
hot=1;
cold=0;
}
else if(30 < temperature < 32)
{
Led_fengshan1 = 0;
Led_fengshan2 = 1;
Led_fengshan3 = 1;
Led_penwu = 0;
hot=1;
cold=0;
}
else if(32 < temperature < 34)
{
Led_fengshan1 = 0;
Led_fengshan2 = 0;
Led_fengshan3 = 1;
Led_penwu = 0;
hot=1;
cold=0;
}
else if(temperature > 34)
{
Led_fengshan1=0;
Led_fengshan2=0;
Led_fengshan3=0;
Led_penwu=0;
hot=1;
cold=0;
}
else
{
humid=0;
dry=0;
}
}
}
display();
}
}