这是给深圳的一个客户做的一个项目,虽说是工业项目吧,但难度也是比毕业设计高一点吧。
原理图:
dht11.h
#ifndef __dht11_H
#define __dht11_H
#include
typedef unsigned char U8; /* 无符号8位整型变量 */
typedef signed char S8; /* 有符号8位整型变量 */
typedef unsigned int U16; /* 无符号16位整型变量 */
typedef signed int S16; /* 有符号16位整型变量 */
typedef unsigned long U32; /* 无符号32位整型变量 */
typedef signed long S32; /* 有符号32位整型变量 */
typedef float F32; /* 单精度浮点数(32位长度) */
typedef double F64; /* 双精度浮点数(64位长度) */
extern U8 U8FLAG,k;
extern U8 U8count,U8temp;
extern U8 U8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8checkdata;
extern U8 U8T_data_H_temp,U8T_data_L_temp,U8RH_data_H_temp,U8RH_data_L_temp,U8checkdata_temp;
extern U8 U8comdata;
sbit P1_0 = P1^0 ;
void Delay(U16 j);
void Delay_10us(void);
void COM(void);
void RH(void);
#endif
dht11.c
#include "dht11.h"
U8 U8FLAG,k;
U8 U8count,U8temp;
U8 U8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8checkdata;
U8 U8T_data_H_temp,U8T_data_L_temp,U8RH_data_H_temp,U8RH_data_L_temp,U8checkdata_temp;
U8 U8comdata;
void Delay(U16 j)
{
U8 i;
for(;j>0;j--)
{
for(i=0;i<27;i++);
}
}
void Delay_10us(void)
{
U8 i;
i--;
i--;
i--;
i--;
i--;
i--;
}
void COM(void)
{
U8 i;
for(i=0;i<8;i++)
{
U8FLAG=2;
while((!P1_0)&&U8FLAG++);
Delay_10us();
Delay_10us();
// Delay_10us();
U8temp=0;
if(P1_0)U8temp=1;
U8FLAG=2;
while((P1_0)&&U8FLAG++);
//超时则跳出for循环
if(U8FLAG==1)break;
//判断数据位是0还是1
// 如果高电平高过预定0高电平值则数据位为 1
U8comdata<<=1;
U8comdata|=U8temp;
}
}
//--------------------------------
//-----湿度读取子程序 ------------
//--------------------------------
//----以下变量均为全局变量--------
//----温度高8位== U8T_data_H------
//----温度低8位== U8T_data_L------
//----湿度高8位== U8RH_data_H-----
//----湿度低8位== U8RH_data_L-----
//----校验 8位 == U8checkdata-----
//----调用相关子程序如下----------
//---- Delay();, Delay_10us();,COM();
//--------------------------------
void RH(void)
{
//主机拉低18ms
P1_0=0;
Delay(180);
P1_0=1;
//总线由上拉电阻拉高 主机延时20us
Delay_10us();
Delay_10us();
Delay_10us();
Delay_10us();
//主机设为输入 判断从机响应信号
P1_0=1;
//判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行
if(!P1_0) //T !
{
U8FLAG=2;
//判断从机是否发出 80us 的低电平响应信号是否结束
while((!P1_0)&&U8FLAG++);
U8FLAG=2;
//判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
while((P1_0)&&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;
P1_0=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;
}
}
}
ds1302.h
#ifndef __DS1302_H
#define __DS1302_H
#include
#define uchar unsigned char
#define uint unsigned int
void Delay_1ms(uint i);
void W_byte(uchar dat);
uchar R_byte(void);
void Rest_ds1302();
void Clear_wp();
void Set_wp();
uchar Dectobcd(uchar dec);
void W_ds1302(uchar add,uchar dat);
uchar R_ds1302(uchar add);
#endif
ds1302.c
#include "ds1302.h"
/**********DS1302定义**********/
sbit D_sclk=P1^1;
sbit D_io =P1^2;
sbit D_rest=P1^3;
/********************************************************************
* 名称 : Delay_1ms()
* 功能 : 延时子程序,延时时间为 1ms * x
* 输入 : x (延时一毫秒的个数)
* 输出 : 无
***********************************************************************/
void Delay_1ms(uint i)//1ms延时
{
uchar x,j;
for(j=0;j for(x=0;x<=148;x++);
}
/********************写入一个字节数据*************************/
void W_byte(uchar dat)
{
uchar i;
D_sclk=0;
for(i=0;i<8;i++)
{
D_io=(bit)(dat&0x01);
D_sclk=1;
dat>>=1;
D_sclk=0;
}
}
/*******************读取一个字节数据*********************/
uchar R_byte()
{
uchar i,dat=0;
for(i=0;i<8;i++)
{
dat>>=1;
if(D_io)
dat|=0x80;
D_sclk=1;
D_sclk=0;
}
return dat;
}
/***************复位DS1302****************/
void Rest_ds1302()
{
D_rest=0;
D_sclk=0;
D_rest=1;
}
/***************清除DS1302保护****************/
void Clear_wp()
{
Rest_ds1302();
D_rest=1;
W_byte(0x8e);
W_byte(0x00);/***写入0清除保护***/
D_io=0;
D_rest=0;
}
/***************写入DS1302保护****************/
void Set_wp()
{
Rest_ds1302();
D_rest=1;
W_byte(0x8e);
W_byte(0x80);/***写入0x80写入保护***/
D_io=0;
D_rest=0;
}
/***********************DEC码转换为BCD码****************/
uchar Dectobcd(uchar dec)
{
uchar bcd;
bcd = 0;
while(dec >= 10)
{
dec -= 10;
bcd++;
}
bcd <<= 4;
bcd |= dec;
return bcd;
}
/********************向DS1302写入数据****************************/
void W_ds1302(uchar add,uchar dat)
{
Rest_ds1302();
D_rest=1;
W_byte(add);
W_byte(dat);
D_io=0;
D_rest=0;
}
/********************从DS1302读取数据*************************/
uchar R_ds1302(uchar add)
{
uchar dat=0;
Rest_ds1302();
D_rest=1;
W_byte(add);
dat=R_byte();
D_io=0;
D_rest=0;
return dat;
}
1602.h
#ifndef __lcd1602_H
#define __lcd1602_H
#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit RS= P2^7;
sbit RW= P2^6;
sbit EN= P2^5;
sbit BUSY=P0^7;
void _delay_ms(uint ms_number);
void _delay_us(uint us_number);
void W_dat(uchar dat);
void W_cmd(uchar cmd);
void Write_dat(uchar cmd,uchar dat);
void Init_LCD1602(void);
void Display_set(uchar add,uchar sec,uchar min,uchar hour,uchar day,uchar month,uchar week,uchar year);
void Display_num(uchar add,uchar num);
void Display_s(uchar add,uchar *dat);
#endif
1602.c
#include "lcd1602.h"
/*--------------------ms延时函数-----------------------*/
void _delay_ms(uint ms_number) // ms延时函数 (AT89C51 @ 11.0592MHz)
{
unsigned int i;
unsigned char j;
for(i=0;i
for(j=0;j<200;j++);
for(j=0;j<102;j++);
}
}
void _delay_us(uint us_number)//延时时间为 1us * x 晶振是11.0592M
{
unsigned int i;
for(i = 0; i < us_number ; i++)
_nop_();
}
/**********************等待函数*********************/
void Wait (void)
{
RS=1;
do
{
RS=0;
RW=1;
EN=0;
_nop_();
EN=1;
} while(BUSY==1);
EN=0;
}
/**************************写数据*************************/
void W_dat(uchar dat)
{
Wait();
_delay_ms(5);
RS=1;
RW=0;
EN=1;
P0= dat;
_nop_();
EN=0;
}
/**************************写命令*************************/
void W_cmd(uchar cmd)
{
Wait();
_delay_ms(5);
RS=0;
RW=0;
EN=1;
P0=cmd;
_nop_();
EN=0;
}
/***********************往固定地址写数据函数*********************/
void Write_dat(uchar cmd,uchar dat)
{
W_cmd(cmd);
W_dat(dat);
}
/**********************LCD1602初始化***************************/
void Init_LCD1602(void)
{
_delay_ms(15);
W_cmd(0x38);//16*2显示,5*7点阵,8位数据接口
_delay_ms(5);
W_cmd(0x38);//16*2显示,5*7点阵,8位数据接口
_delay_ms(5);
W_cmd(0x38);//16*2显示,5*7点阵,8位数据接口
W_cmd(0x08); //关闭显示
W_cmd(0x01);//清屏
W_cmd(0x0C);//显示器开,光标关,光标不允许闪烁
W_cmd(0x06);//文字不动,光标自动右移
}
/**************************显示数字**************************/
void Display_num(uchar add,uchar num)
{
Write_dat(add,num/10+'0');
Write_dat(add+1,num%10+'0');
}
/**************************显示数字**************************/
void Display_set(uchar add,uchar sec,uchar min,uchar hour,uchar day,uchar month,uchar week,uchar year)
{
Write_dat(add,sec/10+'0');
Write_dat(add+1,sec%10+'0');
Write_dat(add+2,min/10+'0');
Write_dat(add+3,min%10+'0');
Write_dat(add+4,hour/10+'0');
Write_dat(add+5,hour%10+'0');
Write_dat(add+7,day/10+'0');
Write_dat(add+8,day%10+'0');
Write_dat(add+9,month/10+'0');
Write_dat(add+10,month%10+'0');
Write_dat(add+11,week/10+'0');
Write_dat(add+12,week%10+'0');
Write_dat(add+14,year/10+'0');
Write_dat(add+15,year%10+'0');
}
/**************************显示字符串**************************/
void Display_s(uchar add,uchar *dat)
{
uchar j=add;
while(*dat!='\0')
{
Write_dat(j,*dat);
j++;
dat++;
}
}
main.c
#include "lcd1602.h"
#include "ds1302.h"
#include "dht11.h"
/**********按键定义**********/
sbit Key_en =P2^0;
sbit Key_up =P2^1; //还是关闭报警开关
sbit Key_down =P2^2;
sbit Key_switch=P2^3;
/**********蜂鸣器定义**********/
sbit Beep=P3^5;
/**********指示灯定义**********/
sbit Led=P3^4;
/**************秒分时,日月周,年***********/
char time[7]={16,23,9,6,8,7,13};
uchar sign=0, flag=0;
//uchar a=0;
/******************函数声明********************/
void Set_time(uchar *timedate);
void Read_time(uchar *timedate);
void Key_scan();
void Beep_play();
/****************设定时间******************/
void Set_time(uchar *timedate)
{ uchar i,temp=0;
for(i=0;i<7;i++)
{
temp=timedate[i]/10;
timedate[i]=timedate[i]%10;
timedate[i]=timedate[i]+temp*16;
}
Clear_wp();
temp=0X80; // 0x80写命令
for(i=0;i<7;i++)
{
W_ds1302(temp,timedate[i]);
temp=temp+2;
}
Set_wp();
}
/*******************读取时间********************/
void Read_time(uchar *timedate)
{
uchar i,temp=0;
temp=0X81; // 0x81读命令
for(i=0;i<7;i++)
{
timedate[i]=R_ds1302(temp);
temp=temp+2;
}
time[0]=time[0]&0x7f;
for(i=0;i<7;i++)
{
temp=timedate[i]/16;
timedate[i]=timedate[i]%16;
timedate[i]=timedate[i]+temp*10;
}
}
/**********************使能关闭时钟************************/
void Key_scan()
{
if(Key_en==0)
{
Delay_1ms(5);
if(Key_en==0)
{
while(!Key_en);
sign=0x80|Dectobcd(time[0]);
Clear_wp();
W_ds1302(0x80,sign);/***时钟停止***/
Set_wp();
flag++;
W_cmd(0x0f);/****光标打开****/ //
}
}
/*************选择函数********************/
if(!Key_switch)
{
Delay_1ms(5);
if(!Key_switch)
while(!Key_switch);
flag++;
}
/**********调节秒钟******************/
if(flag==3)
{
W_cmd(0xC0+0x01); /***标光标***/
if(Key_up==0)
{
Delay_1ms(5);
if(Key_up==0)
{
while(!Key_up);
time[0]++;
if(time[0]==60)
time[0]=0;
Clear_wp();
W_ds1302(0x80,Dectobcd(0x80|time[0]));
Set_wp();
}
}
if(Key_down==0)
{
Delay_1ms(5);
if(Key_down==0)
{
while(!Key_down);
time[0]--;
if(time[0]==-1) time[0]=59;
Clear_wp();
W_ds1302(0x80,Dectobcd(0x80|time[0]));
Set_wp();
}
}
}
/**********调节分钟******************/
if(flag==2)
{
W_cmd(0xC0+0x03); /***标光标***/
if(Key_up==0)
{
Delay_1ms(5);
if(Key_up==0)
{
while(!Key_up);
time[1]++;
if(time[1]==60)
time[1]=0;
Clear_wp();
W_ds1302(0x82,Dectobcd(time[1]));
Set_wp();
}
}
if(Key_down==0)
{
Delay_1ms(5);
if(Key_down==0)
{
while(!Key_down);
time[1]--;
if(time[1]==-1) time[1]=59;
Clear_wp();
W_ds1302(0x82,Dectobcd(time[1]));
Set_wp();
}
}
}
/***********调节小时***********/
if(flag==1)
{
W_cmd(0XC0+0x05);/***标光标***/
if(Key_up==0)
{
Delay_1ms(5);
if(Key_up==0)
{
while(!Key_up);
time[2]++;
if(time[2]==24) time[2]=1;
Clear_wp();
W_ds1302(0x84,Dectobcd(time[2]));
Set_wp();
}
}
if(Key_down==0)
{
Delay_1ms(5);
if(Key_down==0)
{
while(!Key_down);
time[2]--;
if(time[2]==-1) time[2]=23;
Clear_wp();
W_ds1302(0x84,Dectobcd(time[2]));
Set_wp();
}
}
}
/***********调节天数***********/
if(flag==4)
{
W_cmd(0XC0+0X08);/***标光标***/
if(Key_up==0)
{
Delay_1ms(5);
if(Key_up==0)
{
while(!Key_up);
time[3]++;
if(time[3]==31) time[3]=1;
Clear_wp();
W_ds1302(0x86,Dectobcd(time[3]));
Set_wp();
}
}
if(Key_down==0)
{
Delay_1ms(5);
if(Key_down==0)
{
while(!Key_down);
time[3]--;
if(time[3]==-1) time[3]=30;
Clear_wp();
W_ds1302(0x86,Dectobcd(time[3]));
Set_wp();
}
}
}
/***********调节月数***********/
if(flag==5)
{
W_cmd(0XC0+0X10);/***标光标***/
if(Key_up==0)
{
Delay_1ms(5);
if(Key_up==0)
{
while(!Key_up);
time[4]++;
if(time[4]==12) time[4]=1;
Clear_wp();
W_ds1302(0x88,Dectobcd(time[4]));
Set_wp();
}
}
if(Key_down==0)
{
Delay_1ms(5);
if(Key_down==0)
{
while(!Key_down);
time[4]--;
if(time[4]==-1) time[4]=11;
Clear_wp();
W_ds1302(0x88,Dectobcd(time[4]));
Set_wp();
}
}
}
/***********调节周日数***********/
if(flag==6)
{
W_cmd(0XC0+0X12);/***标光标***/
if(Key_up==0)
{
Delay_1ms(5);
if(Key_up==0)
{
while(!Key_up);
time[5]++;
if(time[5]==7) time[5]=1;
Clear_wp();
W_ds1302(0x8A,Dectobcd(time[5]));
Set_wp();
}
}
if(Key_down==0)
{
Delay_1ms(5);
if(Key_down==0)
{
while(!Key_down);
time[5]--;
if(time[5]==-1) time[5]=6;
Clear_wp();
W_ds1302(0x8A,Dectobcd(time[5]));
Set_wp();
}
}
}
/***********调节年********/
if(flag==7)
{
W_cmd(0XC0+0X15);/***标光标***/
if(Key_up==0)
{
Delay_1ms(5);
if(Key_up==0)
{
while(!Key_up);
time[6]++;
Clear_wp();
W_ds1302(0x8C,Dectobcd(time[6]));
Set_wp();
}
}
if(Key_down==0)
{
Delay_1ms(5);
if(Key_down==0)
{
while(!Key_down);
time[6]--;
Clear_wp();
W_ds1302(0x8C,Dectobcd(time[6]));
Set_wp();
}
}
}
/****************使能打开时钟****************/
if(flag>=8)
{
Clear_wp();
W_ds1302(0x80,0);/***时钟开始***/
Set_wp();
flag=0;
W_cmd(0X0C);/****光标关闭****/
Delay_1ms(10);
Init_LCD1602();
Delay_1ms(10);
}
}
/****************蜂鸣器、LED报警*********************/
void Beep_play()
{
//if(a==0)
if((U8RH_data_H >= 70) | (U8T_data_H >= 40))
{
Beep=0;
Led=0;
}
//if((U8RH_data_H < 70) & (U8T_data_H < 40))
//a=0;
if(Key_up==0)
{
Delay_1ms(5);
if(Key_up==0)
{
Beep=1;
Led=1;
// a=1;
while(!Key_up);
}
}
_delay_ms(10);
}
void main()
{
Init_LCD1602();
Set_time(time);
while(1)
{
Beep_play();
RH();
Read_time(time);
Key_scan();
Write_dat(0x80,'R');
Write_dat(0x81,':');
Display_num(0x82,U8RH_data_H);
Write_dat(0x84,'%');
Key_scan();
Write_dat(0x86,'T');
Write_dat(0x87,':');
Key_scan();
Display_num(0x88,U8T_data_H);
Write_dat(0x8A,0xdf);
Write_dat(0x8B,0x43);
Display_set(0xC0,time[2],time[1],time[0],time[3],time[4],time[5],time[6]);
Beep_play();
}
}
实物图: