原创 使用LCD1602、DS1302时钟芯片、DS18B20温度传感器完成该日历

2009-6-7 18:39 5838 7 8 分类: MCU/ 嵌入式

/***********************************************************************************/
/************使用LCD1602、DS1302时钟芯片、DS18B20温度传感器完成该日历**************/
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit rs="P2"^0; // 数据/命令选择端
sbit rw="P2"^1; //读写选择端
sbit e="P2"^2; //使能信号
sbit rst="P2"^5; //时钟芯片复位端
sbit sck="P2"^6; // 时钟信号
sbit io="P2"^7; // 输入/输出端
sbit ds="P2"^3;  //温度传感器信号线
sbit led="P2"^4;  //小灯位定义
uint temp;    // 整型温度值
float f_temp;  //浮点型温度值 
void init();     // 初始化函数
void  delay(uchar z); //延时函数
void write_com(uchar com); //LCD写命令
void write_date(uchar date); //LCD写数据
uint get_temp();    //获得温度
void tempchange(void);   //转换温度
void dsreset(void);    //DS18B20复位
bit tempreadbit(void);   //读DS118B20一位
uchar tempreadbyte(void);   //读DS18B20一个字节
void tempwritebyte(uchar dat);
void deal();   //温度处理函数
void Write_Ds1302_Byte(uchar temp);//写入一个字节
void Write_Ds1302(uchar address,uchar dat);//写入
uchar Read_Ds1302 ( uchar address );   //读取时间 
void Read_RTC(void);  //读取 日历
void Set_RTC(void);  //设定 日历
void time_date();  //时间数据处理
void display(uchar *lp,uchar lc); //显示时间 
void Temp_Display();   //温度显示
uchar table[]="0123456789.C";
uchar table0[]="0123456789-";
uchar table1[]="MONTUEWEDTHUFRISATSUN";
uchar table2[]="0123456789:!";
uchar l_tmpdate[7]={21,59,23,28,10,2,8};
/*初始化时钟芯片,依次是秒分时日月星期年,用十六进制表示十进制,如0x1c表示
1*16+12即28,所以显示出来的就是28*/
uchar l_tmpdisplay[18];
code uchar write_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
//以上是写入时钟芯片的地址,顺序同上
code uchar read_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
//读出数据的地址


/******************************日历主函数************************************/
void main()
{
  init();    //初始化LCD
 Set_RTC();//初始化时钟芯片
 while(1)

 tempchange();//温度转换命令 
    time_date();//显示时间
 Temp_Display(); //显示温度
    deal();    //温度处理
 
 
  P1=0xf0;
   IT0=1;  // 选择外部中断0为电平触发方式(1为跳变沿触发方式)
   EX0=1; 
      EA="1";


  

}
void inter0() interrupt 0    //外部中断0
{
 P1=0xfe;
 if(P1!=0xfe)
 
 delay(10);
 if(P1==0xee)
  {  led=~led;
  write_com(0x1c);
  }
   if(P1==0xde)
  {  led=~led;
  write_com(0x18);
  }


 
}
/***************************以下为温度传感器相关程序************************/


void dsreset(void)  //DS18B20复位,初始化函数
{
 uint i;
 ds=0;
 i=103;
 while(i>0)i--;
 ds=1;
 i=4;
 while(i>0)i--; 
}
bit tempreadbit(void) //读一位数据函数
{
 uint i;
 bit dat;
 ds=0;i++;     //i++起延时的作用
 ds=1;i++;i++;
 dat=ds;
 i=8;while(i>0)i--;
 return(dat); 
}
uchar tempreadbyte(void) //读一个字节数据函数
{
 uchar i,j,dat;
 dat=0;
 for(i=1;i<=8;i++)
 {
  j=tempreadbit();
  dat=(j<<7)|(dat>>1);  //读出的数据最低位在最前面
 }
 return(dat);
}
void tempwritebyte(uchar dat)
{         //写一个字节数据函数
 uint i;
 char j;
 bit testb;
 for(j=1;j<=8;j++)
 {
  testb=dat&0x01;
  dat=dat>>1;
  if(testb)   //写1
  {
   ds=0;
   i++;i++;
   ds=1;
   i=8;while(i>0)i--;
  }
  else       //写0
  {
   ds=0;
   i=8;while(i>0)i--;
   ds=1;
   i++;i++;
  }
 } 
}
void tempchange(void)  //DS18B20开始获取温度并转换
{
 dsreset();
 delay(1);
 tempwritebyte(0xcc);   //写跳过读ROM指令
 tempwritebyte(0x44);  //写温度转换指令  
}
uint get_temp()    //读取寄存器中存储的温度数据
{
 uchar a,b;
 dsreset();
 delay(1);
 tempwritebyte(0xcc);
 tempwritebyte(0xbe);  //读RAM内部9字节的温度数据
 a=tempreadbyte();    //读低8位
 b=tempreadbyte();   //读高8位
 temp=b;
 temp<<=8;
 temp=temp|a;     //两个字节组合为一个字节
 f_temp=temp*0.0625;    // 温度在寄存器中为12位,分辨率为0.0625
 temp=f_temp*10+0.5;    //乘以10表示小数点后面只取1位,加0.5时四舍五入
 f_temp=f_temp+0.05;
 return temp; 
}


