⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 locker_with_lcd_and_clock.txt

📁 本程序用到4x4按键中断扫描法
💻 TXT
📖 第 1 页 / 共 2 页
字号:
/************************************************************************************************************
从指定地址读取数据子函数:
                   在rst为低scl2为低的情况下将rst置高,即允许数据被读出(注意加入延时可以防止干扰) 
       先写入地址
       在分八次吧数据一位位读出,在scl2的一个下降沿数据被读出,数据位从0开始

***************************************************************************************************************/
unsigned char Read_Ds1302 ( unsigned char address )
{
  unsigned char  temp1,temp2;
  RST=0;     
 _nop_();_nop_();_nop_();_nop_();_nop_();
  SCL2=0;
 _nop_();_nop_();_nop_();_nop_();_nop_();
  RST=1;
 _nop_();_nop_();_nop_();_nop_();_nop_();    //开启,写入数据地址,这是本串口协议的开始,加入延时防止干扰
  Write_Ds1302_Byte(address);
 temp1=Read_Ds1302_Byte(); 
 temp2=temp1>>4;
 temp2=temp2*10;
 temp1=temp1&0x0f;
 temp1=temp1+temp2;//读出数据的时候要将BCD码转换成十进制
  RST=0;
  return (temp1);   //返回
}

/***************************************************************************************************
设定时间初值:
   在写入之前应当把要写入的数据转换成BCD码的形式
   每写入一次数据记得都要打开1302的写入允许
   
****************************************************************************************************/
void Set_RTC(void)  //设定 日历
{
 unsigned char i,*p,tmp;
 for(i=0;i<8;i++)
 {    //数据的转换,DS1302以4位存储一个10进制数,因此需要将数据进行转换
  tmp=l_tmpdate[i]/10;
  l_tmpdate[i]=l_tmpdate[i]%10;
  l_tmpdate[i]=l_tmpdate[i]+tmp*16;
 }
  Write_Ds1302(0x8E,0X00);  //打开DS1302的写入允许
 
  p=write_rtc_address; //传地址 
  for(i=0;i<8;i++)  //7次写入 年月日时分秒星期
  {
   Write_Ds1302(*p,l_tmpdate[i]);
    p++;  
  }
  Write_Ds1302(0x8E,0x80);  //关闭DS1302的写入允许
}


/****************************************************************************************************
读取时钟日历:
   循环几次分别读出数据,存放在一个数组中,注意此时读出的数据为BCD码形式
    每读一次数值让1302空运行一次 可有效的防治干扰

******************************************************************************************************/
void Read_RTC(void)  //读取 日历
{
  unsigned char i,*p;
  p=read_rtc_address;  //地址传递
  for(i=0;i<8;i++)  //分7次读取 年月日时分秒星期
  {
    l_tmpdisplay[i]=Read_Ds1302(*p);//读取数据存放于数组变量中
    p++;
    _nop_();_nop_();_nop_();_nop_();_nop_(); //5个空指令
    Read_Ds1302(0x00);      //让1302空运行一次是最好的防干扰方法
  _nop_();_nop_();_nop_();_nop_();_nop_();
  }
}    


/****************************************************************************************************************
液晶显示扫描程序
*****************************************************************************************************************/
void display_scan(uchar add,uchar date)
{

 uchar sw,gw;
 sw=date/10;
 gw=date%10;
 write_com(0x80+add,1);    
 write_date(0x30+sw);
 write_date(0x30+gw); 
}

void week_display()//星期显示函数,自己感觉写的复杂了点,不知道你有什么好的办法没有,我估计用数组实现应该                        
{               //要代码简洁些。你不妨试下
 uchar j;
 write_com(0x80+0x40+11,1);
 switch(xin)
 {
  case 1:
   for(j=0;j<3;j++)
   {
    write_date(date1[j]);
   }   break;
  case 2:
   for(j=0;j<3;j++)
   {
    write_date(date2[j]);
   }   break;
  case 3:
   for(j=0;j<3;j++)
   {
    write_date(date3[j]);
   }   break;
  case 4:
   for(j=0;j<3;j++)
   {
    write_date(date4[j]);
   }   break;
  case 5:
   for(j=0;j<3;j++)
   {
    write_date(date5[j]);
   }   break;
  case 6:
   for(j=0;j<3;j++)
   {
    write_date(date6[j]);
   }   break;

  case 7:
   for(j=0;j<3;j++)
   {
    write_date(date7[j]);
   } 
  }
}


