加载中…
个人资料
sunday
sunday
  • 博客等级:
  • 博客积分:0
  • 博客访问:48,467
  • 关注人气:16
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

密码锁的程序

(2010-03-12 12:50:24)
标签:

lcd

if

case

i2c

教育

分类: 单片机

程序比较多,所以写成了几个文件,同时应用了相当多的标识位来进行信号传递。

我觉得边看程序边画它的流程图会更好地帮助我们读程序。

1.0  main.c文件

 

#include<reg52.h>
#include<string.h>
#include"mydefine_2.h"

static void delay(unsigned int N)//N ms延时_12MHz/准确性高
{
  unsigned int i=0,j=0;
  for(i=1;i<=N;i++)
  for(j=1;j<=355;j++) ;
}

void clock()
{
  key_clock=0;
  delay(15);
  key_clock=1;
}

void init()
{
  key_LCD=0;
  init_1602();

  TMOD=0x01;
  TH0=0x3C;//=(65535-5000)/256
  TL0=0xAF;//(65535-5000)%256
  EA=1;
  ET0=1;
  TR0=0;

  EA=1;//外部中断0唤醒CPU(空闲方式)
  EX0=1;
  IT0=1;
  command(0x80);
  lcd_display(7);
}

void main()
{
  init();

  while(1)
  {
   temp=keyboard_matrix();//扫描输入
   if(temp)//有按键输入信息
   {
    clock();//按键声
    TR0=0;//关闭计时
    timer=0;
    receive(temp);//输入的字符串长度为length( <= 10)
    if(i!=length)//输入时显示"*"
    {
     command(0xC0+length);//为显示密码输入设定位置
     display('*');
     i=length;
  }
  switch(temp)//根据按键号调用任务
  {
       //修改密码
    case 12: if((flag_allow) && (flag_amend==0))//输入密码正确的条件下可以更改
             {
               table_input[0]='\0';
               flag_display=3;//请输入新密码
               flag_confirm=1;//确认键进入确认修改密码功能
               flag_amend=1;//每次按下修改键时都是第一次输入新密码
               length=0;    //重按修改键时也是第一次输入新密码
               i=0;
             }
            else
            {
              flag_confirm=0;//恢复初始态
              flag_amend=0;
              lcd_display(1);//密码不正确
              delay(500);
              flag_display=7;
              length=0;
              i=0;
           }
           break;
    case 11: //取消
       command(0xC0+length);//擦出显示
       display(' ');//显示后光标_显示地址又加了1
       command(0xC0+length);//重置光标_显示地址|实为将光标拉回来
       i=0;
       if(length > 0)
       {
         length--;//input[]位置后退一位
       }
       break;
    case 10: confirm();//确定      
             i=0;
             break;
    case 13: //修改密码的过程中取消修改密码|将系统置于初始态即可
       if((flag_amend==1) || (flag_amend==2))
       {
          flag_amend=0;
          flag_confirm=0;
          lcd_display(8);
          delay(500);
          flag_display=7;
          length=0;
          i=0;
       }
       break;
   }
   lcd_display(flag_display);
  }
  else
  {
    TR0=1;//开始计时等待
  }
  DC_Moter();
  resume_password();
  if(flag_clear)//恢复密码和开锁键_外部中断有效时重新计时
  {
    flag_clear=0;
    timer=0;
  }
  if(timer==100)//10秒后不允许更改密码
  {
    flag_allow=0;
    flag_amend=0;
    flag_confirm=0;
    length=0;
    i=0;
    lcd_display(7);//显示初始态,以提示修改超时
  }
  if(timer==1200)//≈2分钟后休眠|空闲方式
  {
    TR0=0;
    timer=0;
    clear_system();//恢复初始态
    i=0;
    key_clock=0;
    delay(250);
    key_clock=1;
    PCON|=0x01;
    lcd_display(7);//唤醒CPU后显示初始态
  }
 }
}

void int0() interrupt 0
{
  key_LCD=0;//开液晶电源
  key_clock=0;
  delay(250);
  key_clock=1;
  flag_clear=1;
}

void Timer0() interrupt 1 //50ms
{
  TH0=0x3C;//(65535-50000)/256
  TL0=0xAF;//(65535-50000)%256
  timer++;
}

 

2.0  负责实现具体操作的 process_char.c 文件

 

#include<reg52.h>
#include<string.h>
#include"mydefine.h"

sbit key_self=P2^1;//独立按键,用于恢复初始密码
sbit key_LED=P2^0;
sbit key_M=P2^4;//DC电机控制口
sbit key_LCD=P2^7;//液晶电源控制口

extern bit flag_clear;//恢复密码和开锁键_外部中断的有效标识

extern unsigned int timer;//定时器0计数时段标记_50ms一次定时中断
extern unsigned char length=0;//跟踪记录输入table_input[11]的字符长度( <=10 )
extern unsigned char flag_display=0;//根据其值可以确定显示信息
extern unsigned char flag_confirm=0;//确认键根据此标识判定任务,默认为0_即为确定密码状态
extern unsigned char flag_allow=0;//允许修改密码标识,在密码比较正确时置1
extern unsigned char flag_amend=0;//第一/二次输入新密码标识
unsigned char flag_M=0;//允许电机开锁标识

