基于51单片机的密码锁程序

基于51单片机的密码锁程序,三个子程序:4*4的矩阵键盘、I2C芯片、液晶屏最好是用KeiluVision2编写的。。要求是4*4的矩阵键盘,其中10个是数字键,还包括一... 基于51单片机的密码锁程序,
三个子程序:4*4的矩阵键盘、I2C芯片、液晶屏
最好是用Keil uVision2编写的。。
要求是4*4的矩阵键盘,其中10个是数字键,还包括一个确认、一个更改密码、一个退出
展开
 我来答
zgy145
推荐于2017-09-26
知道答主
回答量:2
采纳率:0%
帮助的人:0
展开全部
  用STC52编的,下面是C程序,调试已经成功,自己看程序吧……
  #include<reg52.h>
  #include <intrins.h>

  #define uchar unsigned char
  #define uint unsigned int

  #define LCD_data P0
  sbit SDA=P3^5;
  sbit SCL=P3^4;//24C08控制口设置
  sbit LCD_RS = P3^3; //寄存器选择输入
  sbit LCD_RW = P3^6; //液晶读/写控制
  sbit LCD_EN = P3^7; //液晶使能控制
  sbit LCD_PSB = P3^2; //串/并方式控制
  sbit FM=P2^4;//蜂鸣器控制口
  sbit RS=P2^5;
  sbit T_CLK = P2^0; //实时时钟时钟线引脚 //
  sbit T_IO = P2^1; //实时时钟数据线引脚 //
  sbit T_RST = P2^2; //实时时钟复位线引脚 //
  sbit ds=P2^3;
  sbit EN=P2^6;
  sbit ZZ=P2^7;
  sbit FZ=P3^1;
  sbit ACC0=ACC^0;
  sbit ACC7=ACC^7;

  uint temp1,s_temp; //定义整形变量
  float f_temp; //定义浮点型变量

  uchar time[]=" : : ";
  uchar day[]=" 20 / / ( ) ";
  uchar temp0[]=" 温度: . 度 ";
  uchar num,num1,flag,count,a,b;
  uchar unlock_i;//解密标志位

  uchar t[4];
  uchar t1[4];

  void delay_ms(uint z)//长延时
  {
  uint x,y;
  for(x=z;x>0;x--)
  for(y=110;y>0;y--);
  }

  void delay() //短延时,大约5us
  {
  ; ;
  }
  void reshi()
  {
  if(RS==1)
  { unlock_i=1;
  }
  else
  {
  unlock_i=0;
  }
  }
  uchar code mima[]={'0','1','2','3','4','5','6','7','8','9','0','*'};

  void lcd_xieping0(uchar x,uchar y,uchar date);
  void lcd_xieping(uchar x,uchar y,uchar *str);
  //********************************************************
  // 开机显示
  //********************************************************
  void kjxs()
  {
  uint i,j;
  lcd_xieping(0,0,"****************");
  lcd_xieping(1,0," 欢迎进入 ");
  lcd_xieping(2,0," 密码锁系统! ");
  lcd_xieping(3,0,"****************");
  delay_ms(4000);
  lcd_xieping(0,0," 系统初始化中 ");
  lcd_xieping(1,0," 请稍后… ");
  lcd_xieping(2,0,"————————");
  lcd_xieping(3,0," ");
  for(j=3;j>0;j--)
  {
  for(i=0;i<8;i++)
  {
  lcd_xieping(3,i,"*");
  delay_ms(250);
  }
  lcd_xieping(3,0," ");
  }
  }
  //********************************************************
  // 12864显示
  //********************************************************
  void write_cmd(uchar cmd)
  {
  LCD_RS = 0;
  LCD_RW = 0;
  LCD_EN = 0;
  P0 = cmd;
  delay_ms(5);
  LCD_EN = 1;
  delay_ms(5);
  LCD_EN = 0;
  }
  void write_dat(uchar dat)
  {
  LCD_RS = 1;
  LCD_RW = 0;
  LCD_EN = 0;
  P0 = dat;
  delay_ms(5);
  LCD_EN = 1;
  delay_ms(5);
  LCD_EN = 0;
  }
  void lcd_xieping0(uchar x,uchar y,uchar date)
  {
  switch(x)
  {
  case 0: write_cmd(0x80+y); break;
  case 1: write_cmd(0x90+y); break;
  case 2: write_cmd(0x88+y); break;
  case 3: write_cmd(0x98+y); break;
  }
  write_dat(date);
  }
  void lcd_xieping(uchar x,uchar y,uchar *str)
  {
  switch(x)
  {
  case 0: write_cmd(0x80+y); break;
  case 1: write_cmd(0x90+y); break;
  case 2: write_cmd(0x88+y); break;
  case 3: write_cmd(0x98+y); break;
  }
  while (*str)
  {
  write_dat(*str);
  str++;
  }
  }
  void lcd_init()
  {
  LCD_PSB = 1; //并口方式
  write_cmd(0x30); //基本指令操作
  delay_ms(5);
  write_cmd(0x0C); //显示开,关光标
  delay_ms(5);
  write_cmd(0x01); //清除LCD的显示内容
  delay_ms(5);
  }
  //**************************************************************
  // 键盘扫描函数
  //**************************************************************
  uchar keyscan1() //矩阵键盘扫描函数
  {
  uchar temp;
  while(!num)
  {P1=0xfe; //赋值
  temp=P1; //读回数据
  temp=temp&0xf0; //与运算
  if(temp!=0xf0) //判断
  {
  delay_ms(2); //延时消抖
  temp=P1; //读回数据
  temp=temp&0xf0;
  if(temp!=0xf0)
  {
  switch(temp) //多分支选择
  {
  case 0x70:num=1;break; //跳出
  case 0xb0:num=2;break;
  case 0xd0:num=3;break;
  case 0xe0:num=4;break;
  }
  while(temp!=0xf0)
  {
  temp=P1;
  temp=temp&0xf0;
  }//等待按键释放
  }
  }
  P1=0xfd; //赋值
  temp=P1; //读回数据
  temp=temp&0xf0; //与运算
  if(temp!=0xf0) //判断
  {
  delay_ms(2); //延时消抖
  temp=P1; //读回数据
  temp=temp&0xf0;
  if(temp!=0xf0)
  {
  switch(temp) //多分支选择
  {
  case 0x70:num=5;break; //跳出
  case 0xb0:num=6;break;
  case 0xd0:num=7;break;
  case 0xe0:num=8;break;
  }
  while(temp!=0xf0)
  {
  temp=P1;
  temp=temp&0xf0;
  }//等待按键释放
  }
  }
  P1=0xfb; //赋值
  temp=P1; //读回数据
  temp=temp&0xf0; //与运算
  if(temp!=0xf0) //判断
  {
  delay_ms(2); //延时消抖
  temp=P1; //读回数据
  temp=temp&0xf0;
  if(temp!=0xf0)
  {
  switch(temp) //多分支选择
  {
  case 0x70:num=9;break; //跳出
  case 0xb0:num=10;break;
  case 0xd0:num=11;break;
  case 0xe0:num=12;break;
  }
  while(temp!=0xf0)
  {
  temp=P1;
  temp=temp&0xf0;
  }//等待按键释放
  }
  }
  }
  return(num); //返回值
  }

  uchar keyscan2()
  {
  uchar temp;
  while(!num1)
  {P1=0xf7; //赋值
  temp=P1; //读回数据
  temp=temp&0xf0; //与运算
  if(temp!=0xf0) //判断
  {
  delay_ms(2); //延时消抖
  temp=P1; //读回数据
  temp=temp&0xf0;
  if(temp!=0xf0)
  {
  switch(temp) //多分支选择
  {
  case 0x70:num1=1;break; //跳出
  case 0xb0:num1=2;break;
  case 0xd0:num1=3;break;
  case 0xe0:num1=4;break;
  }
  while(temp!=0xf0)
  {
  temp=P1;
  temp=temp&0xf0;
  }//等待按键释放
  }
  }
  }
  return(num1);
  }
  //**************************************************************
  // 直流电机
  //**************************************************************
  void dianjiZZ()
  {
  EN=1;
  ZZ=1;
  FZ=0;
  }
  void dianjiFZ()
  {
  EN=1;
  ZZ=0;
  FZ=1;
  }
  void dianji_stop()
  {
  EN=0;
  }
  //**************************************************************
  // EPPROM
  //**************************************************************
  void start() //启动信号
  {
  SDA=1;
  delay();
  SCL=1;
  delay();
  SDA=0;
  delay();
  }

  void stop() //停止信号
  {
  SDA=0;
  delay();
  SCL=1;
  delay();
  SDA=1;
  delay();
  }

  void respons() //响应信号
  {
  uchar i;
  SCL=1;
  delay();
  while((SDA==1)&&(i<250))
  i++;
  SCL=0;
  delay();

  }

  void writebyte(uchar date) //写一个字节
  {
  uchar i,temp;
  temp=date;
  for(i=0;i<8;i++)
  {
  temp=temp<<1;
  SCL=0;
  delay();
  SDA=CY;
  delay();
  SCL=1;
  delay();
  }
  SCL=0;
  delay();
  SDA=1; //释放总线
  delay();

  }

  uchar readbyte() //读一个字节
  {
  uchar i,k;
  SCL=0;
  delay();
  SDA=1;
  for(i=0;i<8;i++)
  {
  SCL=1;
  delay();
  k=(k<<1)|SDA;
  SCL=0;
  delay();
  }
  delay();
  return(k);

  }
  void write(uchar add,uchar date) //在一个地址写一个字节
  {
  start();
  writebyte(0xa0);
  respons();
  writebyte(add);
  respons();
  writebyte(date);
  respons();
  stop();

  }
  uchar read(uchar add) //在一个地址读一个字节
  {
  start();
  writebyte(0xa0);
  respons();
  writebyte(add);
  respons();
  start();
  writebyte(0xa1);
  respons();
  b=readbyte();
  respons();
  stop();
  return(b);
  }
  //**************************************************************
  // 时间日期函数
  //**************************************************************
  void v_WTInputByte(uchar ucDa)
  {
  uchar i;
  ACC= ucDa;
  for(i=8; i>0; i--)
  {
  T_IO = ACC0; //*相当于汇编中的 RRC
  T_CLK = 1;
  T_CLK = 0;
  ACC =ACC>> 1;
  }
  }
  uchar uc_RTOutputByte(void)
  {
  uchar i;
  for(i=8; i>0; i--)
  {
  ACC = ACC>>1; //*相当于汇编中的 RRC
  ACC7 = T_IO;
  T_CLK = 1;
  T_CLK = 0;
  }
  return(ACC);
  }
  void v_W1302(uchar ucAddr, uchar ucDa)
  {
  T_RST = 0;
  T_CLK = 0;
  T_RST = 1;
  v_WTInputByte(ucAddr); /* 地址,命令 */
  v_WTInputByte(ucDa); /* 写1Byte数据*/
  T_CLK = 1;
  T_RST =0;
  }
  uchar uc_R1302(uchar ucAddr)
  {
  uchar ucDa;
  T_RST = 0;
  T_CLK = 0;
  T_RST = 1;
  v_WTInputByte(ucAddr); // 地址,命令 //
  ucDa = uc_RTOutputByte(); // 读1Byte数据 //
  T_CLK = 1;
  T_RST =0;
  return(ucDa);
  }
  void Init1302(void)
  {
  v_W1302(0x8e,0x00); //控制写入WP=0
  v_W1302(0x80,0x80);
  v_W1302(0x90,0xa9);
  v_W1302(0x80,0x00); //秒
  v_W1302(0x82,0x24); //分
  v_W1302(0x84,0x12); //时
  v_W1302(0x86,0x29); //日
  v_W1302(0x88,0x10); //月
  v_W1302(0x8a,0x05); //星期
  v_W1302(0x8c,0x10); //年 //
  v_W1302(0x8e,0x80);
  }
  void donetime(void)
  {
  uchar d;
  d=uc_R1302(0x87);
  day[10]=(d&0x0f)+48;
  day[9]=((d>>4)&0x03)+48;
  d=uc_R1302(0x89);
  day[7]=(d&0x0f)+48;
  day[6]=((d>>4)&0x01)+48;
  d=uc_R1302(0x8b);
  day[13]=(d&0x07)+48;
  d=uc_R1302(0x8d);
  day[4]=(d&0x0f)+48;
  day[3]=(d>>4)+48;
  d=uc_R1302(0x81);
  time[15]=(d&0x0f)+48;
  time[14]=(d>>4)+48;
  d=uc_R1302(0x83);
  time[12]=(d&0x0f)+48;
  time[11]=(d>>4)+48;
  d=uc_R1302(0x85);
  time[9]=(d&0x0f)+48;
  time[8]=(d>>4)+48;
  }
  //**************************************************************
  // 温度检测函数
  //**************************************************************
  void dsreset(void) //18B20复位,初始化函数
  {
  uint i;
  ds=0;
  i=103;
  while(i>0)i--;
  ds=1;
  i=4;
  while(i>0)i--;
  }
  bit tempreadbit(void) //读1位函数
  {
  uint i;
  bit dat;
  ds=0;i++; //i++ 起延时作用
  ds=1;i++;i++;
  dat=ds; //读数据
  i=8;while(i>0)i--;
  return (dat);
  }
  uchar tempread(void) //读1个字节
  {
  uchar i,j,dat;
  dat=0;
  for(i=1;i<=8;i++)
  {
  j=tempreadbit();
  dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好一个字节在DAT里
  }
  return(dat);
  }
  void tempwritebyte(uchar dat) //向18B20写一个字节数据
  {
  uint i;
  uchar j;
  bit testb;
  for(j=1;j<=8;j++)
  {
  testb=dat&0x01; //判断最后一位是1还是0
  dat=dat>>1;
  if(testb) //写 1
  {
  ds=0;
  i++;i++;
  ds=1;
  i=8;while(i>0)i--;
  }
  else
  {
  ds=0; //写 0
  i=8;while(i>0)i--;
  ds=1;
  i++;i++;
  }
  }
  }

  void tempchange(void) //DS18B20 开始获取温度并转换
  {
  dsreset(); //初始化,每次对18B20的操作都首先要初始化
  delay_ms(1);
  tempwritebyte(0xcc); // 写跳过读ROM指令
  tempwritebyte(0x44); // 写温度转换指令
  }
  void get_temp() //读取寄存器中存储的温度数据
  {
  uchar a,b;
  dsreset(); //初始化
  delay_ms(1);
  tempwritebyte(0xcc); // 写跳过读ROM指令
  tempwritebyte(0xbe); //写读指令
  a=tempread(); //读低8位
  b=tempread(); //读高8位
  temp1=b;
  temp1<<=8; //两个字节组合为1个字
  temp1=temp1|a;
  f_temp=temp1*0.0625; //温度在寄存器中为12位 分辨率位0.0625°
  }
  //**************************************************************
  // 解密函数
  //**************************************************************
  void unlock()
  {
  uchar in,i;
  if(num==0)
  {
  lcd_xieping(0,0,"**密码锁系统** ");
  lcd_xieping(1,0,"—————————");
  lcd_xieping(2,0," 请输入密码: ");
  lcd_xieping(3,0," ");
  for(i=0;i<4;i++)
  {
  t1[i]=keyscan1();
  lcd_xieping(3,i,"*");
  num=0;
  }//输密码
  }
  in=keyscan1();
  if(in==12)//in-确定键标志位
  {
  in=0;
  num=0;
  if((t1[0]==t[0])&&(t1[1]==t[1])&&(t1[2]==t[2])&&(t1[3]==t[3]))
  {
  flag=1;//解密成功与否标志位
  //unlock_i=1;
  a=0;//功能键标志
  lcd_xieping(0,0,"**密码锁系统** ");
  lcd_xieping(1,0,"——————————");
  lcd_xieping(2,0," 密码正确! ");
  lcd_xieping(3,0," 您的身份已确认");
  delay_ms(1500);
  lcd_xieping(1,0,"————————");
  lcd_xieping(2,0,"功能 I 开锁 ");
  lcd_xieping(3,0," II修改密码");
  }
  else
  {
  flag=0;
  count++;
  if(count==3)
  {
  count=0;
  num=1;
  lcd_xieping(1,0,"——————————");
  lcd_xieping(2,0,"您的机会已用完 ");
  lcd_xieping(3,0,"对不起**无法进入");
  FM=0;
  delay_ms(1000);
  FM=1;
  }
  }
  }
  }
  //**************************************************************
  // 修改密码函数
  //**************************************************************
  void xiugaimima()
  { uchar i,j,l,im,ib;
  uchar t2[4];
  uchar t3[4];
  num=0;
  lcd_xieping(1,0,"————————");
  lcd_xieping(2,0,"请输入新密码: ");
  lcd_xieping(3,0," ");
  for(i=0;i<4;i++)
  {
  t2[i]=keyscan1();
  lcd_xieping0(3,i,mima[num]);
  num=0;
  }
  im=keyscan1();
  if(im==12)//im,in,ib,同为确定键标志位
  {
  im=0;
  num=0;
  lcd_xieping(1,0,"————————");
  lcd_xieping(2,0,"请再次输入新密码");
  lcd_xieping(3,0," ");
  for(i=0;i<4;i++)
  {
  t3[i]=keyscan1();
  lcd_xieping0(3,i,mima[num]);
  num=0;
  }
  }
  ib=keyscan1();
  if(ib==12)
  {
  ib=0;
  num=0;
  if(t2[0]==t3[0]&&t2[1]==t3[1]&&t2[2]==t3[2]&&t2[3]==t3[3])
  {
  t[0]=t3[0];
  t[1]=t3[1];
  t[2]=t3[2];
  t[3]=t3[3];
  lcd_xieping(1,0,"————————");
  lcd_xieping(2,0," 祝贺您! ");
  lcd_xieping(3,0," 密码修改成功 ");
  flag=0;
  for(j=0;j<4;j++)
  {
  l=j+1;
  write(l,t[j]);
  delay_ms(10);
  }//24C08写数据
  delay_ms(1000);
  }
  else
  {
  lcd_xieping(2,0,"两次输入密码不同");
  lcd_xieping(3,0," 密码修改失败 ");
  flag=1;
  delay_ms(500);
  }
  }
  }
  //**************************************************************
  // 显示函数
  //**************************************************************
  void xianshi()
  {
  donetime();
  tempchange();
  get_temp();
  s_temp=f_temp*100;
  temp0[7]=(s_temp/1000)+48;
  temp0[8]=(s_temp%1000/100)+48;
  temp0[10]=(s_temp%100/10)+48;
  temp0[11]=(s_temp%10)+48;
  lcd_xieping(0,0,"**密码锁系统** ");
  lcd_xieping(1,0,temp0);
  lcd_xieping(2,0,day);
  lcd_xieping(3,0,time);
  num=0;
  }
  //**************************************************************
  // 开锁函数
  //**************************************************************
  void kaisuo()
  {
  uchar i;
  lcd_xieping(2,0," 开锁中…… ");
  lcd_xieping(3,0,"——耐心等待——");
  for(i=3;i>0;i--)
  {
  FM=0;
  delay_ms(100);
  FM=1;
  delay_ms(100);
  flag=0;
  }
  dianjiZZ();
  delay_ms(10000);
  dianji_stop();
  lcd_xieping(2,0,"—开锁过程结束—");
  lcd_xieping(3,0," 请开门 ");
  delay_ms(5000);
  dianjiFZ();
  delay_ms(10000);
  dianji_stop();
  flag=0;
  }
  //**************************************************************
  // 主函数
  //**************************************************************
  void main()
  {
  uchar m;
  unlock_i=1;
  lcd_init(); //液晶初始化
  //Init1302();
  kjxs(); //开机显示
  for(m=0;m<4;m++)
  {
  t[m]=read(m+1);
  delay_ms(10);
  }//24C08读数据
  while(1)
  {
  reshi();
  if(!unlock_i)
  {
  unlock();//解密函数
  }
  else
  {
  xianshi();//时间、日期、温度显示函数
  }
  if(flag==1)
  {
  num1=0;
  a=keyscan2();
  if(a==1)
  {
  kaisuo();//开锁函数
  }
  if(a==2)
  {
  xiugaimima();//修改密码函数
  }
  }
  }
  }
