当前位置:首页 > 技术学院 > 热搜器件
[导读]DS1302实时时钟---液晶显示

/*名称:DS1302实时时钟---液晶显示
  说明:向DS1302中写入初始时间,再从DS1302中读取时钟数据,时间可以调节 ,并 在LCD上显示出来。
*/
#include <reg52.h>
#include <intrins.h>
#include <string.h>
#define uint unsigned int
#define uchar unsigned char
#define datport P0


sbit IO = P1^1;    //DS1302数据线
sbit SCLK = P1^0;    //DS1302时钟线
sbit RST = P1^2;    //DS1302复位线
sbit RS = P2^2;     //LCD寄存器选择
sbit RW = P2^3;     //LCD读写控制
sbit EN = P2^4;      //LCD启用


sbit f1 = P3^0;
sbit f2 = P3^1;
sbit f3 = P3^2;
sbit f4 = P3^3;
uchar temp1,temp2;
uchar key();
uchar hour_flag,min_flag,second_flag,flag_key=0;
uchar year_flag,month_flag,day_flag,day_up,day_down;
uchar week_flag;
uchar timecount = 0;
uchar month_table[] = {0,32,29,32,31,32,31,32,32,31,32,31,32};
bit flag;

//1、2、3、4、5、6、7分别对应周一至周日
uchar *WEEK[]=
{
  "***","MON","TUS","WEN","THU","FRI","SAT","SUN"
};
//LCD显示缓冲
uchar LCD_DSY_BUFFER1[]={"DATE 00-00-00    "};
uchar LCD_DSY_BUFFER2[]={"TIME 00:00:00    "};
//存放日期和时间
uchar DateTime[7];


//延时函数
void DelayMS(uint ms)
{
  uchar i;
 while(ms--)
 {
   for(i = 0;i < 120;i ++);
 }
}


//向DS1302写入一字节,根据时序图写函数
//上升沿锁存数据,先发送最低位
void Write_A_Byte_TO_DS1302(uchar x)
{
  uchar i;
 for(i = 0;i < 8;i ++)
 {
   IO = x & 0x01;SCLK = 1;SCLK = 0;x >>= 1;
 }
}


//从DS1302读取一字节,看时序图写函数
//下降沿锁存数据,先发送最低位
///DS1302中的数据是BCD码存放的,所以将寄存器中的数据转换成十六进制返回

uchar Get_A_Byte_FROM_DS1302()
{
  uchar i,b = 0x00; 
 for(i = 0;i < 8;i ++)
 {
   b |= _crol_((uchar)IO,i);//先将最低位存放在b的最低位
                           //再将下一位左移一位存放在b的第二位
         //同样的道理可以将要读取的数据存放在b中
  SCLK = 1;SCLK = 0;     //下降沿锁存数据
 }
 return b / 16 * 10 + b % 16;   //将BCD码转换成十六进制返回
}

 

//从指定地址读取一个数据
uchar Read_Data(uchar addr)
{
  uchar dat;
 RST = 0;SCLK = 0;RST = 1;
    Write_A_Byte_TO_DS1302(addr);  //写入地址
 dat = Get_A_Byte_FROM_DS1302();//读取数据
    SCLK = 1;RST = 0;
 return dat;
}


//向指定地址写入数据
void Write_DS1302(uchar addr,uchar dat)
{
 SCLK = 0;RST = 1;      //高电平使能,SCLK信号线在闲置时为0
    Write_A_Byte_TO_DS1302(addr);
 Write_A_Byte_TO_DS1302(dat);
    SCLK = 0;RST = 0;      //低电平关使能
}

//设置初始时间
void Set_InitTime()
{
 Write_DS1302(0x8e,0x00);   //关闭写保护
 Write_DS1302(0x80,0x58);   //设置秒
 Write_DS1302(0x82,0x59);   //设置分
 Write_DS1302(0x84,0x23);   //设置时
 Write_DS1302(0x86,0x31);   //设置日
 Write_DS1302(0x88,0x12); //设置月
 Write_DS1302(0x8a,0x07);   //设置星期
 Write_DS1302(0x8c,0x05);   //设置年
 Write_DS1302(0x8e,0x80);   //开启写保护
}