extern void command(unsigned char command);
extern void display(unsigned char date);
//向I2C地址为address处写入数据date
extern void write_I2C(unsigned char address,unsigned char date);
//读出I2C地址为address处的数据
extern unsigned char read_I2C(unsigned char address);

static void delay(unsigned int N)//N ms延时/准确性高
{
  unsigned int i=0,j=0;
  for(i=1;i<=N;i++)
  for(j=1;j<=355;j++) ;
}

//休眠前清除table_input中的值
extern void clear_system()
{
 table_input[0]='\0';//恢复初始态
 length=0;
 flag_allow=0;
 flag_confirm=0;
 flag_amend=0;
 flag_clear=0;
 key_LCD=1;//关液晶电源
}

//接收键盘输入|以字符形式存入table_input[11]
extern void receive(unsigned char temp)
{
 //按键在松手时读取按键号,故不会重复读取按键值
 
 if(temp && length<=9)//如此,则无按键时执行效率高
 {
  switch(temp)
  {
   case 1:
   case 2:
   case 3:
   case 4:
   case 5:
   case 6:
   case 7:
   case 8:
   case 9: table_input[length++]=temp+48;//以字符形式存入table_input[11]
     break;
   case 14: table_input[length++]=48;//字符0
  }
 }
}

//根据任务选择显示信息
extern void lcd_display(unsigned char temp)
{
 unsigned char i=0,*p=NULL;
 if(temp)
 {
  switch(temp)//选择显示信息
  {
   case 1: p=table_error;//密码不正确
           break;
   case 2: p=table_pass;//密码正确
           break;
   case 3: p=table_new;//请输入新密码
           break;
   case 4: p=table_again;//请再次输入新密码
           break;
   case 5: p=table_changed;//密码修改成功
           break;
   case 6: p=table_fail;//密码修改失败
           break;
   case 7: p=table_enter;//显示输入密码:The password!
           break;
   case 8: p=table_abandon;//放弃修改密码
           break;
   case 9: p=table_close;//锁闭
           break;
   case 10: p=table_resume;//锁闭
            break;
  }
  command(0x01);
  delay(1);
  command(0x80);
  while(*p!='\0')
  {
    display(*(p++));
  }
  flag_display=0;//显示后清0,避免重复显示
 }
}

//确认
extern void confirm(void)
{
 unsigned char flag_compare=0;//用于记录比较输入与密码的结果|相等时返回1,否则返回0
 unsigned char flag_compare_2=0;//用于记录对两次输入的新密码的比较结果|相等时返回1,否则返回0
 unsigned char i=0;

 if(length > 0)//输入不为空
 {
   table_input[length]='\0';
   length=0;//输入字符串长度清0
 
  if(flag_confirm)//修改密码
  {
   switch(flag_amend)
   {
    case 1: strcpy(table_newpassword,table_input);//第一次输入新密码
            table_input[1]='\0';//避免第一次输入的内容在放弃修改时再次被利用
            flag_amend=2;
            flag_display=4;//请再次输入密码
            break;
    case 2: flag_compare_2=strcmp(table_input,table_newpassword);//第二次输入新密码
            flag_amend=0;//清0,允许再次修改
            flag_confirm=0;//进入初始之确认密码状态
      if(!flag_compare_2)//两次输入相同==0
      {
       strcpy(table_password,table_input);
       table_input[1]='\0';//避免修改完成后再次被利用,造成重复修改,同时避免刚修改了就是pass状态
       lcd_display(5);//修改成功
       delay(500);
       flag_display=7;
      }
      else
      {
        lcd_display(6);//修改失败
        delay(500);
        flag_display=7;
      }
      break;
   }
  }
  else//验证密码
  {
   flag_compare=strcmp(table_input,table_password);
   if(!flag_compare)//密码正确==0
   {
     flag_allow=1;//允许修改密码
     flag_M=1;//允许开锁
     flag_display=2;//密码正确信息:Pass!
     table_input[1]='\0';//改变输入,使不致出乱
   }
   else//密码错误
   {
     flag_allow=0;//不允许修改密码
     lcd_display(1);//密码错误信息:Error!
     delay(500);
     flag_display=7;
   }
  }
 }
}

//电机控制
extern void DC_Moter()
{
 if(flag_M)//允许开锁
 {
  flag_M=0;
  key_M=0;//开锁
  key_LED=0;
  delay(1250);
  key_M=1;
  key_LED=1;
  timer=0;
  lcd_display(7);//进入初始态
 }
}


//恢复初始密码
extern void resume_password()
{
 if(!key_self)//==0
 {
  delay(3);
  if(!key_self)//==0
  {
    while(!key_self) ;//==0
    strcpy(table_password,table_original);
    flag_clear=1;
    lcd_display(10);
    delay(500);
    lcd_display(7);
  }
 }
}

 

  

