基于51单片机的万年历设计

关于设计单片机万年历的收获
1.在改程序中的错误的过程中,知道了许多错误类型,增加了经验,而且我深刻的体会到了做任何事都要有耐心~
2.在结合模块的过程中,我知道了扎实基础很重要,不然这个过程会很混乱…
3.不能半途而废,程序中有些错误改不出来时,有些内容不理解时,我想过换一些模块联动,但是我相信坚持就是胜利~
4.虚心求教的重要性,问过CSDN上的其他博主,B站上的老师等等,他们都给我提供了有力的帮助~
!!万年历具有读取方便,显示直观,功能多样,电路简洁等优点
功能:
1.显示年,月,日,时,分,秒
2.显示温度
3.显示星期
4.按键调节各参数,分别为设置键,加键,减键设置闹钟键
一. 电路组成
1.单片机最小系统
2.LCD1602液晶显示屏电路
3.四路独立按键
4.DS1302时钟电路
5.DS18B20温度传感器
6.系统电源
二.lcd1602介绍
1.引脚定义
VL引脚:为液晶显示器对比度调整端
RS引脚:RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器
R/W引脚:R/W为读写信号线,高电平时进行读操作,低电平时进行写操作。当RS和R/W共同为低电平时可以写入指令或者显示地址,当RS为低电平R/W为高电平时可以读忙信号,当RS为高电平R/W为低电平时可以写入数据。
EN引脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。
在这里插入图片描述
2.控制程序:写数据、写指令、初始化
读状态:输入:RS=L,RW=H,E=H----输出:D0~D7=状态字
写指令:输入:RS=L,RW=L,D0~D7=指令码----输出:无
读数据:输入:RS=H,RW=H,E=H----输出:D0~D7=数据
写数据:输入:RS=H,RW=L,D0~D7=数据,E=高脉冲----输出:无
(1)写数据函数
(2)写指令函数
(3)初始化函数
a.设置写操作:R/W设为低电平;
b.屏幕设置模式:写指令38H;
c.打开显示,关闭光标:写指令0CH;
d.设置显示光标移动位置:写指令06H;
e.设置字符显示位置:写指令(字符显示的起始位置);
由于对LCD1602进行控制时不需要实现读操作,所以R/W在初始化后恒为低电平;对控制器每次进行读写操作前,都必须进行读写检测,确保STA7为0
三.DS18B20介绍
1.初始化
在操作时序的时候,为了防止中断干扰总线时序,先关闭总中断。拉低 DS18B20 这个引脚,持续 500us;延时 60us;读取存在脉冲,并且等待存在脉冲结束。
2.ROM 操作指令
3.RAM 存储器操作指令
4.DS18B20的位读写时序
四.ds1302介绍
本系统的时间读取主要来源于单片机对ds1302的操作
引脚功能
在这里插入图片描述
内部结构在这里插入图片描述
寄存器在这里插入图片描述
操作方法:启动传送,发送命令字节,传送数据

ds18b20

uchar ds18b20_read()
{              //读一个字节
      uchar i=0;
      uchar dat = 0;
      for (i=8;i>0;i--)
      {
           dq = 0; // 给脉冲信号
           dat>>=1;
           dq = 1; // 给脉冲信号
           if(dq)
           dat|=0x80;
           delay1(4);
      }
        return(dat);
}
void ds18b20_write(char dat)
{             //写一个字节
     uchar i=0;
     for (i=8; i>0; i--)
     {
          dq = 0;
          dq = dat&0x01;
          delay1(5);
          dq = 1;
          dat>>=1;
      }
}
int ds18b20_read_temp()
{         //读取温度
         uchar low;
         uchar high;
         unsigned long tmp;
         float value;
         int t;//温度
ds18b20_init();
ds18b20_write(0xCC); //跳过读序列号的操作
ds18b20_write(0x44); //启动温度转换
ds18b20_init();
ds18b20_write(0xCC); //跳过读序列号的操作
ds18b20_write(0xBE); //读取温度寄存器
low=ds18b20_read();//低八位数据
high=ds18b20_read();//高八位数据
tmp=high;
tmp<<=8;
tmp=tmp|low;//此处有正负之分
if(tmp>=63488)
{          //ffff f000 0000 0000-->(f800)
    temp_flag=0;//8位全为1时,加1才进位
   if((~low)==0xff)
   {         //判断low取反加1之后是否进位
      high=(~high)+1;
      low=0;
   }
  else
  {
      high=~high;
      low=(~low)+1;
  }
     tmp=high*256+low;
}
   else
  {
        temp_flag=1;
  }
     value=tmp*0.0625;
     t=value*10+((temp_flag==1)?+0.5:-0.5);//放大十倍输出并四舍五入
     return t;
}