//获取当前时间
void GetTime()
{
  uchar i,addr = 0x81;
 for(i = 0;i<7;i++)
 {
   DateTime[i] = Read_Data(addr);addr += 2;
 }
}


/*
//液晶模块的忙碌状态
uchar Read_LCD_State()
{
  uchar state;
 RS = 0;RW = 1;EN = 1;DelayMS(1); //根据规定,RS为低电平
                           //RW为高电平时,可以读状态
         //EN使能后,才能进行读写
         //延时一会,给硬件反应时间
 state = datport;      //读P0口的值
 EN = 0;DelayMS(1);
 return state;      //返回状态值
}
*/
//LCD忙检测
void LCD_Busy_Wait()
{
// // while((Read_LCD_State()&0x80) == 0x80); //忙,则等待
                                       //当P0口最高位为1则说明忙
 DelayMS(5);
}

//向LCD写入一个字节数据
void Write_LCD_Data(uchar dat)
{
  LCD_Busy_Wait();
 RS = 1;RW = 0;EN = 0;datport = dat;EN = 1;DelayMS(1);EN = 0;
}


//向LCD写入一个字节命令
void Write_LCD_Command(uchar cmd)
{
  LCD_Busy_Wait();
 RS = 0;RW = 0;EN = 0;datport = cmd;EN = 1;DelayMS(1);EN = 0;
}

 

//初始化LCD
void Init_LCD()
{
  Write_LCD_Command(0x38);
 DelayMS(1);
 Write_LCD_Command(0x01);
 DelayMS(1);
 Write_LCD_Command(0x06);
 DelayMS(1);
 Write_LCD_Command(0x0c);
 DelayMS(1);
}


//设置显示位置
void Set_LCD_POS(uchar p)
{
  Write_LCD_Command(p|0x80);
}


//在指定位置显示字符串
void Display_LCD_String(uchar p,uchar *s)
{
  uchar i;
 Set_LCD_POS(p);
 for(i = 0;i < 16;i ++)
 {
  Write_LCD_Data(s[i]);
  DelayMS(1); 
 }
}


//日期与时间值转换成数字字符
void Format_DateTime(uchar d,uchar *a)
{
  a[0] = d / 10 + '0';
 a[1] = d % 10 + '0';
}