void Temp_Display()    //温度显示函数
{
 write_com(0x80+0x40+0x0b);  
 write_date(table[get_temp()/100]);
 write_com(0x80+0x40+0x0c);  
 write_date(table[get_temp()%100/10]);
 write_com(0x80+0x40+0x0d);  
 write_date(table[10]);
 write_com(0x80+0x40+0x0e);  
 write_date(table[get_temp()%10]);
 write_com(0x80+0x40+0x0f);  
 write_date(table[11]); 
}
void deal()   //温度处理函数
{
 uint i;
 i=get_temp();
 if(i>300||i<200) //当温度低于20度或大于30度时小灯闪烁
 {
  led=0;
  delay(100);
  led=1;
 // write_com(0x80+12);
 // write_date(table2[11]);
 }


// else led="1";
  
}



/***********************以上为温度传感器相关程序***********************/


/***********************以下为时钟芯片相关程序***********************/


void Write_Ds1302_Byte(uchar temp) //写入一字节数据
{
 uchar i;
 for (i=0;i<8;i++)      //循环8次 写入数据 ,上升沿写入
  {
     sck="0";
     io="temp"&0x01;      //每次传输低字节
     temp>>=1;    //右移一位
     sck="1";
   }
}
void Write_Ds1302(uchar address,uchar dat)//写入    
{
 
  rst=0;
 delay(1);
  sck=0;
 delay(1);
  rst=1; 
    delay(1);   //启动
  Write_Ds1302_Byte(address); //发送地址
  Write_Ds1302_Byte(dat);  //发送数据
  rst=0;    //恢复
}
uchar Read_Ds1302 (uchar address)   //读取时间
{
  uchar i,time=0x00;
  rst=0;
 delay(1);
  sck=0;
 delay(1);
  rst=1;
 delay(1);
  Write_Ds1302_Byte(address);
  for (i=0;i<8;i++)   //循环8次 读取数据
  {  
   if(io)
   time|=0x80;   //每次传输低字节
  sck=1;      //时钟下降沿读入数据?????????
  time>>=1;   //右移一位 
      sck=0;
 
  
 }
  rst=0;
 delay(1);  //以下为DS1302复位的稳定时间
  rst=0;
 sck=0;
 delay(1);
 sck=1;
 delay(1);
 io=0;
 delay(1);
 io=1;
 delay(1);
 return (time);  

void Read_RTC()  //读取 日历
{
 uchar i,*p;
 p=read_rtc_address;  //地址传递
 for(i=0;i<7;i++)  //分7次读取 年月日时分秒星期
 {
  l_tmpdate=Read_Ds1302(*p);
  p++;
 }
}
void Set_RTC(void)  //设定 日历
{
 uchar i,*p,tmp;
  for(i=0;i<7;i++)
 {
  tmp=l_tmpdate/10;
  l_tmpdate=l_tmpdate%10;
  l_tmpdate=l_tmpdate+tmp*16;
 }
  Write_Ds1302(0x8E,0X00);   //允许写入
 
  p=write_rtc_address; //传地址 
  for(i=0;i<7;i++)  //7次写入 年月日时分秒星期
  {
    Write_Ds1302(*p,l_tmpdate);
      p++; 
  }
  Write_Ds1302(0x8E,0x80); //禁止写入
}


void time_date()  //时间数据处理  
{   
         Read_RTC();
   l_tmpdisplay[0]=l_tmpdate[2]/16;//时    
   l_tmpdisplay[1]=l_tmpdate[2]&0x0f;
   l_tmpdisplay[2]=10;   //加入":"
   l_tmpdisplay[3]=l_tmpdate[1]/16;//分
   l_tmpdisplay[4]=l_tmpdate[1]&0x0f;
   l_tmpdisplay[5]=10;
   l_tmpdisplay[6]=l_tmpdate[0]/16;//秒
   l_tmpdisplay[7]=l_tmpdate[0]&0x0f; 
 
   l_tmpdisplay[8]=2;    //显示2008的2
   l_tmpdisplay[9]=0;   //显示2008的第一个0
   l_tmpdisplay[10]=l_tmpdate[6]/16; //年
   l_tmpdisplay[11]=l_tmpdate[6]&0x0f;
   l_tmpdisplay[12]=10;     //加入“-”
   l_tmpdisplay[13]=l_tmpdate[4]/16;//月
   l_tmpdisplay[14]=l_tmpdate[4]&0x0f;
   l_tmpdisplay[15]=10;
   l_tmpdisplay[16]=l_tmpdate[3]/16;//日
   l_tmpdisplay[17]=l_tmpdate[3]&0x0f;
  
  display(l_tmpdisplay,8);
}


void display(uchar *lp,uchar lc)   //显示时间
{
 unsigned char i;  //定义变量
 
 write_com(0x80);  //液晶第一行显示时间和星期
 for(i=0;i<lc;i++)
 { 
 write_date(table2[lp]);  
 delay(1);  
 }
 write_com(0x80+0x09);
 switch(l_tmpdate[5]) //用英文缩写显示星期
 {
  case 0: write_date(table1[0]);
    write_date(table1[1]);
    write_date(table1[2]);
    break;
  case 1: write_date(table1[3]);
    write_date(table1[4]);
    write_date(table1[5]);
    break;
  case 2: write_date(table1[6]);
    write_date(table1[7]);
    write_date(table1[8]);
    break;
  case 3: write_date(table1[9]);
    write_date(table1[10]);
    write_date(table1[11]);
    break;


  case 4: write_date(table1[12]);
    write_date(table1[13]);
    write_date(table1[14]);
    break;
  case 5: write_date(table1[15]);
    write_date(table1[16]);
    write_date(table1[17]);
    break;
  case 6: write_date(table1[18]);    
    write_date(table1[19]);
    write_date(table1[20]);
    break;
 }  
 write_com(0x80+0x40);  //第二行显示年
 for(i=8;i<lc+10;i++)
 { 
 write_date(table0[lp]);  
 delay(1);  
 }
}
/********************以上为时钟芯片相关程序***************************/


void init()     //LCD初始化函数
{
 e=0;
 write_com(0x38);//显示模式的设置
 delay(1);
 write_com(0x0c);//开显示,光标显示
 delay(1);
 write_com(0x06);//光标位置
 delay(1);
 write_com(0x01);   //清显示
 delay(1);
}
void write_com(uchar com)    //LCD写命令
{
 rs=0;
 rw=0;
 P0=com;
 delay(1);
 e=1;
 delay(1);
 e=0; 
}
void write_date(uchar date)    //LCD写数据
{
 rs=1;
 rw=0;
 P0=date;
 delay(1);
 e=1;
 delay(1);
 e=0; 
}
void  delay(uchar z) //延时函数
{
 uchar x,y;
 for(x=0;x<z;x++)
  for(y=0;y<110;y++);
}
/***************END***********END******************************/ 

PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

用户1545666 2009-6-28 17:08

不可以调整日历,但愿可以改进。谢谢。
相关推荐阅读
用户395791 2011-02-21 10:10
单片机实现贪吃蛇游戏
本文章原创于 www.yafeilinux.com  作者:雨?烟?, 转载请注明出处。最近忙完英语考试了,感觉轻松许多。手痒的很,想写点程序,在玩弄手机时看见自己的手机游戏里连个贪吃蛇都没有呢…为什...
用户395791 2011-02-13 16:20
Qt 的未来
2011年的春节刚过,当我们还不愿意从过年的懒散生活中清醒过来时,一则无法设想的新闻将我们惊醒!   一、事件突发: 1.北京时间2月11日下午消息,诺基亚与微软刚刚宣布,双方计划建立广泛的战略伙伴关...
用户395791 2010-07-17 13:37
Qt串口通信专题教程
本文章原创于www.yafeilinux.com 转载请注明出处。Qt串口通信专题教程前言去年我使用Qt编写串口通信程序时,将自己的学习过程写成了教程(Qt编写串口通信程序全程图文讲解),但是由于时间...
用户395791 2010-06-16 22:32
Led非典型应用——感测外部光线
本文章原创于 www.yafeilinux.com  作者:Jay , 转载请注明出处。基本上初学者学习任何一款单片机都会写同样的一个程序——Led流水灯。就像初学C、C++、Qt之类的语言时都要写“...
用户395791 2010-05-27 18:47
Qt Creator系列教程
Qt Creator系列教程        为了使更多的Qt初学者能尽快入门Qt,也为了Qt及Qt Creator的快速普及,我们花费大量精力写出了这一系列教程。虽然教程的知识可能很浅显,虽然教程的语...
用户395791 2010-03-26 17:51
二十七、Qt数据库(七)QSqlRelationalTableModel(原创)
声明:本文原创于yafeilinux的百度博客,http://hi.baidu.com/yafeilinux 转载请注明出处。讲完QSqlTableModel了,我们这次讲这个类的扩展类QSqlRel...
EE直播间
更多
我要评论
1
7
关闭 站长推荐上一条 /3 下一条