本人尝试将DHT11温湿度程序和ds1302时钟程序合并,实现两种功能 (程序分别运行是可行的,如后面图片)
合并后就出现图片的问题,什么都不显示。
请大神不吝赐教,谢谢。
这是我的代码:
//DHT11.C文件
#include<reg52.h>
#include<INTRINS.H>
#define uint unsigned int
#define uchar unsigned char
/* 时钟 */
sbit key0 = P3^4;//功能键
sbit key1 = P3^6;//增大键
sbit key2 = P3^7;//减小键
sbit RST = P1^7;
sbit SCLK = P1^5;
sbit SDA = P1^6;
sbit LCD_RS = P2^5;
sbit RW = P2^6;
sbit LCD_E = P2^7;
#define DS1302_SECOND_WRITE 0x80
#define DS1302_MINUTE_WRITE 0x82
#define DS1302_HOUR_WRITE 0x84
#define DS1302_DAY_WRITE 0x86
#define DS1302_MON_WRITE 0x88
#define DS1302_YEAR_WRITE 0x8c
#define DS1302_WEEK_WRITE 0x8a
#define DS1302_CURRENT_WRITE 0x90
#define DS1302_SECOND_READ 0x81
#define DS1302_MINUTE_READ 0x83
#define DS1302_HOUR_READ 0x85
#define DS1302_DAY_READ 0x87
#define DS1302_MON_READ 0x89
#define DS1302_YEAR_READ 0x8d
#define DS1302_WEEK_READ 0x8B
#define WRITE_PROTECT 0x8e
uchar sec,min,hour,day,mon,year,week,num,flag;
unsigned char table[]="20 - - ";
unsigned char table1[]=" : : ";
/*****************************/
void Delay_us(unsigned char n);
void write_cmd(uchar com) //写指令
{
LCD_RS=0;
RW=0;
P0=com;
Delay_us(5);
LCD_E=1;
Delay_us(5);
LCD_E=0;
}
/********************/
void write_data(uchar dat) //写数据
{
LCD_RS=1;
RW=0;
P0=dat;
Delay_us(5);
LCD_E=1;
Delay_us(5);
LCD_E=0;
}
/****************/
void write_sf(uchar add,uchar date) //时分秒函数,前一个是定义位置,后一个则是分离数据
{
uchar ge,shi;
shi=date/10;
ge=date%10;
write_cmd(0x80+add); //设置显示的位置
// Delay_us(10);
write_data(0x30+shi); //给十位送数据
// Delay_us(10);
write_data(0x30+ge); //给个位送数据
}
/**********************************/
void lcd_write_week(uchar week)//写液晶星期显示函数
{
write_cmd(0x80+11);//设置显示位置
switch(week)
{
case 1: write_data('M');Delay_us(5);
write_data('O');Delay_us(5);
write_data('N');break;
case 2: write_data('T');Delay_us(5);
write_data('U');Delay_us(5);
write_data('E');break;
case 3: write_data('W');Delay_us(5);
write_data('E');Delay_us(5);
write_data('D');break;
case 4: write_data('T');Delay_us(5);
write_data('H');Delay_us(5);
write_data('U');break;
case 5: write_data('F');Delay_us(5);
write_data('R');Delay_us(5);
write_data('I');break;
case 6: write_data('S');Delay_us(5);
write_data('A');Delay_us(5);
write_data('T');break;
case 7: write_data('S');Delay_us(5);
write_data('U');Delay_us(5);
write_data('N');break;
}
}
/*************************/
void init() //1602初始化
{
uchar i;
LCD_E=0;
write_cmd(0x38); //显示模式设置
write_cmd(0x0c); //开显示,光标不闪烁
write_cmd(0x06);
// write_cmd(0x01);
write_cmd(0x80);
for(i=0;i<14;i++)
{
write_data(table
);
Delay_us(10);
}
write_cmd(0xc0);
for(i=0;i<12;i++)
{
write_data(table1);
Delay_us(10); //1602位置的初始化
}
// while(1);
} //以上便是液晶1602的初始化
/***********************************/
uchar DS1302ReadByte() //读一个字节
{
uchar i,dat;
Delay_us(2);
for(i=0;i<8;i++)
{
dat>>=1;//要返回的数据左移一位
if(SDA==1)//当数据线为高时,证明该位数据为1
dat|=0x80;//要传输数据的当前值置为1,若不是,则为0
SCLK=1;//拉高时钟线
Delay_us(2);
SCLK=0;//制造下降沿
Delay_us(2);
}
return dat;//返回读取出的数据
}
/************************************************/
void DS1302WriteByte(uchar dat) //写一个字节
{
uchar i;
SCLK=0;//初始时钟线置为0
Delay_us(2);
for(i=0;i<8;i++)//开始传输8个字节的数据
{
SDA=dat&0x01;//取最低位,注意DS1302的数据和地址都是从最低位开始传输的
Delay_us(2);
SCLK=1;//时钟线拉高,制造上升沿,SDA的数据被传输
Delay_us(2);
SCLK=0;//时钟线拉低,为下一个上升沿做准备
dat>>=1;//数据右移一位,准备传输下一位数据
}
}
/********************************/
uchar DS1302Read(uchar cmd) //读命令
{
uchar dat;
RST=0;//初始CE线置为0
SCLK=0;//初始时钟线置为0
RST=1;//初始CE置为1,传输开始
DS1302WriteByte(cmd);//传输命令字,要读取的时间/日历地址
dat=DS1302ReadByte();//读取要得到的时间/日期
Delay_us(4);
SCLK=1;//时钟线拉高
RST=0;//读取结束,CE置为0,结束数据的传输
dat = dat/16*10+dat%16; //分离十位和个位,将十六进制数转化为十进制数
return dat;//返回得到的时间/日期
}
/*********** */
void DS1302Write(uchar cmd, uchar dat) //往1302中写数据
{
RST=0; //初始CE线置为0
SCLK=0; //初始时钟线置为0
RST=1; //初始CE置为1,传输开始
DS1302WriteByte(cmd); //传输命令字,要写入的时间/日历地址
DS1302WriteByte(dat); //写入要修改的时间/日期
SCLK=1; //时钟线拉高
RST=0; //读取结束,CE置为0,结束数据的传输
}
/***********************************/
void Init_DS1302() //1302初始化
{
DS1302Write(0x8e,0x00);//写保护关
DS1302Write(0x8e,0x80);
}
/***************************/
void display() //主要是显示程序,从DS1302中读取数值
{
day=DS1302Read(DS1302_DAY_READ);
mon=DS1302Read(DS1302_MON_READ);
year=DS1302Read(DS1302_YEAR_READ);
week=DS1302Read(DS1302_WEEK_READ);
sec=DS1302Read(DS1302_SECOND_READ);
min=DS1302Read(DS1302_MINUTE_READ);
hour=DS1302Read(DS1302_HOUR_READ);
write_sf(8,day);
write_sf(5,mon);
write_sf(2,year);
lcd_write_week(week);
write_sf(0x40+4,hour);
write_sf(0x40+7,min);
write_sf(0x40+10,sec);
}
/***********************************/
void keyscan() //键盘扫描
{
if(key0==0)//确认功能键按下
{
Delay_us(20);
if(key0==0)//功能键确实按下
{
while(!key0);//释放
num++;//按下次数记录
switch(num)
{
case 1: flag=1;//修改时间,液晶禁止从DS1302读数据
write_cmd(0x0f);//光标开始闪烁
write_cmd(0x80+2);//第一次按下,光标定位到年位置
break;
case 2: write_cmd(0x80+5);//第二次按下,光标定位到月位置
break;
case 3: write_cmd(0x80+8);//第三次按下,光标定位到日位置
break;
case 4: write_cmd(0x80+11);//第四次按下,光标定位到星期位置
break;
case 5: write_cmd(0x80+0x40+4);//第五次按下,光标定位到时位置
break;
case 6: write_cmd(0x80+0x40+7);//第六次按下,光标定位到分位置
break;
case 7: write_cmd(0x80+0x40+10);//第七次按下,光标定位到秒位置
break;
case 8: num=0;//第八次按下,记录清零
write_cmd(0x0c);//不显示光标
DS1302Write(WRITE_PROTECT,0x00);//禁止写保护
DS1302Write(0x80,(sec/10*16)+sec%10);//将调节后的秒写入DS1302
DS1302Write(0x82,(min/10*16)+min%10);//将调节后的分写入DS1302
DS1302Write(0x84,(hour/10*16)+hour%10);//将调节后的时写入DS1302
DS1302Write(0x8a,(week/10*16)+week%10);//将调节后的星期写入DS1302
DS1302Write(0x86,(day/10*16)+day%10);//将调节后的日写入DS1302
DS1302Write(0x88,(mon/10*16)+mon%10);//将调节后的月写入DS1302
DS1302Write(0x8c,(year/10*16)+year%10);//将调节后的年写入DS1302
DS1302Write(WRITE_PROTECT,0x80);//开写保护
flag=0;//时间修改完毕,允许液晶从DS1302读数据
break;
}
}
}
if(num!=0)
{
if(key1==0)//确认增大键按下
{
Delay_us(20);
if(key1==0)//增大键确实按下
{
while(!key1);
switch(num)
{
case 1: year++;//调节年
if(year==100)year=0;
write_sf(2,year);//将调节后的年送入液晶显示
write_cmd(0x80+2);//光标回到指定处
break;
case 2: mon++;//调节月
if(mon==13)mon=1;
write_sf(5,mon);//将调节后的月送入液晶显示
write_cmd(0x80+5);//光标回到指定处
break;
case 3: day++;//调节日
if(day==32)day=1;
write_sf(8,day);//将调节后的日送入液晶显示
write_cmd(0x80+8);//光标回到指定处
break;
case 4: week++;
if(week==8)week=1;
lcd_write_week(week);//将调节后的星期送入液晶显示
write_cmd(0x80+11);//光标回到指定处
break;
case 5: hour++;
if(hour==24)hour=0;
write_sf(0x40+4,hour);//将调节后的小时送入液晶显示
write_cmd(0x80+0x40+4);//光标回到指定处
break;
case 6: min++;
if(min==60)min=0;
write_sf(0x40+7,min);//将调节后的分送入液晶显示
write_cmd(0x80+0x40+7);//光标回到指定处
break;
case 7: sec++;
if(sec==60)sec=0;
write_sf(0x40+10,sec);//将调节后的秒送入液晶显示
write_cmd(0x80+0x40+10);//光标回到指定处
break;
default: break;
}
}
}
if(key2==0)//确认减小键按下
{
Delay_us(10);
if(key2==0)//减小键确实按下
{
while(!key2);
switch(num)
{
case 1: year--;//调节年
if(year==-1)year=99;
write_sf(2,year);
write_cmd(0x80+2);
break;
case 2: mon--;//调节月
if(mon==0)mon=12;
write_sf(5,mon);
write_cmd(0x80+5);
break;
case 3: day--;//调节日
if(day==0)day=31;
write_sf(8,day);
write_cmd(0x80+8);
break;
case 4: week--;//调节星期
if(week==0)week=7;
lcd_write_week(week);
write_cmd(0x80+11);
break;
case 5: hour--;//调节时
if(hour==-1)hour=23;
write_sf(0x40+4,hour);
write_cmd(0x80+0x40+4);
break;
case 6: min--;//调节分
if(min==-1)min=59;
write_sf(0x40+7,min);
write_cmd(0x80+0x40+7);
break;
case 7: sec--;//调节秒
if(sec==-1)sec=59;
write_sf(0x40+10,sec);
write_cmd(0x80+0x40+10);
break;
default:break;
}
}
}
}
}
//#include<timee_Delay.h>
//The main only needs to call getDHT11()
//then the temperature and huminity was geted in F16T,F16RH as float
sbit bit11=P2^0;
unsigned char U8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8checkdata;
float F16T,F16RH;
//read 8 bits onice
void Delay_us(unsigned char n);
char COM(void)
{
char i,U8temp,U8comdata;
for(i=0;i<8;i++)
{
while(!bit11);//表示读取的高电位延时大于20多us,则读取的是1,否则读取的是0
Delay_us(35);
U8temp=0;
if(bit11)
U8temp=1;
while(bit11);
U8comdata<<=1;
U8comdata|=U8temp; //0
}//rof
return U8comdata;
}
//------------------------
//----温湿度读取子程序----
//------------------------
//----以下变量均为全局变量----
//----温度高8位==U8T_data_H----
//----温度低8位==U8T_data_L----
//----湿度高8位==U8RH_data_H----
//----湿度低8位==U8RH_data_L----
//----校验8位==U8checkdata----
//----调用相关子程序如下----
//----Delay();,Delay_10us();,COM();
//------------------------
void Delay_ms(unsigned int n);
void getDHT11(void)
{
//主机拉低18ms
GO1: bit11=0;
Delay_ms(20);
bit11=1;
//总线由上拉电阻拉高 主机延时20us
Delay_us(60);
//主机设为输入 判断从机响应信号
// bit11=1
//判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行
if(!bit11) //T!
{
while(!bit11); //wait DHT goto high
while(bit11);
//数据接受状态
U8RH_data_H=COM();
U8RH_data_L=COM();
U8T_data_H=COM();
U8T_data_L=COM();
U8checkdata=COM();
bit11=1;
//数据校验
if((U8T_data_H+U8T_data_L+U8RH_data_H+U8RH_data_L)!=U8checkdata)
//if check wrong,read again
goto GO1;
}//fi
F16T=U8T_data_H+(float)U8T_data_L/256; //change integer to float
F16RH=U8RH_data_H+(float)U8RH_data_L/256;
}
//----LCD1602----
#include<reg52.h>
#include<stdio.h>
#include<INTRINS.H>
//#include<Lcd_1602.h>
//#include<Time_Delay.h>
#define LCD_DATA P0 //LCD1602 data transfer define
#define uint unsigned int
#define uchar unsigned char
/****
只由主函数调用的有
Init_Lcd()
LCD_write_str(uchar X,uchar Y,uchar *s)
LCD_value(unsigned char x,unsigned char y,float f)
****/
//sbit LCD_RS=P2^5; //1602 control define
//sbit RW=P2^6;
//sbit LCD_E=P2^7;
/*****************************************
#define LCD_SCREEN_ON 0x0C //显示开
#define LCD_SCREEN_OFF 0x08 //显示关
#define LCD_CURSOR_ON 0X0A //显示光标
#define LCD_CURSOR_OFF 0x0c //无光标
#define LCD_C_FLASH_ON 0x0f //有光标,光标闪动
#define LCD_C_FLASH_OFF 0x0c //有光标,光标不闪动
//进入模式设置指令
#define LCD_AC_UP 0x06 //新数据后光标右移
#define LCD_AC_DOWN 0x04 //新数据后光标左移
#define LCD_S_MOVE_ON 0X05 //画面可平移
#define LCD_S_MOVE_OFF 0x04 //画面不可平移
//设定显示屏或光标移动方向指令
#define LCD_C_LEFT 0x10 //光标左移1格,且AC值减1
#define LCD_C_RIGHT 0x11 //光标右移1格,且AC值加1
#define LCD_CHAR_LEFT 0x18 //显示器上字符全部左移1格,但光标不动
#define LCD_CHAR_RIGHT 0x1C //显示器上字符全部右移1格,但光标不动
*******************************************/
//注 有主函数调用的函数都已作说明 其他函数一般不由主函数调用
/*********************************************
* 名 称:Init_Lcd() 主函数调用
* 功 能:Lcd 初始化
* 入口参数:无
* 出口参数:无
*范 例:在主函数中直接调用
**********************************************/
void LCD_write_char(uchar cd,uchar ab);
void Init_Lcd() //LCD初始化
{
LCD_write_char(0x38,0);
Delay_ms(1);
LCD_write_char(0x38,0);
Delay_ms(1);
LCD_write_char(0x38,0);
Delay_ms(1);
LCD_write_char(0x0c,0);
Delay_ms(1);
LCD_write_char(0x06,0);
Delay_ms(1);
LCD_write_char(0x0c,0);
Delay_ms(1);
}
/******************************************************
*名 称:LCD_write_str(uchar X,uchar Y,uchar *s)主函数调用
*功 能:在指定地址写一个字符串 eg:Y=0,1,2,3,4,5,6,7,8,9,10...15。 X=0,1。
*入口参数:X:横坐标 Y:纵坐标 *s:字符串首地址
*出口参数:无
*范 例:LCD_write_str(1,1,uchar *s)
*****************************************************/
void LCD_set_xy(uchar x,uchar y);
void LCD_write_str(unsigned char X,unsigned char Y,unsigned char *s)
{
LCD_write_char(0,' ');
LCD_set_xy(X,Y); //写地址
while(*s) //写显示字符
{
LCD_write_char(0,*s);
s++;
}
}
/******************************************************
*名 称:LCD_set_xy(uchar x,uchar y) the optic sign flash?
*功 能:指定一个地址
*入口参数:X:横坐标 Y:纵坐标
*出口参数:无
*范 例:LCD_set_xy(5,1)
*****************************************************/
void LCD_set_xy(uchar x,uchar y) //写地址函数
{
unsigned char address;
if(y==0)
address=0x80+x;
else
address=0xc0+x;
LCD_write_char(address,0);
}
/*******************************************************
*名 称:LCD_en_write(void)
*功 能:液晶使能
*入口参数:无
*出口参数:无
*范 例:直接调用
******************************************************/
void LCD_en_write(void) //液晶使能
{
//_nop_();
LCD_E=1; //EN=1
//_nop_();
LCD_E=0; //EN=0
}
//------------------------------------------------------
/************************************************
*名 称:LCD_write_char(uchar cd,uchar ab)
*功 能:写指令或数据 当写ab时 应使cd=0 当cd不为0 且ab的赋值无效
*入口参数:cd:指令内容 ab:数据内容 指令常量已在上面定义 但一般不用
*出口参数:无
*范 例:LCD_write_char(0,'f')
***********************************************/
void LCD_byte(unsigned char abc);
void LCD_write_char(uchar cd,uchar ab) //写数据
{
Delay_us(20);
if(cd==0)
{
LCD_RS=1; //RS=1,写显示内容
LCD_byte(ab);
}
else
{
LCD_RS=0; //RS=0,写命令
LCD_byte(cd);
}
}
/*************************************************
*名 称:LCD_byte(abc);
*功 能:写一个字符到 or called one byte to LCD 中
*入口参数:
*出口参数:无
*************************************************/
void LCD_byte(unsigned char abc)
{
RW=0;
LCD_E=0;
LCD_DATA=abc;
LCD_en_write();
}
//在液晶中显示浮点数函数
LCD_value(unsigned char x,unsigned char y,float f)
{
unsigned char str[15]; //不能定义为char *str,数组长度一定要大于浮点
//数的总位数
sprintf(str,"%.1f",f); //1表示小数位数 小数太多 自动四舍五入
LCD_write_str(x,y,str);
return 0;
}
//主函数文件
#include<reg52.h>
#include<intrins.h>
//#include<Lcd_1602.h>
//#include<Time_Delay.h>
//#include"DHT11.H"
extern float F16T,F16RH; //全局变量声明
/* */
/**** 主 函 数 ****/
/* */
void main()
{
if(P3^3)
{
Init_Lcd();
LCD_write_str(0,1,"Bless You!"); //液晶预显示测试
LCD_value(0,0,2015.520);
Delay_ms(2000);
Init_Lcd();
while(1)
{
getDHT11();
LCD_write_str(0,0,"Tem=");
LCD_value(5,0,F16T);
LCD_write_str(8,0,""C"); //字符 " 应用转义格式
LCD_write_str(0,1,"Hum=");
LCD_value(5,1,F16RH);
LCD_write_str(9,1,"%");
Delay_ms(500);
}
}
else
{
init();
Init_DS1302();
while(1)
{
keyscan();
if(flag==0)
display();
}
}
}
//延时函数文件
//以下为延时函数 this is fit to old C51 12MHz,12 devide frequency
void Delay_ms(unsigned int n) //n毫秒延时
{
unsigned char j;
while(n--)
{
for(j=0;j<125;j++);
}
}
void Delay_us(unsigned char n) //N us 延时函数
{
n=n/2;
while(--n);
}
-
时钟
-
温湿度
I2C怎么了,你按它的协议走就没有问题啊,有好多协议的文章你可以找找
一周热门 更多>