//将获取的时间转换成数字后存放在缓冲区
void Format_Changer()
{
 //Format_DateTime(DateTime[6],LCD_DSY_BUFFER1 + 5);//将年转换成数字字符

 if(1 == year_flag)
  if(flag == 1)
  {
    LCD_DSY_BUFFER1[5] = ' ';
    LCD_DSY_BUFFER1[6] = 0x20;
  }
  else
  {  
   Format_DateTime(DateTime[6],LCD_DSY_BUFFER1 + 5); //将时转换成数字字符   
  }
 else
 {
   Format_DateTime(DateTime[6],LCD_DSY_BUFFER1 + 5); //将时转换成数字字符 
 }

 //Format_DateTime(DateTime[4],LCD_DSY_BUFFER1 + 8);//将月转换成数字字符

 if(1 == month_flag)
  if(flag == 1)
  {
    LCD_DSY_BUFFER1[8] = 0x20;
    LCD_DSY_BUFFER1[9] = 0x20;
  }
  else
  {  
   Format_DateTime(DateTime[4],LCD_DSY_BUFFER1 + 8); //将时转换成数字字符   
  }
 else
 {
   Format_DateTime(DateTime[4],LCD_DSY_BUFFER1 + 8); //将时转换成数字字符 
 }
 //Format_DateTime(DateTime[3],LCD_DSY_BUFFER1 + 11); //将日转换成数字字符

 if(1 == day_flag)
  if(flag == 1)
  {
    LCD_DSY_BUFFER1[11] = 0x20;
    LCD_DSY_BUFFER1[12] = 0x20;
  }
  else
  {  
   Format_DateTime(DateTime[3],LCD_DSY_BUFFER1 + 11); //将时转换成数字字符   
  }
 else
 {
   Format_DateTime(DateTime[3],LCD_DSY_BUFFER1 + 11); //将时转换成数字字符 
 }

// strcpy(LCD_DSY_BUFFER1 + 13,WEEK[DateTime[5]]); //将星期转换成数字字符
 if(1 == week_flag)
  if(flag == 1)
  {
    LCD_DSY_BUFFER1[13] = 0x20;
    LCD_DSY_BUFFER1[14] = 0x20;
    LCD_DSY_BUFFER1[15] = 0x20;
  }
  else
  {  
   strcpy(LCD_DSY_BUFFER1 + 13,WEEK[DateTime[5]]); //将星期转换成数字字符  
  }
 else
 {
   strcpy(LCD_DSY_BUFFER1 + 13,WEEK[DateTime[5]]); //将星期转换成数字字符
 }


 if(1 == hour_flag)
  if(flag == 1)
  {
    LCD_DSY_BUFFER2[5] = ' ';
    LCD_DSY_BUFFER2[6] = 0x20;
  }
  else
  {  
   Format_DateTime(DateTime[2],LCD_DSY_BUFFER2 + 5); //将时转换成数字字符   
  }
 else
 {
   Format_DateTime(DateTime[2],LCD_DSY_BUFFER2 + 5); //将时转换成数字字符 
 }


 if(1 == min_flag)
  if(flag == 1)
  {
    LCD_DSY_BUFFER2[8] = 0x20;
    LCD_DSY_BUFFER2[9] = 0x20;
  }
  else
  {  
   Format_DateTime(DateTime[1],LCD_DSY_BUFFER2 + 8); //将时转换成数字字符   
  }
 else
 {
   Format_DateTime(DateTime[1],LCD_DSY_BUFFER2 + 8); //将时转换成数字字符 
 }


 if(1 == second_flag)
  if(flag == 1)
  {
    LCD_DSY_BUFFER2[11] = 0x20;
    LCD_DSY_BUFFER2[12] = 0x20;
  }
  else
  {  
   Format_DateTime(DateTime[0],LCD_DSY_BUFFER2 + 11); //将时转换成数字字符   
  }
 else
 {
   Format_DateTime(DateTime[0],LCD_DSY_BUFFER2 + 11); //将时转换成数字字符 
 }
 
 
  
//    LCD_DSY_BUFFER2[15] = '0' + flag_key;
// Format_DateTime(DateTime[1],LCD_DSY_BUFFER2 + 8);  //将分钟转换成数字字符
// Format_DateTime(DateTime[0],LCD_DSY_BUFFER2 + 11); //将秒转换成数字字符
}

