找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4365|回复: 6
收起左侧

单片机简易密码锁判断程序一直错误,无法判断按下的三个按键是否正确,怎么回事?

[复制链接]
ID:626711 发表于 2019-10-19 19:11 | 显示全部楼层 |阅读模式
简易的单片机密码锁用不了,使用的是静态数码管+矩阵按键+蜂鸣器+继电器
自己写的程序,下载到单片机后按键可以使用,按下一个按键,数码管会正常显示按键按下对应的字符,但按了123后蜂鸣器和继电器没有反应,下面是我写的单片机程序(附件有单片机原理图和实物图)


#include "reg52.h"

#define jian_pan P1
#define shumaguan P0

sbit buzzer=P2^3;   //蜂鸣器
sbit relay=P2^2;     //继电器

int data password[4];
unsigned char cunfang;  //存放矩阵键盘按下的位置对应的0~f字符
unsigned char code number[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
                                        0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值  共阴

void delay(unsigned long int i)             //延时函数
{
  while(i--);
}

void keydown()          //检测哪个按键按下
{
        int a=0;
        jian_pan=0x0f;
        if(jian_pan!=0x0f)
        {
          delay(100);//延时10ms
          if(jian_pan!=0x0f)
          {
                    //测试列
                 jian_pan=0x0f;
                 switch(jian_pan)
                  {
                   case(0x07) : cunfang=0;break;
                   case(0x0b) : cunfang=4;break;
                   case(0x0d) : cunfang=8;break;
                   case(0x0e) : cunfang=12;break;
                  }
                  //测试行
                  jian_pan=0xf0;
                  switch(jian_pan)
                   {
                   case(0x70) : cunfang=cunfang;break;
                   case(0xb0) : cunfang=cunfang+1;break;
                   case(0xd0) : cunfang=cunfang+2;break;
                   case(0xe0) : cunfang=cunfang+3;break;
                   }
                  while((a<50)&&(jian_pan!=0xf0))
                  {
                          delay(1000); //延时100ms
                        a++;
                  }
             }
        }
}

void judge_number()    //检测按下的三次是否依次为123
{
   int mi_ma=0,n;
   if(cunfang!=0)       //判断存放按键的数值是否为零,当不为零的话相当于输入了一位密码
   {
     mi_ma=mi_ma+1;                //记录按下的次数
          password[mi_ma]=cunfang;   //把按下的密码存放到数组中
  if(mi_ma==3)                      //判断是否按下了三次
   {
    password[0]=password[1]*100+password[2]*10+password[3];   把前三次输入的数字合并
    if(password[0]==123)   //设置正确密码是123 并判断用户输入的密码是否为123       】
        {                                                                                                                  |
         buzzer=0;                                                                                                    |
         for(n=0;n<1000;n++)                                                                                   |    当密码输入正确继电器打开,蜂鸣器响
          {                                                                                                                |
                  relay=~relay;                                                                                        |
                delay(10);                                                                                             |
          }                                                                                                                】
          delay(6553400);                                       //延时约1分钟相当于开锁一分钟
         }
    }
   }
}

void main()
{
  while(1)
  {
   keydown(); //判断键入的字符
   shumaguan=~number[cunfang];//数码管显示按下的字符
   judge_number();  //检测按下的三次是否依次为123
  }
}




开发板

开发板

EM3_V3.0原理图.pdf

316.22 KB, 下载次数: 7

原理图

回复

使用道具 举报

ID:491577 发表于 2019-10-20 10:18 | 显示全部楼层
你的程序是按下1按键后一直输出1直到松开按键为止,void judge_number()  这个函数是只要有按键按下就一直累加,按1就是1一直累加,累加3次之后得到3个1,如果你把密码改成111,就可以打开继电器了。修改的方法:void judge_number() 中加入判断保证每按下一个按键只累加一次,才可以得到你想要的结果。
回复

使用道具 举报

ID:626711 发表于 2019-10-20 18:32 | 显示全部楼层
hhh402 发表于 2019-10-20 10:18
你的程序是按下1按键后一直输出1直到松开按键为止,void judge_number()  这个函数是只要有按键按下就一直 ...

还是不行,把密码改成111,不管是长按111还是短按111继电器都不会打开
我的keydown();函数按下一次应该是只能返回一个数字
回复

使用道具 举报

ID:626711 发表于 2019-10-20 19:05 | 显示全部楼层
hhh402 发表于 2019-10-20 10:18
你的程序是按下1按键后一直输出1直到松开按键为止,void judge_number()  这个函数是只要有按键按下就一直 ...

还是不行,我把密码改成111,无论是长按111还是短按111,继电器都不会打开
keydown()函数应该一次只能得到一个数值
回复

使用道具 举报

ID:491577 发表于 2019-10-21 11:48 | 显示全部楼层
void judge_number()函数中的变量 int mi_ma=0;是局部变量,每运行一次都会重新初始化为0,mi_ma永远为零,要改成:   
void judge_number()    //检测按下的三次是否依次为123
{
   static int mi_ma=0,a1=0;    int n;
   if(cunfang!=0)       //判断存放按键的数值是否为零,当不为零的话相当于输入了一位密码
   {  if(a1==0)   //这个与else a1=1;配合保证每次按键只计算一次。a1必须是静态变量或全局变量。
       {
           a1=1;
          mi_ma=mi_ma+1;                //记录按下的次数
          password[mi_ma]=cunfang;   //把按下的密码存放到数组中
       }
     else a1=0;
/*上面这7行(if    else语句)是保证每次按键只计算一次,原理:原来a1=0,第一次按键时if语句运行一次后a1=1,以后就不会再运行if里面的语句     了,直到按键释放后a1才会等于0,如此循环。这个语句要牢记,处理按键时都会用到。注意:这个语句里面的变量必须是静态变量或全局变量。
*/
   }
if(mi_ma==3)                      //判断是否按下了三次
   {
    mi_ma=0; //复位
    password[0]=password[1]*100+password[2]*10+password[3];   把前三次输入的数字合并
    if(password[0]==123)   //设置正确密码是123 并判断用户输入的密码是否为123       】
        {                                                                                                                  |
         buzzer=0;                                                                                                    |
         for(n=0;n<1000;n++)                                                                                   |    当密码输入正确继电器打开,蜂鸣器响
          {                                                                                                                |
                  relay=~relay;                                                                                        |
                delay(10);                                                                                             |
          }                                                                                                                】
          delay(6553400);                                       //延时约1分钟相当于开锁一分钟
         }
   }
}
回复

使用道具 举报

ID:626711 发表于 2019-10-22 13:25 | 显示全部楼层
hhh402 发表于 2019-10-21 11:48
void judge_number()函数中的变量 int mi_ma=0;是局部变量,每运行一次都会重新初始化为0,mi_ma永远为零, ...

还是不行,不过把密码改成111可以工作
回复

使用道具 举报

ID:626711 发表于 2019-10-22 13:43 | 显示全部楼层
hhh402 发表于 2019-10-21 11:48
void judge_number()函数中的变量 int mi_ma=0;是局部变量,每运行一次都会重新初始化为0,mi_ma永远为零, ...

我知道这次的问题出在哪儿了,当我按下1的时候
if(cunfang!=0)       //判断存放按键的数值是否为零,当不为零的话相当于输入了一位密码
   {  if(a1==0)   //这个与else a1=1;配合保证每次按键只计算一次。a1必须是静态变量或全局变量。
       {
           a1=1;
          mi_ma=mi_ma+1;                //记录按下的次数
          password[mi_ma]=cunfang;   //把按下的密码存放到数组中
       }
     else a1=0;
第一次循环的时候记录下我的密码1,然后我还没松开的时候他第二次循环就来了这次把a1变成零,然后紧接着第三次循环记录下第二位密码还是1,我按下1的那一会儿它会循环很多次,然后都相当于密码是111
给这个     else a1=0;
改成再加一个判断语句,把矩阵键盘的数据传送进来,判断矩阵键盘是否松开松开的话a1=0
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表