void main(void)     //入口函数
{
 uchar j,flag1,flag0;
 init();
 Set_RTC();
 EA=1;   //首先开启总中断
 EX0=1;    //开启外部中断 0
 IT0=1;        // 设置成 下降沿触发方式
 P0=0xf0;//P0口高位输高电平,经过74HC21四输入与门,连接外中断0,有键按下调用中断函数
 while(1)
 {
  Read_RTC();
  if(take==1)
  {
   if(flag0==0)
   {
    write_com(0x80+6,1); 
    write_date(0x3a); //加入:号显示
  
    write_com(0x80+9,1); 
    write_date(0x3a);
  
    write_com(0x80+0x47,1); 
    write_date(0x2d);//加入-显示
  
    write_com(0x80+0x44,1); 
    write_date(0x2d);
  
    shi  =  l_tmpdisplay[2];
    fen  =  l_tmpdisplay[1];
    miao =  l_tmpdisplay[0];
    nian =  l_tmpdisplay[5];
    yue  =  l_tmpdisplay[4];
    ri   =  l_tmpdisplay[3];
    xin  =  l_tmpdisplay[6];
    week_display();
    display_scan(4,shi);
    display_scan(7,fen);
    display_scan(10,miao);
    display_scan(0x40+2,nian);
    display_scan(0x40+5,yue);
    display_scan(0x40+8,ri);
   }
  }
  
  else//如果开锁键按下了
  {
   delay(20);
   if(take==0)
   {
    while(!take)
    {
     SPK=0;
    }
    flag0=1;
    SPK=1;
    flag1=1;
    write_com(0x01,1); //显示清屏,数据指针和地址指针全部清零
    write_com(0x80,1);//在第一行显示请输入密码
    for(j=0;j<15;j++)
     write_date(table_num[j]);  
    }
 
    if(flag1==1)//如果开锁键已经按下了
    {
     write_com(0x80+0x40,1); //在第二行显示被按下的数字  
    for(j=0;j<4;j++)//有按键按下一次显示一个数
    {
     write_date(l_tmpdate1[j]+0x30);
    }
    }
  }

  if(OK==0) //如果确认键被按下
  {
   delay(20);
   if(OK==0)
   {
    while(!OK)
    {SPK=0;}
    SPK=1;
    if(mima==1)//并且密码正确
    { 
     mima=0;
     write_com(0x01,1); //显示清屏,数据指针和地址指针全部清零
     write_com(0x80+3,1);
     for(j=0;j<12;j++)//流动显示欢迎使用
     {
      write_date(table_right[j]);
      delay(20);
     }
     }
    else //如果密码不正确
    {
     SPK=0;
     write_com(0x01,1); //显示清屏,数据指针和地址指针全部清零
     write_com(0x80+2,1);
     for(j=0;j<12;j++)
     {
      write_date( table_error[j]);
      delay(20);
     }
     write_com(0x80+0X41,1);
     for(j=0;j<14;j++)
     {
      write_date(table_error1[j]);
      delay(20);
     }
     
     
    }
    }
  }
   

 }//while(1)
}//main

void key_scan()   interrupt 0    //外部中断 0  0的优先级最高        
{ 
 EX0=0;     //在读键盘期间,我们关闭中断,防止干扰带来的多次中断

       //为了消除抖动带来的干扰,在按下键后我们采用延时十多毫秒再读取键值
      //如果采用循环语句来延时,比如(for,while。。。)会使CPU处理循环而占用       //系统资源,所以这里我们采用定时器中断法,让定时器等待十多毫秒触发定时器       //中断,这里用到定时器0

 TMOD&=0XF1;    //设置定时器0为模式1方式,
 TH0=0X2E;    //设置初值,为12毫秒
 TL0=0X00;
 ET0=1;     //开启定时器中断0
 TR0=1;     //启动定时器计数 
} 
void timer0_isr(void) interrupt 1 //定时器0的中断函数
{ 
 TR0=0; //中断后我们停止计数
 
 ReadKey();     //定时器计数12毫秒后产生中断,调用此函数,读取键值
 
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -