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

📄 locker_with_lcd_and_clock.txt

📁 本程序用到4x4按键中断扫描法
💻 TXT
📖 第 1 页 / 共 2 页
字号:

程序说明:
        本程序用到4x4按键中断扫描法,用lcd显示,开机时候显示一个数字钟(时间不可设,稍后加入该功能),钟正常走
  如果按下开锁键,进入以请输入密码界面,输入密码,如果密码正确,显示欢迎使用,密码错误蜂鸣器报警
   且LCD显示密码错误,请重新输入。
 注:数字时钟用的是DS1302实现,由于本人也才学单片机一个多月,所以注释非常详细,初学者很容易看懂。

**************************************************************************************************************/


#include <reg52.h>
#include <intrins.h>


sbit SPK=P3^4;  //SPK定义为P3口的第4位,就是驱动蜂鸣器的那个脚
sbit JDQ=P3^5;  //JDQ定义为P3口的第5位,就是驱动继电器的那个脚
sbit lcdrs  =  P1^0;   //数据命令选择端 (H/L)
sbit lcdrw  =  P1^1;   //读写选择端 (H/L)
sbit lcde   =  P1^2;   //使能信号
sbit OK     =  P0^5; //密码输入确认键
sbit H      =  P0^4;//独立按键定义位
sbit take   =  P0^6;//开锁键
sbit SCL2   =  P1^3;  //SCL2定义为P1口的第3位脚,连接DS1302SCL和ADC0831SCL脚
sbit SDA2   =  P1^4;  //SDA2定义为P1口的第4位脚,连接DS1302SCL和ADC0831SDA脚 
sbit RST    =  P1^5;   // DS1302片选脚

#define LCD_Data  P2
#define Busy     0x80 //用于检测LCD状态字中的Busy标识
#define uchar unsigned char
#define uint unsigned int

code unsigned char table[]=
   {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
   0x77,0x7c,0x39,0x5e,0x79,0x71};
   //共阴数码管 0-9 a-f 表

code unsigned char key_tab[10]={0xed,0x7e,0x7d,0x7b,
        0xbe,0xbd,0xbb,0xde,
        0xdd,0xdb,};//0x77,0xb7,
       // 0xee,0xd7,0xeb,0xe7,0XFF};//========================此数组为键盘编码,
               //本人采用类式类似电话按键的编码方式,方便以后设计
          // 1 2 3 a     0x01 0x02 0x03 0x0a
          // 4 5 6 b 对应16进制码:  0x04 0x05 0x06 0x0b
          // 7 8 9 e     0x07 0x08 0x09 0x0e
          // * 0 # f     0x0c 0x00 0x0e 0x0f
          //打个比方,如果你按下0键,P0口读到数据为0xed
          //如果你按下2键,P0口读到数据为0x7d,按下9键为0xdb,
          //我们将读到的P0口数据经过查表法就能得到相应的16进制码
     
          //键盘的读取,我们采用中断法,电路用一个4与门(74HC21)接入
          //中断口(INT0),利用中断来扫描键盘矩阵,读取数据

unsigned char l_tmpdate1[4]={0,0,0,0};//定义数组变量
uchar table_password[4]={1,2,3,4}; //密码
code uchar table_right[]="welcome use!";
code uchar table_num[]="input password:";
code uchar table_error[]="input error!";
code uchar table_error1[]="Pls try again!";
unsigned char l_key=0;     //定义变量,存放键值 
unsigned char l_keyold=0xFF; //做为按键松开否的凭证    
uchar buzyc,flag=0,mima;
uchar funtion_flag=0,temp_num;
char shi,fen,miao,nian,yue,ri,xin;

unsigned char l_tmpdate[8]={0x00,59,12,19,2,8,2};//显示初值
unsigned char l_tmpdisplay[8]={0x40,0x40,0x40,0x40,0x40,0x40,0x40,0};//待显示的数
code unsigned char write_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8c,0x8a}; //1302写入地址
code unsigned char read_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8d,0x8b};//1302读出地址
//code unsigned char table[]= {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0x00};//共阴数码管 0-9  '-' '熄灭‘表
uchar date1[]="MON";
uchar date2[]="TUE";
uchar date3[]="WED";
uchar date4[]="THU";
uchar date5[]="FRI";
uchar date6[]="SAT";
uchar date7[]="SUN"; 