//主函数
void main()
{
 
 
 Init_LCD(); //初始化LCD
 Set_InitTime();//设置初始时间
 TMOD=0x01;
   TH0=(65535-50000)/256;
  TL0=(65535-50000)%256;
   EA=1;
   TR0=1;
 ET0=1;
 while(1)
 {
  //GetTime(); //获取当前时间
  //Format_Changer(); //转换后送给缓冲区

  //Display_LCD_String(0x00,LCD_DSY_BUFFER1); //显示年月日和星期
  //Display_LCD_String(0x40,LCD_DSY_BUFFER2); //显示时分秒
  temp2 = key();
  switch(temp1)
  {
  case 0: //day_flag = 0;
    week_flag = 0;
   // second_flag = 0;
     flag_key = 0;
 
    GetTime(); //获取当前时间
    Format_Changer(); //转换后送给缓冲区
    Display_LCD_String(0x00,LCD_DSY_BUFFER1); //显示年月日和星期
    Display_LCD_String(0x40,LCD_DSY_BUFFER2); //显示时分秒
   break;
  case 1: hour_flag = 1;    flag_key = 1;
    GetTime();       //hour    
    if(10 == temp2)
    {
     DateTime[2]++;
     if(24 == DateTime[2]) DateTime[2] = 0;

     DateTime[2] = DateTime[2] / 10 * 16 + DateTime[2] % 10;

     Write_DS1302(0x8e,0x00);   //关闭写保护
        Write_DS1302(0x84,DateTime[2]);   //设置时
     Write_DS1302(0x8e,0x80);   //开启写保护    */
    }
    if(20 == temp2)
    { 
     if(0 == DateTime[2])
     DateTime[2] = 24;   
     DateTime[2]--;
     DateTime[2] = DateTime[2] / 10 * 16 + DateTime[2] % 10;
     Write_DS1302(0x8e,0x00);   //关闭写保护
        Write_DS1302(0x84,DateTime[2]);   //设置时
     Write_DS1302(0x8e,0x80);   //开启写保护    */
    }
    GetTime(); //获取当前时间
    Format_Changer(); //转换后送给缓冲区
    Display_LCD_String(0x00,LCD_DSY_BUFFER1); //显示年月日和星期
    Display_LCD_String(0x40,LCD_DSY_BUFFER2); //显示时分秒
/*{
  uchar i,addr = 0x81;
 for(i = 0;i<7;i++)
 {
   DateTime[i] = Read_Data(addr);addr += 2;
 }
   Write_DS1302(0x8e,0x00);   //关闭写保护
 Write_DS1302(0x80,0x58);   //设置秒
 Write_DS1302(0x82,0x59);   //设置分
 Write_DS1302(0x84,0x23);   //设置时
 Write_DS1302(0x86,0x31);   //设置日
 Write_DS1302(0x88,0x12); //设置月
 Write_DS1302(0x8a,0x07);   //设置星期
 Write_DS1302(0x8c,0x05);   //设置年
 Write_DS1302(0x8e,0x80);   //开启写保护    */
   break;
  case 2:hour_flag = 0; min_flag = 1;    flag_key = 2;
   
    GetTime();       //min
    if(10 == temp2)
    {
     DateTime[1]++;
     if(60 == DateTime[1]) DateTime[1] = 0;

     DateTime[1] = DateTime[1] / 10 * 16 + DateTime[1] % 10;

     Write_DS1302(0x8e,0x00);   //关闭写保护
        Write_DS1302(0x82,DateTime[1]);   //设置时
     Write_DS1302(0x8e,0x80);   //开启写保护    */
    }
    if(20 == temp2)
    { 
     if(0 == DateTime[1])
     DateTime[1] = 60;   
     DateTime[1]--;
     DateTime[1] = DateTime[1] / 10 * 16 + DateTime[1] % 10;
     Write_DS1302(0x8e,0x00);   //关闭写保护
        Write_DS1302(0x82,DateTime[1]);   //设置时
     Write_DS1302(0x8e,0x80);   //开启写保护    */
    }
      GetTime(); //获取当前时间
    Format_Changer(); //转换后送给缓冲区
    Display_LCD_String(0x00,LCD_DSY_BUFFER1); //显示年月日和星期
    Display_LCD_String(0x40,LCD_DSY_BUFFER2); //显示时分秒  
 
   break;
  case 3: min_flag = 0;second_flag = 1;      flag_key = 3;
 
    GetTime();       //second
    if((10 == temp2) || (20 == temp2))
    {
     DateTime[0] = 0;

     Write_DS1302(0x8e,0x00);   //关闭写保护
        Write_DS1302(0x80,DateTime[0]);   //设置时
     Write_DS1302(0x8e,0x80);   //开启写保护    */
    }
   
     GetTime(); //获取当前时间
    Format_Changer(); //转换后送给缓冲区
    Display_LCD_String(0x00,LCD_DSY_BUFFER1); //显示年月日和星期
    Display_LCD_String(0x40,LCD_DSY_BUFFER2); //显示时分秒  
   break;
  case 4:  second_flag = 0;year_flag = 1;

    GetTime();       //min
    if(10 == temp2)
    {
     DateTime[6]++;
     if(100 == DateTime[6]) DateTime[6] = 0;

     DateTime[6] = DateTime[6] / 10 * 16 + DateTime[6] % 10;

     Write_DS1302(0x8e,0x00);   //关闭写保护
        Write_DS1302(0x8c,DateTime[6]);   //设置时
     Write_DS1302(0x8e,0x80);   //开启写保护   
    }
    if(20 == temp2)
    { 
     if(0 == DateTime[6])
     DateTime[6] = 100;   
     DateTime[6]--;
     DateTime[6] = DateTime[6] / 10 * 16 + DateTime[6] % 10;
     Write_DS1302(0x8e,0x00);   //关闭写保护
        Write_DS1302(0x8c,DateTime[6]);   //设置时
     Write_DS1302(0x8e,0x80);   //开启写保护    */
    }
     GetTime(); //获取当前时间
    Format_Changer(); //转换后送给缓冲区
    Display_LCD_String(0x00,LCD_DSY_BUFFER1); //显示年月日和星期
    Display_LCD_String(0x40,LCD_DSY_BUFFER2); //显示时分秒  
   break;
       
  case 5:  year_flag = 0;month_flag = 1;

    GetTime();       //min
    if(10 == temp2)
    {
     DateTime[4]++;
     if(13 == DateTime[4]) DateTime[4] = 1;

     DateTime[4] = DateTime[4] / 10 * 16 + DateTime[4] % 10;

     Write_DS1302(0x8e,0x00);   //关闭写保护
        Write_DS1302(0x88,DateTime[4]);   //设置时
     Write_DS1302(0x8e,0x80);   //开启写保护   
    }
    if(20 == temp2)
    { 
     if(1 == DateTime[4])
     DateTime[4] = 13;   
     DateTime[4]--;
     DateTime[4] = DateTime[4] / 10 * 16 + DateTime[4] % 10;
     Write_DS1302(0x8e,0x00);   //关闭写保护
        Write_DS1302(0x88,DateTime[4]);   //设置时
     Write_DS1302(0x8e,0x80);   //开启写保护    */
    }
     GetTime(); //获取当前时间
    Format_Changer(); //转换后送给缓冲区
    Display_LCD_String(0x00,LCD_DSY_BUFFER1); //显示年月日和星期
    Display_LCD_String(0x40,LCD_DSY_BUFFER2); //显示时分秒  
   break;
  case 6:  month_flag = 0;day_flag = 1;

    GetTime();       //min
    day_up = month_table[DateTime[4]];
    if((DateTime[4] == 2)&& (DateTime[6] % 4 == 0))
    day_up = 30;  
    day_down = 1;
    if(10 == temp2)
    {
     DateTime[3]++;
     if(day_up == DateTime[3]) DateTime[3] = day_down;

     DateTime[3] = DateTime[3] / 10 * 16 + DateTime[3] % 10;

     Write_DS1302(0x8e,0x00);   //关闭写保护
        Write_DS1302(0x86,DateTime[3]);   //设置时
     Write_DS1302(0x8e,0x80);   //开启写保护   
    }
    if(20 == temp2)
    {    
     if(day_down == DateTime[3])
     DateTime[3] = day_up;   
     DateTime[3]--;
     DateTime[3] = DateTime[3] / 10 * 16 + DateTime[3] % 10;
     Write_DS1302(0x8e,0x00);   //关闭写保护
        Write_DS1302(0x86,DateTime[3]);   //设置时
     Write_DS1302(0x8e,0x80);   //开启写保护    */
    }
     GetTime(); //获取当前时间
    Format_Changer(); //转换后送给缓冲区
    Display_LCD_String(0x00,LCD_DSY_BUFFER1); //显示年月日和星期
    Display_LCD_String(0x40,LCD_DSY_BUFFER2); //显示时分秒  
   break;
  case 7:  day_flag = 0;week_flag = 1;

    GetTime();       //min
    if(10 == temp2)
    {
     DateTime[5]++;
     if(8 == DateTime[5]) DateTime[5] = 1;

     DateTime[5] = DateTime[5] / 10 * 16 + DateTime[5] % 10;

     Write_DS1302(0x8e,0x00);   //关闭写保护
        Write_DS1302(0x8a,DateTime[5]);   //设置时
     Write_DS1302(0x8e,0x80);   //开启写保护   
    }
    if(20 == temp2)
    { 
     if(1 == DateTime[5])
     DateTime[5] = 8;   
     DateTime[5]--;
     DateTime[5] = DateTime[5] / 10 * 16 + DateTime[5] % 10;
     Write_DS1302(0x8e,0x00);   //关闭写保护
        Write_DS1302(0x8a,DateTime[5]);   //设置时
     Write_DS1302(0x8e,0x80);   //开启写保护    */
    }
     GetTime(); //获取当前时间
    Format_Changer(); //转换后送给缓冲区
    Display_LCD_String(0x00,LCD_DSY_BUFFER1); //显示年月日和星期
    Display_LCD_String(0x40,LCD_DSY_BUFFER2); //显示时分秒  
   break;
       
 
  }
 


 }
}