LCD1602

void write_1602com(uchar com)
{              //1602写指令
    rs=0;
    lcden=0;
    P2=com;
    delay(5);
    lcden=1;
    delay(5);
    lcden=0;
}
void write_1602data(uchar dat)
{      //1602写数据
	  rs=1;
	  lcden=0;
      P2=dat;
      delay(5);
      lcden=1;
      delay(5);
      lcden=0;
}
void init_1602()
{     //初始化1602液晶
rw=0;
lcden=0;
write_1602com(0x38);//设置显示模式
write_1602com(0x0c);//显示开关及光标是否显示和闪动
write_1602com(0x06);//光标移动方向
write_1602com(0x01);//清屏
}

ds1302

void write_ds1302_byte(uchar temp)
{          //ds1302写一个字节数据
    uchar i;
    for(i=0;i<8;i++)
    {
        io=temp&0x01;//将数据放到IO口上
        scl=0;//scl为低时准备数据
        scl=1;//上升沿写入
        temp>>=1;
     }
}
void write_ds1302(uchar add,uchar dat)
{         //向地址add写入数据dat
     rst=0;
     scl=0;
     rst=1;
     write_ds1302_byte(add);
     write_ds1302_byte(dat);
     scl=1;
     rst=0;
}
uchar read_ds1302(uchar add)
{      //ds1302读数据
     uchar i,dat;
     rst=0;
     scl=0;
     rst=1;
     write_ds1302_byte(add);//首先写入要读的数据处的地址
     for(i=0;i<8;i++)
     {
         if(io==1)
         {
             dat|=0x80;
         }
           scl=1;
           scl=0;//下降沿读取数据
           dat>>=1;
      }
           scl=1;
           rst=0;
           return dat;
}
void read_time(uchar curr_time[])
{
       uchar i;
       uchar ucAddr = 0x81;
       for (i=0;i<7;i++)
       {
       curr_time[i] = read_ds1302(ucAddr);//格式为: 秒 分 时 日 月 星期 年
       ucAddr += 2;
       }
}
void set_time(uchar *pSecDa)
{        //设定时间
      uchar i;
      uchar ucAddr = 0x80;
      write_ds1302(0x8e,0x00);
      for(i =7;i>0;i--)
      {
      write_ds1302(ucAddr,*pSecDa); //秒 分 时 日 月 星期 年
      pSecDa++;
      ucAddr+=2;
      }
      write_ds1302(0x8e,0x80);
}
void init_ds1302()
{     //ds1302初始化
    isInit_1302=read_ds1302(0x81);//读出时钟状态
    if(isInit_1302&0x80)
    {     //说明没有初始化
    write_ds1302(0x8e,0x00);//关闭写保护
    write_ds1302(0x90,0xa5); //辅助电源充电命令 一个二极管一个2K电阻
    write_ds1302(0x80,0x00);//秒 CH置0 开启时钟
    write_ds1302(0x82,0x59);//分
    write_ds1302(0x84,0x10);//时
    write_ds1302(0x86,0x07);//日
    write_ds1302(0x88,0x05);//月
    write_ds1302(0x8a,0x04);//星期
    write_ds1302(0x8c,0x14);//年
    write_ds1302(0x8e,0x80);
    }
}

闹钟设置

void init_alarm()
{    //闹钟设置界面 只有首次进入才执行
   uchar code x[]="SET ALARM";
   uchar i;
   if(alarm==0)
   {
         write_1602com(0x01);//清屏
         write_1602com(0x80+3);//设置数据指针
         for(i=0;i<9;i++)
         {
              write_1602data(x[i]);
         }
              display_alarm(0x80+0x40+5,shi);//载入闹钟的时分
              write_1602com(0x80+0x40+7);
              write_1602data(':');
              display_alarm(0x80+0x40+8,fen);
              if(isOpen)
              {        //初始化的时候如果已经设定闹钟则显示ON
                   write_1602com(0x80+0x40+13);
                   write_1602data(' ');
                   write_1602data('O');
                   write_1602data('N');
               }
              else 
             {
                   write_1602com(0x80+0x40+13);
                   write_1602data('O');
                   write_1602data('F');
                   write_1602data('F');
            } 
   }
}
  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智商已欠费.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值