确认函数_ confirm()操作:

0_将 '\0' 置于输入table_input[]结尾

(table_input[]的长度返回值在length里面)

根据操作标识选择任务:

1_确认密码:判定输入密码正确与否

2_修改密码:确认第一次输入并保存

            要求第二次输入

                     比较两次输入是否相同

根据比较结果选择任务:

修改失败,进入输入密码态

修改成功,将输入复制到table_password[]

 

确认函数_confirm()相关标识位目录:

flag_display;//根据其值可以确定显示信息

 flag_confirm;//确认键根据此标识判定任务,默认为0_即为确定密码状态

flag_allow;//允许修改密码标识,在密码比较正确时置1

flag_amend;//第一/二次输入新密码标识

flag_M;//允许电机开锁标识

 

相关变量

sbit M=P3^6;//电机控制口

flag_confirm;//操作任务标识位

flag_compare;//比较输入与密码|相等时返回1,否则返回0

                        static flag_amend;//修改密码时的标识

第一次输入前=1,输入后置2

第二次输入前=2,输入后置0

          flag_display=0;//确认键操作的返回值根据返回值可以确定显示信息

        flag_allow;//允许改密码标识,在密码比较正确时置1,不正确时置0

            process_char()函数::_M;//DC电机控制口

 process_char()函数::_length;//跟踪记录输入table_input[11]的字符长度( <=10 )

 

lcd_display()函数中标识位flag_display的值与意义:

=0:不显示|不刷新显示

=1:密码错误

=2:密码正确

=3:请输入新密码

=4:请再次输入新密码

=5:密码修改成功

=6:密码修改失败

=7:显示输入密码状态_The password!

=8:放弃修改密码

=9:已开锁

 

3.0  定义各个数组的头文件mydefine.h

 

extern unsigned char table_input[11]={0};  //接收键盘输入
unsigned char table_password[11]="123456";  //密文
unsigned char table_newpassword[11]="456";  //接收新密码

unsigned char code table_original[11]="123456"; //初始密码

//显示信息
unsigned char code table_pass[]="Pass!";  //成功进入
unsigned char code table_error[]="Operate Error!";  //密码错误信息
unsigned char code table_enter[]="The password:";  //输入密码
unsigned char code table_new[]="New password:";  //输入新密码
unsigned char code table_again[]="Enter again:";  //再次输入新密码
unsigned char code table_changed[]="Changed!";  //密码修改成功
unsigned char code table_fail[]="Fail changce!";  //密码修改失败
unsigned char code table_abandon[]="Abandon changce!";//放弃修改密码
unsigned char code table_close[]="Locked!";//锁闭
unsigned char code table_resume[]="Resumed!";//恢复初始密码

 

4.0  头文件mydefine_2.h

     定义了各个外部文件向主函数用到的操作函数和外部变量

 

#ifndef _mydefine_2_h_
#define _mydefine_2_h_

 

sbit key_LED=P2^0;
sbit key_clock=P3^3;//蜂鸣器
sbit key_LCD=P2^7;//液晶电源控制口

extern bit flag_clear=0;//恢复密码和开锁键_外部中断的有效标识
extern unsigned int timer=0;//定时器0计数时段标记_50ms一次定时中断
static unsigned char i=0;//显示*用变量
unsigned char temp=0;//用于接收键盘输入(按键在松手时读取按键号)

extern unsigned int table_input[11];//接收输入
extern unsigned char flag_allow;//允许改密码标识,在密码比较正确时置1
extern unsigned char flag_confirm;//确认键根据此标识判定任务,默认为0_即为确定密码状态
extern unsigned char flag_display;//确认键操作的返回值,根据返回值可以确定显示信息
extern unsigned char flag_amend;//第一/二次输入新密码标识
extern unsigned char length;//输入input的字符长度(length <= 16)

//1602液晶:extern_1602.c *****************************************************************

extern void init_1602();
extern void command(unsigned char command);
extern void display(unsigned char date);


//键盘:extern_keyboard_no_T0_2.c *********************************************************

//矩阵键盘.无按键动作时其返回值num_key=0,否则返回按键号num_key
extern unsigned char keyboard_matrix();//(在松手时读取按键号****检测高四位)


//密码处理:process_char.c ****************************************************************

//电机控制
extern void DC_Moter();
//接收键盘输入|以bit形式存入input__返回值为输入的字符串长度length(length <= 10)
extern void receive(unsigned char temp);//涉及文件间变量length
//确认按键操作
extern void confirm(void);//涉及跨文件调用的变量flag_confirm,flag_allow,flag_amend
//根据任务选择显示信息
extern void lcd_display(unsigned char flag_display);//涉及跨文件调用的变量flag_display
extern void clear_system();//恢复初始态
extern void resume_password();//恢复初始密码

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

 

#endif 

 

键盘和1602显示的程序见其他文章。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有