uchar key()
  {
   if(!f1)
   {
    DelayMS(5);
    if(!f1)
    {
     temp1++;
     temp1 = temp1 % 8;
     while(!f1);
    }
   }


   if(!f2)
   {
    DelayMS(5);
    if(!f2)
    {
     return  10;//+
    }
   }

   if(!f3)
   {
    DelayMS(5);
    if(!f3)
    {
     return 20; //-
    }
   }
   return temp1;
  }
void t0(void) interrupt 1 using 0
{
  TH0=(65535-50000)/256; //50ms定时
  TL0=(65535-50000)%256; 
  timecount++;
  if(timecount>9)
   {
    timecount=0;   
    flag=~flag;        
   } 
}

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

特朗普集团近日取消了其新推出的T1智能手机“将在美国制造”的宣传标语,此举源于外界对这款手机能否以当前定价在美国本土生产的质疑。

关键字: 特朗普 苹果 AI

美国总统特朗普在公开场合表示,他已要求苹果公司CEO蒂姆·库克停止在印度建厂,矛头直指该公司生产多元化的计划。

关键字: 特朗普 苹果 AI

4月10日消息,据媒体报道,美国总统特朗普宣布,美国对部分贸易伙伴暂停90天执行新关税政策,同时对中国的关税提高到125%,该消息公布后苹果股价飙升了15%。这次反弹使苹果市值增加了4000多亿美元,目前苹果市值接近3万...