山大科技馆
2020-12-10 · 贡献了超过120个回答
知道答主
回答量:120
采纳率:100%
帮助的人:6.4万
展开全部

第一节课

已赞过 已踩过<
你对这个回答的评价是?
评论 收起
xq_xss
2010-12-22
知道答主
回答量:83
采纳率:0%
帮助的人:26.7万
展开全部
sbit rs = P1^7; //数据/命令选择
sbit rw = P3^0; //读写,高电平读,低电平写
sbit en = P2^7; //使能,高脉冲输入
sbit light = P2^4; //背光使能,低电平时液晶板显示

/********************************************************************************************/
//写指令
void write_com( uchar com )
{
rs = 0;
rw = 0;
P0 = com;
delaynms( 10 );
en = 1;
delaynms( 5 );
en = 0;
}

/*******************************************************************************************/
//写数据
void write_data( uchar udata )
{
rs = 1;
rw = 0;
P0 = udata;
delaynms( 10 );
en = 1;
delaynms( 5 );
en = 0;
}

/*********************************************************************************************/
//初始化LCD
void LCD_init( void )
{
light = 0;
en = 0;
write_com( 0x38 ); //显示模式设置,16X2显示
write_com( 0x0e ); //开显示,显示光标,光标不闪烁
write_com( 0x01 ); //显示清屏
write_com( 0x06 ); //显示光标移动设置
write_com( 0x80 ); //初始地址
}
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 1条折叠回答
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式