void ReadKey(void)      //读键盘值
{
 unsigned char i,j,key,n;
 j=0xfe;
 key=0xff;//设定初值
 for (i=0;i<3;i++)
 {  
  P0=j;    //P0口低4位循环输出0,扫描键盘
  if ((P0&0xf0)!=0xf0)
  { //如果有键按下,P0口高4位不会为1,         
   key=P0;      //读取P0口,退出循环,否则循环下次 
   break;  
  }
  j=_crol_(j,1);   //此函数功能为左循环移位
 }
 if (key==0xff)
 {    //如果读取不到P0口的值,比如是干扰,我们不做键值处理,返回
  l_keyold=0xff;
  P0=0xf0;   //恢复P0口,等待按键按下
  EX0=1;     //返回之前,开启外中断
  SPK=1;
  return;
 }
 SPK=0;     //有键按下,我们驱动蜂鸣器响
 if(l_keyold==key)
 {  //检测按键放开否,如果一样表明没放开,
  TH0=0X2E;   //我们继续启动定时器,检测按键松开否
  TL0=0;
  TR0=1;
   
     return;
 }  
 TH0=0X2E;   
 TL0=0;
 TR0=1;     //我们继续启动定时器,检测按键松开否

 l_keyold=key;   //获取键码做为放开的凭证

 for(i=0;i<10;i++)
 {   //查表获得相应的16进制值存放l_key变量中
  if (key==key_tab[i])
  {
   l_key=i;

   l_tmpdate1[n]=l_key;//将获得的数装入一个新的数组
   n++;
   if(n==4) //装满四位就从新装入
   n=0;
   //判断被按下去的数字与设定密码是否相符
   if(l_tmpdate1[0]==table_password[0]&l_tmpdate1[1]==table_password[1]&l_tmpdate1[2]==table_password[2]&l_tmpdate1[3]==table_password[3])
   mima=1;
   break;
  }
 }
   //程序运行到这里,就表明有键值被读取存放于l_key变量中,主程序就可以检测此变量做相应外理,
   //此时我们回到主程序
}  
 

//延时函数
void delay(uint z)  //延时函数,z的取值为这个函数的延时ms数,如delay(200);大约延时200ms.
{     //delay(500);大约延时500ms.
 uint x,y;
 for(x=z;x>0;x--)
  for(y=110;y>0;y--); 
}


//读状态,忙检测处理函数
unsigned char ReadStatusLCD(void)
{
 LCD_Data = 0xFF; 
 lcdrs = 0;
 lcdrw = 1;
 lcde = 0;
 lcde = 0;
 lcde = 1;
 while ((LCD_Data & Busy)==Busy); //检测忙信号
 return(LCD_Data); 
}

//写命令子函数
void write_com(uchar com,buzyc)
{
 if(buzyc)
 ReadStatusLCD();//忙检测
 lcdrw=0;
 lcdrs=0;
 P2=com;
 delay(3);
 lcde=1;
 delay(6);
 lcde=0; 
}


//写数据子函数
void write_date(uchar date)
{
 ReadStatusLCD();//忙检测
 lcdrw=0;
 lcdrs=1;
 P2=date;
 delay(3);
 lcde=1;
 delay(6);
 lcde=0; 
}


//初始化函数
void init()
{
 H=0;
 lcde=0;
 delay(15);
 write_com(0x38,0);
 delay(5);
 write_com(0x38,0);
 delay(5);
 write_com(0x38,0);
 write_com(0x38,1); //设置led为16×2显示,5×7点阵,8位数据口
  write_com(0x0f,1); //开显示,显示光标,光标闪烁
 write_com(0x06,1); //光标自动移动,整屏不动
 write_com(0x01,1); //显示清屏,数据指针和地址指针全部清零
 write_com(0x80,1); //设置数据指针到屏幕的最开始端

}


/*****************************************************************************************************
字节写入子函数:
  将要写入的数字先右移一位,是最低位溢出,然后在scl2的一个上升沿数据被写入DS1302,注意
  数据的写入时从低位到高位
*****************************************************************************************************/

void Write_Ds1302_Byte(unsigned  char date) 
{
 uchar j,temp;
 temp=date;
 for(j=0;j<8;j++)
 {
  temp=temp>>1; //将数据右移一位使最低位溢出
  SDA2=CY; //将待写入数据最低位写入数据缓冲
  SCL2=0;
  SCL2=1;  //在scl的上升延写入数据
 }
}  


/*****************************************************************************************************
字节读出子函数:
   分8次读出数据,将读出的数据存入temp:在时钟信号的下降沿读出一个字节的数据
   数据读出也是从低位到高位的
*****************************************************************************************************/
uchar Read_Ds1302_Byte()
{
 uchar j,temp;
 for(j=0;j<8;j++)
 {
  temp=temp>>1; //将temp右移一位使最高位变为次高位,最高为为0
  SDA2=1;
  SCL2=1;
  SCL2=0; //在scl2的一个下降沿数据读出
  if(SDA2==1)//如果读出的数据为1,即在temp的最高位写入1,为0的时候则写入0
  temp=temp|0x80;
  temp=temp|0x00;  
 }
 return temp;
}


/***************************************************************************************************************
数据写入DS1302函数:
   在指定地址写入指定数据,在rst为低scl2为低的情况下将rst置高,即允许数据写入
   先写入地址
   然后写入数据
   最后将rst拉低结束数据写入
****************************************************************************************************************/
void Write_Ds1302( unsigned char address,unsigned char dat )     
{
  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); //发送地址
  Write_Ds1302_Byte(dat);  //发送数据
  RST=0;    //恢复
}


⌨️ 快捷键说明

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