关键字: 特朗普 AI 人工智能 特斯拉

3月25日消息,据报道,当地时间3月20日,美国总统特朗普在社交媒体平台“真实社交”上发文写道:“那些被抓到破坏特斯拉的人,将有很大可能被判入狱长达20年,这包括资助(破坏特斯拉汽车)者,我们正在寻找你。”

关键字: 特朗普 AI 人工智能 特斯拉

1月22日消息,刚刚,新任美国总统特朗普放出重磅消息,将全力支持美国AI发展。

关键字: 特朗普 AI 人工智能

特朗普先生有两件事一定会载入史册,一个是筑墙,一个是挖坑。在美墨边境筑墙的口号确保边境安全,降低因非法移民引起的犯罪率过高问题;在中美科技产业之间挖坑的口号也是安全,美国企业不得使用对美国国家安全构成威胁的电信设备,总统...

关键字: 特朗普 孤立主义 科技产业

据路透社1月17日消息显示,知情人士透露,特朗普已通知英特尔、铠侠在内的几家华为供应商,将要撤销其对华为的出货的部分许可证,同时将拒绝其他数十个向华为供货的申请。据透露,共有4家公司的8份许可被撤销。另外,相关公司收到撤...

关键字: 华为 芯片 特朗普

曾在2018年时被美国总统特朗普称作“世界第八奇迹”的富士康集团在美国威斯康星州投资建设的LCD显示屏工厂项目,如今却因为富士康将项目大幅缩水并拒绝签订新的合同而陷入了僵局。这也导致富士康无法从当地政府那里获得约40亿美...

关键字: 特朗普 富士康

今年5月,因自己发布的推文被贴上“无确凿依据”标签而与推特发生激烈争执后,美国总统特朗普签署了一项行政令,下令要求重审《通信规范法》第230条。

关键字: 谷歌 facebook 特朗普

众所周知,寄往白宫的所有邮件在到达白宫之前都会在他地进行分类和筛选。9月19日,根据美国相关执法官员的通报,本周早些时候,执法人员截获了一个寄给特朗普总统的包裹,该包裹内包含蓖麻毒蛋白。

关键字: 美国 白宫 特朗普
关闭